Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/softoken/kbkdf.c
Line
Count
Source (jump to first uncovered line)
1
#include "pkcs11i.h"
2
#include "blapi.h"
3
#include "secerr.h"
4
#include "softoken.h"
5
6
/* Overview:
7
 *
8
 * This file contains implementations of the three KDFs from NIST SP800-108
9
 * "Recommendation for Key Derivation Using Pseudorandom Functions":
10
 *
11
 *  1. KDF in Counter Mode (section 5.1)
12
 *  2. KDF in Feedback Mode (section 5.2)
13
 *  3. KDF in Double-Pipeline Iteration Mode (section 5.3)
14
 *
15
 * These KDFs are a form of negotiable building blocks for KDFs: protocol
16
 * designers can choose various fields, their endianness, and the underlying
17
 * PRF. These constructs are generic enough to handle creation of arbitrary,
18
 * (but known ahead of time) length outputs.
19
 *
20
 * The families of PRFs described here are used, among other places, in
21
 * Kerberos and GlobalPlatform's Secure Channel Protocol 03. The PKCS#11 v3.0
22
 * design for this KDF facilitates a wide range of uses.
23
 *
24
 * Implementation Details:
25
 *
26
 * We reuse the new sftk_MACCtx for handling the underlying MACing; with a few
27
 * safe restrictions, we can reuse whatever it gives us to use as a PRF.
28
 *
29
 * We implement the core of the KDF in the *Raw(...) version of the function
30
 * call. The PKCS#11 key handling happens in the non-Raw version. This means
31
 * we need a single large allocation upfront (large enough to store the entire
32
 * key stream), but means we can share key parsing logic and enable the
33
 * creation of data objects.
34
 */
35
36
/* [ section: #define's ] */
37
38
0
#define VALID_CK_BOOL(x) ((x) == CK_TRUE || (x) == CK_FALSE)
39
0
#define IS_COUNTER(_mech) ((_mech) == CKM_SP800_108_COUNTER_KDF || (_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA)
40
0
#define DOES_DERIVE_DATA(_mech) ((_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA)
41
42
/* [ section: parameter validation ] */
43
44
static CK_RV
45
kbkdf_LoadParameters(CK_MECHANISM_TYPE mech, CK_MECHANISM_PTR pMechanism, CK_SP800_108_KDF_PARAMS_PTR kdf_params, CK_BYTE_PTR *initial_value, CK_ULONG_PTR initial_value_length)
46
0
{
47
    /* This function loads the parameters for the given mechanism into the
48
     * specified kdf_params, splitting off the IV if present. In PKCS#11 v3.0,
49
     * CK_SP800_108_FEEDBACK_KDF_PARAMS and CK_SP800_108_KDF_PARAMS have
50
     * different ordering of internal parameters, which means that it isn't
51
     * easy to reuse feedback parameters in the same functions as non-feedback
52
     * parameters. Rather than duplicating the logic, split out the only
53
     * Feedback-specific data (the IV) into a separate argument and repack it
54
     * into the passed kdf_params struct instead. */
55
0
    PR_ASSERT(pMechanism != NULL && kdf_params != NULL && initial_value != NULL && initial_value_length != NULL);
56
57
0
    CK_SP800_108_KDF_PARAMS_PTR in_params;
58
0
    CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR feedback_params;
59
60
0
    if (mech == CKM_SP800_108_FEEDBACK_KDF || mech == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA) {
61
0
        if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)) {
62
0
            return CKR_MECHANISM_PARAM_INVALID;
63
0
        }
64
65
0
        feedback_params = (CK_SP800_108_FEEDBACK_KDF_PARAMS *)pMechanism->pParameter;
66
67
0
        if (feedback_params->pIV == NULL && feedback_params->ulIVLen > 0) {
68
0
            return CKR_MECHANISM_PARAM_INVALID;
69
0
        }
70
71
0
        kdf_params->prfType = feedback_params->prfType;
72
0
        kdf_params->ulNumberOfDataParams = feedback_params->ulNumberOfDataParams;
73
0
        kdf_params->pDataParams = feedback_params->pDataParams;
74
0
        kdf_params->ulAdditionalDerivedKeys = feedback_params->ulAdditionalDerivedKeys;
75
0
        kdf_params->pAdditionalDerivedKeys = feedback_params->pAdditionalDerivedKeys;
76
77
0
        *initial_value = feedback_params->pIV;
78
0
        *initial_value_length = feedback_params->ulIVLen;
79
0
    } else {
80
0
        if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_KDF_PARAMS)) {
81
0
            return CKR_MECHANISM_PARAM_INVALID;
82
0
        }
83
84
0
        in_params = (CK_SP800_108_KDF_PARAMS *)pMechanism->pParameter;
85
86
0
        (*kdf_params) = *in_params;
87
0
    }
88
89
0
    return CKR_OK;
90
0
}
91
92
static CK_RV
93
kbkdf_ValidateParameter(CK_MECHANISM_TYPE mech, const CK_PRF_DATA_PARAM *data)
94
0
{
95
    /* This function validates that the passed data parameter (data) conforms
96
     * to PKCS#11 v3.0's expectations for KDF parameters. This depends both on
97
     * the type of this parameter (data->type) and on the KDF mechanism (mech)
98
     * as certain parameters are context dependent (like Iteration Variable).
99
     */
100
101
    /* If the parameter is missing a value when one is expected, then this
102
     * parameter is invalid. */
103
0
    if ((data->pValue == NULL) != (data->ulValueLen == 0)) {
104
0
        return CKR_MECHANISM_PARAM_INVALID;
105
0
    }
106
107
0
    switch (data->type) {
108
0
        case CK_SP800_108_ITERATION_VARIABLE:
109
0
        case CK_SP800_108_OPTIONAL_COUNTER: {
110
0
            if (data->type == CK_SP800_108_ITERATION_VARIABLE && !IS_COUNTER(mech)) {
111
                /* In Feedback and Double Pipeline KDFs, PKCS#11 v3.0 connotes the
112
                 * iteration variable as the chaining value from the previous PRF
113
                 * invocation. In contrast, counter mode treats this variable as a
114
                 * COUNTER_FORMAT descriptor. Thus we can skip validation of
115
                 * iteration variable parameters outside of counter mode. However,
116
                 * PKCS#11 v3.0 technically mandates that pValue is NULL, so we
117
                 * still have to validate that. */
118
119
0
                if (data->pValue != NULL) {
120
0
                    return CKR_MECHANISM_PARAM_INVALID;
121
0
                }
122
123
0
                return CKR_OK;
124
0
            }
125
126
            /* In counter mode, data->pValue should be a pointer to an instance of
127
             * CK_SP800_108_COUNTER_FORMAT; validate its length. */
128
0
            if (data->ulValueLen != sizeof(CK_SP800_108_COUNTER_FORMAT)) {
129
0
                return CKR_MECHANISM_PARAM_INVALID;
130
0
            }
131
132
0
            CK_SP800_108_COUNTER_FORMAT_PTR param = (CK_SP800_108_COUNTER_FORMAT_PTR)data->pValue;
133
134
            /* Validate the endian parameter. */
135
0
            if (!VALID_CK_BOOL(param->bLittleEndian)) {
136
0
                return CKR_MECHANISM_PARAM_INVALID;
137
0
            }
138
139
            /* Due to restrictions by our underlying hashes, we restrict bit
140
             * widths to actually be byte widths by ensuring they're a multiple
141
             * of eight. */
142
0
            if ((param->ulWidthInBits % 8) != 0) {
143
0
                return CKR_MECHANISM_PARAM_INVALID;
144
0
            }
145
146
            /* Note that section 5.1 denotes the maximum length of the counter
147
             * to be 32. */
148
0
            if (param->ulWidthInBits > 32) {
149
0
                return CKR_MECHANISM_PARAM_INVALID;
150
0
            }
151
0
            break;
152
0
        }
153
0
        case CK_SP800_108_DKM_LENGTH: {
154
            /* data->pValue should be a pointer to an instance of
155
             * CK_SP800_108_DKM_LENGTH_FORMAT; validate its length. */
156
0
            if (data->ulValueLen != sizeof(CK_SP800_108_DKM_LENGTH_FORMAT)) {
157
0
                return CKR_MECHANISM_PARAM_INVALID;
158
0
            }
159
160
0
            CK_SP800_108_DKM_LENGTH_FORMAT_PTR param = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)data->pValue;
161
162
            /* Validate the method parameter. */
163
0
            if (param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS &&
164
0
                param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) {
165
0
                return CKR_MECHANISM_PARAM_INVALID;
166
0
            }
167
168
            /* Validate the endian parameter. */
169
0
            if (!VALID_CK_BOOL(param->bLittleEndian)) {
170
0
                return CKR_MECHANISM_PARAM_INVALID;
171
0
            }
172
173
            /* Validate the maximum width: we restrict it to being a byte width
174
             * instead of a bit width due to restrictions by the underlying
175
             * PRFs. */
176
0
            if ((param->ulWidthInBits % 8) != 0) {
177
0
                return CKR_MECHANISM_PARAM_INVALID;
178
0
            }
179
180
            /* Ensure that the width doesn't overflow a 64-bit int. This
181
             * restriction is arbitrary but since the counters can't exceed
182
             * 32-bits (and most PRFs output at most 1024 bits), you're unlikely
183
             * to need all 64-bits of length indicator. */
184
0
            if (param->ulWidthInBits > 64) {
185
0
                return CKR_MECHANISM_PARAM_INVALID;
186
0
            }
187
0
            break;
188
0
        }
189
0
        case CK_SP800_108_BYTE_ARRAY:
190
            /* There is no additional data to validate for byte arrays; we can
191
             * only assume the byte array is of the specified size. */
192
0
            break;
193
0
        default:
194
            /* Unexpected parameter type. */
195
0
            return CKR_MECHANISM_PARAM_INVALID;
196
0
    }
