Coverage Report

Created: 2026-06-09 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/ua_securechannel_crypto.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2014, 2016-2017 (c) Florian Palm
7
 *    Copyright 2015-2016 (c) Sten GrĂ¼ner
8
 *    Copyright 2015 (c) Oleksiy Vasylyev
9
 *    Copyright 2016 (c) TorbenD
10
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
11
 *    Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
12
 *    Copyright 2025 (c) o6 Automation GmbH (Author: Julius Pfrommer)
13
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Andreas Ebner)
14
 */
15
16
#include "open62541/transport_generated.h"
17
#include "ua_securechannel.h"
18
#include "ua_types_encoding_binary.h"
19
20
UA_StatusCode
21
0
UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) {
22
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
23
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
24
0
    UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local nonce");
25
26
    /* Is the length of the previous nonce correct? */
27
0
    size_t nonceLength = sp->nonceLength;
28
0
    if(nonceLength == 0)
29
0
        return UA_STATUSCODE_GOOD;
30
31
    /* At least 32 byte */
32
0
    if(nonceLength < 32)
33
0
        nonceLength = 32;
34
35
0
    if(channel->localNonce.length != nonceLength) {
36
0
        UA_ByteString_clear(&channel->localNonce);
37
0
        UA_StatusCode res = UA_ByteString_allocBuffer(&channel->localNonce, nonceLength);
38
0
        UA_CHECK_STATUS(res, return res);
39
0
    }
40
41
    /* Generate the nonce */
42
0
    channel->localNonce.data[0] = 'e';
43
0
    channel->localNonce.data[1] = 'p';
44
0
    channel->localNonce.data[2] = 'h';
45
0
    return sp->generateNonce(sp, channel->channelContext, &channel->localNonce);
46
0
}
47
48
UA_StatusCode
49
0
UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
50
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
51
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
52
0
    UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local keys");
53
54
0
    void *cc = channel->channelContext;
55
0
    const UA_SecurityPolicyEncryptionAlgorithm *ea = &sp->symEncryptionAlgorithm;
56
57
    /* Generate symmetric key buffer of the required length. The block size is
58
     * identical for local/remote. For AEAD ciphers the IV length differs from
59
     * the block size, so use getLocalIvLength when available. */
60
0
    UA_ByteString buf;
61
0
    size_t encrKL = ea->getLocalKeyLength(sp, cc);
62
0
    size_t encrBS = ea->getRemoteBlockSize(sp, cc);
63
0
    size_t ivLen = ea->getLocalIvLength ? ea->getLocalIvLength(sp, cc) : encrBS;
64
0
    size_t signKL = sp->symSignatureAlgorithm.getLocalKeyLength(sp, cc);
65
0
    if(ivLen + signKL + encrKL == 0)
66
0
        return UA_STATUSCODE_GOOD; /* No keys to generate */
67
68
0
    UA_StatusCode res = UA_ByteString_allocBuffer(&buf, ivLen + signKL + encrKL);
69
0
    UA_CHECK_STATUS(res, return res);
70
0
    UA_ByteString localSigningKey = {signKL, buf.data};
71
0
    UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
72
0
    UA_ByteString localIv = {ivLen, &buf.data[signKL + encrKL]};
73
74
    /* TODO: Signal that no ECC salt is generated. Find a clean solution for this.  */
75
0
    buf.data[0] = 0x00;
76
77
    /* Generate key */
78
0
    res = sp->generateKey(sp, cc, &channel->remoteNonce, &channel->localNonce, &buf);
79
0
    UA_CHECK_STATUS(res, goto error);
80
81
    /* Set the channel context */
82
0
    res |= sp->setLocalSymSigningKey(sp, cc, &localSigningKey);
83
0
    res |= sp->setLocalSymEncryptingKey(sp, cc, &localEncryptingKey);
84
0
    res |= sp->setLocalSymIv(sp, cc, &localIv);
85
86
0
 error:
