Coverage Report

Created: 2024-05-20 06:23

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