197
198
0
    return CKR_OK;
199
0
}
200
201
static CK_RV
202
kbkdf_ValidateDerived(CK_DERIVED_KEY_PTR key)
203
0
{
204
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
205
0
    PRUint64 keySize = 0;
206
207
    /* The pointer to the key handle shouldn't be NULL. If it is, we can't
208
     * do anything else, so exit early. Every other failure case sets the
209
     * key->phKey = CK_INVALID_HANDLE, so we can't use `goto failure` here. */
210
0
    if (key->phKey == NULL) {
211
0
        return CKR_MECHANISM_PARAM_INVALID;
212
0
    }
213
214
    /* Validate that we have no attributes if and only if pTemplate is NULL.
215
     * Otherwise, there's an inconsistency somewhere. */
216
0
    if ((key->ulAttributeCount == 0) != (key->pTemplate == NULL)) {
217
0
        goto failure;
218
0
    }
219
220
0
    for (size_t offset = 0; offset < key->ulAttributeCount; offset++) {
221
0
        CK_ATTRIBUTE_PTR template = key->pTemplate + offset;
222
223
        /* We only look for the CKA_VALUE_LEN and CKA_KEY_TYPE attributes.
224
         * Everything else we assume we can set on the key if it is passed
225
         * here. However, if we can't inquire as to a length (and barring
226
         * that, if we have a key type without a standard length), we're
227
         * definitely stuck. This mirrors the logic at the top of
228
         * NSC_DeriveKey(...). */
229
0
        if (template->type == CKA_KEY_TYPE) {
230
0
            if (template->ulValueLen != sizeof(CK_KEY_TYPE)) {
231
0
                goto failure;
232
0
            }
233
234
0
            keyType = *(CK_KEY_TYPE *)template->pValue;
235
0
        } else if (template->type == CKA_VALUE_LEN) {
236
0
            if (template->ulValueLen != sizeof(CK_ULONG)) {
237
0
                goto failure;
238
0
            }
239
240
0
            keySize = *(CK_ULONG *)template->pValue;
241
0
        }
242
0
    }
243
244
0
    if (keySize == 0) {
245
        /* When we lack a keySize, see if we can infer it from the type of the
246
         * passed key. */
247
0
        keySize = sftk_MapKeySize(keyType);
248
0
    }
249
250
    /* The main piece of information we validate is that we have a length for
251
     * this key. */
252
0
    if (keySize == 0 || keySize >= (1ull << 32ull)) {
253
0
        goto failure;
254
0
    }
255
256
0
    return CKR_OK;
257
258
0
failure:
259
    /* PKCS#11 v3.0: If the failure was caused by the content of a specific
260
     * key's template (ie the template defined by the content of pTemplate),
261
     * the corresponding phKey value will be set to CK_INVALID_HANDLE to
262
     * identify the offending template. */
263
0
    *(key->phKey) = CK_INVALID_HANDLE;
264
0
    return CKR_MECHANISM_PARAM_INVALID;
265
0
}
266
267
static PRBool
268
kbkdf_ValidPRF(CK_SP800_108_PRF_TYPE prf)
269
0
{
270
    // See Table 161 of PKCS#11 v3.0 or Table 192 of PKCS#11 v3.1.
271
0
    switch (prf) {
272
0
        case CKM_AES_CMAC:
273
            /* case CKM_DES3_CMAC: */
274
0
            return PR_TRUE;
275
0
        case CKM_SHA_1_HMAC:
276
0
        case CKM_SHA224_HMAC:
277
0
        case CKM_SHA256_HMAC:
278
0
        case CKM_SHA384_HMAC:
279
0
        case CKM_SHA512_HMAC:
280
0
        case CKM_SHA3_224_HMAC:
281
0
        case CKM_SHA3_256_HMAC:
282
0
        case CKM_SHA3_384_HMAC:
283
0
        case CKM_SHA3_512_HMAC:
284
            /* Valid HMAC <-> HASH isn't NULL */
285
0
            return sftk_HMACMechanismToHash(prf) != HASH_AlgNULL;
286
0
    }
287
0
    return PR_FALSE;
288
0
}
289
290
static CK_RV
291
kbkdf_ValidateParameters(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, CK_ULONG keySize)
292
0
{
293
0
    CK_RV ret = CKR_MECHANISM_PARAM_INVALID;
294
0
    int param_type_count[5] = { 0, 0, 0, 0, 0 };
295
0
    size_t offset = 0;
296
297
    /* Start with checking the prfType as a mechanism against a list of
298
     * PRFs allowed by PKCS#11 v3.0. */
299
0
    if (!kbkdf_ValidPRF(params->prfType)) {
300
0
        return CKR_MECHANISM_PARAM_INVALID;
301
0
    }
302
303
    /* We can't have a null pDataParams pointer: we always need at least one
304
     * parameter to succeed. */
305
0
    if (params->pDataParams == NULL) {
306
0
        return CKR_HOST_MEMORY;
307
0
    }
308
309
    /* Validate each KDF parameter. */
310
0
    for (offset = 0; offset < params->ulNumberOfDataParams; offset++) {
311
        /* Validate this parameter has acceptable values. */
312
0
        ret = kbkdf_ValidateParameter(mech, params->pDataParams + offset);
313
0
        if (ret != CKR_OK) {
314
0
            return CKR_MECHANISM_PARAM_INVALID;
315
0
        }
316
317
        /* Count that we have a parameter of this type. The above logic
318
         * in ValidateParameter MUST validate that type is within the
319
         * appropriate range. */
320
0
        PR_ASSERT(params->pDataParams[offset].type < sizeof(param_type_count) / sizeof(param_type_count[0]));
321
0
        param_type_count[params->pDataParams[offset].type] += 1;
322
0
    }
323
324
0
    if (IS_COUNTER(mech)) {
325
        /* We have to have at least one iteration variable parameter. */
326
0
        if (param_type_count[CK_SP800_108_ITERATION_VARIABLE] == 0) {
327
0
            return CKR_MECHANISM_PARAM_INVALID;
328
0
        }
329
330
        /* We can't have any optional counters parameters -- these belong in
331
         * iteration variable parameters instead. */
332
0
        if (param_type_count[CK_SP800_108_OPTIONAL_COUNTER] != 0) {
333
0
            return CKR_MECHANISM_PARAM_INVALID;
334
0
        }
335
0
    }
336
337
    /* Validate basic assumptions about derived keys:
338
     *      NULL <-> ulAdditionalDerivedKeys > 0
339
     */
340
0
    if ((params->ulAdditionalDerivedKeys == 0) != (params->pAdditionalDerivedKeys == NULL)) {
341
0
        return CKR_MECHANISM_PARAM_INVALID;
342
0
    }
343
344
    /* Validate each derived key. */
345
0
    for (offset = 0; offset < params->ulAdditionalDerivedKeys; offset++) {
346
0
        ret = kbkdf_ValidateDerived(params->pAdditionalDerivedKeys + offset);
347
0
        if (ret != CKR_OK) {
348
0
            return CKR_MECHANISM_PARAM_INVALID;
349
0
        }
350
0
    }
351
352
    /* Validate the length of our primary key. */
353
0
    if (keySize == 0 || ((PRUint64)keySize) >= (1ull << 32ull)) {
354
0
        return CKR_KEY_SIZE_RANGE;
355
0
    }
356
357
0
    return CKR_OK;
358
0
}
359
360
/* [ section: parameter helpers ] */
361
362
static CK_VOID_PTR
363
kbkdf_FindParameter(const CK_SP800_108_KDF_PARAMS *params, CK_PRF_DATA_TYPE type)
364
0
{
365
0
    for (size_t offset = 0; offset < params->ulNumberOfDataParams; offset++) {
366
0
        if (params->pDataParams[offset].type == type) {
367
0
            return params->pDataParams[offset].pValue;
368
0
        }
369
0
    }
370
371
0
    return NULL;
372
0
}
373
374
size_t
375
kbkdf_IncrementBuffer(size_t cur_offset, size_t consumed, size_t prf_length)
376
0
{
377
0
    return cur_offset + PR_ROUNDUP(consumed, prf_length);
378
0
}
379
380
CK_ULONG
381
kbkdf_GetDerivedKeySize(CK_DERIVED_KEY_PTR derived_key)
382
0
{
383
    /* Precondition: kbkdf_ValidateDerived(...) returns CKR_OK for this key,
384
     * which implies that keySize is defined. */
385
386
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
387
0
    CK_ULONG keySize = 0;
388
389
0
    for (size_t offset = 0; offset < derived_key->ulAttributeCount; offset++) {
390
0
        CK_ATTRIBUTE_PTR template = derived_key->pTemplate + offset;
391
392
        /* Find the two attributes we care about. */
393
0
        if (template->type == CKA_KEY_TYPE) {
394
0
            keyType = *(CK_KEY_TYPE *)template->pValue;
395
0
        } else if (template->type == CKA_VALUE_LEN) {
396
0
            keySize = *(CK_ULONG *)template->pValue;
397
0
        }
398
0
    }
399
400
    /* Prefer keySize, if we have it. */
401
0
    if (keySize > 0) {
402
0
        return keySize;
403
0
    }
404
405
    /* Else, fall back to this mapping. We know kbkdf_ValidateDerived(...)
406
     * passed, so this should return non-zero. */
407
0
    return sftk_MapKeySize(keyType);
408
0
}
409
410
static CK_RV
411
kbkdf_CalculateLength(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, CK_ULONG ret_key_size, PRUint64 *output_bitlen, size_t *buffer_length)
412
0
{
413
    /* Two cases: either we have additional derived keys or we don't. In the
414
     * case that we don't, the length of the derivation is the size of the
415
     * single derived key, and that is the length of the PRF buffer. Otherwise,
416
     * we need to use the proper CK_SP800_108_DKM_LENGTH_METHOD to calculate
417
     * the length of the output (in bits), with a separate value for the size
418
     * of the PRF data buffer. This means that, under PKCS#11 with additional
419
     * derived keys, we lie to the KDF about the _actual_ length of the PRF
420
     * output.
421
     *
422
     * Note that *output_bitlen is the L parameter in NIST SP800-108 and is in
423
     * bits. However, *buffer_length is in bytes.
424
     */
425
426
0
    if (params->ulAdditionalDerivedKeys == 0) {
427
        /* When we have no additional derived keys, we get the keySize from
428
         * the value passed to one of our KBKDF_* methods. */
429
0
        *output_bitlen = ret_key_size;
430
0
        *buffer_length = ret_key_size;
431
0
    } else {
432
        /* Offset in the additional derived keys array. */
433
0
        size_t offset = 0;
434
435
        /* Size of the derived key. */
436
0
        CK_ULONG derived_size = 0;
437
438
        /* In the below, we place the sum of the keys into *output_bitlen
439
         * and the size of the buffer (with padding mandated by PKCS#11 v3.0)
440
         * into *buffer_length. If the method is the segment sum, then we
441
         * replace *output_bitlen with *buffer_length at the end. This ensures
442
         * we always get a output buffer large enough to handle all derived
443
         * keys, and *output_bitlen reflects the correct L value. */
444
445
        /* Count the initial derived key. */
446
0
        *output_bitlen = ret_key_size;
447
0
        *buffer_length = kbkdf_IncrementBuffer(0, ret_key_size, ctx->mac_size);
448
449
        /* Handle n - 1 keys. The last key is special. */
450
0
        for (; offset < params->ulAdditionalDerivedKeys - 1; offset++) {
451
0
            derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset);
452
453
0
            *output_bitlen += derived_size;
454
0
            *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size);
455
0
        }