87
0
    if(res != UA_STATUSCODE_GOOD) {
88
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel,
89
0
                             "Could not generate local keys (%s)",
90
0
                             UA_StatusCode_name(res));
91
0
    }
92
0
    UA_ByteString_clear(&buf);
93
0
    return res;
94
0
}
95
96
UA_StatusCode
97
0
generateRemoteKeys(const UA_SecureChannel *channel) {
98
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
99
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
100
0
    UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new remote keys");
101
102
0
    void *cc = channel->channelContext;
103
0
    const UA_SecurityPolicyEncryptionAlgorithm *ea = &sp->symEncryptionAlgorithm;
104
105
    /* Generate symmetric key buffer of the required length. For AEAD ciphers
106
     * the IV length differs from the block size, so use getLocalIvLength when
107
     * available. */
108
0
    UA_ByteString buf;
109
0
    size_t encrKL = ea->getRemoteKeyLength(sp, cc);
110
0
    size_t encrBS = ea->getRemoteBlockSize(sp, cc);
111
0
    size_t ivLen = ea->getLocalIvLength ? ea->getLocalIvLength(sp, cc) : encrBS;
112
0
    size_t signKL = sp->symSignatureAlgorithm.getRemoteKeyLength(sp, cc);
113
0
    if(ivLen + signKL + encrKL == 0)
114
0
        return UA_STATUSCODE_GOOD; /* No keys to generate */
115
116
0
    UA_StatusCode res = UA_ByteString_allocBuffer(&buf, ivLen + signKL + encrKL);
117
0
    UA_CHECK_STATUS(res, return res);
118
0
    UA_ByteString remoteSigningKey = {signKL, buf.data};
119
0
    UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
120
0
    UA_ByteString remoteIv = {ivLen, &buf.data[signKL + encrKL]};
121
122
    /* TODO: Signal that no ECC salt is generated. Find a clean solution for this.  */
123
0
    buf.data[0] = 0x00;
124
125
    /* Generate key */
126
0
    res = sp->generateKey(sp, cc, &channel->localNonce, &channel->remoteNonce, &buf);
127
0
    UA_CHECK_STATUS(res, goto error);
128
129
    /* Set the channel context */
130
0
    res |= sp->setRemoteSymSigningKey(sp, cc, &remoteSigningKey);
131
0
    res |= sp->setRemoteSymEncryptingKey(sp, cc, &remoteEncryptingKey);
132
0
    res |= sp->setRemoteSymIv(sp, cc, &remoteIv);
133
134
0
 error:
135
0
    if(res != UA_STATUSCODE_GOOD) {
136
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel,
137
0
                               "Could not generate remote keys (%s)",
138
0
                               UA_StatusCode_name(res));
139
0
    }
140
0
    UA_ByteString_clear(&buf);
141
0
    return res;
142
0
}
143
144
/***************************/
145
/* Send Asymmetric Message */
146
/***************************/
147
148
/* The length of the static header content */
149
0
#define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12
150
151
size_t
152
0
calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
153
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
154
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
155
156
0
    size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH +
157
0
                              sp->policyUri.length;
158
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
159
0
        return asymHeaderLength;
160
161
    /* OPN is always encrypted even if the mode is sign only */
162
0
    asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
163
0
    asymHeaderLength += sp->localCertificate.length;
164
0
    return asymHeaderLength;
165
0
}
166
167
UA_StatusCode
168
prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
169
                   const UA_Byte *buf_end, size_t totalLength,
170
                   size_t securityHeaderLength, UA_UInt32 requestId,
171
0
                   size_t *const encryptedLength) {
172
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
173
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
174
175
0
    void *cc = channel->channelContext;
176
177
0
    *encryptedLength = totalLength;
178
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE) {
179
0
        size_t dataToEncryptLength = totalLength -
180
0
            (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength);
181
0
        size_t plainTextBlockSize = sp->asymEncryptionAlgorithm.
182
0
            getRemotePlainTextBlockSize(sp, cc);
183
0
        size_t encryptedBlockSize = sp->asymEncryptionAlgorithm.
184
0
            getRemoteBlockSize(sp, cc);
185
186
        /* Padding always fills up the last block */
187
0
        UA_assert(plainTextBlockSize > 0);
188
0
        UA_assert(dataToEncryptLength % plainTextBlockSize == 0);
189
0
        size_t blocks = dataToEncryptLength / plainTextBlockSize;
190
0
        *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize);
