Coverage Report

Created: 2026-11-12 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xmlsec/src/openssl/kdf.c
Line
Count
Source
1
/**
2
 * XML Security Library (http://www.aleksey.com/xmlsec).
3
 *
4
 * This is free software; see the Copyright file in the source distribution for precise wording.
5
 *
6
 * Copyright (C) 2002-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
7
 */
8
/**
9
 * @addtogroup xmlsec_openssl_crypto
10
 * @brief OpenSSL KDF (key derivation) transforms implementation.
11
 */
12
#include "globals.h"
13
14
#include <stdlib.h>
15
#include <string.h>
16
17
#include <xmlsec/xmlsec.h>
18
#include <xmlsec/keys.h>
19
#include <xmlsec/errors.h>
20
#include <xmlsec/private.h>
21
#include <xmlsec/xmltree.h>
22
23
#include <xmlsec/openssl/crypto.h>
24
#include "openssl_compat.h"
25
26
#include "../cast_helpers.h"
27
#include "../keysdata_helpers.h"
28
#include "../transform_helpers.h"
29
30
/* KDF is only supported in OpenSSL 3.0.0+ */
31
#if !defined(XMLSEC_OPENSSL_API_111)
32
33
#include <openssl/kdf.h>
34
#include <openssl/core_names.h>
35
#include <openssl/obj_mac.h>
36
#include <openssl/param_build.h>
37
38
/******************************************************************************
39
 *
40
 * Internal KDF CTX for OpenSSL 3.0 or newer (https://www.openssl.org/docs/man3.0/man3/EVP_KDF_CTX_new.html)
41
 *
42
 *****************************************************************************/
43
44
934
#define XMLSEC_OPENSSL_KDF_DEFAULT_BUF_SIZE     64
45
570
#define XMLSEC_OPENSSL_KDF_MAX_PARAMS           16
46
47
typedef struct _xmlSecOpenSSLKdfCtx    xmlSecOpenSSLKdfCtx, *xmlSecOpenSSLKdfCtxPtr;
48
struct _xmlSecOpenSSLKdfCtx {
49
    const char * kdfName;
50
    xmlSecKeyDataId  keyId;
51
    xmlSecSize expectedOutputSize;
52
53
    EVP_KDF_CTX *kctx;
54
55
    /* kdf params */
56
    OSSL_PARAM params[XMLSEC_OPENSSL_KDF_MAX_PARAMS];
57
    xmlSecSize paramsPos;
58
    int paramsInitialized;
59
    const char * keyParamName;
60
61
    /* buffers to hold data for params (kdf specific) */
62
    xmlChar* digest;
63
    xmlChar* mac;
64
65
    xmlSecBuffer buffer;
66
    xmlSecBuffer buffer2;
67
    xmlSecBuffer keyBuffer;
68
    unsigned int param1;
69
};
70
8.46k
XMLSEC_TRANSFORM_DECLARE(OpenSSLKdf, xmlSecOpenSSLKdfCtx)
71
8.46k
#define xmlSecOpenSSLKdfCtxSize XMLSEC_TRANSFORM_SIZE(OpenSSLKdf)
72
8.46k
73
8.46k
static int      xmlSecOpenSSLKdfCheckId                   (xmlSecTransformPtr transform);
74
8.46k
static int      xmlSecOpenSSLKdfInitialize                (xmlSecTransformPtr transform);
75
8.46k
static void     xmlSecOpenSSLKdfFinalize                  (xmlSecTransformPtr transform);
76
8.46k
static int      xmlSecOpenSSLKdfSetKeyReq                 (xmlSecTransformPtr transform,
77
8.46k
                                                           xmlSecKeyReqPtr keyReq);
78
8.46k
static int      xmlSecOpenSSLKdfSetKey                    (xmlSecTransformPtr transform,
79
8.46k
                                                           xmlSecKeyPtr key);
80
8.46k
static int      xmlSecOpenSSLKdfExecute                   (xmlSecTransformPtr transform,
81
8.46k
                                                           int last,
82
8.46k
                                                           xmlSecTransformCtxPtr transformCtx);
83
8.46k
84
8.46k
85
8.46k
static int
86
8.46k
xmlSecOpenSSLKdfCheckId(xmlSecTransformPtr transform) {
87
88
1.88k
#ifndef XMLSEC_NO_CONCATKDF
89
1.88k
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformConcatKdfId)) {
90
0
        return(1);
91
0
    } else
92
1.88k
#endif /* XMLSEC_NO_CONCATKDF */
93
94
1.88k
#ifndef XMLSEC_NO_PBKDF2
95
1.88k
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformPbkdf2Id)) {
96
1.03k
        return(1);
97
1.03k
    }
98
852
#endif /* XMLSEC_NO_PBKDF2 */
99
100
852
#ifndef XMLSEC_NO_HKDF
101
852
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHkdfId)) {
102
852
        return(1);
103
852
    }
104
0
#endif /* XMLSEC_NO_HKDF */
105
106
    /* not found */
107
0
    return(0);
108
852
}
109
110
111
static int
112
934
xmlSecOpenSSLKdfInitialize(xmlSecTransformPtr transform) {
113
934
    xmlSecOpenSSLKdfCtxPtr ctx;
114
934
    EVP_KDF *kdf;
115
934
    int ret;
116
117
934
    xmlSecAssert2(xmlSecOpenSSLKdfCheckId(transform), -1);
118
934
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
119
120
934
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
121
934
    xmlSecAssert2(ctx != NULL, -1);
122
123
    /* initialize context */
124
934
    memset(ctx, 0, sizeof(xmlSecOpenSSLKdfCtx));
125
126
934
#ifndef XMLSEC_NO_CONCATKDF
127
934
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformConcatKdfId)) {
128
0
        ctx->keyId = xmlSecOpenSSLKeyDataConcatKdfId;
129
0
        ctx->kdfName = OSSL_KDF_NAME_SSKDF;
130
0
        ctx->keyParamName = OSSL_KDF_PARAM_SECRET;
131
0
    } else