456
457
        /* Handle the last key. */
458
0
        derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset);
459
460
0
        *output_bitlen += derived_size;
461
0
        *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size);
462
463
        /* Pointer to the DKM method parameter. Note that this implicit cast
464
         * is safe since we've assumed we've been validated by
465
         * kbkdf_ValidateParameters(...). When kdm_param is NULL, we don't
466
         * use the output_bitlen parameter. */
467
0
        CK_SP800_108_DKM_LENGTH_FORMAT_PTR dkm_param = kbkdf_FindParameter(params, CK_SP800_108_DKM_LENGTH);
468
0
        if (dkm_param != NULL) {
469
0
            if (dkm_param->dkmLengthMethod == CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) {
470
0
                *output_bitlen = *buffer_length;
471
0
            }
472
0
        }
473
0
    }
474
475
    /* Note that keySize is the size in bytes and ctx->mac_size is also
476
     * the size in bytes. However, output_bitlen needs to be in bits, so
477
     * multiply by 8 here. */
478
0
    *output_bitlen *= 8;
479
480
0
    return CKR_OK;
481
0
}
482
483
static CK_RV
484
kbkdf_CalculateIterations(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, size_t buffer_length, PRUint32 *num_iterations)
485
0
{
486
0
    CK_SP800_108_COUNTER_FORMAT_PTR param_ptr = NULL;
487
0
    PRUint64 iteration_count;
488
0
    PRUint64 r = 32;
489
490
    /* We need to know how many full iterations are required. This is done
491
     * by rounding up the division of the PRF length into buffer_length.
492
     * However, we're not guaranteed that the last output is a full PRF
493
     * invocation, so handle that here. */
494
0
    iteration_count = buffer_length + (ctx->mac_size - 1);
495
0
    iteration_count = iteration_count / ctx->mac_size;
496
497
    /* NIST SP800-108, section 5.1, process step #2:
498
     *
499
     *      if n > 2^r - 1, then indicate an error and stop.
500
     *
501
     * In non-counter mode KDFs, r is set at 32, leaving behavior
502
     * under-defined when the optional counter is included but fewer than
503
     * 32 bits. This implementation assumes r is 32, but if the counter
504
     * parameter is included, validates it against that. In counter-mode
505
     * KDFs, this is in the ITERATION_VARIABLE parameter; in feedback- or
506
     * pipeline-mode KDFs, this is in the COUNTER parameter.
507
     *
508
     * This is consistent with the supplied sample CAVP tests; none reuses the
509
     * same counter value. In some configurations, this could result in
510
     * duplicated KDF output. We seek to avoid that from happening.
511
     */
512
0
    if (IS_COUNTER(mech)) {
513
0
        param_ptr = kbkdf_FindParameter(params, CK_SP800_108_ITERATION_VARIABLE);
514
515
        /* Validated by kbkdf_ValidateParameters(...) above. */
516
0
        PR_ASSERT(param_ptr != NULL);
517
518
0
        r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits;
519
0
    } else {
520
0
        param_ptr = kbkdf_FindParameter(params, CK_SP800_108_COUNTER);
521
522
        /* Not guaranteed to exist, hence the default value of r=32. */
523
0
        if (param_ptr != NULL) {
524
0
            r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits;
525
0
        }
526
0
    }
527
528
0
    if (iteration_count >= (1ull << r) || r > 32) {
529
0
        return CKR_MECHANISM_PARAM_INVALID;
530
0
    }
531
532
0
    *num_iterations = (PRUint32)iteration_count;
533
534
0
    return CKR_OK;
535
0
}
536
537
static CK_RV
538
kbkdf_AddParameters(CK_MECHANISM_TYPE mech, sftk_MACCtx *ctx, const CK_SP800_108_KDF_PARAMS *params, PRUint32 counter, PRUint64 length, const unsigned char *chaining_prf, size_t chaining_prf_len, CK_PRF_DATA_TYPE exclude)
539
0
{
540
0
    size_t offset = 0;
541
0
    CK_RV ret = CKR_OK;
542
543
0
    for (offset = 0; offset < params->ulNumberOfDataParams; offset++) {
544
0
        CK_PRF_DATA_PARAM_PTR param = params->pDataParams + offset;
545
546
0
        if (param->type == exclude) {
547
            /* Necessary for Double Pipeline mode: when constructing the IV,
548
             * we skip the  optional counter. */
549
0
            continue;
550
0
        }
551
552
0
        switch (param->type) {
553
0
            case CK_SP800_108_ITERATION_VARIABLE: {
554
                /* When present in COUNTER mode, this signifies adding the counter
555
                 * variable to the PRF. Otherwise, it signifies the chaining
556
                 * value for other KDF modes. */
557
0
                if (IS_COUNTER(mech)) {
558
0
                    CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue;
559
0
                    CK_BYTE buffer[sizeof(PRUint64)];
560
0
                    CK_ULONG num_bytes;
561
0
                    sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes);
562
0
                    ret = sftk_MAC_Update(ctx, buffer, num_bytes);
563
0
                } else {
564
0
                    ret = sftk_MAC_Update(ctx, chaining_prf, chaining_prf_len);
565
0
                }
566
0
                break;
567
0
            }
568
0
            case CK_SP800_108_COUNTER: {
569
                /* Only present in the case when not using COUNTER mode. */
570
0
                PR_ASSERT(!IS_COUNTER(mech));
571
572
                /* We should've already validated that this parameter is of
573
                 * type COUNTER_FORMAT. */
574
0
                CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue;
575
0
                CK_BYTE buffer[sizeof(PRUint64)];
576
0
                CK_ULONG num_bytes;
577
0
                sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes);
578
0
                ret = sftk_MAC_Update(ctx, buffer, num_bytes);
579
0
                break;
580
0
            }
581
0
            case CK_SP800_108_BYTE_ARRAY:
582
0
                ret = sftk_MAC_Update(ctx, (CK_BYTE_PTR)param->pValue, param->ulValueLen);
583
0
                break;
584
0
            case CK_SP800_108_DKM_LENGTH: {
585
                /* We've already done the hard work of calculating the length in
586
                 * the kbkdf_CalculateIterations function; we merely need to add
587
                 * the length to the desired point in the input stream. */
588
0
                CK_SP800_108_DKM_LENGTH_FORMAT_PTR length_format = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)param->pValue;
589
0
                CK_BYTE buffer[sizeof(PRUint64)];
590
0
                CK_ULONG num_bytes;
591
0
                sftk_EncodeInteger(length, length_format->ulWidthInBits, length_format->bLittleEndian, buffer, &num_bytes);
592
0
                ret = sftk_MAC_Update(ctx, buffer, num_bytes);
593
0
                break;
594
0
            }
595
0
            default:
596
                /* This should've been caught by kbkdf_ValidateParameters(...). */
597
0
                PR_ASSERT(PR_FALSE);
598
0
                return CKR_MECHANISM_PARAM_INVALID;
599
0
        }
600
601
0
        if (ret != CKR_OK) {
602
0
            return ret;
603
0
        }
