Coverage Report

Created: 2026-08-30 06:27

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
/* OPC UA Part 6 v1.05.07 §6.8.1 step 2 "Extract" — IKM chaining (enhanced
49
 * policies only). The IKM is XORed with the new shared secret on each renewal;
50
 * the accumulator is the curve's coordinate size (half the nonceLength, e.g. 32
51
 * bytes for P-256). It is carried through sp->generateKey without changing that
52
 * signature by prepending it to the `secret` ByteString: the backend's
53
 * DeriveKeys helper detects the prepend (key1 longer than the ephemeral public
54
 * key), XORs, and writes the chained IKM back into the slot. */
55
#define IKM_PREPEND_LENGTH(channel) \
56
0
    ((channel)->enhancedSecurity ? ((channel)->securityPolicy->nonceLength / 2) : 0)
57
58
/* Allocate and fill the prepend buffer [currentIKM | nonce] when
59
 * chaining is active; otherwise point *outInput at the original
60
 * nonce. The caller frees *outCombined with UA_ByteString_clear. */
61
static UA_StatusCode
62
prepareKeyInput(UA_SecureChannel *channel, const UA_ByteString *nonce,
63
0
                UA_ByteString *outInput, UA_ByteString *outCombined) {
64
0
    size_t ikmLen = IKM_PREPEND_LENGTH(channel);
65
0
    if(ikmLen == 0) {
66
0
        *outInput = *nonce;
67
0
        *outCombined = UA_BYTESTRING_NULL;
68
0
        return UA_STATUSCODE_GOOD;
69
0
    }
70
0
    UA_StatusCode res =
71
0
        UA_ByteString_allocBuffer(outCombined, ikmLen + nonce->length);
72
0
    if(res != UA_STATUSCODE_GOOD)
73
0
        return res;
74
0
    if(channel->currentIKM.length == ikmLen)
75
0
        memcpy(outCombined->data, channel->currentIKM.data, ikmLen);
76
0
    else
77
0
        memset(outCombined->data, 0, ikmLen);
78
0
    memcpy(outCombined->data + ikmLen, nonce->data, nonce->length);
79
0
    *outInput = *outCombined;
80
0
    return UA_STATUSCODE_GOOD;
81
0
}
82
83
/* Pull the (possibly updated) IKM from the prepend slot and store
84
 * it as channel->currentIKM. Called only by the local-keys pass;
85
 * the remote-keys pass leaves the accumulator untouched. */