132
934
#endif /* XMLSEC_NO_CONCATKDF */
133
134
934
#ifndef XMLSEC_NO_PBKDF2
135
934
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformPbkdf2Id)) {
136
512
        ctx->keyId = xmlSecOpenSSLKeyDataPbkdf2Id;
137
512
        ctx->kdfName = OSSL_KDF_NAME_PBKDF2;
138
512
        ctx->keyParamName = OSSL_KDF_PARAM_PASSWORD;
139
512
    } else
140
422
#endif /* XMLSEC_NO_PBKDF2 */
141
142
422
#ifndef XMLSEC_NO_HKDF
143
422
    if(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHkdfId)) {
144
422
        ctx->keyId = xmlSecOpenSSLKeyDataHkdfId;
145
422
        ctx->kdfName = OSSL_KDF_NAME_HKDF;
146
422
        ctx->keyParamName = OSSL_KDF_PARAM_KEY;
147
422
    } else
148
0
#endif /* XMLSEC_NO_HKDF */
149
150
    /* not found */
151
0
    {
152
0
        xmlSecInvalidTransformError(transform);
153
0
        return(-1);
154
0
    }
155
156
    /* create EVP KDF context */
157
934
    xmlSecAssert2(ctx->kdfName != NULL, -1);
158
934
    kdf = EVP_KDF_fetch(xmlSecOpenSSLGetLibCtx(), ctx->kdfName, NULL);
159
934
    if(kdf == NULL) {
160
0
        xmlSecOpenSSLError2("EVP_KDF_fetch", NULL, "kdf=%s", xmlSecErrorsSafeString(ctx->kdfName));
161
0
        xmlSecOpenSSLKdfFinalize(transform);
162
0
        return(-1);
163
0
    }
164
165
934
    ctx->kctx = EVP_KDF_CTX_new(kdf);
166
934
    if(ctx->kctx == NULL) {
167
0
        xmlSecOpenSSLError2("EVP_KDF_CTX_new", NULL, "kdf=%s", xmlSecErrorsSafeString(ctx->kdfName));
168
0
        xmlSecOpenSSLKdfFinalize(transform);
169
0
        EVP_KDF_free(kdf);
170
0
        return(-1);
171
0
    }
172
934
    EVP_KDF_free(kdf);
173
174
    /* init the rest */
175
934
    ret = xmlSecBufferInitialize(&(ctx->buffer), XMLSEC_OPENSSL_KDF_DEFAULT_BUF_SIZE);
176
934
    if(ret < 0) {
177
0
        xmlSecInternalError("xmlSecBufferInitialize(buffer)", NULL);
178
0
        xmlSecOpenSSLKdfFinalize(transform);
179
0
        return(-1);
180
0
    }
181
934
    xmlSecBufferMakeSecure(&(ctx->buffer));
182
183
934
    ret = xmlSecBufferInitialize(&(ctx->buffer2), 0);
184
934
    if(ret < 0) {
185
0
        xmlSecInternalError("xmlSecBufferInitialize(buffer2)", NULL);
186
0
        xmlSecOpenSSLKdfFinalize(transform);
187
0
        return(-1);
188
0
    }
189
934
    xmlSecBufferMakeSecure(&(ctx->buffer2));
190
191
934
    ret = xmlSecBufferInitialize(&(ctx->keyBuffer), 0);
192
934
    if(ret < 0) {
193
0
        xmlSecInternalError("xmlSecBufferInitialize(keyBuffer)", NULL);
194
0
        xmlSecOpenSSLKdfFinalize(transform);
195
0
        return(-1);
196
0
    }
197
934
    xmlSecBufferMakeSecure(&(ctx->keyBuffer));
198
199
    /* done */
200
934
    return(0);
201
934
}
202
203
static void
204
934
xmlSecOpenSSLKdfFinalize(xmlSecTransformPtr transform) {
205
934
    xmlSecOpenSSLKdfCtxPtr ctx;
206
207
934
    xmlSecAssert(xmlSecOpenSSLKdfCheckId(transform));
208
934
    xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize));
209
210
934
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
211
934
    xmlSecAssert(ctx != NULL);
212
213
934
    if(ctx->kctx != NULL) {
214
934
        EVP_KDF_CTX_free(ctx->kctx);
215
934
    }
216
217
934
    if(ctx->digest != NULL) {
218
20
        xmlFree(ctx->digest);
219
20
    }
220
221
934
    if(ctx->mac != NULL) {
222
20
        xmlFree(ctx->mac);
223
20
    }
224
225
934
    xmlSecBufferFinalize(&(ctx->buffer));
226
934
    xmlSecBufferFinalize(&(ctx->buffer2));
227
934
    xmlSecBufferFinalize(&(ctx->keyBuffer));
228
229
934
    OPENSSL_cleanse(ctx, sizeof(xmlSecOpenSSLKdfCtx));
230
934
}
231
232
233
static int
234
18
xmlSecOpenSSLKdfSetKeyReq(xmlSecTransformPtr transform,  xmlSecKeyReqPtr keyReq) {
235
18
    xmlSecOpenSSLKdfCtxPtr ctx;
236
237
18
    xmlSecAssert2(xmlSecOpenSSLKdfCheckId(transform), -1);
238
18
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
239
18
    xmlSecAssert2(keyReq != NULL, -1);
240
241
18
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
242
18
    xmlSecAssert2(ctx->keyId != NULL, -1);
243
244
18
    keyReq->keyId       = ctx->keyId;
245
18
    keyReq->keyType     = xmlSecKeyDataTypeSymmetric;
246
18
    keyReq->keyUsage    = xmlSecKeyUsageKeyDerive;
247
18
    return(0);
248
18
}
249
250
static int
251
0
xmlSecOpenSSLKdfSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
252
0
    xmlSecOpenSSLKdfCtxPtr ctx;
253
0
    xmlSecKeyDataPtr value;
254
0
    xmlSecBufferPtr buffer;
255
0
    xmlSecByte * keyData;
256
0
    xmlSecSize keySize;
257
0
    int ret;