604
0
    }
605
606
0
    return CKR_OK;
607
0
}
608
609
CK_RV
610
kbkdf_SaveKey(SFTKObject *key, unsigned char *key_buffer, unsigned int key_len)
611
0
{
612
0
    return sftk_forceAttribute(key, CKA_VALUE, key_buffer, key_len);
613
0
}
614
615
CK_RV
616
kbkdf_CreateKey(CK_MECHANISM_TYPE kdf_mech, CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject **ret_key)
617
0
{
618
    /* Largely duplicated from NSC_DeriveKey(...) */
619
0
    CK_RV ret = CKR_HOST_MEMORY;
620
0
    SFTKObject *key = NULL;
621
0
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
622
0
    size_t offset = 0;
623
624
    /* Slot should be non-NULL because NSC_DeriveKey(...) has already
625
     * performed a sftk_SlotFromSessionHandle(...) call on this session
626
     * handle. However, Coverity incorrectly flagged this (see 1607955). */
627
0
    PR_ASSERT(slot != NULL);
628
0
    PR_ASSERT(ret_key != NULL);
629
0
    PR_ASSERT(derived_key != NULL);
630
0
    PR_ASSERT(derived_key->phKey != NULL);
631
632
0
    if (slot == NULL) {
633
0
        return CKR_SESSION_HANDLE_INVALID;
634
0
    }
635
636
    /* Create the new key object for this additional derived key. */
637
0
    key = sftk_NewObject(slot);
638
0
    if (key == NULL) {
639
0
        return CKR_HOST_MEMORY;
640
0
    }
641
642
    /* Setup the key from the provided template. */
643
0
    for (offset = 0; offset < derived_key->ulAttributeCount; offset++) {
644
0
        ret = sftk_AddAttributeType(key, sftk_attr_expand(derived_key->pTemplate + offset));
645
0
        if (ret != CKR_OK) {
646
0
            sftk_FreeObject(key);
647
0
            return ret;
648
0
        }
649
0
    }
650
651
    /* When using the CKM_SP800_* series of mechanisms, the result must be a
652
     * secret key, so its contents can be adequately protected in FIPS mode.
653
     * However, when using the special CKM_NSS_SP800_*_DERIVE_DATA series, the
654
     * contents need not be protected, so we set CKO_DATA on these "keys". */
655
0
    CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
656
0
    if (DOES_DERIVE_DATA(kdf_mech)) {
657
0
        classType = CKO_DATA;
658
0
    }
659
660
0
    ret = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
661
0
    if (ret != CKR_OK) {
662
0
        sftk_FreeObject(key);
663
0
        return ret;
664
0
    }
665
666
0
    *ret_key = key;
667
0
    return CKR_OK;
668
0
}
669
670
CK_RV
671
kbkdf_FinalizeKey(CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject *key)
672
0
{
673
    /* Largely duplicated from NSC_DeriveKey(...) */
674
0
    CK_RV ret = CKR_HOST_MEMORY;
675
0
    SFTKSession *session = NULL;
676
677
0
    PR_ASSERT(derived_key != NULL && key != NULL);
678
679
0
    SFTKSessionObject *sessionForKey = sftk_narrowToSessionObject(key);
680
0
    PR_ASSERT(sessionForKey != NULL);
681
0
    sessionForKey->wasDerived = PR_TRUE;
682
683
0
    session = sftk_SessionFromHandle(hSession);
684
685
    /* Session should be non-NULL because NSC_DeriveKey(...) has already
686
     * performed a sftk_SessionFromHandle(...) call on this session handle. */
687
0
    PR_ASSERT(session != NULL);
688
689
0
    ret = sftk_handleObject(key, session);
690
0
    if (ret != CKR_OK) {
691
0
        goto done;
692
0
    }
693
694
0
    *(derived_key->phKey) = key->handle;
695
696
0
done:
697
    /* Guaranteed that key != NULL */
698
0
    sftk_FreeObject(key);
699
700
    /* Doesn't do anything. */
701
0
    if (session) {
702
0
        sftk_FreeSession(session);
703
0
    }
704
705
0
    return ret;
706
0
}
707
708
CK_RV
709
kbkdf_SaveKeys(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_SP800_108_KDF_PARAMS_PTR params, unsigned char *output_buffer, size_t buffer_len, size_t prf_length, SFTKObject *ret_key, CK_ULONG ret_key_size)
710
0
{
711
0
    CK_RV ret;
712
0
    size_t key_offset = 0;
713
0
    size_t buffer_offset = 0;
714
715
0
    PR_ASSERT(output_buffer != NULL && buffer_len > 0 && ret_key != NULL);
716
717
    /* First place key material into the main key. */
718
0
    ret = kbkdf_SaveKey(ret_key, output_buffer + buffer_offset, ret_key_size);
719
0
    if (ret != CKR_OK) {
720
0
        return ret;
721
0
    }
722
723
    /* Then increment the offset based on PKCS#11 additional key guidelines:
724
     * no two keys may share the key stream from the same PRF invocation. */
725
0
    buffer_offset = kbkdf_IncrementBuffer(buffer_offset, ret_key_size, prf_length);
726
727
0
    if (params->ulAdditionalDerivedKeys > 0) {
728
        /* Note that the following code is technically incorrect: PKCS#11 v3.0
729
         * says that _no_ key should be set in the event of failure to derive
730
         * _any_ key. */
731
0
        for (key_offset = 0; key_offset < params->ulAdditionalDerivedKeys; key_offset++) {
732
0
            CK_DERIVED_KEY_PTR derived_key = params->pAdditionalDerivedKeys + key_offset;
733
0
            SFTKObject *key_obj = NULL;
734
0
            size_t key_size = kbkdf_GetDerivedKeySize(derived_key);
735
736
            /* Create a new internal key object for this derived key. */
737
0
            ret = kbkdf_CreateKey(mech, hSession, derived_key, &key_obj);
738
0
            if (ret != CKR_OK) {
739
0
                *(derived_key->phKey) = CK_INVALID_HANDLE;
740
0
                return ret;
741
0
            }
742
743
            /* Save the underlying key bytes to the key object. */
744
0
            ret = kbkdf_SaveKey(key_obj, output_buffer + buffer_offset, key_size);
745
0
            if (ret != CKR_OK) {
746
                /* When kbkdf_CreateKey(...) exits with an error, it will free
747
                 * the constructed key object. kbkdf_FinalizeKey(...) also
748
                 * always frees the key object. In the unlikely event that
749
                 * kbkdf_SaveKey(...) _does_ fail, we thus need to free it
750
                 * manually. */
751
0
                sftk_FreeObject(key_obj);
752
0
                *(derived_key->phKey) = CK_INVALID_HANDLE;
753
0
                return ret;
754
0
            }
755
756
            /* Handle the increment. */
757
0
            buffer_offset = kbkdf_IncrementBuffer(buffer_offset, key_size, prf_length);
758
759
            /* Finalize this key. */
760
0
            ret = kbkdf_FinalizeKey(hSession, derived_key, key_obj);
761
0
            if (ret != CKR_OK) {
762
0
                *(derived_key->phKey) = CK_INVALID_HANDLE;
763
0
                return ret;
764
0
            }
765
0
        }
766
0
    }
767
768
0
    return CKR_OK;
769
0
}
770
771
/* [ section: KDFs ] */
772
773
static CK_RV
774
kbkdf_CounterRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
775
0
{
776
0
    CK_RV ret = CKR_OK;
777
778
    /* Counter variable for this KDF instance. */
779
0
    PRUint32 counter;
780
781
    /* Number of iterations required of this PRF necessary to reach the
782
     * desired output length. */
783
0
    PRUint32 num_iterations;
784
785
    /* Offset in ret_buffer that we're at. */
786
0
    size_t buffer_offset = 0;
787
788
    /* Size of this block, in bytes. Defaults to ctx->mac_size except on
789
     * the last iteration where it could be a partial block. */
790
0
    size_t block_size = ctx->mac_size;
791
792
    /* Calculate the number of iterations required based on the size of the
793
     * output buffer. */
794
0
    ret = kbkdf_CalculateIterations(CKM_SP800_108_COUNTER_KDF, params, ctx, buffer_length, &num_iterations);
795
0
    if (ret != CKR_OK) {
796
0
        return ret;
797
0
    }
798
799
    /*
800
     * 5.1 - [ KDF in Counter Mode ]
801
     *
802
     * Fixed values:
803
     *      1. h - the length of the PRF in bits (ctx->mac_size)
804
     *      2. r - the length of the binary representation of the counter i
805
     *          (params[k: params[k].type == CK_SP800_108_ITERATION_VARIABLE:].data->ulWidthInBits)
806
     * Input:
807
     *      1. K_I - the key for the PRF (base_key)
808
     *      2. label - a binary data field, usually before the separator. Optional.
809
     *      3. context - a binary data field, usually after the separator. Optional.
810
     *      4. L - length of the output in bits (output_bitlen)
811
     *
812
     * Process:
813
     *      1. n := ceil(L / h) (num_iterations)
814
     *      2. if n > 2^r - 1, then indicate an error and stop
815
     *      3. result(0) = NULL
816
     *      4. for i = 1 to n, do
817
     *          a. K(i) = PRF(K_I, [i]_2 || Label || 0x00 || Context || [L]_2)
818
     *          b. result(i) := result(i - 1) || K(i).
819
     *      5. return K_O := the leftmost L bits of result(n).
820
     */
821
0
    for (counter = 1; counter <= num_iterations; counter++) {
822
0
        if (counter == num_iterations) {
823
0
            block_size = buffer_length - buffer_offset;
824
825
            /* Assumption: if we've validated our arguments correctly, this
826
             * should always be true. */
827
0
            PR_ASSERT(block_size <= ctx->mac_size);
828
0
        }
829
830
        /* Add all parameters required by this instance of the KDF to the
831
         * input stream of the underlying PRF. */
832
0
        ret = kbkdf_AddParameters(CKM_SP800_108_COUNTER_KDF, ctx, params, counter, output_bitlen, NULL, 0 /* chaining_prf output */, 0 /* exclude */);
833
0
        if (ret != CKR_OK) {
834
0
            return ret;
835
0
        }
836
837
        /* Finalize this iteration of the PRF. */
838
0
        ret = sftk_MAC_End(ctx, ret_buffer + buffer_offset, NULL, block_size);
839
0
        if (ret != CKR_OK) {
840
0
            return ret;
841
0
        }
842
843
        /* Increment our position in the key material. */
844
0
        buffer_offset += block_size;
845
846
0
        if (counter < num_iterations) {
847
            /* Reset the underlying PRF for the next iteration. Only do this
848
             * when we have a next iteration since it isn't necessary to do
849
             * either before the first iteration (MAC is already initialized)
850
             * or after the last iteration (we won't be called again). */
851
0
            ret = sftk_MAC_Reset(ctx);
852
0
            if (ret != CKR_OK) {
853
0
                return ret;
854
0
            }
855
0
        }
856
0
    }
857
858
0
    return CKR_OK;
859
0
}
860
861
static CK_RV
862
kbkdf_FeedbackRaw(const CK_SP800_108_KDF_PARAMS *params, const unsigned char *initial_value, CK_ULONG initial_value_length, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
863
0
{
864
0
    CK_RV ret = CKR_OK;
865
866
    /* Counter variable for this KDF instance. */
867
0
    PRUint32 counter;
868
869
    /* Number of iterations required of this PRF necessary to reach the
870
     * desired output length. */
871
0
    PRUint32 num_iterations;
872
873
    /* Offset in ret_buffer that we're at. */
874
0
    size_t buffer_offset = 0;
875
876
    /* Size of this block, in bytes. Defaults to ctx->mac_size except on
877
     * the last iteration where it could be a partial block. */
878
0
    size_t block_size = ctx->mac_size;
879
880
    /* The last PRF invocation and/or the initial value; used for feedback
881
     * chaining in this KDF. Note that we have to make it large enough to
882
     * fit the output of the PRF, but we can delay its actual creation until
883
     * the first PRF invocation. Until then, point to the IV value. */
884
0
    unsigned char *chaining_value = (unsigned char *)initial_value;
885
886
    /* Size of the chaining value discussed above. Defaults to the size of
887
     * the IV value. */
888
0
    size_t chaining_length = initial_value_length;
889
890
    /* Calculate the number of iterations required based on the size of the
891
     * output buffer. */
892
0
    ret = kbkdf_CalculateIterations(CKM_SP800_108_FEEDBACK_KDF, params, ctx, buffer_length, &num_iterations);
893
0
    if (ret != CKR_OK) {
894
0
        goto finish;
895
0
    }
896
897
    /*
898
     * 5.2 - [ KDF in Feedback Mode ]
899
     *
900
     * Fixed values:
901
     *      1. h - the length of the PRF in bits (ctx->mac_size)
902
     *      2. r - the length of the binary representation of the counter i
903
     *          (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits)
904
     *          Note that it is only specified when the optional counter is requested.
905
     * Input:
906
     *      1. K_I - the key for the PRF (base_key)
907
     *      2. label - a binary data field, usually before the separator. Optional.
908
     *      3. context - a binary data field, usually after the separator. Optional.
909
     *      4. IV - a binary data field, initial PRF value. (params->pIV)
910
     *      5. L - length of the output in bits (output_bitlen)
911
     *
912
     * Process:
913
     *      1. n := ceil(L / h) (num_iterations)
914
     *      2. if n > 2^32 - 1, then indicate an error and stop
915
     *      3. result(0) = NULL, K(0) := IV (chaining_value)
916
     *      4. for i = 1 to n, do
917
     *          a. K(i) = PRF(K_I, K(i-1) {|| [i]_2} || Label || 0x00 || Context || [L]_2)
918
     *          b. result(i) := result(i - 1) || K(i).
919
     *      5. return K_O := the leftmost L bits of result(n).
920
     */
921
0
    for (counter = 1; counter <= num_iterations; counter++) {
922
0
        if (counter == num_iterations) {
923
0
            block_size = buffer_length - buffer_offset;
924
925
            /* Assumption: if we've validated our arguments correctly, this
926
             * should always be true. */
927
0
            PR_ASSERT(block_size <= ctx->mac_size);
928
0
        }
929
930
        /* Add all parameters required by this instance of the KDF to the
931
         * input stream of the underlying PRF. */
932
0
        ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */);
933
0
        if (ret != CKR_OK) {
934
0
            goto finish;
935
0
        }
936
937
0
        if (counter == 1) {
938
            /* On the first iteration, chaining_value points to the IV from
939
             * the caller and chaining_length is the length of that IV. We
940
             * now need to allocate a buffer of suitable length to store the
941
             * MAC output. */
942
0
            chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size);
943
0
            chaining_length = ctx->mac_size;
944
945
0
            if (chaining_value == NULL) {
946
0
                ret = CKR_HOST_MEMORY;
947
0
                goto finish;
948
0
            }
949
0
        }
950
951
        /* Finalize this iteration of the PRF. Unlike other KDF forms, we
952
         * first save this to the chaining value so that we can reuse it
953
         * in the next iteration before copying the necessary length to
954
         * the output buffer. */
955
0
        ret = sftk_MAC_End(ctx, chaining_value, NULL, chaining_length);
956
0
        if (ret != CKR_OK) {
957
0
            goto finish;
958
0
        }
959
960
        /* Save as much of the chaining value as we need for output. */
961
0
        PORT_Memcpy(ret_buffer + buffer_offset, chaining_value, block_size);
962
963
        /* Increment our position in the key material. */
964
0
        buffer_offset += block_size;
965
966
0
        if (counter < num_iterations) {
967
            /* Reset the underlying PRF for the next iteration. Only do this
968
             * when we have a next iteration since it isn't necessary to do
969
             * either before the first iteration (MAC is already initialized)
970
             * or after the last iteration (we won't be called again). */
971
0
            ret = sftk_MAC_Reset(ctx);
972
0
            if (ret != CKR_OK) {
973
0
                goto finish;
974
0
            }
975
0
        }
976
0
    }