86
static UA_StatusCode
87
0
captureIKMSlot(UA_SecureChannel *channel, const UA_ByteString *combined) {
88
0
    size_t ikmLen = IKM_PREPEND_LENGTH(channel);
89
0
    if(ikmLen == 0)
90
0
        return UA_STATUSCODE_GOOD;
91
0
    UA_ByteString_clear(&channel->currentIKM);
92
0
    UA_ByteString ikmSlot = {ikmLen, combined->data};
93
0
    return UA_ByteString_copy(&ikmSlot, &channel->currentIKM);
94
0
}
95
96
UA_StatusCode
97
0
UA_SecureChannel_generateLocalKeys(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 local 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. The block size is
106
     * identical for local/remote. For AEAD ciphers the IV length differs from
107
     * the block size, so use getLocalIvLength when available. */
108
0
    UA_ByteString buf;
109
0
    size_t encrKL = ea->getLocalKeyLength(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.getLocalKeyLength(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 localSigningKey = {signKL, buf.data};
119
0
    UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
120
0
    UA_ByteString localIv = {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
    /* Build the IKM-prefixed `secret` input (the helper detects
126
     * the prepend via the length mismatch against the local
127
     * ephemeral public key). The `seed` arg is passed unchanged —
128
     * the helper uses it as the alternate ephemeral public key
129
     * candidate and as part of the salt, so the prepend must not
130
     * appear there. */
131
0
    UA_ByteString secretInput, seedInput = channel->localNonce;
132
0
    UA_ByteString secretCombined = UA_BYTESTRING_NULL;
133
0
    res = prepareKeyInput(channel, &channel->remoteNonce,
134
0
                         &secretInput, &secretCombined);
135
0
    UA_CHECK_STATUS(res, goto error);
136
137
    /* Generate key. The policy's wrapper detects the prepend (via the
138
     * length mismatch in key1 vs the local ephemeral public key) and
139
     * performs the IKM chaining, deriving against the *previous*
140
     * accumulator (channel->currentIKM). The new accumulator is NOT
141
     * promoted here: the local- and remote-keys passes of one OPN must
142
     * both derive against the same previous accumulator, so the
143
     * advance to IKM_n happens exactly once, in generateRemoteKeys
144
     * (the last of the two passes). */
145
0
    res = sp->generateKey(sp, cc, &secretInput, &seedInput, &buf);
146
0
    UA_CHECK_STATUS(res, goto error);
147
148
    /* Set the channel context */
149
0
    res |= sp->setLocalSymSigningKey(sp, cc, &localSigningKey);
150
0
    res |= sp->setLocalSymEncryptingKey(sp, cc, &localEncryptingKey);
151
0
    res |= sp->setLocalSymIv(sp, cc, &localIv);
152
153
0
 error:
154
0
    if(res != UA_STATUSCODE_GOOD) {
155
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel,
156
0
                             "Could not generate local keys (%s)",
157
0
                             UA_StatusCode_name(res));
158
0
    }
159
0
    UA_ByteString_clear(&buf);
160
0
    UA_ByteString_clear(&secretCombined);
161
0
    return res;
162
0
}
163
164
UA_StatusCode
165
0
generateRemoteKeys(UA_SecureChannel *channel) {
166
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
167
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
168
0
    UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new remote keys");
169
170
0
    void *cc = channel->channelContext;
171
0
    const UA_SecurityPolicyEncryptionAlgorithm *ea = &sp->symEncryptionAlgorithm;
172
173
    /* Generate symmetric key buffer of the required length. For AEAD ciphers
174
     * the IV length differs from the block size, so use getLocalIvLength when
175
     * available. */
176
0
    UA_ByteString buf;
177
0
    size_t encrKL = ea->getRemoteKeyLength(sp, cc);
178
0
    size_t encrBS = ea->getRemoteBlockSize(sp, cc);
179
0
    size_t ivLen = ea->getLocalIvLength ? ea->getLocalIvLength(sp, cc) : encrBS;
180
0
    size_t signKL = sp->symSignatureAlgorithm.getRemoteKeyLength(sp, cc);
181
0
    if(ivLen + signKL + encrKL == 0)
182
0
        return UA_STATUSCODE_GOOD; /* No keys to generate */
183
184
0
    UA_StatusCode res = UA_ByteString_allocBuffer(&buf, ivLen + signKL + encrKL);
185
0
    UA_CHECK_STATUS(res, return res);
186
0
    UA_ByteString remoteSigningKey = {signKL, buf.data};
187
0
    UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
188
0
    UA_ByteString remoteIv = {ivLen, &buf.data[signKL + encrKL]};
189
190
    /* TODO: Signal that no ECC salt is generated. Find a clean solution for this.  */
191
0
    buf.data[0] = 0x00;
192
193
    /* Build the IKM-prefixed `secret` input. Both the local- and
194
     * remote-keys passes of one OPN derive against the *same* previous
195
     * accumulator (channel->currentIKM); generateLocalKeys deliberately
196
     * did not advance it. The `seed` arg is passed unchanged — the
197
     * helper uses it as the alternate ephemeral public key candidate
198
     * and as part of the salt, so the prepend must not appear there. */
199
0
    UA_ByteString secretInput, seedInput = channel->remoteNonce;
200
0
    UA_ByteString secretCombined = UA_BYTESTRING_NULL;
201
0
    res = prepareKeyInput(channel, &channel->localNonce,
202
0
                         &secretInput, &secretCombined);
203
0
    UA_CHECK_STATUS(res, goto error);
204
205
    /* Generate key. The policy's wrapper XORs the previous accumulator
206
     * with the new shared secret and writes the result (IKM_n) back
207
     * into secretCombined. */
208
0
    res = sp->generateKey(sp, cc, &secretInput, &seedInput, &buf);
209
0
    UA_CHECK_STATUS(res, goto error);
210
211
    /* This is the last derivation of the OPN: promote the just-updated
212
     * IKM slot into channel->currentIKM so the next renewal chains from
213
     * IKM_n. (On the first OPN currentIKM was empty, so IKM_0 == the raw
214
     * shared secret for both passes — matching the spec's "no chaining
215
     * on the first OpenSecureChannel".) */
216
0
    res = captureIKMSlot(channel, &secretCombined);
217
0
    if(res != UA_STATUSCODE_GOOD) {
218
0
        res = UA_STATUSCODE_BADOUTOFMEMORY;
219
0
        goto error;
220
0
    }
221
222
    /* Set the channel context */
223
0
    res |= sp->setRemoteSymSigningKey(sp, cc, &remoteSigningKey);
224
0
    res |= sp->setRemoteSymEncryptingKey(sp, cc, &remoteEncryptingKey);
225
0
    res |= sp->setRemoteSymIv(sp, cc, &remoteIv);
226
227
0
 error:
228
0
    if(res != UA_STATUSCODE_GOOD) {
229
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel,
230
0
                               "Could not generate remote keys (%s)",
231
0
                               UA_StatusCode_name(res));
232
0
    }
233
0
    UA_ByteString_clear(&buf);
234
0
    UA_ByteString_clear(&secretCombined);
235
0
    return res;
236
0
}
237
238
/* v1.05.07 channel-bound SignatureData (SecureChannelEnhancements): the
239
 * CreateSession / ActivateSession signatures are bound to the SecureChannel by
240
 * prepending the ChannelThumbprint and including certificate hashes (not the
241
 * raw certs). */
242
243
/* The certificate hash is provided by the crypto backend via the global
244
 * UA_SecurityPolicy_hashCertificate (the algorithm is derived from the policy
245
 * URI). Wrapped here so this file links without a crypto backend - the
246
 * builders below are only reached at runtime for enhanced-security policies,
247
 * which only exist when encryption is enabled. */
248
#ifdef UA_ENABLE_ENCRYPTION
249
static UA_StatusCode
250
hashCert(const UA_SecurityPolicy *sp, const UA_ByteString *cert,
251
0
         UA_ByteString *hash) {
252
0
    return UA_SecurityPolicy_hashCertificate(sp, cert, hash);
253
0
}
254
#else
255
static UA_StatusCode
256
hashCert(const UA_SecurityPolicy *sp, const UA_ByteString *cert,
257
         UA_ByteString *hash) {
258
    (void)sp; (void)cert; (void)hash;
259
    return UA_STATUSCODE_BADINTERNALERROR;
260
}
261
#endif
262
263
/* Assemble a channel-bound SignatureData (OPC UA Part 6 v1.05.07,
264
 * SecureChannelEnhancements). All three share the shape
265
 *   channelThumbprint | nonceA | H(cert_0) .. H(cert_n-1) | nonceB
266
 * and differ only in which certificate hashes appear and the nonce order:
267
 *
268
 *   CreateSession ServerSignature   (server signs, client verifies):
269
 *     TP | clientNonce | H(serverChannelCert) | H(clientChannelCert) | serverNonce
270
 *   ActivateSession ClientSignature (client signs, server verifies):
271
 *     TP | serverNonce | H(serverAppCert) | H(serverChannelCert) |
272
 *                        H(clientChannelCert) | clientNonce
273
 *   ActivateSession user-token sig  (client signs w/ user key, server verifies):
274
 *     TP | serverNonce | H(serverAppCert) | H(serverChannelCert) |
275
 *                        H(clientAppCert) | H(clientChannelCert) | clientNonce
276
 *
277
 * H() = the policy's curve hash of the leaf DER. Both peers must produce the
278
 * SAME bytes, so each side maps the logical certificate roles onto its own
279
 * local vs. remote view (the certs are channel-scoped: app == channel cert in
280
 * open62541, hence the duplicated hashes). The user/X.509-token certificate is
281
 * NOT part of the signed data (it is conveyed and validated separately).
282
 *
283
 *   logical cert role      server passes               client passes
284
 *   --------------------------------------------------------------------------
285
 *   server App / Channel   sp->localCertificate        channel->remoteCertificate
286
 *   client App / Channel   channel->remoteCertificate  sp->localCertificate
287
 *
288
 *   serverNonce = the session ServerNonce, clientNonce = the session
289
 *   ClientNonce (the same value on both sides). */
290
0
#define UA_MAX_SIGDATA_CERTS 4
291
static UA_StatusCode
292
buildChannelBoundSignatureData(const UA_SecureChannel *channel,
293
                               const UA_ByteString *firstNonce,
294
                               const UA_ByteString *const *certs, size_t certCount,
295
0
                               const UA_ByteString *lastNonce, UA_ByteString *out) {
296
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
297
0
    if(!sp || !channel->enhancedSecurity || certCount > UA_MAX_SIGDATA_CERTS ||
298
0
       channel->channelThumbprint.length == 0)
299
0
        return UA_STATUSCODE_BADINTERNALERROR;
300
301
    /* Hash the certificates. The inputs may be DER chains (e.g. the OPN
302
     * SenderCertificate stored in remoteCertificate), so hash only the leaf -
303
     * independent of how a given crypto backend's hashCert handles a chain. */
304
0
    UA_ByteString hashes[UA_MAX_SIGDATA_CERTS];
305
0
    for(size_t i = 0; i < UA_MAX_SIGDATA_CERTS; i++)
306
0
        hashes[i] = UA_BYTESTRING_NULL;
307
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
308
0
    size_t hashesLen = 0;
309
0
    for(size_t i = 0; i < certCount && res == UA_STATUSCODE_GOOD; i++) {
310
0
        UA_ByteString leaf = getLeafCertificate(*certs[i]);
311
0
        res = hashCert(sp, &leaf, &hashes[i]);
312
0
        hashesLen += hashes[i].length;
313
0
    }
314
0
    if(res != UA_STATUSCODE_GOOD)
315
0
        goto cleanup;
316
317
    /* channelThumbprint | firstNonce | hashes | lastNonce */
318
0
    const UA_ByteString *tp = &channel->channelThumbprint;
319
0
    res = UA_ByteString_allocBuffer(out, tp->length + firstNonce->length +
320
0
                                    hashesLen + lastNonce->length);
321
0
    if(res != UA_STATUSCODE_GOOD)
322
0
        goto cleanup;
323
324
0
    size_t o = 0;
325
0
    memcpy(out->data + o, tp->data, tp->length); o += tp->length;
326
0
    memcpy(out->data + o, firstNonce->data, firstNonce->length); o += firstNonce->length;
327
0
    for(size_t i = 0; i < certCount; i++) {
328
0
        memcpy(out->data + o, hashes[i].data, hashes[i].length);
329
0
        o += hashes[i].length;
330
0
    }
331
0
    memcpy(out->data + o, lastNonce->data, lastNonce->length);
332
333
0
 cleanup:
334
0
    for(size_t i = 0; i < certCount; i++)
335
0
        UA_ByteString_clear(&hashes[i]);
336
0
    return res;
337
0
}
338
339
/* CreateSession ServerSignature (see the layout table above). */
340
UA_StatusCode
341
UA_SecureChannel_buildCreateSessionSignatureData(
342
    const UA_SecureChannel *channel, const UA_ByteString *clientNonce,
343
    const UA_ByteString *serverNonce, const UA_ByteString *serverChannelCert,
344
0
    const UA_ByteString *clientChannelCert, UA_ByteString *out) {
345
0
    const UA_ByteString *certs[] = {serverChannelCert, clientChannelCert};
346
0
    return buildChannelBoundSignatureData(channel, clientNonce, certs, 2,
347
0
                                          serverNonce, out);
348
0
}
349
350
/* ActivateSession ClientSignature (see the layout table above). */
351
UA_StatusCode
352
UA_SecureChannel_buildActivateSessionSignatureData(
353
    const UA_SecureChannel *channel, const UA_ByteString *serverNonce,
354
    const UA_ByteString *clientNonce, const UA_ByteString *serverAppCert,
355
    const UA_ByteString *serverChannelCert, const UA_ByteString *clientChannelCert,
356
0
    UA_ByteString *out) {
357
0
    const UA_ByteString *certs[] = {serverAppCert, serverChannelCert, clientChannelCert};
358
0
    return buildChannelBoundSignatureData(channel, serverNonce, certs, 3,
359
0
                                          clientNonce, out);
360
0
}
361
362
/* ActivateSession X.509 user-token signature (see the layout table above). */
363
UA_StatusCode
364
UA_SecureChannel_buildUserTokenSignatureData(
365
    const UA_SecureChannel *channel, const UA_ByteString *serverNonce,
366
    const UA_ByteString *clientNonce, const UA_ByteString *serverAppCert,
367
    const UA_ByteString *serverChannelCert, const UA_ByteString *clientAppCert,
368
0
    const UA_ByteString *clientChannelCert, UA_ByteString *out) {
369
0
    const UA_ByteString *certs[] = {serverAppCert, serverChannelCert,
370
0
                                    clientAppCert, clientChannelCert};
371
0
    return buildChannelBoundSignatureData(channel, serverNonce, certs, 4,
372
0
                                          clientNonce, out);
373
0
}
374
375
/***************************/
376
/* Send Asymmetric Message */
377
/***************************/
378
379
/* The length of the static header content */
380
0
#define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12
381
382
size_t
383
0
calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
384
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
385
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
386
387
0
    size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH +
388
0
                              sp->policyUri.length;
389
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
390
0
        return asymHeaderLength;
391
392
    /* OPN is always encrypted even if the mode is sign only */
393
0
    asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
394
0
    asymHeaderLength += sp->localCertificate.length;
395
0
    return asymHeaderLength;
396
0
}
397
398
UA_StatusCode
399
prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
400
                   const UA_Byte *buf_end, size_t totalLength,