191
0
    }
192
193
0
    UA_TcpMessageHeader messageHeader;
194
0
    messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
195
0
    messageHeader.messageSize = (UA_UInt32)*encryptedLength;
196
0
    UA_UInt32 secureChannelId = channel->securityToken.channelId;
197
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
198
0
    res |= UA_encodeBinaryInternal(&messageHeader,
199
0
                                   &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
200
0
                                   &header_pos, &buf_end, NULL, NULL, NULL);
201
0
    res |= UA_UInt32_encodeBinary(&secureChannelId, &header_pos, buf_end);
202
0
    UA_CHECK_STATUS(res, return res);
203
204
0
    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
205
0
    UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
206
0
    asymHeader.securityPolicyUri = sp->policyUri;
207
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
208
0
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
209
0
        asymHeader.senderCertificate = sp->localCertificate;
210
0
        asymHeader.receiverCertificateThumbprint.length = 20;
211
0
        asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
212
0
    }
213
0
    res = UA_encodeBinaryInternal(&asymHeader,
214
0
                                  &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
215
0
                                  &header_pos, &buf_end, NULL, NULL, NULL);
216
0
    UA_CHECK_STATUS(res, return res);
217
218
    /* Increase the sequence number in the channel */
219
0
    channel->sendSequenceNumber++;
220
221
0
    UA_SequenceHeader seqHeader;
222
0
    seqHeader.requestId = requestId;
223
0
    seqHeader.sequenceNumber = channel->sendSequenceNumber;
224
0
    res = UA_encodeBinaryInternal(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
225
0
                                  &header_pos, &buf_end, NULL, NULL, NULL);
226
0
    return res;
227
0
}
228
229
void
230
hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
231
0
              const UA_Byte **buf_end) {
232
    /* Set buf_start to the beginning of the encrypted body */
233
0
    *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
234
0
    *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
235
236
    /* Hide only the SequenceHeader for None  */
237
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) {
238
0
        *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
239
0
        return;
240
0
    }
241
242
    /* The max plaintext length depends on the number of encrypted blocks that
243
     * can fit into the remaining chunk */
244
0
    void *cc = channel->channelContext;
245
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
246
0
    size_t plainTextBlockSize =
247
0
        sp->asymEncryptionAlgorithm.getRemotePlainTextBlockSize(sp, cc);
248
0
    size_t encryptedBlockSize =
249
0
        sp->asymEncryptionAlgorithm.getRemoteBlockSize(sp, cc);
250
251
0
    size_t max_encrypted = (size_t)(*buf_end - *buf_start);
252
0
    UA_assert(encryptedBlockSize > 0);
253
0
    size_t max_blocks = max_encrypted / encryptedBlockSize;
254
0
    size_t max_plaintext = max_blocks * plainTextBlockSize;
255
256
    /* Reserve plaintext length for the SequenceHeader and Footer.
257
     * But don't reserve for the the padding itself -- which can be zero. */
258
0
    max_plaintext -= UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
259
0
    max_plaintext -= sp->asymSignatureAlgorithm.getLocalSignatureSize(sp, cc);
260
0
    UA_Boolean extraPadding =
261
0
        (sp->asymEncryptionAlgorithm.getRemoteKeyLength(sp, cc) > 2048);
262
0
    max_plaintext -= (UA_LIKELY(!extraPadding)) ? 1u : 2u;
263
264
    /* Adjust the buffer */
265
0
    *buf_end = *buf_start + max_plaintext;
266
0
    *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