977
978
0
finish:
979
0
    if (chaining_value != initial_value && chaining_value != NULL) {
980
0
        PORT_ZFree(chaining_value, chaining_length);
981
0
    }
982
983
0
    return ret;
984
0
}
985
986
static CK_RV
987
kbkdf_PipelineRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
988
0
{
989
0
    CK_RV ret = CKR_OK;
990
991
    /* Counter variable for this KDF instance. */
992
0
    PRUint32 counter;
993
994
    /* Number of iterations required of this PRF necessary to reach the
995
     * desired output length. */
996
0
    PRUint32 num_iterations;
997
998
    /* Offset in ret_buffer that we're at. */
999
0
    size_t buffer_offset = 0;
1000
1001
    /* Size of this block, in bytes. Defaults to ctx->mac_size except on
1002
     * the last iteration where it could be a partial block. */
1003
0
    size_t block_size = ctx->mac_size;
1004
1005
    /* The last PRF invocation. This is used for the first of the double
1006
     * PRF invocations this KDF is named after. This defaults to NULL,
1007
     * signifying that we have to calculate the initial value from params;
1008
     * when non-NULL, we directly add only this value to the PRF. */
1009
0
    unsigned char *chaining_value = NULL;
1010
1011
    /* Size of the chaining value discussed above. Defaults to 0. */
1012
0
    size_t chaining_length = 0;
1013
1014
    /* Calculate the number of iterations required based on the size of the
1015
     * output buffer. */
1016
0
    ret = kbkdf_CalculateIterations(CKM_SP800_108_DOUBLE_PIPELINE_KDF, params, ctx, buffer_length, &num_iterations);
1017
0
    if (ret != CKR_OK) {
1018
0
        goto finish;
1019
0
    }
1020
1021
    /*
1022
     * 5.3 - [ KDF in Double-Pipeline Iteration Mode ]
1023
     *
1024
     * Fixed values:
1025
     *      1. h - the length of the PRF in bits (ctx->mac_size)
1026
     *      2. r - the length of the binary representation of the counter i
1027
     *          (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits)
1028
     *          Note that it is only specified when the optional counter is requested.
1029
     * Input:
1030
     *      1. K_I - the key for the PRF (base_key)
1031
     *      2. label - a binary data field, usually before the separator. Optional.
1032
     *      3. context - a binary data field, usually after the separator. Optional.
1033
     *      4. L - length of the output in bits (output_bitlen)
1034
     *
1035
     * Process:
1036
     *      1. n := ceil(L / h) (num_iterations)
1037
     *      2. if n > 2^32 - 1, then indicate an error and stop
1038
     *      3. result(0) = NULL
1039
     *      4. A(0) := IV := Label || 0x00 || Context || [L]_2
1040
     *      5. for i = 1 to n, do
1041
     *          a. A(i) := PRF(K_I, A(i-1))
1042
     *          b. K(i) := PRF(K_I, A(i) {|| [i]_2} || Label || 0x00 || Context || [L]_2
1043
     *          c. result(i) := result(i-1) || K(i)
1044
     *      6. return K_O := the leftmost L bits of result(n).
1045
     */
1046
0
    for (counter = 1; counter <= num_iterations; counter++) {
1047
0
        if (counter == num_iterations) {
1048
0
            block_size = buffer_length - buffer_offset;
1049
1050
            /* Assumption: if we've validated our arguments correctly, this
1051
             * should always be true. */
1052
0
            PR_ASSERT(block_size <= ctx->mac_size);
1053
0
        }
1054
1055
        /* ===== First pipeline: construct A(i) ===== */
1056
0
        if (counter == 1) {
1057
            /* On the first iteration, we have no chaining value so specify
1058
             * NULL for the pointer and 0 for the length, and exclude the
1059
             * optional counter if it exists. This is what NIST specifies as
1060
             * the IV for the KDF. */
1061
0
            ret = kbkdf_AddParameters(CKM_SP800_108_DOUBLE_PIPELINE_KDF, ctx, params, counter, output_bitlen, NULL, 0, CK_SP800_108_OPTIONAL_COUNTER);
1062
0
            if (ret != CKR_OK) {
1063
0
                goto finish;
1064
0
            }
1065
1066
            /* Allocate the chaining value so we can save the PRF output. */
1067
0
            chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size);
1068
0
            chaining_length = ctx->mac_size;
1069
0
            if (chaining_value == NULL) {
1070
0
                ret = CKR_HOST_MEMORY;
1071
0
                goto finish;
1072
0
            }
1073
0
        } else {
1074
            /* On all other iterations, the next stage of the first pipeline
1075
             * comes directly from this stage. */
1076
0
            ret = sftk_MAC_Update(ctx, chaining_value, chaining_length);
1077
0
            if (ret != CKR_OK) {
1078
0
                goto finish;
1079
0
            }
1080
0
        }
1081
1082
        /* Save the PRF output to chaining_value for use in the second
1083
         * pipeline. */
1084
0
        ret = sftk_MAC_End(ctx, chaining_value, NULL, chaining_length);
1085
0
        if (ret != CKR_OK) {
1086
0
            goto finish;
1087
0
        }
1088
1089
        /* Reset the PRF so we can reuse it for the second pipeline. */
1090
0
        ret = sftk_MAC_Reset(ctx);
1091
0
        if (ret != CKR_OK) {
1092
0
            goto finish;
1093
0
        }
1094
1095
        /* ===== Second pipeline: construct K(i) ===== */
1096
1097
        /* Add all parameters required by this instance of the KDF to the
1098
         * input stream of the underlying PRF. Note that this includes the
1099
         * chaining value we calculated from the previous pipeline stage. */
1100
0
        ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */);