401
                   size_t securityHeaderLength, UA_UInt32 requestId,
402
0
                   size_t *const encryptedLength) {
403
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
404
0
    UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
405
406
0
    void *cc = channel->channelContext;
407
408
0
    *encryptedLength = totalLength;
409
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE) {
410
0
        size_t dataToEncryptLength = totalLength -
411
0
            (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength);
412
0
        size_t plainTextBlockSize = sp->asymEncryptionAlgorithm.
413
0
            getRemotePlainTextBlockSize(sp, cc);
414
0
        size_t encryptedBlockSize = sp->asymEncryptionAlgorithm.
415
0
            getRemoteBlockSize(sp, cc);
416
417
        /* Padding always fills up the last block */
418
0
        UA_assert(plainTextBlockSize > 0);
419
0
        UA_assert(dataToEncryptLength % plainTextBlockSize == 0);
420
0
        size_t blocks = dataToEncryptLength / plainTextBlockSize;
421
0
        *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize);
422
0
    }
423
424
0
    UA_TcpMessageHeader messageHeader;
425
0
    messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
426
0
    messageHeader.messageSize = (UA_UInt32)*encryptedLength;
427
0
    UA_UInt32 secureChannelId = channel->securityToken.channelId;
428
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
429
0
    res |= UA_encodeBinaryInternal(&messageHeader,
430
0
                                   &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
431
0
                                   &header_pos, &buf_end, NULL, NULL, NULL);