267
0
}
268
269
/* Assumes that pos can be advanced to the end of the current block */
270
void
271
padChunk(UA_SecureChannel *channel,
272
         const UA_SecurityPolicySignatureAlgorithm *sa,
273
         const UA_SecurityPolicyEncryptionAlgorithm *ea,
274
0
         const UA_Byte *start, UA_Byte **pos) {
275
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
276
0
    void *cc = channel->channelContext;
277
278
0
    const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start;
279
280
0
    size_t signatureSize = sa->getLocalSignatureSize(sp, cc);
281
0
    size_t plainTextBlockSize = ea->getRemotePlainTextBlockSize(sp, cc);
282
0
    UA_Boolean extraPadding = (ea->getRemoteKeyLength(sp, cc) > 2048);
283
0
    size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
284
285
0
    UA_assert(plainTextBlockSize > 0);
286
0
    size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize);
287
0
    size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0;
288
289
0
    UA_assert((bytesToWrite + signatureSize +
290
0
               paddingBytes + paddingLength) % plainTextBlockSize == 0);
291
292
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
293
0
                         "Add %lu bytes of padding plus %lu padding size bytes",
294
0
                         (long unsigned int)paddingLength,
295
0
                         (long unsigned int)paddingBytes);
296
297
    /* Write the padding. This is <= because the paddingSize byte also has to be
298
     * written */
299
0
    UA_Byte paddingByte = (UA_Byte)paddingLength;
300
0
    for(size_t i = 0; i <= paddingLength; ++i) {
301
0
        **pos = paddingByte;
302
0
        ++*pos;
303
0
    }
304
305
    /* Write the extra padding byte if required */
306
0
    if(extraPadding) {
307
0
        **pos = (UA_Byte)(paddingLength >> 8u);
308
0
        ++*pos;
309
0
    }
310
0
}
311
312
UA_StatusCode
313
signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
314
                   UA_ByteString *buf, size_t securityHeaderLength,
