Coverage Report

Created: 2026-11-12 06:54

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