258
259
0
    xmlSecAssert2(xmlSecOpenSSLKdfCheckId(transform), -1);
260
0
    xmlSecAssert2(((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt)), -1);
261
0
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
262
0
    xmlSecAssert2(key != NULL, -1);
263
264
0
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
265
0
    xmlSecAssert2(ctx != NULL, -1);
266
0
    xmlSecAssert2(ctx->keyId != NULL, -1);
267
0
    xmlSecAssert2(ctx->keyParamName != NULL, -1);
268
0
    xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
269
0
    xmlSecAssert2(ctx->paramsInitialized == 0, -1);
270
271
0
    value = xmlSecKeyGetValue(key);
272
0
    xmlSecAssert2(value != NULL, -1);
273
274
0
    buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
275
0
    xmlSecAssert2(buffer != NULL, -1);
276
277
0
    keyData = xmlSecBufferGetData(buffer);
278
0
    keySize = xmlSecBufferGetSize(buffer);
279
0
    if((keyData == NULL) || (keySize == 0)) {
280
0
        xmlSecInvalidZeroKeyDataSizeError(xmlSecTransformGetName(transform));
281
0
        return(-1);
282
0
    }
283
284
    /* copy the key into a ctx-owned buffer so the OSSL_PARAM pointer remains
285
     * valid until EVP_KDF_derive() is called */
286
0
    ret = xmlSecBufferSetData(&(ctx->keyBuffer), keyData, keySize);
287
0
    if(ret < 0) {
288
0
        xmlSecInternalError("xmlSecBufferSetData(key)", xmlSecTransformGetName(transform));
289
0
        return(-1);
290
0
    }
291
0
    keyData = xmlSecBufferGetData(&(ctx->keyBuffer));
292
0
    xmlSecAssert2(keyData != NULL, -1);
293
294
    /* set key */
295
0
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
296
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
297
0
        return(-1);
298
0
    }
299
0
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_octet_string(ctx->keyParamName, keyData, keySize);
300
301
    /* done with params! */
302
0
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
303
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
304
0
        return(-1);
305
0
    }
306
0
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_end();
307
0
    ctx->paramsInitialized = 1;
308
309
    /* success */
310
0
    return(0);
311
0
}
312
313
static int
314
xmlSecOpenSSLKdfExecute(
315
    xmlSecTransformPtr transform,
316
    int last,
317
    xmlSecTransformCtxPtr transformCtx
318
0
) {
319
0
    xmlSecOpenSSLKdfCtxPtr ctx;
320
0
    xmlSecBufferPtr in, out;
321
0
    int ret;
322
323
0
    xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
324
0
    xmlSecAssert2(((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt)), -1);
325
0
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
326
0
    xmlSecAssert2(transformCtx != NULL, -1);
327
328
    /* the KDF derives a key from the keying material only: it never consumes
329
     * transform input; data pushed into the transform is a caller error and
330
     * must not be silently dropped */
331
0
    in = &(transform->inBuf);
332
0
    out = &(transform->outBuf);
333
0
    xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
334
0
    xmlSecAssert2(xmlSecBufferIsSecure(out), -1);
335
336
0
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
337
0
    xmlSecAssert2(ctx != NULL, -1);
338
0
    xmlSecAssert2(ctx->kctx != NULL, -1);
339
0
    xmlSecAssert2(ctx->paramsInitialized != 0, -1);
340
341
0
    if(transform->status == xmlSecTransformStatusNone) {
342
        /* we should already be initialized when we set key */
343
0
        transform->status = xmlSecTransformStatusWorking;
344
0
    }
345
346
0
    if((transform->status == xmlSecTransformStatusWorking) && (last == 0)) {
347
        /* do nothing */
348
0
    } else if((transform->status == xmlSecTransformStatusWorking) && (last != 0)) {
349
0
        xmlSecByte * outData;
350
351
0
        if(transform->expectedOutputSize <= 0) {
352
0
            xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_SIZE, NULL, "KDF output key size is not specified");
353
0
            return(-1);
354
0
        }
355
0
        if((ctx->expectedOutputSize > 0) && (ctx->expectedOutputSize != transform->expectedOutputSize)) {
356
0
            xmlSecInvalidSizeError("expectedOutputSize",
357
0
                transform->expectedOutputSize, ctx->expectedOutputSize, xmlSecTransformGetName(transform));
358
0
            return(-1);
359
0
        }
360
361
0
        ret = xmlSecBufferSetSize(out, transform->expectedOutputSize);
362
0
        if(ret < 0) {
363
0
            xmlSecInternalError2("xmlSecBufferSetSize", NULL,
364
0
                "size=" XMLSEC_SIZE_FMT, transform->expectedOutputSize);
365
0
            return(-1);
366
0
        }
367
0
        outData = xmlSecBufferGetData(out);
368
0
        xmlSecAssert2(outData != NULL, -1);
369
370
0
        ret = EVP_KDF_derive(ctx->kctx, outData, transform->expectedOutputSize, ctx->params);
371
0
        if(ret <= 0) {
372
0
            xmlSecOpenSSLError("EVP_KDF_derive", xmlSecTransformGetName(transform));
373
0
            return(-1);
374
0
        }
375
376
0
        transform->status = xmlSecTransformStatusFinished;
377
0
        return(0);
378
0
    } else if(transform->status == xmlSecTransformStatusFinished) {
379
        /* the only way we can get here is if there is no input */
380
0
        xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
381
0
    } else {
382
0
        xmlSecInvalidTransformStatusError(transform);
383
0
        return(-1);
384
0
    }
385
386
0
    return(0);
387
0
}
388
389
/* Helper macro to define the KDF transform klass */
390
#define XMLSEC_OPENSSL_KDF_KLASS_EX(name, readNode)                                                                  \
391
static xmlSecTransformKlass xmlSecOpenSSL ## name ## Klass = {                                                       \
392
    sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */                                           \
393
    xmlSecOpenSSLKdfCtxSize,                    /* xmlSecSize objSize */                                             \
394
    xmlSecName ## name,                         /* const xmlChar* name; */                                           \