315
0
                   size_t totalLength) {
316
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
317
0
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
318
0
        return UA_STATUSCODE_GOOD;
319
320
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
321
0
    void *cc = channel->channelContext;
322
323
    /* Sign message */
324
0
    const UA_ByteString dataToSign = {preSignLength, buf->data};
325
0
    size_t sigsize = sp->asymSignatureAlgorithm.getLocalSignatureSize(sp, cc);
326
0
    UA_ByteString signature = {sigsize, buf->data + preSignLength};
327
0
    UA_StatusCode retval = sp->asymSignatureAlgorithm.
328
0
        sign(sp, cc, &dataToSign, &signature);
329
0
    UA_CHECK_STATUS(retval, return retval);
330
331
    /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
332
     * signed and encrypted if the SecurityMode is not None (even if the
333
     * SecurityMode is SignOnly). */
334
0
    size_t unencrypted_length =
335
0
        UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength;
336
0
    UA_ByteString dataToEncrypt =
337
0
        {totalLength - unencrypted_length, &buf->data[unencrypted_length]};
338
0
    return sp->asymEncryptionAlgorithm.encrypt(sp, cc, &dataToEncrypt);
339
0
}
340
341
/**************************/
342
/* Send Symmetric Message */
343
/**************************/
344
345
UA_StatusCode
346
signAndEncryptSym(UA_MessageContext *messageContext,
347
0
                  size_t preSigLength, size_t totalLength) {
348
0
    const UA_SecureChannel *channel = messageContext->channel;
349
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
350
0
        return UA_STATUSCODE_GOOD;
351
352
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
353
0
    void *cc = channel->channelContext;
354
355
    /* For AEAD policies (ChaCha20-Poly1305), set the message security
356
     * parameters for nonce masking. Then let the encrypt callback handle
357
     * both authentication and encryption. */
358
0
    if(sp->policyType == UA_SECURITYPOLICYTYPE_ECC_AEAD) {
359
        /* Set AEAD parameters: tokenId, previous seqNo, AAD */
360
0
        if(sp->setMessageSecurityParameters) {
361
0
            UA_ByteString aad;
362
0
            aad.data = messageContext->messageBuffer.data;
363
0
            aad.length = UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
364
0
                         UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
365
0
            UA_UInt32 prevSeqNo = channel->sendSequenceNumber > 0 ?
366
0
                (UA_UInt32)(channel->sendSequenceNumber - 1) : 0;
367
0
            UA_StatusCode res = sp->setMessageSecurityParameters(
368
0
                sp, cc, channel->securityToken.tokenId, prevSeqNo, &aad);
369
0
            UA_CHECK_STATUS(res, return res);
370
0
        }
371
372
0
        if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
373
            /* Full AEAD: encrypt + compute auth tag. Data includes
374
             * the 16-byte tag space at the end. */
375
0
            UA_ByteString dataToProcess;
376
0
            dataToProcess.data = messageContext->messageBuffer.data +
377
0
                UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
378
0
                UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
379
0
            dataToProcess.length = totalLength -
380
0
                (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
381
0
                 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
382
0
            return sp->symEncryptionAlgorithm.encrypt(sp, cc, &dataToProcess);
383
0
        }
384
385
        /* Sign-only: Compute Poly1305 auth tag */
386
0
        UA_ByteString dataToSign = messageContext->messageBuffer;
387
0
        dataToSign.length = preSigLength;
388
0
        UA_ByteString signature;
389
0
        signature.length =
390
0
            sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
391
0
        signature.data = messageContext->buf_pos;
392
0
        return sp->symSignatureAlgorithm.
393
0
            sign(sp, cc, &dataToSign, &signature);
394
0
    }
395
396
    /* Sign */
397
0
    UA_ByteString dataToSign = messageContext->messageBuffer;
398
0
    dataToSign.length = preSigLength;
399
0
    UA_ByteString signature;
400
0
    signature.length =
401
0
        sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
402
0
    signature.data = messageContext->buf_pos;
403
0
    UA_StatusCode res = sp->symSignatureAlgorithm.
404
0
        sign(sp, cc, &dataToSign, &signature);
405
0
    UA_CHECK_STATUS(res, return res);
406
407
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
408
0
        return UA_STATUSCODE_GOOD;
409
410
    /* Encrypt */
411
0
    UA_ByteString dataToEncrypt;
412
0
    dataToEncrypt.data = messageContext->messageBuffer.data +
413
0
        UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
414
0
        UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
415
0
    dataToEncrypt.length = totalLength -
416
0
        (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
417
0
         UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
418
0
    return sp->symEncryptionAlgorithm.encrypt(sp, cc, &dataToEncrypt);
419
0
}
420
421
void
422
0
setBufPos(UA_MessageContext *mc) {
423
    /* Forward the data pointer so that the payload is encoded after the message
424
     * header. This has to be a symmetric message because OPN (with asymmetric
425
     * encryption) does not support chunking. */
426
0
    mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
427
0
    mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
428
429
0
    if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
430
0
        return;
431
432
0
    const UA_SecureChannel *channel = mc->channel;
433
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
434
0
    void *cc = channel->channelContext;
435
436
    /* For AEAD (ChaCha20-Poly1305): no padding, no block alignment.
437
     * Only reserve space for the authentication tag (signature size). */
438
0
    if(sp->policyType == UA_SECURITYPOLICYTYPE_ECC_AEAD) {
439
0
        size_t sigsize =
440
0
            sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
441
0
        mc->buf_end -= sigsize;
442
0
        UA_LOG_TRACE_CHANNEL(sp->logger, channel,
443
0
                             "Prepare an AEAD symmetric message buffer of length %lu "
444
0
                             "with a usable maximum payload length of %lu",
445
0
                             (long unsigned)mc->messageBuffer.length,
446
0
                             (long unsigned)((uintptr_t)mc->buf_end -
447
0
                                             (uintptr_t)mc->messageBuffer.data));
448
0
        return;
449
0
    }
450
451
0
    size_t sigsize =
452
0
        sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
453
0
    size_t plainBlockSize =
454
0
        sp->symEncryptionAlgorithm.getRemotePlainTextBlockSize(sp, cc);
455
456
    /* Assuming that for symmetric encryption the plainTextBlockSize ==
457
     * cypherTextBlockSize. For symmetric encryption the remote/local block
458
     * sizes are identical. */
459
0
    UA_assert(sp->symEncryptionAlgorithm.getRemoteBlockSize(sp, cc) == plainBlockSize);
460
461
    /* Leave enough space for the signature and padding */
462
0
    mc->buf_end -= sigsize;
463
0
    UA_assert(plainBlockSize > 0);
464
0
    mc->buf_end -= mc->messageBuffer.length % plainBlockSize;
465
466
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
467
        /* Reserve space for the padding bytes */
468
0
        UA_Boolean extraPadding =
469
0
            (sp->symEncryptionAlgorithm.getRemoteKeyLength(sp, cc) > 2048);
470
0
        mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2;
471
0
    }
472
473
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
474
0
                         "Prepare a symmetric message buffer of length %lu "
475
0
                         "with a usable maximum payload length of %lu",
476
0
                         (long unsigned)mc->messageBuffer.length,
477
0
                         (long unsigned)((uintptr_t)mc->buf_end -
478
0
                                         (uintptr_t)mc->messageBuffer.data));