1101
0
        if (ret != CKR_OK) {
1102
0
            goto finish;
1103
0
        }
1104
1105
        /* Finalize this iteration of the PRF directly to the output buffer.
1106
         * Unlike Feedback mode, this pipeline doesn't influence the previous
1107
         * stage. */
1108
0
        ret = sftk_MAC_End(ctx, ret_buffer + buffer_offset, NULL, block_size);
1109
0
        if (ret != CKR_OK) {
1110
0
            goto finish;
1111
0
        }
1112
1113
        /* Increment our position in the key material. */
1114
0
        buffer_offset += block_size;
1115
1116
0
        if (counter < num_iterations) {
1117
            /* Reset the underlying PRF for the next iteration. Only do this
1118
             * when we have a next iteration since it isn't necessary to do
1119
             * either before the first iteration (MAC is already initialized)
1120
             * or after the last iteration (we won't be called again). */
1121
0
            ret = sftk_MAC_Reset(ctx);
1122
0
            if (ret != CKR_OK) {
1123
0
                goto finish;
1124
0
            }
1125
0
        }
1126
0
    }
1127
1128
0
finish:
1129
0
    PORT_ZFree(chaining_value, chaining_length);
1130
1131
0
    return ret;
1132
0
}
1133
1134
static CK_RV
1135
kbkdf_RawDispatch(CK_MECHANISM_TYPE mech,
1136
                  const CK_SP800_108_KDF_PARAMS *kdf_params,
1137
                  const CK_BYTE *initial_value,
1138
                  CK_ULONG initial_value_length,
1139
                  SFTKObject *prf_key, const unsigned char *prf_key_bytes,
1140
                  unsigned int prf_key_length, unsigned char **out_key_bytes,
1141
                  size_t *out_key_length, unsigned int *mac_size,
1142
                  CK_ULONG ret_key_size)
1143
0
{
1144
0
    CK_RV ret;
1145
    /* Context for our underlying PRF function.
1146
     *
1147
     * Zeroing context required unconditional call of sftk_MAC_DestroyContext.
1148
     */
1149
0
    sftk_MACCtx ctx = { 0 };
1150
1151
    /* We need one buffers large enough to fit the entire KDF key stream for
1152
     * all iterations of the PRF. This needs only include to the end of the
1153
     * last key, so it isn't an even multiple of the PRF output size. */
1154
0
    unsigned char *output_buffer = NULL;
1155
1156
    /* Size of the above buffer, in bytes. Note that this is technically
1157
     * separate from the below output_bitlen variable due to the presence
1158
     * of additional derived keys. See commentary in kbkdf_CalculateLength.
1159
     */
1160
0
    size_t buffer_length = 0;
1161
1162
    /* While NIST specifies a maximum length (in bits) for the counter, they
1163
     * don't for the maximum length. It is unlikely, but theoretically
1164
     * possible for output of the PRF to exceed 32 bits while keeping the
1165
     * counter under 2^32. Thus, use a 64-bit variable for the maximum
1166
     * output length.
1167
     *
1168
     * It is unlikely any caller will request this much data in practice.
1169
     * 2^32 invocations of the PRF (for a 512-bit PRF) would be 256GB of
1170
     * data in the KDF key stream alone. The bigger limit is the number of
1171
     * and size of keys (again, 2^32); this could easily exceed 256GB when
1172
     * counting the backing softoken key, the key data, template data, and
1173
     * the input parameters to this KDF.
1174
     *
1175
     * This is the L parameter in NIST SP800-108.
1176
     */
1177
0
    PRUint64 output_bitlen = 0;
1178
1179
    /* First validate our passed input parameters against PKCS#11 v3.0
1180
     * and NIST SP800-108 requirements. */
1181
0
    ret = kbkdf_ValidateParameters(mech, kdf_params, ret_key_size);
1182
0
    if (ret != CKR_OK) {
1183
0
        goto finish;
1184
0
    }
1185
1186
    /* Initialize the underlying PRF state. */
1187
0
    if (prf_key) {
1188
0
        ret = sftk_MAC_Init(&ctx, kdf_params->prfType, prf_key);
1189
0
    } else {
1190
0
        ret = sftk_MAC_InitRaw(&ctx, kdf_params->prfType, prf_key_bytes,
1191
0
                               prf_key_length, PR_TRUE);
1192
0
    }
1193
0
    if (ret != CKR_OK) {
1194
0
        goto finish;
1195
0
    }
1196
1197
    /* Compute the size of our output buffer based on passed parameters and
1198
     * the output size of the underlying PRF. */
1199
0
    ret = kbkdf_CalculateLength(kdf_params, &ctx, ret_key_size, &output_bitlen, &buffer_length);
1200
0
    if (ret != CKR_OK) {
1201
0
        goto finish;
1202
0
    }
1203
1204
    /* Allocate memory for the PRF output */
1205
0
    output_buffer = PORT_ZNewArray(unsigned char, buffer_length);
1206
0
    if (output_buffer == NULL) {
1207
0
        ret = CKR_HOST_MEMORY;
1208
0
        goto finish;
1209
0
    }
1210
1211
    /* Call into the underlying KDF */
1212
0
    switch (mech) {
1213
0
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
1214
0
        case CKM_SP800_108_COUNTER_KDF:
1215
0
            ret = kbkdf_CounterRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen);
1216
0
            break;
1217
0
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
1218
0
        case CKM_SP800_108_FEEDBACK_KDF:
1219
0
            ret = kbkdf_FeedbackRaw(kdf_params, initial_value, initial_value_length, &ctx, output_buffer, buffer_length, output_bitlen);
1220
0
            break;
1221
0
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
1222
0
        case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
1223
0
            ret = kbkdf_PipelineRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen);
1224
0
            break;
1225
0
        default:
1226
            /* Shouldn't happen unless NIST introduces a new KBKDF type. */
1227
0
            PR_ASSERT(PR_FALSE);
1228
0
            ret = CKR_FUNCTION_FAILED;
1229
0
    }
1230
1231
    /* Validate the above KDF succeeded. */
1232
0
    if (ret != CKR_OK) {
1233
0
        goto finish;
1234
0
    }
1235
1236
0
    *out_key_bytes = output_buffer;
1237
0
    *out_key_length = buffer_length;
1238
0
    *mac_size = ctx.mac_size;
1239
1240
0
    output_buffer = NULL; /* returning the buffer, don't zero and free it */
1241
1242
0
finish:
1243
0
    PORT_ZFree(output_buffer, buffer_length);
1244
1245
    /* Free the PRF. This should handle clearing all sensitive information. */
1246
0
    sftk_MAC_DestroyContext(&ctx, PR_FALSE);
1247
0
    return ret;