395
    xmlSecHref ## name,                         /* const xmlChar* href; */                                           \
396
    xmlSecTransformUsageKeyDerivationMethod,    /* xmlSecTransformUsage usage; */                                    \
397
    xmlSecOpenSSLKdfInitialize,                 /* xmlSecTransformInitializeMethod initialize; */                    \
398
    xmlSecOpenSSLKdfFinalize,                   /* xmlSecTransformFinalizeMethod finalize; */                        \
399
    readNode,                                   /* xmlSecTransformNodeReadMethod readNode; */                        \
400
    NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */                      \
401
    xmlSecOpenSSLKdfSetKeyReq,                  /* xmlSecTransformSetKeyRequirementsMethod setKeyReq; */             \
402
    xmlSecOpenSSLKdfSetKey,                     /* xmlSecTransformSetKeyMethod setKey; */                            \
403
    NULL,                                       /* xmlSecTransformVerifyMethod verify; */                            \
404
    xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */                  \
405
    xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */                          \
406
    xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */                            \
407
    NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */                          \
408
    NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */                            \
409
    xmlSecOpenSSLKdfExecute,                    /* xmlSecTransformExecuteMethod execute; */                          \
410
    NULL,                                       /* void* reserved0; */                                               \
411
    NULL,                                       /* void* reserved1; */                                               \
412
};
413
414
415
/******************************************************************************
416
 *
417
 * ConcatKDF (SSKDF) transform (https://www.openssl.org/docs/man3.0/man7/EVP_KDF-SS.html)
418
 *
419
 *****************************************************************************/
420
421
#ifndef XMLSEC_NO_CONCATKDF
422
423
424
static int      xmlSecOpenSSLConcatKdfNodeRead           (xmlSecTransformPtr transform,
425
                                                          xmlNodePtr node,
426
                                                          xmlSecTransformCtxPtr transformCtx);
427
428
429
430
/* convert DigestMethod to OpenSSL algo and set it in the params */
431
static int
432
0
xmlSecOpenSSLConcatKdfSetDigestNameFromHref(xmlSecOpenSSLKdfCtxPtr ctx, const xmlChar* href) {
433
0
    const char * digestName = NULL;
434
435
0
    xmlSecAssert2(ctx != NULL, -1);
436
0
    xmlSecAssert2(ctx->digest == NULL, -1);
437
438
    /* use SHA256 by default */
439
0
    if(href == NULL) {
440
0
#ifndef XMLSEC_NO_SHA256
441
0
        digestName = SN_sha256;
442
#else  /* XMLSEC_NO_SHA256 */
443
        xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
444
            "No digest algorithm is specified and the default SHA256 digest is disabled");
445
        return(-1);
446
#endif /* XMLSEC_NO_SHA256 */
447
0
    } else
448
449
0
#ifndef XMLSEC_NO_SHA1
450
0
    if(xmlStrcmp(href, xmlSecHrefSha1) == 0) {
451
0
        digestName = SN_sha1;
452
0
    } else
453
0
#endif /* XMLSEC_NO_SHA1 */
454
455
0
#ifndef XMLSEC_NO_SHA224
456
0
    if(xmlStrcmp(href, xmlSecHrefSha224) == 0) {
457
0
        digestName = SN_sha224;
458
0
    } else
459
0
#endif /* XMLSEC_NO_SHA224 */
460
461
0
#ifndef XMLSEC_NO_SHA256
462
0
    if(xmlStrcmp(href, xmlSecHrefSha256) == 0) {
463
0
        digestName = SN_sha256;
464
0
    } else
465
0
#endif /* XMLSEC_NO_SHA256 */
466
467
0
#ifndef XMLSEC_NO_SHA384
468
0
    if(xmlStrcmp(href, xmlSecHrefSha384) == 0) {
469
0
        digestName = SN_sha384;
470
0
    } else
471
0
#endif /* XMLSEC_NO_SHA384 */
472
473
0
#ifndef XMLSEC_NO_SHA512
474
0
    if(xmlStrcmp(href, xmlSecHrefSha512) == 0) {
475
0
        digestName = SN_sha512;
476
0
    } else
477
0
#endif /* XMLSEC_NO_SHA512 */
478
479
0
#ifndef XMLSEC_NO_SHA3
480
0
    if(xmlStrcmp(href, xmlSecHrefSha3_224) == 0) {
481
0
        digestName = SN_sha3_224;
482
0
    } else if(xmlStrcmp(href, xmlSecHrefSha3_256) == 0) {
483
0
        digestName = SN_sha3_256;
484
0
    } else if(xmlStrcmp(href, xmlSecHrefSha3_384) == 0) {
485
0
        digestName = SN_sha3_384;
486
0
    } else if(xmlStrcmp(href, xmlSecHrefSha3_512) == 0) {
487
0
        digestName = SN_sha3_512;
488
0
    } else
489
490
0
#endif /* XMLSEC_NO_SHA3 */
491
0
    {
492
0
        xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
493
0
            "href=%s", xmlSecErrorsSafeString(href));
494
0
        return(-1);
495
0
    }
496
497
    /* save algorithm in the context, params just holds a pointer */
498
0
    xmlSecAssert2(digestName != NULL, -1);
499
0
    ctx->digest = xmlStrdup(BAD_CAST digestName);
500
0
    if(ctx->digest == NULL) {
501
0
        xmlSecStrdupError(BAD_CAST digestName, NULL);
502
0
        return(-1);
503
0
    }
504
505
0
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
506
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", NULL);
507
0
        return(-1);
508
0
    }
509
0
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char*)ctx->digest, strlen((char*)ctx->digest));
510
511
    /* done */
512
0
    return(0);