432
0
    res |= UA_UInt32_encodeBinary(&secureChannelId, &header_pos, buf_end);
433
0
    UA_CHECK_STATUS(res, return res);
434
435
0
    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
436
0
    UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
437
0
    asymHeader.securityPolicyUri = sp->policyUri;
438
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
439
0
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
440
0
        asymHeader.senderCertificate = sp->localCertificate;
441
0
        asymHeader.receiverCertificateThumbprint.length = 20;
442
0
        asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
443
0
    }
444
0
    res = UA_encodeBinaryInternal(&asymHeader,
445
0
                                  &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
446
0
                                  &header_pos, &buf_end, NULL, NULL, NULL);
447
0
    UA_CHECK_STATUS(res, return res);
448
449
0
    UA_SequenceHeader seqHeader;
450
0
    seqHeader.requestId = requestId;
451
0
    seqHeader.sequenceNumber = UA_SecureChannel_nextSequenceNumber(channel);
452
0
    res = UA_encodeBinaryInternal(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
453
0
                                  &header_pos, &buf_end, NULL, NULL, NULL);
454
0
    return res;
455
0
}
456
457
void
458
hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
459
0
              const UA_Byte **buf_end) {
460
    /* Set buf_start to the beginning of the encrypted body */
461
0
    *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
462
0
    *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
463
464
    /* Hide only the SequenceHeader for None  */
465
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) {
466
0
        *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
467
0
        return;
468
0
    }
469
470
    /* The max plaintext length depends on the number of encrypted blocks that
471
     * can fit into the remaining chunk */
472
0
    void *cc = channel->channelContext;
473
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
474
0
    size_t plainTextBlockSize =
475
0
        sp->asymEncryptionAlgorithm.getRemotePlainTextBlockSize(sp, cc);
476
0
    size_t encryptedBlockSize =
477
0
        sp->asymEncryptionAlgorithm.getRemoteBlockSize(sp, cc);
478
479
0
    size_t max_encrypted = (size_t)(*buf_end - *buf_start);
480
0
    UA_assert(encryptedBlockSize > 0);
481
0
    size_t max_blocks = max_encrypted / encryptedBlockSize;
482
0
    size_t max_plaintext = max_blocks * plainTextBlockSize;
483
484
    /* Reserve plaintext length for the SequenceHeader and Footer.
485
     * But don't reserve for the the padding itself -- which can be zero. */
486
0
    max_plaintext -= UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
487
0
    max_plaintext -= sp->asymSignatureAlgorithm.getLocalSignatureSize(sp, cc);
488
0
    UA_Boolean extraPadding =
489
0
        (sp->asymEncryptionAlgorithm.getRemoteKeyLength(sp, cc) > 2048);
490
0
    max_plaintext -= (UA_LIKELY(!extraPadding)) ? 1u : 2u;
491
492
    /* Adjust the buffer */
493
0
    *buf_end = *buf_start + max_plaintext;
494
0
    *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
495
0
}
496
497
/* Assumes that pos can be advanced to the end of the current block */
498
void
499
padChunk(UA_SecureChannel *channel,
500
         const UA_SecurityPolicySignatureAlgorithm *sa,
501
         const UA_SecurityPolicyEncryptionAlgorithm *ea,
502
0
         const UA_Byte *start, UA_Byte **pos) {
503
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
504
0
    void *cc = channel->channelContext;
505
506
0
    const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start;
507
508
0
    size_t signatureSize = sa->getLocalSignatureSize(sp, cc);
509
0
    size_t plainTextBlockSize = ea->getRemotePlainTextBlockSize(sp, cc);
510
0
    UA_Boolean extraPadding = (ea->getRemoteKeyLength(sp, cc) > 2048);
511
0
    size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
512
513
0
    UA_assert(plainTextBlockSize > 0);
514
0
    size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize);
515
0
    size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0;
516
517
0
    UA_assert((bytesToWrite + signatureSize +
518
0
               paddingBytes + paddingLength) % plainTextBlockSize == 0);
519
520
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
521
0
                         "Add %lu bytes of padding plus %lu padding size bytes",
522
0
                         (long unsigned int)paddingLength,
523
0
                         (long unsigned int)paddingBytes);
524
525
    /* Write the padding. This is <= because the paddingSize byte also has to be
526
     * written */
527
0
    UA_Byte paddingByte = (UA_Byte)paddingLength;
528
0
    for(size_t i = 0; i <= paddingLength; ++i) {
529
0
        **pos = paddingByte;
530
0
        ++*pos;
531
0
    }
532
533
    /* Write the extra padding byte if required */
534
0
    if(extraPadding) {
535
0
        **pos = (UA_Byte)(paddingLength >> 8u);
536
0
        ++*pos;
537
0
    }
538
0
}
539
540
UA_StatusCode
541
signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
542
                   UA_ByteString *buf, size_t securityHeaderLength,