479
0
}
480
481
/****************************/
482
/* Process a received Chunk */
483
/****************************/
484
485
static size_t
486
decodePadding(const UA_SecureChannel *channel,
487
              const UA_SecurityPolicyEncryptionAlgorithm *encryptionAlgorithm,
488
0
              const UA_ByteString *chunk, size_t sigsize) {
489
    /* Read the byte with the padding size */
490
0
    size_t paddingSize = chunk->data[chunk->length - sigsize - 1];
491
492
    /* Extra padding size */
493
0
    if(encryptionAlgorithm->getLocalKeyLength(channel->securityPolicy,
494
0
                                              channel->channelContext) > 2048) {
495
0
        paddingSize <<= 8u;
496
0
        paddingSize += chunk->data[chunk->length - sigsize - 2];
497
0
        paddingSize += 1; /* Extra padding byte itself */
498
0
    }
499
500
    /* Add one since the paddingSize byte itself needs to be removed as well */
501
0
    return paddingSize + 1;
502
0
}
503
504
/* Sets the payload to a pointer inside the chunk buffer. Returns the requestId
505
 * and the sequenceNumber */
506
UA_StatusCode
507
decryptAndVerifyChunk(const UA_SecureChannel *channel,
508
                      const UA_SecurityPolicySignatureAlgorithm *signatureAlgorithm,
509
                      const UA_SecurityPolicyEncryptionAlgorithm *encryptionAlgorithm,
510
                      UA_MessageType messageType, UA_ByteString *chunk,
511
0
                      size_t offset) {
512
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
513
0
    void *cc = channel->channelContext;
514
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
515
516
    /* AEAD path (ChaCha20-Poly1305): the decrypt callback handles both
517
     * decryption and authentication tag verification in one step. */
518
0
    if(sp->policyType == UA_SECURITYPOLICYTYPE_ECC_AEAD &&
519
0
       messageType != UA_MESSAGETYPE_OPN) {
520
521
        /* Set AEAD parameters before decrypt/verify */
522
0
        if(sp->setMessageSecurityParameters) {
523
0
            UA_ByteString aad = {offset, chunk->data};
524
0
            res = sp->setMessageSecurityParameters(
525
0
                sp, cc, channel->securityToken.tokenId,
526
0
                channel->receiveSequenceNumber, &aad);
527
0
            UA_CHECK_STATUS(res, return res);
528
0
        }
529
530
0
        if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
531
            /* Full AEAD decrypt + verify. The decrypt callback processes
532
             * the data including the 16-byte auth tag at the end. On
533
             * success, it reduces cipher.length by the tag size. */
534
0
            UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
535
0
            res = encryptionAlgorithm->decrypt(sp, cc, &cipher);
536
0
            UA_CHECK_STATUS(res,
537
0
                UA_LOG_WARNING_CHANNEL(sp->logger, channel,
538
0
                                       "AEAD decryption/verification failed");
539
0
                return res);
540
0
            chunk->length = cipher.length + offset;
541
0
        } else if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN) {
542
            /* Sign-only: verify the auth tag without decryption */
543
0
            size_t sigsize = signatureAlgorithm->getRemoteSignatureSize(sp, cc);
544
0
            UA_CHECK(sigsize < chunk->length,
545
0
                     return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
546
0
            const UA_ByteString content = {chunk->length - sigsize, chunk->data};
547
0
            const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
548
0
            res = signatureAlgorithm->verify(sp, cc, &content, &sig);
549
0
            UA_CHECK_STATUS(res,
550
0
                UA_LOG_WARNING_CHANNEL(sp->logger, channel,
551
0
                                       "AEAD signature verification failed");
552
0
                return res);
553
0
            chunk->length -= sigsize;
554
0
        }
555
556
        /* Verify the content length */
557
0
        UA_CHECK(offset + 9 < chunk->length,
558
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel,
559
0
                                      "AEAD message too short");
560
0
                 return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
561
0
        return UA_STATUSCODE_GOOD;
562
0
    }