513
0
}
514
515
static int
516
xmlSecOpenSSLConcatKdfNodeRead(xmlSecTransformPtr transform, xmlNodePtr node,
517
0
                          xmlSecTransformCtxPtr transformCtx XMLSEC_ATTRIBUTE_UNUSED) {
518
0
    xmlSecOpenSSLKdfCtxPtr ctx;
519
0
    xmlSecTransformConcatKdfParams params;
520
0
    int paramsInitialized = 0;
521
0
    xmlSecByte * fixedInfoData;
522
0
    xmlSecSize fixedInfoSize;
523
0
    xmlNodePtr cur;
524
0
    int ret;
525
0
    int res = -1;
526
527
0
    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformConcatKdfId), -1);
528
0
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
529
0
    xmlSecAssert2(node!= NULL, -1);
530
0
    XMLSEC_UNREFERENCED(transformCtx);
531
532
0
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
533
0
    xmlSecAssert2(ctx != NULL, -1);
534
535
    /* prepare for parsing */
536
0
    ret = xmlSecTransformConcatKdfParamsInitialize(&params);
537
0
    if(ret < 0) {
538
0
        xmlSecInternalError("xmlSecTransformConcatKdfParamsInitialize", xmlSecTransformGetName(transform));
539
0
        goto done;
540
0
    }
541
0
    paramsInitialized = 1;
542
543
    /* first (and only) node is required ConcatKDFParams */
544
0
    cur  = xmlSecGetNextElementNode(node->children);
545
0
    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeConcatKDFParams, xmlSecEnc11Ns))) {
546
0
        xmlSecInvalidNodeError(cur, xmlSecNodeConcatKDFParams, NULL);
547
0
        goto done;
548
0
    }
549
550
0
    ret = xmlSecTransformConcatKdfParamsRead(&params, cur);
551
0
    if(ret < 0) {
552
0
        xmlSecInternalError("xmlSecTransformConcatKdfParamsRead", xmlSecTransformGetName(transform));
553
0
        goto done;
554
555
0
    }
556
557
    /* if we have something else then it's an error */
558
0
    cur = xmlSecGetNextElementNode(cur->next);
559
0
    if(cur != NULL) {
560
0
        xmlSecUnexpectedNodeError(cur,  NULL);
561
0
        goto done;
562
0
    }
563
564
    /* set FixedInfo from params and save in the context, params just holds a pointer */
565
0
    ret = xmlSecTransformConcatKdfParamsGetFixedInfo(&params, &(ctx->buffer));
566
0
    if(ret < 0) {
567
0
        xmlSecInternalError("xmlSecTransformConcatKdfParamsGetFixedInfo", xmlSecTransformGetName(transform));
568
0
        goto done;
569
0
    }
570
0
    fixedInfoData = xmlSecBufferGetData(&(ctx->buffer));
571
0
    fixedInfoSize = xmlSecBufferGetSize(&(ctx->buffer));
572
    /* FixedInfo is optional per NIST SP 800-56A; all components (AlgorithmID, PartyUInfo,
573
     * PartyVInfo, SuppPubInfo, SuppPrivInfo) may be absent. Only set OSSL_KDF_PARAM_INFO
574
     * when fixedInfo is non-empty. */
575
0
    if((fixedInfoData != NULL) && (fixedInfoSize > 0)) {
576
0
        if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
577
0
            xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
578
0
            goto done;
579
0
        }
580
0
        ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, fixedInfoData, fixedInfoSize);
581
0
    }
582
583
    /* set OpenSSL digest name from params */
584
0
    ret = xmlSecOpenSSLConcatKdfSetDigestNameFromHref(ctx, params.digestMethod);
585
0
    if(ret < 0) {
586
0
        xmlSecInternalError("xmlSecOpenSSLConcatKdfSetDigestNameFromHref", xmlSecTransformGetName(transform));
587
0
        goto done;
588
0
    }
589
590
    /* success */
591
0
    res = 0;
592
593
0
done:
594
0
    if(paramsInitialized != 0) {
595
0
        xmlSecTransformConcatKdfParamsFinalize(&params);
596
0
    }
597
0
    return(res);
598
0
}
599
600
/* ConcatKDF key derivation algorithm */
601
XMLSEC_OPENSSL_KDF_KLASS_EX(ConcatKdf, xmlSecOpenSSLConcatKdfNodeRead)
602
603
/**
604
 * @brief The ConcatKDF key derivation transform klass.
605
 * @return the ConcatKDF key derivation transform klass.
606
 */
607
xmlSecTransformId
608
2.82k
xmlSecOpenSSLTransformConcatKdfGetKlass(void) {
609
2.82k
    return(&xmlSecOpenSSLConcatKdfKlass);
610
2.82k
}
611
612
#endif /* XMLSEC_NO_CONCATKDF */
613
614
615
616
/******************************************************************************
617
 *
618
 * PBKDF2 transform (https://www.openssl.org/docs/man3.0/man7/EVP_KDF-PBKDF2.html)
619
 *
620
 *****************************************************************************/
621
622
#ifndef XMLSEC_NO_PBKDF2
623
624
625
static int      xmlSecOpenSSLPbkdf2NodeRead               (xmlSecTransformPtr transform,
626
                                                          xmlNodePtr node,
627
                                                          xmlSecTransformCtxPtr transformCtx);
628
629
630
/* convert PRF algorithm href to OpenSSL algo and set it in the params */
631
static int
632
262
xmlSecOpenSSLPbkdf2SetDigestNameFromHref(xmlSecOpenSSLKdfCtxPtr ctx, const xmlChar* href) {
633
262
    const char * digestName = NULL;
634
635
262
    xmlSecAssert2(ctx != NULL, -1);
636
262
    xmlSecAssert2(ctx->digest == NULL, -1);
637
262
    xmlSecAssert2(ctx->mac == NULL, -1);
638
639
    /* use SHA256 by default */
640
262
    if(href == NULL) {
641
0
#ifndef XMLSEC_NO_SHA256
642
0
        digestName = SN_sha256;
643
#else  /* XMLSEC_NO_SHA256 */
644
        xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
645
            "No digest algorithm is specified and the default SHA256 digest is disabled");
646
        return(-1);
647
#endif /* XMLSEC_NO_SHA256 */
648
0
    } else
649
650
262
#ifndef XMLSEC_NO_SHA1
651
262
    if(xmlStrcmp(href, xmlSecHrefHmacSha1) == 0) {
652
2
        digestName = SN_sha1;
653
2
    } else