543
0
                   size_t totalLength) {
544
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
545
0
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
546
0
        return UA_STATUSCODE_GOOD;
547
548
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
549
0
    void *cc = channel->channelContext;
550
551
    /* OPC UA Part 6 v1.05.07 §6.7.5 "ChannelThumbprint" (enhanced policies,
552
     * FIRST OPN only — an empty channelThumbprint identifies the first OPN; NOT
553
     * on renewals. The OPN response signature is extended with the first OPN
554
     * request signature: the client (request side) stores its just-computed
555
     * signature for the later response verify; the server (response side)
556
     * appends the request signature captured by decryptAndVerifyChunk to the
557
     * data being signed. */
558
0
    UA_Boolean firstOPN = (channel->enhancedSecurity &&
559
0
                           channel->channelThumbprint.length == 0);
560
0
    UA_ByteString *appendSig = NULL;
561
0
    if(firstOPN && channel->firstRequestSignature.length > 0)
562
0
        appendSig = &channel->firstRequestSignature; /* server: extend signed data */
563
564
0
    size_t sigsize = sp->asymSignatureAlgorithm.getLocalSignatureSize(sp, cc);
565
566
    /* Prepare the data to sign. If we need to append the request
567
     * signature, build a contiguous buffer [body | requestSig] and sign
568
     * that. Otherwise sign the body in-place. */
569
0
    UA_ByteString signature = {sigsize, buf->data + preSignLength};
570
0
    UA_StatusCode retval;
571
572
0
    if(appendSig) {
573
0
        size_t bodyLen = preSignLength;
574
0
        size_t extLen = bodyLen + appendSig->length;
575
0
        UA_Byte *ext = (UA_Byte*)UA_malloc(extLen);
576
0
        if(!ext)
577
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
578
0
        memcpy(ext, buf->data, bodyLen);
579
0
        memcpy(ext + bodyLen, appendSig->data, appendSig->length);
580
0
        UA_ByteString dataToSignExt = {extLen, ext};
581
0
        retval = sp->asymSignatureAlgorithm.sign(sp, cc, &dataToSignExt, &signature);
582
0
        UA_free(ext);
583
0
    } else {
584
0
        const UA_ByteString dataToSign = {preSignLength, buf->data};
585
0
        retval = sp->asymSignatureAlgorithm.sign(sp, cc, &dataToSign, &signature);
586
        /* First-OPN client side: remember the just-computed request
587
         * signature. The verify path on the client will use it to
588
         * extend the response body. */
589
0
        if(retval == UA_STATUSCODE_GOOD && firstOPN && signature.length > 0) {
590
0
            UA_StatusCode clip =
591
0
                UA_ByteString_copy(&signature, &channel->firstRequestSignature);
592
0
            if(clip != UA_STATUSCODE_GOOD)
593
0
                retval = clip;
594
0
        }
595
0
    }
596
597
0
    UA_CHECK_STATUS(retval, return retval);
598
599
    /* Server, first OPN response (appendSig != NULL): the just-computed
600
     * signature is the ChannelThumbprint - capture it (preserved across renewals
601
     * to bind the session SignatureData) and release the consumed request
602
     * signature. (The client stored its request signature above; that copy is
603
     * released later by the OPN-response verify.) */
604
0
    if(appendSig != NULL) {
605
0
        UA_StatusCode tp = UA_ByteString_copy(&signature, &channel->channelThumbprint);
606
0
        UA_CHECK_STATUS(tp, return tp);
607
0
        UA_ByteString_clear(&channel->firstRequestSignature);
608
0
    }
609
610
    /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
611
     * signed and encrypted if the SecurityMode is not None (even if the
612
     * SecurityMode is SignOnly). */
613
0
    size_t unencrypted_length =
614
0
        UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength;
615
0
    UA_ByteString dataToEncrypt =
616
0
        {totalLength - unencrypted_length, &buf->data[unencrypted_length]};
617
0
    return sp->asymEncryptionAlgorithm.encrypt(sp, cc, &dataToEncrypt);
618
0
}
619
620
/**************************/
621
/* Send Symmetric Message */
622
/**************************/
623
624
UA_StatusCode
625
signAndEncryptSym(UA_MessageContext *messageContext,
626
0
                  size_t preSigLength, size_t totalLength) {
627
0
    const UA_SecureChannel *channel = messageContext->channel;
628
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
629
0
        return UA_STATUSCODE_GOOD;
630
631
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
632
0
    void *cc = channel->channelContext;
633
634
    /* For AEAD policies (ChaCha20-Poly1305), set the message security
635
     * parameters for nonce masking. Then let the encrypt callback handle
636
     * both authentication and encryption. */
637
0
    if(UA_SecurityPolicy_isAead(sp)) {
638
        /* Set AEAD parameters: tokenId, previous seqNo, AAD */
639
0
        if(sp->setMessageSecurityParameters) {
640
0
            UA_ByteString aad;
641
0
            aad.data = messageContext->messageBuffer.data;
642
0
            aad.length = UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
643
0
                         UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
644
            /* The AEAD nonce is masked with the PREVIOUS sequence number: the
645
             * receiver masks with its receiveSequenceNumber, which is still the
646
             * prior chunk's number at decrypt time (incremented only after
647
             * decryption). sendSequenceNumber is the post-increment counter, so
648
             * the value just emitted is (sendSequenceNumber - 1) and the
649
             * previous one is (sendSequenceNumber - 2). ECC_AEAD always uses the
650
             * non-legacy counter (first emitted number is 0). */
651
0
            UA_UInt32 prevSeqNo = channel->sendSequenceNumber >= 2 ?
652
0
                (UA_UInt32)(channel->sendSequenceNumber - 2) : 0;
653
0
            UA_StatusCode res = sp->setMessageSecurityParameters(
654
0
                sp, cc, channel->securityToken.tokenId, prevSeqNo, &aad);
655
0
            UA_CHECK_STATUS(res, return res);
656
0
        }
657
658
0
        if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
659
            /* Full AEAD: encrypt + compute auth tag. Data includes
660
             * the 16-byte tag space at the end. */
661
0
            UA_ByteString dataToProcess;
662
0
            dataToProcess.data = messageContext->messageBuffer.data +
663
0
                UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
664
0
                UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
665
0
            dataToProcess.length = totalLength -
666
0
                (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
667
0
                 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
668
0
            return sp->symEncryptionAlgorithm.encrypt(sp, cc, &dataToProcess);
669
0
        }
670
671
        /* Sign-only: Compute Poly1305 auth tag */
672
0
        UA_ByteString dataToSign = messageContext->messageBuffer;
673
0
        dataToSign.length = preSigLength;
674
0
        UA_ByteString signature;
675
0
        signature.length =
676
0
            sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
677
0
        signature.data = messageContext->buf_pos;
678
0
        return sp->symSignatureAlgorithm.
679
0
            sign(sp, cc, &dataToSign, &signature);
680
0
    }
681
682
    /* Sign */
683
0
    UA_ByteString dataToSign = messageContext->messageBuffer;
684
0
    dataToSign.length = preSigLength;
685
0
    UA_ByteString signature;
686
0
    signature.length =
687
0
        sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
688
0
    signature.data = messageContext->buf_pos;
689
0
    UA_StatusCode res = sp->symSignatureAlgorithm.
690
0
        sign(sp, cc, &dataToSign, &signature);
691
0
    UA_CHECK_STATUS(res, return res);
692
693
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
694
0
        return UA_STATUSCODE_GOOD;
695
696
    /* Encrypt */
697
0
    UA_ByteString dataToEncrypt;
698
0
    dataToEncrypt.data = messageContext->messageBuffer.data +
699
0
        UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
700
0
        UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
701
0
    dataToEncrypt.length = totalLength -
702
0
        (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
703
0
         UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
704
0
    return sp->symEncryptionAlgorithm.encrypt(sp, cc, &dataToEncrypt);
705
0
}
706
707
void
708
0
setBufPos(UA_MessageContext *mc) {
709
    /* Forward the data pointer so that the payload is encoded after the message
710
     * header. This has to be a symmetric message because OPN (with asymmetric
711
     * encryption) does not support chunking. */
712
0
    mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
713
0
    mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
714
715
0
    if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
716
0
        return;
717
718
0
    const UA_SecureChannel *channel = mc->channel;
719
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
720
0
    void *cc = channel->channelContext;
721
722
    /* For AEAD (ChaCha20-Poly1305): no padding, no block alignment.
723
     * Only reserve space for the authentication tag (signature size). */
724
0
    if(UA_SecurityPolicy_isAead(sp)) {
725
0
        size_t sigsize =
726
0
            sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
727
0
        mc->buf_end -= sigsize;
728
0
        UA_LOG_TRACE_CHANNEL(sp->logger, channel,
729
0
                             "Prepare an AEAD symmetric message buffer of length %lu "
730
0
                             "with a usable maximum payload length of %lu",
731
0
                             (long unsigned)mc->messageBuffer.length,
732
0
                             (long unsigned)((uintptr_t)mc->buf_end -
733
0
                                             (uintptr_t)mc->messageBuffer.data));
734
0
        return;
735
0
    }
736
737
0
    size_t sigsize =
738
0
        sp->symSignatureAlgorithm.getLocalSignatureSize(sp, cc);
739
0
    size_t plainBlockSize =
740
0
        sp->symEncryptionAlgorithm.getRemotePlainTextBlockSize(sp, cc);
741
742
    /* Assuming that for symmetric encryption the plainTextBlockSize ==
743
     * cypherTextBlockSize. For symmetric encryption the remote/local block
744
     * sizes are identical. */
745
0
    UA_assert(sp->symEncryptionAlgorithm.getRemoteBlockSize(sp, cc) == plainBlockSize);
746
747
    /* Leave enough space for the signature and padding */
748
0
    mc->buf_end -= sigsize;
749
0
    UA_assert(plainBlockSize > 0);
750
0
    mc->buf_end -= mc->messageBuffer.length % plainBlockSize;
751
752
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
753
        /* Reserve space for the padding bytes */
754
0
        UA_Boolean extraPadding =
755
0
            (sp->symEncryptionAlgorithm.getRemoteKeyLength(sp, cc) > 2048);
756
0
        mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2;
757
0
    }
758
759
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel,
760
0
                         "Prepare a symmetric message buffer of length %lu "
761
0
                         "with a usable maximum payload length of %lu",
762
0
                         (long unsigned)mc->messageBuffer.length,
763
0
                         (long unsigned)((uintptr_t)mc->buf_end -
764
0
                                         (uintptr_t)mc->messageBuffer.data));