563
564
    /* Decrypt the chunk */
565
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
566
0
       messageType == UA_MESSAGETYPE_OPN) {
567
0
        UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
568
0
        res = encryptionAlgorithm->decrypt(sp, cc, &cipher);
569
0
        UA_CHECK_STATUS(res, return res);
570
0
        chunk->length = cipher.length + offset;
571
0
    }
572
573
    /* Does the message have a signature? */
574
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
575
0
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
576
0
       messageType != UA_MESSAGETYPE_OPN)
577
0
        return UA_STATUSCODE_GOOD;
578
579
    /* Verify the chunk signature */
580
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Verifying chunk signature");
581
0
    size_t sigsize = signatureAlgorithm->getRemoteSignatureSize(sp, cc);
582
0
    UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
583
0
    const UA_ByteString content = {chunk->length - sigsize, chunk->data};
584
0
    const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
585
0
    res = signatureAlgorithm->verify(sp, cc, &content, &sig);
586
0
    UA_CHECK_STATUS(res, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
587
0
                                                "Could not verify the signature");
588
0
                    return res);
589
590
    /* Compute the padding if the payload is encrypted (not ECC policy) */
591
0
    size_t padSize = 0;
592
0
    if((messageType != UA_MESSAGETYPE_OPN &&
593
0
        channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) ||
594
0
       (messageType == UA_MESSAGETYPE_OPN &&
595
0
        sp->policyType == UA_SECURITYPOLICYTYPE_RSA)) {
596
0
        padSize = decodePadding(channel, encryptionAlgorithm, chunk, sigsize);
597
0
        UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Calculated padding size to be %lu",
598
0
                             (long unsigned)padSize);
599
0
    }
600
601
    /* Verify the content length. The encrypted payload has to be at least 9
602
     * bytes long: 8 byte for the SequenceHeader and one byte for the actual
603
     * message */
604
0
    UA_CHECK(offset + padSize + sigsize + 9 < chunk->length,
605
0
             UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Impossible padding value");
606
0
             return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
607
608
    /* Hide the signature and padding */
609
0
    chunk->length -= (sigsize + padSize);
610
0
    return UA_STATUSCODE_GOOD;
611
0
}
612
613
/* The certificate in the header is verified via the configured PKI plugin as
614
 * certificateVerification.verifyCertificate(...). We cannot do it here because
615
 * the client/server context is needed. */