654
260
#endif /* XMLSEC_NO_SHA1 */
655
656
260
#ifndef XMLSEC_NO_SHA224
657
260
    if(xmlStrcmp(href, xmlSecHrefHmacSha224) == 0) {
658
2
        digestName = SN_sha224;
659
2
    } else
660
258
#endif /* XMLSEC_NO_SHA224 */
661
662
258
#ifndef XMLSEC_NO_SHA256
663
258
    if(xmlStrcmp(href, xmlSecHrefHmacSha256) == 0) {
664
2
        digestName = SN_sha256;
665
2
    } else
666
256
#endif /* XMLSEC_NO_SHA256 */
667
668
256
#ifndef XMLSEC_NO_SHA384
669
256
    if(xmlStrcmp(href, xmlSecHrefHmacSha384) == 0) {
670
2
        digestName = SN_sha384;
671
2
    } else
672
254
#endif /* XMLSEC_NO_SHA384 */
673
674
254
#ifndef XMLSEC_NO_SHA512
675
254
    if(xmlStrcmp(href, xmlSecHrefHmacSha512) == 0) {
676
2
        digestName = SN_sha512;
677
2
    } else
678
252
#endif /* XMLSEC_NO_SHA512 */
679
680
252
    {
681
252
        xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
682
252
            "href=%s", xmlSecErrorsSafeString(href));
683
252
        return(-1);
684
252
    }
685
686
    /* save algorithm in the context, params just holds a pointer */
687
10
    xmlSecAssert2(digestName != NULL, -1);
688
10
    ctx->digest = xmlStrdup(BAD_CAST digestName);
689
10
    if(ctx->digest == NULL) {
690
0
        xmlSecStrdupError(BAD_CAST digestName, NULL);
691
0
        return(-1);
692
0
    }
693
10
    ctx->mac = xmlStrdup(BAD_CAST SN_hmac);
694
10
    if(ctx->mac == NULL) {
695
0
        xmlSecStrdupError(BAD_CAST SN_hmac, NULL);
696
0
        return(-1);
697
0
    }
698
699
    /* set params */
700
10
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
701
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", NULL);
702
0
        return(-1);
703
0
    }
704
10
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char*)ctx->digest, strlen((char*)ctx->digest));
705
706
10
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
707
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", NULL);
708
0
        return(-1);
709
0
    }
710
10
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, (char*)ctx->mac, strlen((char*)ctx->mac));
711
712
    /* done */
713
10
    return(0);
714
10
}
715
716
static int
717
xmlSecOpenSSLPbkdf2NodeRead(xmlSecTransformPtr transform, xmlNodePtr node,
718
512
                          xmlSecTransformCtxPtr transformCtx XMLSEC_ATTRIBUTE_UNUSED) {
719
512
    xmlSecOpenSSLKdfCtxPtr ctx;
720
512
    xmlSecTransformPbkdf2Params params;
721
512
    int paramsInitialized = 0;
722
512
    xmlSecByte * saltData;
723
512
    xmlSecSize saltSize;
724
512
    xmlNodePtr cur;
725
512
    int ret;
726
512
    int res = -1;
727
728
512
    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformPbkdf2Id), -1);
729
512
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
730
512
    xmlSecAssert2(node!= NULL, -1);
731
512
    XMLSEC_UNREFERENCED(transformCtx);
732
733
512
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
734
512
    xmlSecAssert2(ctx != NULL, -1);
735
736
512
    ret = xmlSecTransformPbkdf2ParamsInitialize(&params);
737
512
    if(ret < 0) {
738
0
        xmlSecInternalError("xmlSecTransformPbkdf2ParamsInitialize", xmlSecTransformGetName(transform));
739
0
        goto done;
740
0
    }
741
512
    paramsInitialized = 1;
742
743
    /* first (and only) node is required Pbkdf2Params */
744
512
    cur  = xmlSecGetNextElementNode(node->children);
745
512
    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodePbkdf2Params, xmlSecEnc11Ns))) {
746
4
        xmlSecInvalidNodeError(cur, xmlSecNodePbkdf2Params, NULL);
747
4
        goto done;
748
4
    }
749
508
    ret = xmlSecTransformPbkdf2ParamsRead(&params, cur);
750
508
    if(ret < 0) {
751
246
        xmlSecInternalError("xmlSecTransformPbkdf2ParamsRead", xmlSecTransformGetName(transform));
752
246
        goto done;
753
246
    }
754
755
    /* if we have something else then it's an error */
756
262
    cur = xmlSecGetNextElementNode(cur->next);
757
262
    if(cur != NULL) {
758
0
        xmlSecUnexpectedNodeError(cur,  NULL);
759
0
        goto done;
760
0
    }
761
762
    /* set output key length */
763
262
    if(params.keyLength <= 0) {
764
0
        xmlSecInvalidSizeDataError("keyLength", params.keyLength, "> 0", xmlSecTransformGetName(transform));
765
0
        goto done;
766
0
    }
767
262
    ctx->expectedOutputSize = params.keyLength;
768
769
    /* set iterations count */
770
262
    if(params.iterationCount <= 0) {
771
0
        xmlSecInvalidSizeDataError("iterationCount", params.iterationCount, "> 0", xmlSecTransformGetName(transform));
772
0
        goto done;
773
0
    }
774
262
    XMLSEC_SAFE_CAST_SIZE_TO_UINT(params.iterationCount, ctx->param1, goto done, xmlSecTransformGetName(transform));
775
262
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
776
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
777
0
        goto done;
778
0
    }
779
262
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, &(ctx->param1));
780
781
    /* set salt, this also swaps secure flag */
782
262
    xmlSecBufferSwap(&(ctx->buffer), &(params.salt));
783
784
262
    saltData = xmlSecBufferGetData(&(ctx->buffer));
785
262
    saltSize = xmlSecBufferGetSize(&(ctx->buffer));