1248
0
}
1249
1250
/* [ section: PKCS#11 entry ] */
1251
1252
CK_RV
1253
kbkdf_Dispatch(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, SFTKObject *prf_key, SFTKObject *ret_key, CK_ULONG ret_key_size)
1254
0
{
1255
    /* This handles boilerplate common to all KBKDF types. Instead of placing
1256
     * this in pkcs11c.c, place it here to reduce clutter. */
1257
1258
0
    CK_RV ret;
1259
1260
    /* Assumptions about our calling environment. */
1261
0
    PR_ASSERT(pMechanism != NULL && prf_key != NULL && ret_key != NULL);
1262
1263
    /* Validate that the caller passed parameters. */
1264
0
    if (pMechanism->pParameter == NULL) {
1265
0
        return CKR_MECHANISM_PARAM_INVALID;
1266
0
    }
1267
1268
    /* Create a common set of parameters to use for all KDF types. This
1269
     * separates out the KDF parameters from the Feedback-specific IV,
1270
     * allowing us to use a common type for all calls. */
1271
0
    CK_SP800_108_KDF_PARAMS kdf_params = { 0 };
1272
0
    CK_BYTE_PTR initial_value = NULL;
1273
0
    CK_ULONG initial_value_length = 0;
1274
0
    unsigned char *output_buffer = NULL;
1275
0
    size_t buffer_length = 0;
1276
0
    unsigned int mac_size = 0;
1277
1278
    /* Split Feedback-specific IV from remaining KDF parameters. */
1279
0
    ret = kbkdf_LoadParameters(mech, pMechanism, &kdf_params, &initial_value, &initial_value_length);
1280
0
    if (ret != CKR_OK) {
1281
0
        goto finish;
1282
0
    }
1283
    /* let rawDispatch handle the rest. We split this out so we could
1284
     * handle the POST test without accessing pkcs #11 objects. */
1285
0
    ret = kbkdf_RawDispatch(mech, &kdf_params, initial_value,
1286
0
                            initial_value_length, prf_key, NULL, 0,
1287
0
                            &output_buffer, &buffer_length, &mac_size,
1288
0
                            ret_key_size);
1289
0
    if (ret != CKR_OK) {
1290
0
        goto finish;
1291
0
    }
1292
1293
    /* Write the output of the PRF into the appropriate keys. */
1294
0
    ret = kbkdf_SaveKeys(mech, hSession, &kdf_params, output_buffer, buffer_length, mac_size, ret_key, ret_key_size);
1295
0
    if (ret != CKR_OK) {
1296
0
        goto finish;
1297
0
    }
1298
1299
0
finish:
1300
0
    PORT_ZFree(output_buffer, buffer_length);
1301
1302
0
    return ret;
1303
0
}
1304
1305
struct sftk_SP800_Test_struct {
1306
    CK_MECHANISM_TYPE mech;
1307
    CK_SP800_108_KDF_PARAMS kdf_params;
1308
    unsigned int expected_mac_size;
1309
    unsigned int ret_key_length;
1310
    const unsigned char expected_key_bytes[64];
1311
};
1312
1313
static const CK_SP800_108_COUNTER_FORMAT counter_32 = { 0, 32 };
1314
static const CK_PRF_DATA_PARAM counter_32_data = { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_32, sizeof(counter_32) };
1315
1316
#ifdef NSS_FULL_POST
1317
static const CK_SP800_108_COUNTER_FORMAT counter_16 = { 0, 16 };
1318
static const CK_PRF_DATA_PARAM counter_16_data = { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_16, sizeof(counter_16) };
1319
static const CK_PRF_DATA_PARAM counter_null_data = { CK_SP800_108_ITERATION_VARIABLE, NULL, 0 };
1320
#endif
1321
1322
static const struct sftk_SP800_Test_struct sftk_SP800_Tests[] = {
1323
#ifdef NSS_FULL_POST
1324
    {
1325
        CKM_SP800_108_COUNTER_KDF,
1326
        { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_16_data, 0, NULL },
1327
        16,
1328
        64,
1329
        { 0x7b, 0x1c, 0xe7, 0xf3, 0x14, 0x67, 0x15, 0xdd,
1330
          0xde, 0x0c, 0x09, 0x46, 0x3f, 0x47, 0x7b, 0xa6,
1331
          0xb8, 0xba, 0x40, 0x07, 0x7c, 0xe3, 0x19, 0x53,
1332
          0x26, 0xac, 0x4c, 0x2e, 0x2b, 0x37, 0x41, 0xe4,
1333
          0x1b, 0x01, 0x3f, 0x2f, 0x2d, 0x16, 0x95, 0xee,
1334
          0xeb, 0x7e, 0x72, 0x7d, 0xa4, 0xab, 0x2e, 0x67,
1335
          0x1d, 0xef, 0x6f, 0xa2, 0xc6, 0xee, 0x3c, 0xcf,
1336
          0xef, 0x88, 0xfd, 0x5c, 0x1d, 0x7b, 0xa0, 0x5a },
1337
    },
1338
    {
1339
        CKM_SP800_108_COUNTER_KDF,
1340
        { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
1341
        48,
1342
        64,
1343
        { 0xe6, 0x62, 0xa4, 0x32, 0x5c, 0xe4, 0xc2, 0x28,
1344
          0x73, 0x8a, 0x5d, 0x94, 0xe7, 0x05, 0xe0, 0x5a,
1345
          0x71, 0x61, 0xb2, 0x3c, 0x51, 0x28, 0x03, 0x1d,
1346
          0xa7, 0xf5, 0x10, 0x83, 0x34, 0xdb, 0x11, 0x73,
1347
          0x92, 0xa6, 0x79, 0x74, 0x81, 0x5d, 0x22, 0x7e,
1348
          0x8d, 0xf2, 0x59, 0x14, 0x56, 0x60, 0xcf, 0xb2,
1349
          0xb3, 0xfd, 0x46, 0xfd, 0x9b, 0x74, 0xfe, 0x4a,
1350
          0x09, 0x30, 0x4a, 0xdf, 0x07, 0x43, 0xfe, 0x85 },
1351
    },
1352
    {
1353
        CKM_SP800_108_COUNTER_KDF,
1354
        { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
1355
        64,
1356
        64,
1357
        { 0xb0, 0x78, 0x36, 0xe1, 0x15, 0xd6, 0xf0, 0xac,
1358
          0x68, 0x7b, 0x42, 0xd3, 0xb6, 0x82, 0x51, 0xad,
1359
          0x95, 0x0a, 0x69, 0x88, 0x84, 0xc2, 0x2e, 0x07,
1360
          0x34, 0x62, 0x8d, 0x42, 0x72, 0x0f, 0x22, 0xe6,
1361
          0xd5, 0x7f, 0x80, 0x15, 0xe6, 0x84, 0x00, 0x65,
1362
          0xef, 0x64, 0x77, 0x29, 0xd6, 0x3b, 0xc7, 0x9a,
1363
          0x15, 0x6d, 0x36, 0xf3, 0x96, 0xc9, 0x14, 0x3f,
1364
          0x2d, 0x4a, 0x7c, 0xdb, 0xc3, 0x6c, 0x3d, 0x6a },
1365
    },
1366
    {
1367
        CKM_SP800_108_FEEDBACK_KDF,
1368
        { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1369
        16,
1370
        64,
1371
        { 0xc0, 0xa0, 0x23, 0x96, 0x16, 0x4d, 0xd6, 0xbd,
1372
          0x2a, 0x75, 0x8e, 0x72, 0xf5, 0xc3, 0xa0, 0xb8,
1373
          0x78, 0x83, 0x15, 0x21, 0x34, 0xd3, 0xd8, 0x71,
1374
          0xc9, 0xe7, 0x4b, 0x20, 0xb7, 0x65, 0x5b, 0x13,
1375
          0xbc, 0x85, 0x54, 0xe3, 0xb6, 0xee, 0x73, 0xd5,
1376
          0xf2, 0xa0, 0x94, 0x1a, 0x79, 0x66, 0x3b, 0x1e,
1377
          0x67, 0x3e, 0x69, 0xa4, 0x12, 0x40, 0xa9, 0xda,
1378
          0x8d, 0x14, 0xb1, 0xce, 0xf1, 0x4b, 0x79, 0x4e },
1379
    },
1380
    {
1381
        CKM_SP800_108_FEEDBACK_KDF,
1382
        { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1383
        32,
1384
        64,
1385
        { 0x99, 0x9b, 0x08, 0x79, 0x14, 0x2e, 0x58, 0x34,
1386
          0xd7, 0x92, 0xa7, 0x7e, 0x7f, 0xc2, 0xf0, 0x34,
1387
          0xa3, 0x4e, 0x33, 0xf0, 0x63, 0x95, 0x2d, 0xad,
1388
          0xbf, 0x3b, 0xcb, 0x6d, 0x4e, 0x07, 0xd9, 0xe9,
1389
          0xbd, 0xbd, 0x77, 0x54, 0xe1, 0xa3, 0x36, 0x26,
1390
          0xcd, 0xb1, 0xf9, 0x2d, 0x80, 0x68, 0xa2, 0x01,
1391
          0x4e, 0xbf, 0x35, 0xec, 0x65, 0xae, 0xfd, 0x71,
1392
          0xa6, 0xd7, 0x62, 0x26, 0x2c, 0x3f, 0x73, 0x63 },
1393
    },
1394
    {
1395
        CKM_SP800_108_FEEDBACK_KDF,
1396
        { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1397
        48,
1398
        64,
1399
        { 0xc8, 0x7a, 0xf8, 0xd9, 0x6b, 0x90, 0x82, 0x35,
1400
          0xea, 0xf5, 0x2c, 0x8f, 0xce, 0xaa, 0x3b, 0xa5,
1401
          0x68, 0xd3, 0x7f, 0xae, 0x31, 0x93, 0xe6, 0x69,
1402
          0x0c, 0xd1, 0x74, 0x7f, 0x8f, 0xc2, 0xe2, 0x33,
1403
          0x93, 0x45, 0x23, 0xba, 0xb3, 0x73, 0xc9, 0x2c,
1404
          0xd6, 0xd2, 0x10, 0x16, 0xe9, 0x9f, 0x9e, 0xe8,
1405
          0xc1, 0x0e, 0x29, 0x95, 0x3d, 0x16, 0x68, 0x24,
1406
          0x40, 0x4d, 0x40, 0x21, 0x41, 0xa6, 0xc8, 0xdb },
1407
    },
1408
    {
1409
        CKM_SP800_108_FEEDBACK_KDF,
1410
        { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1411
        64,
1412
        64,
1413
        { 0x81, 0x39, 0x12, 0xc2, 0xf9, 0x31, 0x24, 0x7c,
1414
          0x71, 0x12, 0x97, 0x08, 0x82, 0x76, 0x83, 0x55,
1415
          0x8c, 0x82, 0xf3, 0x09, 0xd6, 0x1b, 0x7a, 0xa2,
1416
          0x6e, 0x71, 0x6b, 0xad, 0x46, 0x57, 0x60, 0x89,
1417
          0x38, 0xcf, 0x63, 0xfa, 0xf4, 0x38, 0x27, 0xef,
1418
          0xf0, 0xaf, 0x75, 0x4e, 0xc2, 0xe0, 0x31, 0xdb,
1419
          0x59, 0x7d, 0x19, 0xc9, 0x6d, 0xbb, 0xed, 0x95,
1420
          0xaf, 0x3e, 0xd8, 0x33, 0x76, 0xab, 0xec, 0xfa },
1421
    },
1422
    {
1423
        CKM_SP800_108_DOUBLE_PIPELINE_KDF,
1424
        { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1425
        16,
1426
        64,
1427
        { 0x3e, 0xa8, 0xbf, 0x77, 0x84, 0x90, 0xb0, 0x3a,
1428
          0x89, 0x16, 0x32, 0x01, 0x92, 0xd3, 0x1f, 0x1b,
1429
          0xc1, 0x06, 0xc5, 0x32, 0x62, 0x03, 0x50, 0x16,
1430
          0x3b, 0xb9, 0xa7, 0xdc, 0xb5, 0x68, 0x6a, 0xbb,
1431
          0xbb, 0x7d, 0x63, 0x69, 0x24, 0x6e, 0x09, 0xd6,
1432
          0x6f, 0x80, 0x57, 0x65, 0xc5, 0x62, 0x33, 0x96,
1433
          0x69, 0xe6, 0xab, 0x65, 0x36, 0xd0, 0xe2, 0x5c,
1434
          0xd7, 0xbd, 0xe4, 0x68, 0x13, 0xd6, 0xb1, 0x46 },
1435
    },
1436
    {
1437
        CKM_SP800_108_DOUBLE_PIPELINE_KDF,
1438
        { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1439
        32,
1440
        64,
1441
        { 0xeb, 0x28, 0xd9, 0x2c, 0x19, 0x33, 0xb9, 0x2a,
1442
          0xf9, 0xac, 0x85, 0xbd, 0xf4, 0xdb, 0xfa, 0x88,
1443
          0x73, 0xf4, 0x36, 0x08, 0xdb, 0xfe, 0x13, 0xd1,
1444
          0x5a, 0xec, 0x7b, 0x68, 0x13, 0x53, 0xb3, 0xd1,
1445
          0x31, 0xf2, 0x83, 0xae, 0x9f, 0x75, 0x47, 0xb6,
1446
          0x6d, 0x3c, 0x20, 0x16, 0x47, 0x9c, 0x27, 0x66,
1447
          0xec, 0xa9, 0xdf, 0x0c, 0xda, 0x2a, 0xf9, 0xf4,
1448
          0x55, 0x74, 0xde, 0x9d, 0x3f, 0xe3, 0x5e, 0x14 },
1449
    },
1450
    {
1451
        CKM_SP800_108_DOUBLE_PIPELINE_KDF,
1452
        { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1453
        48,
1454
        64,
1455
        { 0xa5, 0xca, 0x32, 0x40, 0x00, 0x93, 0xb2, 0xcc,
1456
          0x78, 0x3c, 0xa6, 0xc4, 0xaf, 0xa8, 0xb3, 0xd0,
1457
          0xa4, 0x6b, 0xb5, 0x31, 0x35, 0x87, 0x33, 0xa2,
1458
          0x6a, 0x6b, 0xe1, 0xff, 0xea, 0x1d, 0x6e, 0x9e,
1459
          0x0b, 0xde, 0x8b, 0x92, 0x15, 0xd6, 0x56, 0x2f,
1460
          0xb6, 0x1a, 0xd7, 0xd2, 0x01, 0x3e, 0x28, 0x2e,
1461
          0xfa, 0x84, 0x3c, 0xc0, 0xe8, 0xbe, 0x94, 0xc0,
1462
          0x06, 0xbd, 0xbf, 0x87, 0x1f, 0xb8, 0x64, 0xc2 },
1463
    },
1464
    {
1465
        CKM_SP800_108_DOUBLE_PIPELINE_KDF,
1466
        { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
1467
        64,
1468
        64,
1469
        { 0x3f, 0xd9, 0x4e, 0x80, 0x58, 0x21, 0xc8, 0xea,
1470
          0x22, 0x17, 0xcf, 0x7d, 0xce, 0xfd, 0xec, 0x03,
1471
          0xb9, 0xe4, 0xa2, 0xf7, 0xc0, 0xf1, 0x68, 0x81,
1472
          0x53, 0x71, 0xb7, 0x42, 0x14, 0x4e, 0x5b, 0x09,
1473
          0x05, 0x31, 0xb9, 0x27, 0x18, 0x2d, 0x23, 0xf8,
1474
          0x9c, 0x3d, 0x4e, 0xd0, 0xdd, 0xf3, 0x1e, 0x4b,
1475
          0xf2, 0xf9, 0x1a, 0x5d, 0x00, 0x66, 0x22, 0x83,
1476
          0xae, 0x3c, 0x53, 0xd2, 0x54, 0x4b, 0x06, 0x4c },
1477
    },
1478
#endif
1479
    {
1480
        CKM_SP800_108_COUNTER_KDF,
1481
        { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
1482
        32,
1483
        64,
1484
        { 0xfb, 0x2b, 0xb5, 0xde, 0xce, 0x5a, 0x2b, 0xdc,
1485
          0x25, 0x8f, 0x54, 0x17, 0x4b, 0x5a, 0xa7, 0x90,
1486
          0x64, 0x36, 0xeb, 0x43, 0x1f, 0x1d, 0xf9, 0x23,
1487
          0xb2, 0x22, 0x29, 0xa0, 0xfa, 0x2e, 0x21, 0xb6,
1488
          0xb7, 0xfb, 0x27, 0x0a, 0x1c, 0xa6, 0x58, 0x43,
1489
          0xa1, 0x16, 0x44, 0x29, 0x4b, 0x1c, 0xb3, 0x72,
1490
          0xd5, 0x98, 0x9d, 0x27, 0xd5, 0x75, 0x25, 0xbf,
1491
          0x23, 0x61, 0x40, 0x48, 0xbb, 0x0b, 0x49, 0x8e },
1492
    }
1493
};
1494
1495
SECStatus
1496
sftk_fips_SP800_108_PowerUpSelfTests(void)
1497
0
{
1498
0
    int i;
1499
0
    CK_RV crv;
1500
1501
0
    const unsigned char prf_key[] = {
1502
0
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1503
0
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
1504
0
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
1505
0
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1506
0
        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
1507
0
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
1508
0
        0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
1509
0
        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78
1510
0
    };
1511
0
    for (i = 0; i < PR_ARRAY_SIZE(sftk_SP800_Tests); i++) {
1512
0
        const struct sftk_SP800_Test_struct *test = &sftk_SP800_Tests[i];
1513
0
        unsigned char *output_buffer;
1514
0
        size_t buffer_length;
1515
0
        unsigned int mac_size;
1516
1517
0
        crv = kbkdf_RawDispatch(test->mech, &test->kdf_params,
1518
0
                                prf_key, test->expected_mac_size,
1519
0
                                NULL, prf_key, test->expected_mac_size,
1520
0
                                &output_buffer, &buffer_length, &mac_size,
1521
0
                                test->ret_key_length);
1522
0
        if (crv != CKR_OK) {
1523
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1524
0
            return SECFailure;
1525
0
        }
1526
0
        if ((mac_size != test->expected_mac_size) ||
1527
0
            (buffer_length != test->ret_key_length) ||
1528
0
            (output_buffer == NULL) ||
1529
0
            (PORT_Memcmp(output_buffer, test->expected_key_bytes, buffer_length) != 0)) {
1530
0
            PORT_ZFree(output_buffer, buffer_length);
1531
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1532
0
            return SECFailure;
1533
0
        }
1534
0
        PORT_ZFree(output_buffer, buffer_length);
1535
0
    }
1536
0
    return SECSuccess;
1537
0
}