616
UA_StatusCode
617
checkAsymHeader(UA_SecureChannel *channel,
618
0
                const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
619
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
620
0
    if(!UA_String_equal(&sp->policyUri, &asymHeader->securityPolicyUri))
621
0
        return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
622
0
    return sp->compareCertThumbprint(sp, &asymHeader->receiverCertificateThumbprint);
623
0
}
624
625
UA_StatusCode
626
checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId,
627
0
               UA_DateTime nowMonotonic) {
628
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
629
0
    (void)sp;
630
631
    /* If no match, try to revolve to the next token after a
632
     * RenewSecureChannel */
633
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
634
0
    UA_ChannelSecurityToken *token = &channel->securityToken;
635
0
    switch(channel->renewState) {
636
0
    case UA_SECURECHANNELRENEWSTATE_NORMAL:
637
0
    case UA_SECURECHANNELRENEWSTATE_SENT:
638
0
    default:
639
0
        break;
640
641
0
    case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER:
642
        /* Old token still in use */
643
0
        if(tokenId == channel->securityToken.tokenId)
644
0
            break;
645
646
        /* Not the new token */
647
0
        UA_CHECK(tokenId == channel->altSecurityToken.tokenId,
648
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Unknown SecurityToken");
649
0
                 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
650
651
        /* Roll over to the new token, generate new local and remote keys */
652
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
653
0
        channel->securityToken = channel->altSecurityToken;
654
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
655
0
        retval |= UA_SecureChannel_generateLocalKeys(channel);
656
0
        retval |= generateRemoteKeys(channel);
657
0
        UA_CHECK_STATUS(retval, return retval);
658
0
        break;
659
660
0
    case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT:
661
        /* The server is still using the old token. That's okay. */
662
0
        if(tokenId == channel->altSecurityToken.tokenId) {
663
0
            token = &channel->altSecurityToken;
664
0
            break;
665
0
        }
666
667
        /* Not the new token */
668
0
        UA_CHECK(tokenId == channel->securityToken.tokenId,
669
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Unknown SecurityToken");
670
0
                 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
671
672
        /* The remote server uses the new token for the first time. Delete the
673
         * old token and roll the remote key over. The local key already uses
674
         * the nonce pair from the last OPN exchange. */
675
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
676
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
677
0
        retval = generateRemoteKeys(channel);
678
0
        UA_CHECK_STATUS(retval, return retval);
679
0
    }
680
681
0
    UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC);
682
0
    if(channel->state == UA_SECURECHANNELSTATE_OPEN && timeout < nowMonotonic) {
683
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel, "SecurityToken timed out");
684
0
        UA_SecureChannel_shutdown(channel, UA_SHUTDOWNREASON_TIMEOUT);
685
0
        return UA_STATUSCODE_BADSECURECHANNELCLOSED;
686
0
    }
687
688
0
    return UA_STATUSCODE_GOOD;
689
0
}
690
691
UA_Boolean
692
0
UA_SecureChannel_checkTimeout(UA_SecureChannel *channel, UA_DateTime nowMonotonic) {
693
    /* Compute the timeout date of the SecurityToken */
694
0
    UA_DateTime timeout = channel->securityToken.createdAt +
695
0
        (UA_DateTime)(channel->securityToken.revisedLifetime * UA_DATETIME_MSEC);
696
697
    /* The token has timed out. Try to do the token revolving now instead of
698
     * shutting the channel down.
699
     *
700
     * Part 4, 5.5.2 says: Servers shall use the existing SecurityToken to
701
     * secure outgoing Messages until the SecurityToken expires or the
702
     * Server receives a Message secured with a new SecurityToken.*/
703
0
    if(timeout < nowMonotonic &&
704
0
       channel->renewState == UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER) {
705
        /* Revolve the token manually. This is otherwise done in checkSymHeader. */
706
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
707
0
        channel->securityToken = channel->altSecurityToken;
708
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
709
0
        UA_SecureChannel_generateLocalKeys(channel);
710
0
        generateRemoteKeys(channel);
711
712
        /* Use the timeout of the new SecurityToken */
713
0
        timeout = channel->securityToken.createdAt +
714
0
            (UA_DateTime)(channel->securityToken.revisedLifetime * UA_DATETIME_MSEC);
715
0
    }
716
717
0
    return (timeout < nowMonotonic);
718
0
}