786
262
    if((saltData == NULL) || (saltSize == 0)) {
787
0
        xmlSecInvalidSizeDataError("saltSize", saltSize, "> 0", xmlSecTransformGetName(transform));
788
0
        goto done;
789
0
    }
790
262
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
791
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
792
0
        goto done;
793
0
    }
794
262
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, saltData, saltSize);
795
796
    /* set OpenSSL digest algorithm name from params */
797
262
    ret = xmlSecOpenSSLPbkdf2SetDigestNameFromHref(ctx, params.prfAlgorithmHref);
798
262
    if(ret < 0) {
799
252
        xmlSecInternalError("xmlSecOpenSSLPbkdf2SetDigestNameFromHref", xmlSecTransformGetName(transform));
800
252
        goto done;
801
252
    }
802
803
    /* success */
804
10
    res = 0;
805
806
512
done:
807
512
    if(paramsInitialized != 0) {
808
512
        xmlSecTransformPbkdf2ParamsFinalize(&params);
809
512
    }
810
512
    return(res);
811
10
}
812
813
/* PBKDF2 key derivation algorithm */
814
XMLSEC_OPENSSL_KDF_KLASS_EX(Pbkdf2, xmlSecOpenSSLPbkdf2NodeRead)
815
816
/**
817
 * @brief The PBKDF2 key derivation transform klass.
818
 * @return the PBKDF2 key derivation transform klass.
819
 */
820
xmlSecTransformId
821
3.33k
xmlSecOpenSSLTransformPbkdf2GetKlass(void) {
822
3.33k
    return(&xmlSecOpenSSLPbkdf2Klass);
823
3.33k
}
824
825
#endif /* XMLSEC_NO_PBKDF2 */
826
827
/******************************************************************************
828
 *
829
 * HKDF transform (https://www.openssl.org/docs/man3.0/man7/EVP_KDF-HKDF.html)
830
 *
831
 *****************************************************************************/
832
#ifndef XMLSEC_NO_HKDF
833
834
static int      xmlSecOpenSSLHkdfNodeRead               (xmlSecTransformPtr transform,
835
                                                         xmlNodePtr node,
836
                                                         xmlSecTransformCtxPtr transformCtx);
837
838
/* convert PRF algorithm href to OpenSSL digest name and set it in the params */
839
static int
840
252
xmlSecOpenSSLHkdfSetDigestNameFromHref(xmlSecOpenSSLKdfCtxPtr ctx, const xmlChar* href) {
841
252
    const char * digestName = NULL;
842
843
252
    xmlSecAssert2(ctx != NULL, -1);
844
252
    xmlSecAssert2(ctx->digest == NULL, -1);
845
846
    /* use SHA256 by default */
847
252
    if(href == NULL) {
848
0
#ifndef XMLSEC_NO_SHA256
849
0
        digestName = SN_sha256;
850
#else  /* XMLSEC_NO_SHA256 */
851
        xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
852
            "No digest algorithm is specified and the default SHA256 digest is disabled");
853
        return(-1);
854
#endif /* XMLSEC_NO_SHA256 */
855
0
    } else
856
857
252
#ifndef XMLSEC_NO_SHA1
858
252
    if(xmlStrcmp(href, xmlSecHrefHmacSha1) == 0) {
859
4
        digestName = SN_sha1;
860
4
    } else
861
248
#endif /* XMLSEC_NO_SHA1 */
862
863
248
#ifndef XMLSEC_NO_SHA224
864
248
    if(xmlStrcmp(href, xmlSecHrefHmacSha224) == 0) {
865
0
        digestName = SN_sha224;
866
0
    } else
867
248
#endif /* XMLSEC_NO_SHA224 */
868
869
248
#ifndef XMLSEC_NO_SHA256
870
248
    if(xmlStrcmp(href, xmlSecHrefHmacSha256) == 0) {
871
2
        digestName = SN_sha256;
872
2
    } else
873
246
#endif /* XMLSEC_NO_SHA256 */
874
875
246
#ifndef XMLSEC_NO_SHA384
876
246
    if(xmlStrcmp(href, xmlSecHrefHmacSha384) == 0) {
877
2
        digestName = SN_sha384;
878
2
    } else
879
244
#endif /* XMLSEC_NO_SHA384 */
880
881
244
#ifndef XMLSEC_NO_SHA512
882
244
    if(xmlStrcmp(href, xmlSecHrefHmacSha512) == 0) {
883
2
        digestName = SN_sha512;
884
2
    } else
885
242
#endif /* XMLSEC_NO_SHA512 */
886
887
242
    {
888
242
        xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_ALGORITHM, NULL,
889
242
            "href=%s", xmlSecErrorsSafeString(href));
890
242
        return(-1);
891
242
    }
892
893
    /* save algorithm in the context, params just holds a pointer */
894
10
    xmlSecAssert2(digestName != NULL, -1);
895
10
    ctx->digest = xmlStrdup(BAD_CAST digestName);
896
10
    if(ctx->digest == NULL) {
897
0
        xmlSecStrdupError(BAD_CAST digestName, NULL);
898
0
        return(-1);
899
0
    }
900
901
10
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
902
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", NULL);
903
0
        return(-1);
904
0
    }
905
10
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char*)ctx->digest, strlen((char*)ctx->digest));
906
907
    /* done */
908
10
    return(0);
909
10
}
910
911
static int
912
xmlSecOpenSSLHkdfNodeRead(xmlSecTransformPtr transform, xmlNodePtr node,
913
422
                          xmlSecTransformCtxPtr transformCtx XMLSEC_ATTRIBUTE_UNUSED) {
914
422
    xmlSecOpenSSLKdfCtxPtr ctx;
915
422
    xmlSecTransformHkdfParams params;
916
422
    int paramsInitialized = 0;
917
422
    xmlSecByte * saltData;
918
422
    xmlSecSize saltSize;
919
422
    xmlSecByte * infoData;
920
422
    xmlSecSize infoSize;
921
422
    xmlNodePtr cur;
922
422
    int ret;
923
422
    int res = -1;
924
925
422
    xmlSecAssert2(xmlSecTransformCheckId(transform, xmlSecOpenSSLTransformHkdfId), -1);
926
422
    xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecOpenSSLKdfCtxSize), -1);
927
422
    xmlSecAssert2(node != NULL, -1);
928
422
    XMLSEC_UNREFERENCED(transformCtx);
929
930
422
    ctx = xmlSecOpenSSLKdfGetCtx(transform);
931
422
    xmlSecAssert2(ctx != NULL, -1);
932
422
    xmlSecAssert2(ctx->mac == NULL, -1);
933
934
422
    ret = xmlSecTransformHkdfParamsInitialize(&params);
935
422
    if(ret < 0) {
936
0
        xmlSecInternalError("xmlSecTransformHkdfParamsInitialize", xmlSecTransformGetName(transform));
937
0
        goto done;
938
0
    }
939
422
    paramsInitialized = 1;
940
941
    /* first (and only) node is required HKDFParams */
942
422
    cur = xmlSecGetNextElementNode(node->children);
943
422
    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeHkdfParams, xmlSecDSig2021MoreNs))) {
944
4
        xmlSecInvalidNodeError(cur, xmlSecNodeHkdfParams, NULL);
945
4
        goto done;
946
4
    }
947
418
    ret = xmlSecTransformHkdfParamsRead(&params, cur);
948
418
    if(ret < 0) {
949
164
        xmlSecInternalError("xmlSecTransformHkdfParamsRead", xmlSecTransformGetName(transform));
950
164
        goto done;
951
164
    }
952
953
    /* if we have something else then it's an error */
954
254
    cur = xmlSecGetNextElementNode(cur->next);
955
254
    if(cur != NULL) {
956
2
        xmlSecUnexpectedNodeError(cur, NULL);
957
2
        goto done;
958
2
    }
959
960
    /* set PRF digest (required) */
961
252
    ret = xmlSecOpenSSLHkdfSetDigestNameFromHref(ctx, params.prfAlgorithmHref);
962
252
    if(ret < 0) {
963
242
        xmlSecInternalError("xmlSecOpenSSLHkdfSetDigestNameFromHref", xmlSecTransformGetName(transform));
964
242
        goto done;
965
242
    }
966
967
    /* set HKDF mode: EXTRACT_AND_EXPAND (the mode string is stored in ctx->mac, which has no HKDF-specific meaning; a transform instance is only ever one KDF type) */
968
10
    ctx->mac = xmlStrdup(BAD_CAST "EXTRACT_AND_EXPAND");
969
10
    if(ctx->mac == NULL) {
970
0
        xmlSecStrdupError(BAD_CAST "EXTRACT_AND_EXPAND", NULL);
971
0
        goto done;
972
0
    }
973
10
    if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
974
0
        xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
975
0
        goto done;
976
0
    }
977
10
    ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, (char*)ctx->mac, strlen((char*)ctx->mac));
978
979
    /* set output key length (optional; 0 means caller-specified via expectedOutputSize) */
980
10
    if(params.keyLength > 0) {
981
6
        ctx->expectedOutputSize = params.keyLength;
982
6
    }
983
984
    /* set salt (optional) */
985
10
    saltData = xmlSecBufferGetData(&(params.salt));
986
10
    saltSize = xmlSecBufferGetSize(&(params.salt));
987
10
    if((saltData != NULL) && (saltSize > 0)) {
988
        /* this also swaps secure flag */
989
6
        xmlSecBufferSwap(&(ctx->buffer), &(params.salt));
990
991
6
        saltData = xmlSecBufferGetData(&(ctx->buffer));
992
6
        saltSize = xmlSecBufferGetSize(&(ctx->buffer));
993
6
        if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
994
0
            xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
995
0
            goto done;
996
0
        }
997
6
        ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, saltData, saltSize);
998
6
    }
999
1000
    /* set info (optional) */
1001
10
    infoData = xmlSecBufferGetData(&(params.info));
1002
10
    infoSize = xmlSecBufferGetSize(&(params.info));
1003
10
    if((infoData != NULL) && (infoSize > 0)) {
1004
        /* swap info into ctx->buffer2 so the data remains valid after params finalize (this also swaps the secure flag) */
1005
0
        xmlSecBufferSwap(&(ctx->buffer2), &(params.info));
1006
1007
0
        infoData = xmlSecBufferGetData(&(ctx->buffer2));
1008
0
        infoSize = xmlSecBufferGetSize(&(ctx->buffer2));
1009
0
        if(ctx->paramsPos >= XMLSEC_OPENSSL_KDF_MAX_PARAMS) {
1010
0
            xmlSecInvalidSizeDataError("Kdf Params Number", ctx->paramsPos, "too big", xmlSecTransformGetName(transform));
1011
0
            goto done;
1012
0
        }
1013
0
        ctx->params[ctx->paramsPos++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, infoData, infoSize);
1014
0
    }
1015
1016
    /* success */
1017
10
    res = 0;
1018
1019
422
done:
1020
422
    if(paramsInitialized != 0) {
1021
422
        xmlSecTransformHkdfParamsFinalize(&params);
1022
422
    }
1023
422
    return(res);
1024
10
}
1025
1026
/* HKDF key derivation algorithm */
1027
XMLSEC_OPENSSL_KDF_KLASS_EX(Hkdf, xmlSecOpenSSLHkdfNodeRead)
1028
1029
/**
1030
 * @brief The HKDF key derivation transform klass.
1031
 * @return the HKDF key derivation transform klass.
1032
 */
1033
xmlSecTransformId
1034
1.69k
xmlSecOpenSSLTransformHkdfGetKlass(void) {
1035
1.69k
    return(&xmlSecOpenSSLHkdfKlass);
1036
1.69k
}
1037
1038
#endif /* XMLSEC_NO_HKDF */
1039
1040
#else /* !defined(XMLSEC_OPENSSL_API_111) */
1041
1042
/* ISO C forbids an empty translation unit */
1043
typedef int make_iso_compilers_happy;
1044
1045
#endif /* !defined(XMLSEC_OPENSSL_API_111) */