765
0
}
766
767
/****************************/
768
/* Process a received Chunk */
769
/****************************/
770
771
static size_t
772
decodePadding(const UA_SecureChannel *channel,
773
              const UA_SecurityPolicyEncryptionAlgorithm *encryptionAlgorithm,
774
0
              const UA_ByteString *chunk, size_t sigsize) {
775
    /* Read the byte with the padding size */
776
0
    size_t paddingSize = chunk->data[chunk->length - sigsize - 1];
777
778
    /* Extra padding size */
779
0
    if(encryptionAlgorithm->getLocalKeyLength(channel->securityPolicy,
780
0
                                              channel->channelContext) > 2048) {
781
0
        paddingSize <<= 8u;
782
0
        paddingSize += chunk->data[chunk->length - sigsize - 2];
783
0
        paddingSize += 1; /* Extra padding byte itself */
784
0
    }
785
786
    /* Add one since the paddingSize byte itself needs to be removed as well */
787
0
    return paddingSize + 1;
788
0
}
789
790
/* Sets the payload to a pointer inside the chunk buffer. Returns the requestId
791
 * and the sequenceNumber */
792
UA_StatusCode
793
decryptAndVerifyChunk(UA_SecureChannel *channel,
794
                      const UA_SecurityPolicySignatureAlgorithm *signatureAlgorithm,
795
                      const UA_SecurityPolicyEncryptionAlgorithm *encryptionAlgorithm,
796
                      UA_MessageType messageType, UA_ByteString *chunk,
797
0
                      size_t offset) {
798
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
799
0
    void *cc = channel->channelContext;
800
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
801
802
    /* AEAD path (ChaCha20-Poly1305): the decrypt callback handles both
803
     * decryption and authentication tag verification in one step. */
804
0
    if(UA_SecurityPolicy_isAead(sp) &&
805
0
       messageType != UA_MESSAGETYPE_OPN) {
806
807
        /* Set AEAD parameters before decrypt/verify. The masked nonce is keyed
808
         * on the TokenId of *this* message, which is taken from the chunk's
809
         * symmetric SecurityHeader (right after the 12-byte channel header) and
810
         * not from channel->securityToken: during a token rollover the peer may
811
         * still secure messages with the old token (Part 4 §5.5.2) while the
812
         * channel already holds the new token. Using the wrong TokenId here
813
         * makes the AEAD tag verification fail. */
814
0
        if(sp->setMessageSecurityParameters) {
815
0
            UA_ByteString aad = {offset, chunk->data};
816
0
            size_t tokenOffset = UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
817
0
            UA_UInt32 msgTokenId = channel->securityToken.tokenId;
818
0
            if(offset >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH)
819
0
                UA_UInt32_decodeBinary(chunk, &tokenOffset, &msgTokenId);
820
0
            res = sp->setMessageSecurityParameters(
821
0
                sp, cc, msgTokenId,
822
0
                channel->receiveSequenceNumber, &aad);
823
0
            UA_CHECK_STATUS(res, return res);
824
0
        }
825
826
0
        if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
827
            /* Full AEAD decrypt + verify. The decrypt callback processes
828
             * the data including the 16-byte auth tag at the end. On
829
             * success, it reduces cipher.length by the tag size. */
830
0
            UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
831
0
            res = encryptionAlgorithm->decrypt(sp, cc, &cipher);
832
0
            UA_CHECK_STATUS(res,
833
0
                UA_LOG_WARNING_CHANNEL(sp->logger, channel,
834
0
                                       "AEAD decryption/verification failed");
835
0
                return res);
836
0
            chunk->length = cipher.length + offset;
837
0
        } else if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN) {
838
            /* Sign-only: verify the auth tag without decryption */
839
0
            size_t sigsize = signatureAlgorithm->getRemoteSignatureSize(sp, cc);
840
0
            UA_CHECK(sigsize < chunk->length,
841
0
                     return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
842
0
            const UA_ByteString content = {chunk->length - sigsize, chunk->data};
843
0
            const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
844
0
            res = signatureAlgorithm->verify(sp, cc, &content, &sig);
845
0
            UA_CHECK_STATUS(res,
846
0
                UA_LOG_WARNING_CHANNEL(sp->logger, channel,
847
0
                                       "AEAD signature verification failed");
848
0
                return res);
849
0
            chunk->length -= sigsize;
850
0
        }
851
852
        /* Verify the content length */
853
0
        UA_CHECK(offset + 9 < chunk->length,
854
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel,
855
0
                                      "AEAD message too short");
856
0
                 return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
857
0
        return UA_STATUSCODE_GOOD;
858
0
    }
859
860
    /* Decrypt the chunk */
861
0
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
862
0
       messageType == UA_MESSAGETYPE_OPN) {
863
0
        UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
864
0
        res = encryptionAlgorithm->decrypt(sp, cc, &cipher);
865
0
        UA_CHECK_STATUS(res, return res);
866
0
        chunk->length = cipher.length + offset;
867
0
    }
868
869
    /* Does the message have a signature? */
870
0
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
871
0
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
872
0
       messageType != UA_MESSAGETYPE_OPN)
873
0
        return UA_STATUSCODE_GOOD;
874
875
    /* Verify the chunk signature */
876
0
    UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Verifying chunk signature");
877
0
    size_t sigsize = signatureAlgorithm->getRemoteSignatureSize(sp, cc);
878
0
    UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
879
0
    const UA_ByteString content = {chunk->length - sigsize, chunk->data};
880
0
    const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
881
882
    /* OPC UA Part 6 v1.05.07 §6.7.5 "ChannelThumbprint" (only for the first
883
     * OPN exchange and only for SecurityPolicies with
884
     * secureChannelEnhancements = true). For the *first* OPN only:
885
     *
886
     *   Server side (verify an incoming OPN request): the request
887
     *   signature is unknown to the server until it has been
888
     *   verified. Capture the bytes now (BEFORE stripping) so the
889
     *   sign path of the OPN response can append them.
890
     *
891
     *   Client side (verify the OPN response): the client's own
892
     *   request signature was stored in firstRequestSignature when
893
     *   the request was sent. Extend the verify content with it.
894
     *
895
     * For OPN *renewals* the firstRequestSignature is empty (it was
896
     * cleared by the first exchange) and the normal v1.05.06 verify
897
     * path is used. */
898
0
    UA_ByteString verifyContent = content;
899
0
    UA_Byte *extendedBuf = NULL;
900
0
    UA_Boolean capturedIncoming = false;
901
    /* First-OPN only (channelThumbprint empty). On renewals neither capture nor
902
     * extend - the v1.05.06 verify path is used. */
903
0
    UA_Boolean firstOPN = (channel->enhancedSecurity &&
904
0
                           messageType == UA_MESSAGETYPE_OPN &&
905
0
                           channel->channelThumbprint.length == 0);
906
0
    if(firstOPN) {
907
0
        if(channel->firstRequestSignature.length == 0) {
908
            /* First-OPN, receiving side: capture the incoming signature.
909
             * The sign path of the response will consume it. */
910
0
            UA_StatusCode clip = UA_ByteString_copy(&sig, &channel->firstRequestSignature);
911
0
            UA_CHECK_STATUS(clip, return clip);
912
0
            capturedIncoming = true;
913
0
        } else {
914
            /* Verifying the OPN response: extend the content. */
915
0
            extendedBuf = (UA_Byte*)UA_malloc(
916
0
                content.length + channel->firstRequestSignature.length);
917
0
            if(!extendedBuf) {
918
0
                UA_ByteString_clear(&channel->firstRequestSignature);
919
0
                return UA_STATUSCODE_BADOUTOFMEMORY;
920
0
            }
921
0
            memcpy(extendedBuf, content.data, content.length);
922
0
            memcpy(extendedBuf + content.length,
923
0
                   channel->firstRequestSignature.data,
924
0
                   channel->firstRequestSignature.length);
925
0
            verifyContent.data = extendedBuf;
926
0
            verifyContent.length =
927
0
                content.length + channel->firstRequestSignature.length;
928
0
        }
929
0
    }
930
931
0
    res = signatureAlgorithm->verify(sp, cc, &verifyContent, &sig);
932
0
    UA_free(extendedBuf);
933
934
    /* Single-use: if we just consumed the stored signature (client side
935
     * verifying the response), clear it. If we just captured the
936
     * incoming signature (server side verifying the request), keep
937
     * it — the sign path of the response will use and then clear it. */
938
0
    if(firstOPN && !capturedIncoming) {
939
0
        UA_ByteString_clear(&channel->firstRequestSignature);
940
0
    }
941
942
0
    UA_CHECK_STATUS(res, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
943
0
                                                "Could not verify the signature");
944
0
                    return res);
945
946
    /* OPC UA Part 6 v1.05.07 ChannelThumbprint: on the client, the
947
     * verified first-OPN *response* signature (sig) is the
948
     * ChannelThumbprint. capturedIncoming is false only on the
949
     * client response-verify path. Capture once, preserve across
950
     * renewals; binds the session SignatureData to this channel. */
951
0
    if(channel->enhancedSecurity && messageType == UA_MESSAGETYPE_OPN &&
952
0
       !capturedIncoming && channel->channelThumbprint.length == 0) {
953
0
        UA_StatusCode tp = UA_ByteString_copy(&sig, &channel->channelThumbprint);
954
0
        UA_CHECK_STATUS(tp, return tp);
955
0
    }
956
957
    /* Compute the padding if the payload is encrypted (not ECC policy) */
958
0
    size_t padSize = 0;
959
0
    if((messageType != UA_MESSAGETYPE_OPN &&
960
0
        channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) ||
961
0
       (messageType == UA_MESSAGETYPE_OPN &&
962
0
        sp->policyType == UA_SECURITYPOLICYTYPE_RSA)) {
963
0
        padSize = decodePadding(channel, encryptionAlgorithm, chunk, sigsize);
964
0
        UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Calculated padding size to be %lu",
965
0
                             (long unsigned)padSize);
966
0
    }
967
968
    /* Verify the content length. The encrypted payload has to be at least 9
969
     * bytes long: 8 byte for the SequenceHeader and one byte for the actual
970
     * message */
971
0
    UA_CHECK(offset + padSize + sigsize + 9 < chunk->length,
972
0
             UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Impossible padding value");
973
0
             return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
974
975
    /* Hide the signature and padding */
976
0
    chunk->length -= (sigsize + padSize);
977
0
    return UA_STATUSCODE_GOOD;
978
0
}
979
980
/* The certificate in the header is verified via the configured PKI plugin as
981
 * certificateVerification.verifyCertificate(...). We cannot do it here because
982
 * the client/server context is needed. */
983
UA_StatusCode
984
checkAsymHeader(UA_SecureChannel *channel,
985
0
                const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
986
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
987
0
    if(!UA_String_equal(&sp->policyUri, &asymHeader->securityPolicyUri))
988
0
        return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
989
0
    return sp->compareCertThumbprint(sp, &asymHeader->receiverCertificateThumbprint);
990
0
}
991
992
UA_StatusCode
993
checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId,
994
0
               UA_DateTime nowMonotonic) {
995
0
    UA_SecurityPolicy *sp = channel->securityPolicy;
996
0
    (void)sp;
997
998
    /* If no match, try to revolve to the next token after a
999
     * RenewSecureChannel */
1000
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
1001
0
    UA_ChannelSecurityToken *token = &channel->securityToken;
1002
0
    switch(channel->renewState) {
1003
0
    case UA_SECURECHANNELRENEWSTATE_NORMAL:
1004
0
    case UA_SECURECHANNELRENEWSTATE_SENT:
1005
0
    default:
1006
0
        break;
1007
1008
0
    case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER:
1009
        /* Old token still in use */
1010
0
        if(tokenId == channel->securityToken.tokenId)
1011
0
            break;
1012
1013
        /* Not the new token */
1014
0
        UA_CHECK(tokenId == channel->altSecurityToken.tokenId,
1015
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Unknown SecurityToken");
1016
0
                 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
1017
1018
        /* Roll over to the new token, generate new local and remote keys */
1019
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
1020
0
        channel->securityToken = channel->altSecurityToken;
1021
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
1022
0
        retval |= UA_SecureChannel_generateLocalKeys(channel);
1023
0
        retval |= generateRemoteKeys(channel);
1024
0
        UA_CHECK_STATUS(retval, return retval);
1025
0
        break;
1026
1027
0
    case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT:
1028
        /* The server is still using the old token. That's okay. */
1029
0
        if(tokenId == channel->altSecurityToken.tokenId) {
1030
0
            token = &channel->altSecurityToken;
1031
0
            break;
1032
0
        }
1033
1034
        /* Not the new token */
1035
0
        UA_CHECK(tokenId == channel->securityToken.tokenId,
1036
0
                 UA_LOG_ERROR_CHANNEL(sp->logger, channel, "Unknown SecurityToken");
1037
0
                 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
1038
1039
        /* The remote server uses the new token for the first time. Delete the
1040
         * old token and roll the remote key over. The local key already uses
1041
         * the nonce pair from the last OPN exchange. */
1042
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
1043
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
1044
0
        retval = generateRemoteKeys(channel);
1045
0
        UA_CHECK_STATUS(retval, return retval);
1046
0
    }
1047
1048
0
    UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC);
1049
0
    if(channel->state == UA_SECURECHANNELSTATE_OPEN && timeout < nowMonotonic) {
1050
0
        UA_LOG_ERROR_CHANNEL(sp->logger, channel, "SecurityToken timed out");
1051
0
        UA_SecureChannel_shutdown(channel, UA_SHUTDOWNREASON_TIMEOUT);
1052
0
        return UA_STATUSCODE_BADSECURECHANNELCLOSED;
1053
0
    }
1054
1055
0
    return UA_STATUSCODE_GOOD;
1056
0
}
1057
1058
UA_Boolean
1059
0
UA_SecureChannel_checkTimeout(UA_SecureChannel *channel, UA_DateTime nowMonotonic) {
1060
    /* Compute the timeout date of the SecurityToken */
1061
0
    UA_DateTime timeout = channel->securityToken.createdAt +
1062
0
        (UA_DateTime)(channel->securityToken.revisedLifetime * UA_DATETIME_MSEC);
1063
1064
    /* The token has timed out. Try to do the token revolving now instead of
1065
     * shutting the channel down.
1066
     *
1067
     * Part 4, 5.5.2 says: Servers shall use the existing SecurityToken to
1068
     * secure outgoing Messages until the SecurityToken expires or the
1069
     * Server receives a Message secured with a new SecurityToken.*/
1070
0
    if(timeout < nowMonotonic &&
1071
0
       channel->renewState == UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER) {
1072
        /* Revolve the token manually. This is otherwise done in checkSymHeader. */
1073
0
        channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
1074
0
        channel->securityToken = channel->altSecurityToken;
1075
0
        UA_ChannelSecurityToken_init(&channel->altSecurityToken);
1076
0
        UA_SecureChannel_generateLocalKeys(channel);
1077
0
        generateRemoteKeys(channel);
1078
1079
        /* Use the timeout of the new SecurityToken */
1080
0
        timeout = channel->securityToken.createdAt +
1081
0
            (UA_DateTime)(channel->securityToken.revisedLifetime * UA_DATETIME_MSEC);
1082
0
    }
1083
1084
0
    return (timeout < nowMonotonic);
1085
0
}