Bug Summary

File:root/firefox-clang/security/nss/lib/softoken/sftkike.c
Warning:line 1205, column 9
The first element of the 2nd argument is undefined
Note:line 1205, column 9
Other elements might also be undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name sftkike.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D SOFTOKEN_LIB_NAME="libsoftokn3.so" -D SHLIB_VERSION="3" -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/lib/softoken -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/security/nss/lib/softoken/sftkike.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4/*
5 * This file implements PKCS 11 on top of our existing security modules
6 *
7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8 * This implementation has two slots:
9 * slot 1 is our generic crypto support. It does not require login.
10 * It supports Public Key ops, and all they bulk ciphers and hashes.
11 * It can also support Private Key ops for imported Private keys. It does
12 * not have any token storage.
13 * slot 2 is our private key support. It requires a login before use. It
14 * can store Private Keys and Certs as token objects. Currently only private
15 * keys and their associated Certificates are saved on the token.
16 *
17 * In this implementation, session objects are only visible to the session
18 * that created or generated them.
19 */
20#include "seccomon.h"
21#include "secitem.h"
22#include "secport.h"
23#include "blapi.h"
24#include "pkcs11.h"
25#include "pkcs11i.h"
26#include "pkcs1sig.h"
27#include "lowkeyi.h"
28#include "secder.h"
29#include "secdig.h"
30#include "lowpbe.h" /* We do PBE below */
31#include "pkcs11t.h"
32#include "secoid.h"
33#include "alghmac.h"
34#include "softoken.h"
35#include "secasn1.h"
36#include "secerr.h"
37
38#include "prprf.h"
39#include "prenv.h"
40
41/*
42 * A common prfContext to handle both hmac and aes xcbc
43 * hash contexts have non-null hashObj and hmac, aes
44 * contexts have non-null aes */
45typedef struct prfContextStr {
46 HASH_HashType hashType;
47 const SECHashObject *hashObj;
48 HMACContext *hmac;
49 AESContext *aes;
50 unsigned int nextChar;
51 unsigned char padBuf[AES_BLOCK_SIZE16];
52 unsigned char macBuf[AES_BLOCK_SIZE16];
53 unsigned char k1[AES_BLOCK_SIZE16];
54 unsigned char k2[AES_BLOCK_SIZE16];
55 unsigned char k3[AES_BLOCK_SIZE16];
56} prfContext;
57
58/* iv full of zeros used in several places in aes xcbc */
59static const unsigned char iv_zero[] = {
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
62};
63
64/*
65 * Generate AES XCBC keys from the AES MAC key.
66 * k1 is used in the actual mac.
67 * k2 and k3 are used in the final pad step.
68 */
69static CK_RV
70sftk_aes_xcbc_get_keys(const unsigned char *keyValue, unsigned int keyLen,
71 unsigned char *k1, unsigned char *k2, unsigned char *k3)
72{
73 SECStatus rv;
74 CK_RV crv;
75 unsigned int tmpLen;
76 AESContext *aes_context = NULL((void*)0);
77 unsigned char newKey[AES_BLOCK_SIZE16];
78
79 /* AES XCBC keys. k1, k2, and k3 are derived by encrypting
80 * k1data, k2data, and k3data with the mac key.
81 */
82 static const unsigned char k1data[] = {
83 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
84 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
85 };
86 static const unsigned char k2data[] = {
87 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
88 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
89 };
90 static const unsigned char k3data[] = {
91 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
92 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
93 };
94
95 /* k1_0 = aes_ecb(0, k1data) */
96 static const unsigned char k1_0[] = {
97 0xe1, 0x4d, 0x5d, 0x0e, 0xe2, 0x77, 0x15, 0xdf,
98 0x08, 0xb4, 0x15, 0x2b, 0xa2, 0x3d, 0xa8, 0xe0
99
100 };
101 /* k2_0 = aes_ecb(0, k2data) */
102 static const unsigned char k2_0[] = {
103 0x5e, 0xba, 0x73, 0xf8, 0x91, 0x42, 0xc5, 0x48,
104 0x80, 0xf6, 0x85, 0x94, 0x37, 0x3c, 0x5c, 0x37
105 };
106 /* k3_0 = aes_ecb(0, k3data) */
107 static const unsigned char k3_0[] = {
108 0x8d, 0x34, 0xef, 0xcb, 0x3b, 0xd5, 0x45, 0xca,
109 0x06, 0x2a, 0xec, 0xdf, 0xef, 0x7c, 0x0b, 0xfa
110 };
111
112 /* first make sure out input key is the correct length
113 * rfc 4434. If key is shorter, pad with zeros to the
114 * the right. If key is longer newKey = aes_xcbc(0, key, keyLen).
115 */
116 if (keyLen < AES_BLOCK_SIZE16) {
117 PORT_Memcpymemcpy(newKey, keyValue, keyLen);
118 PORT_Memsetmemset(&newKey[keyLen], 0, AES_BLOCK_SIZE16 - keyLen);
119 keyValue = newKey;
120 } else if (keyLen > AES_BLOCK_SIZE16) {
121 /* calculate our new key = aes_xcbc(0, key, keyLen). Because the
122 * key above is fixed (0), we can precalculate k1, k2, and k3.
123 * if this code ever needs to be more generic (support any xcbc
124 * function rather than just aes, we would probably want to just
125 * recurse here using our prf functions. This would be safe because
126 * the recurse case would have keyLen == blocksize and thus skip
127 * this conditional.
128 */
129 aes_context = AES_CreateContext(k1_0, iv_zero, NSS_AES_CBC1,
130 PR_TRUE1, AES_BLOCK_SIZE16, AES_BLOCK_SIZE16);
131 /* we know the following loop will execute at least once */
132 while (keyLen > AES_BLOCK_SIZE16) {
133 rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE16,
134 keyValue, AES_BLOCK_SIZE16);
135 if (rv != SECSuccess) {
136 goto fail;
137 }
138 keyValue += AES_BLOCK_SIZE16;
139 keyLen -= AES_BLOCK_SIZE16;
140 }
141 PORT_Memcpymemcpy(newKey, keyValue, keyLen);
142 sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE16, k2_0, k3_0);
143 rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE16,
144 newKey, AES_BLOCK_SIZE16);
145 if (rv != SECSuccess) {
146 goto fail;
147 }
148 keyValue = newKey;
149 AES_DestroyContext(aes_context, PR_TRUE1);
150 }
151 /* the length of the key in keyValue is known to be AES_BLOCK_SIZE,
152 * either because it was on input, or it was shorter and extended, or
153 * because it was mac'd down using aes_xcbc_prf.
154 */
155 aes_context = AES_CreateContext(keyValue, iv_zero,
156 NSS_AES0, PR_TRUE1, AES_BLOCK_SIZE16, AES_BLOCK_SIZE16);
157 if (aes_context == NULL((void*)0)) {
158 goto fail;
159 }
160 rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE16,
161 k1data, sizeof(k1data));
162 if (rv != SECSuccess) {
163 goto fail;
164 }
165 rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE16,
166 k2data, sizeof(k2data));
167 if (rv != SECSuccess) {
168 goto fail;
169 }
170 rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE16,
171 k3data, sizeof(k3data));
172 if (rv != SECSuccess) {
173 goto fail;
174 }
175 AES_DestroyContext(aes_context, PR_TRUE1);
176 PORT_Memsetmemset(newKey, 0, AES_BLOCK_SIZE16);
177 return CKR_OK0x00000000UL;
178fail:
179 crv = sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
180 if (aes_context) {
181 AES_DestroyContext(aes_context, PR_TRUE1);
182 }
183 PORT_Memsetmemset(k1, 0, AES_BLOCK_SIZE16);
184 PORT_Memsetmemset(k2, 0, AES_BLOCK_SIZE16);
185 PORT_Memsetmemset(k3, 0, AES_BLOCK_SIZE16);
186 PORT_Memsetmemset(newKey, 0, AES_BLOCK_SIZE16);
187 return crv;
188}
189
190/* encode the final pad block of aes xcbc, padBuf is modified */
191CK_RV
192sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
193 unsigned int blockSize, const unsigned char *k2,
194 const unsigned char *k3)
195{
196 unsigned int i;
197 if (bufLen == blockSize) {
198 for (i = 0; i < blockSize; i++) {
199 padBuf[i] ^= k2[i];
200 }
201 } else {
202 padBuf[bufLen++] = 0x80;
203 for (i = bufLen; i < blockSize; i++) {
204 padBuf[i] = 0x00;
205 }
206 for (i = 0; i < blockSize; i++) {
207 padBuf[i] ^= k3[i];
208 }
209 }
210 return CKR_OK0x00000000UL;
211}
212
213/* Map the mechanism to the underlying hash. If the type is not a hash
214 * or HMAC, return HASH_AlgNULL. This can happen legitimately if
215 * we are doing AES XCBC */
216static HASH_HashType
217sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type)
218{
219 switch (type) {
220 case CKM_SHA_1_HMAC0x00000221UL:
221 case CKM_SHA_10x00000220UL:
222 return HASH_AlgSHA1;
223 case CKM_MD5_HMAC0x00000211UL:
224 case CKM_MD50x00000210UL:
225 return HASH_AlgMD5;
226 case CKM_MD2_HMAC0x00000201UL:
227 case CKM_MD20x00000200UL:
228 return HASH_AlgMD2;
229 case CKM_SHA224_HMAC0x00000256UL:
230 case CKM_SHA2240x00000255UL:
231 return HASH_AlgSHA224;
232 case CKM_SHA256_HMAC0x00000251UL:
233 case CKM_SHA2560x00000250UL:
234 return HASH_AlgSHA256;
235 case CKM_SHA384_HMAC0x00000261UL:
236 case CKM_SHA3840x00000260UL:
237 return HASH_AlgSHA384;
238 case CKM_SHA512_HMAC0x00000271UL:
239 case CKM_SHA5120x00000270UL:
240 return HASH_AlgSHA512;
241 }
242 return HASH_AlgNULL;
243}
244
245/*
246 * Generally setup the context based on the mechanism.
247 * If the mech is HMAC, context->hashObj should be set
248 * Otherwise it is assumed to be AES XCBC. prf_setup
249 * checks these assumptions and will return an error
250 * if they are not met. NOTE: this function does not allocate
251 * anything, so there is no requirement to free context after
252 * prf_setup like there is if you call prf_init.
253 */
254static CK_RV
255prf_setup(prfContext *context, CK_MECHANISM_TYPE mech)
256{
257 context->hashType = sftk_map_hmac_to_hash(mech);
258 context->hashObj = NULL((void*)0);
259 context->hmac = NULL((void*)0);
260 context->aes = NULL((void*)0);
261 if (context->hashType != HASH_AlgNULL) {
262 context->hashObj = HASH_GetRawHashObject(context->hashType);
263 if (context->hashObj == NULL((void*)0)) {
264 return CKR_GENERAL_ERROR0x00000005UL;
265 }
266 return CKR_OK0x00000000UL;
267 } else if (mech == CKM_AES_XCBC_MAC0x0000108CUL) {
268 return CKR_OK0x00000000UL;
269 }
270 return CKR_MECHANISM_PARAM_INVALID0x00000071UL;
271}
272
273/* return the underlying prf length for this context. This will
274 * function once the context is setup */
275static CK_RV
276prf_length(prfContext *context)
277{
278 if (context->hashObj) {
279 return context->hashObj->length;
280 }
281 return AES_BLOCK_SIZE16; /* AES */
282}
283
284/* set up the key for the prf. prf_update or prf_final should not be called if
285 * prf_init has not been called first. Once prf_init returns hmac and
286 * aes contexts should set and valid.
287 */
288static CK_RV
289prf_init(prfContext *context, const unsigned char *keyValue,
290 unsigned int keyLen)
291{
292 CK_RV crv;
293
294 context->hmac = NULL((void*)0);
295 if (context->hashObj) {
296 context->hmac = HMAC_Create(context->hashObj,
297 keyValue, keyLen, PR_FALSE0);
298 if (context->hmac == NULL((void*)0)) {
299 return sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
300 }
301 HMAC_Begin(context->hmac);
302 } else {
303 crv = sftk_aes_xcbc_get_keys(keyValue, keyLen, context->k1,
304 context->k2, context->k3);
305 if (crv != CKR_OK0x00000000UL)
306 return crv;
307 context->nextChar = 0;
308 context->aes = AES_CreateContext(context->k1, iv_zero, NSS_AES_CBC1,
309 PR_TRUE1, sizeof(context->k1), AES_BLOCK_SIZE16);
310 if (context->aes == NULL((void*)0)) {
311 crv = sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
312 PORT_Memsetmemset(context->k1, 0, sizeof(context->k1));
313 PORT_Memsetmemset(context->k2, 0, sizeof(context->k2));
314 PORT_Memsetmemset(context->k3, 0, sizeof(context->k2));
315 return crv;
316 }
317 }
318 return CKR_OK0x00000000UL;
319}
320
321/*
322 * process input to the prf
323 */
324static CK_RV
325prf_update(prfContext *context, const unsigned char *buf, unsigned int len)
326{
327 unsigned int tmpLen;
328 SECStatus rv;
329
330 if (context->hmac) {
331 HMAC_Update(context->hmac, buf, len);
332 } else {
333 /* AES MAC XCBC*/
334 /* We must keep the last block back so that it can be processed in
335 * final. This is why we only check that nextChar + len > blocksize,
336 * rather than checking that nextChar + len >= blocksize */
337 while (context->nextChar + len > AES_BLOCK_SIZE16) {
338 if (context->nextChar != 0) {
339 /* first handle fill in any partial blocks in the buffer */
340 unsigned int left = AES_BLOCK_SIZE16 - context->nextChar;
341 /* note: left can be zero */
342 PORT_Memcpymemcpy(context->padBuf + context->nextChar, buf, left);
343 /* NOTE: AES MAC XCBC xors the data with the previous block
344 * We don't do that step here because our AES_Encrypt mode
345 * is CBC, which does the xor automatically */
346 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
347 sizeof(context->macBuf), context->padBuf,
348 sizeof(context->padBuf));
349 if (rv != SECSuccess) {
350 return sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
351 }
352 context->nextChar = 0;
353 len -= left;
354 buf += left;
355 } else {
356 /* optimization. if we have complete blocks to write out
357 * (and will still have leftover blocks for padbuf in the end).
358 * we can mac directly out of our buffer without first copying
359 * them to padBuf */
360 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
361 sizeof(context->macBuf), buf, AES_BLOCK_SIZE16);
362 if (rv != SECSuccess) {
363 return sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
364 }
365 len -= AES_BLOCK_SIZE16;
366 buf += AES_BLOCK_SIZE16;
367 }
368 }
369 PORT_Memcpymemcpy(context->padBuf + context->nextChar, buf, len);
370 context->nextChar += len;
371 }
372 return CKR_OK0x00000000UL;
373}
374
375/*
376 * free the data associated with the prf. Clear any possible CSPs
377 * This can safely be called on any context after prf_setup. It can
378 * also be called an an already freed context.
379 * A free context can be reused by calling prf_init again without
380 * the need to call prf_setup.
381 */
382static void
383prf_free(prfContext *context)
384{
385 if (context->hmac) {
386 HMAC_Destroy(context->hmac, PR_TRUE1);
387 context->hmac = NULL((void*)0);
388 }
389 if (context->aes) {
390 PORT_Memsetmemset(context->k1, 0, sizeof(context->k1));
391 PORT_Memsetmemset(context->k2, 0, sizeof(context->k2));
392 PORT_Memsetmemset(context->k3, 0, sizeof(context->k2));
393 PORT_Memsetmemset(context->padBuf, 0, sizeof(context->padBuf));
394 PORT_Memsetmemset(context->macBuf, 0, sizeof(context->macBuf));
395 AES_DestroyContext(context->aes, PR_TRUE1);
396 context->aes = NULL((void*)0);
397 }
398}
399
400/*
401 * extract the final prf value. On success, this has the side effect of
402 * also freeing the context data and clearing the keys
403 */
404static CK_RV
405prf_final(prfContext *context, unsigned char *buf, unsigned int len)
406{
407 unsigned int tmpLen;
408 SECStatus rv;
409
410 if (context->hmac) {
8
Assuming field 'hmac' is null
9
Taking false branch
411 unsigned int outLen;
412 HMAC_Finish(context->hmac, buf, &outLen, len);
413 if (outLen != len) {
414 return CKR_GENERAL_ERROR0x00000005UL;
415 }
416 } else {
417 /* prf_update had guarrenteed that the last full block is still in
418 * the padBuf if the input data is a multiple of the blocksize. This
419 * allows sftk_xcbc_mac_pad to process that pad buf accordingly */
420 CK_RV crv = sftk_xcbc_mac_pad(context->padBuf, context->nextChar,
421 AES_BLOCK_SIZE16, context->k2, context->k3);
422 if (crv != CKR_OK0x00000000UL) {
10
Assuming 'crv' is equal to CKR_OK
11
Taking false branch
423 return crv;
424 }
425 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
426 sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE16);
427 if (rv != SECSuccess) {
12
Assuming 'rv' is not equal to SECSuccess
13
Taking true branch
428 return sftk_MapCryptError(PORT_GetErrorPORT_GetError_Util());
14
Returning without writing to '*buf'
429 }
430 PORT_Memcpymemcpy(buf, context->macBuf, len);
431 }
432 prf_free(context);
433 return CKR_OK0x00000000UL;
434}
435
436/*
437 * There are four flavors of ike prf functions here.
438 * ike_prf is used in both ikeV1 and ikeV2 to generate
439 * an initial key that all the other keys are generated with.
440 *
441 * These functions are called from NSC_DeriveKey with the inKey value
442 * already looked up, and it expects the CKA_VALUE for outKey to be set.
443 *
444 * Depending on usage it returns either:
445 * 1. prf(Ni|Nr, inKey); (bDataAsKey=TRUE, bRekey=FALSE)
446 * 2. prf(inKey, Ni|Nr); (bDataAsKkey=FALSE, bRekey=FALSE)
447 * 3. prf(inKey, newKey | Ni | Nr); (bDataAsKey=FALSE, bRekey=TRUE)
448 * The resulting output key is always the length of the underlying prf
449 * (as returned by prf_length()).
450 * The combination of bDataAsKey=TRUE and bRekey=TRUE is not allowed
451 *
452 * Case 1 is used in
453 * a. ikev2 (rfc5996) inKey is called g^ir, the output is called SKEYSEED
454 * b. ikev1 (rfc2409) inKey is called g^ir, the output is called SKEYID
455 * Case 2 is used in ikev1 (rfc2409) inkey is called pre-shared-key, output
456 * is called SKEYID
457 * Case 3 is used in ikev2 (rfc5996) rekey case, inKey is SK_d, newKey is
458 * g^ir (new), the output is called SKEYSEED
459 */
460CK_RV
461sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
462 const CK_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey)
463{
464 SFTKAttribute *newKeyValue = NULL((void*)0);
465 SFTKObject *newKeyObj = NULL((void*)0);
466 unsigned char outKeyData[HASH_LENGTH_MAX64];
467 unsigned char *newInKey = NULL((void*)0);
468 unsigned int newInKeySize = 0;
469 unsigned int macSize;
470 CK_RV crv = CKR_OK0x00000000UL;
471 prfContext context;
472
473 /* Bound the caller-supplied nonce lengths so that ulNiLen + ulNrLen can
474 * never overflow or be truncated when stored in the unsigned-int
475 * newInKeySize used to size the Ni||Nr concatenation buffer below.
476 * IKE nonces are at most 256 octets (RFC 7296 section 2.10) and IKE
477 * payload length fields are 16-bit, so 0xffff is far above any
478 * legitimate value. */
479 if (params->ulNiLen > 0xffff || params->ulNrLen > 0xffff) {
480 return CKR_MECHANISM_PARAM_INVALID0x00000071UL;
481 }
482
483 crv = prf_setup(&context, params->prfMechanism);
484 if (crv != CKR_OK0x00000000UL) {
485 return crv;
486 }
487 macSize = prf_length(&context);
488 if ((params->bDataAsKey) && (params->bRekey)) {
489 return CKR_ARGUMENTS_BAD0x00000007UL;
490 }
491 if (params->bRekey) {
492 /* lookup the value of new key from the session and key handle */
493 SFTKSession *session = sftk_SessionFromHandle(hSession);
494 if (session == NULL((void*)0)) {
495 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
496 }
497 newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session);
498 sftk_FreeSession(session);
499 if (newKeyObj == NULL((void*)0)) {
500 return CKR_KEY_HANDLE_INVALID0x00000060UL;
501 }
502 newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE0x00000011UL);
503 if (newKeyValue == NULL((void*)0)) {
504 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
505 goto fail;
506 }
507 }
508 if (params->bDataAsKey) {
509 /* The key is Ni || Np, so we need to concatenate them together first */
510 newInKeySize = params->ulNiLen + params->ulNrLen;
511 newInKey = PORT_AllocPORT_Alloc_Util(newInKeySize);
512 if (newInKey == NULL((void*)0)) {
513 crv = CKR_HOST_MEMORY0x00000002UL;
514 goto fail;
515 }
516 PORT_Memcpymemcpy(newInKey, params->pNi, params->ulNiLen);
517 PORT_Memcpymemcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen);
518 crv = prf_init(&context, newInKey, newInKeySize);
519 if (crv != CKR_OK0x00000000UL) {
520 goto fail;
521 }
522 /* key as the data */
523 crv = prf_update(&context, inKey->attrib.pValue,
524 inKey->attrib.ulValueLen);
525 if (crv != CKR_OK0x00000000UL) {
526 goto fail;
527 }
528 } else {
529 /* ikev1 isn't validated, if we use this function in ikev1 mode,
530 * mark the resulting key as not FIPS */
531 if (!params->bRekey) {
532 sftk_setFIPS(outKey, PR_FALSE0);
533 }
534
535 crv = prf_init(&context, inKey->attrib.pValue,
536 inKey->attrib.ulValueLen);
537 if (crv != CKR_OK0x00000000UL) {
538 goto fail;
539 }
540 if (newKeyValue) {
541 crv = prf_update(&context, newKeyValue->attrib.pValue,
542 newKeyValue->attrib.ulValueLen);
543 if (crv != CKR_OK0x00000000UL) {
544 goto fail;
545 }
546 }
547 crv = prf_update(&context, params->pNi, params->ulNiLen);
548 if (crv != CKR_OK0x00000000UL) {
549 goto fail;
550 }
551 crv = prf_update(&context, params->pNr, params->ulNrLen);
552 if (crv != CKR_OK0x00000000UL) {
553 goto fail;
554 }
555 }
556 crv = prf_final(&context, outKeyData, macSize);
557 if (crv != CKR_OK0x00000000UL) {
558 goto fail;
559 }
560
561 crv = sftk_forceAttribute(outKey, CKA_VALUE0x00000011UL, outKeyData, macSize);
562fail:
563 if (newInKey) {
564 PORT_ZFreePORT_ZFree_Util(newInKey, newInKeySize);
565 }
566 if (newKeyValue) {
567 sftk_FreeAttribute(newKeyValue);
568 }
569 if (newKeyObj) {
570 sftk_FreeObject(newKeyObj);
571 }
572 PORT_Memsetmemset(outKeyData, 0, macSize);
573 prf_free(&context);
574 return crv;
575}
576
577/*
578 * The second flavor of ike prf is ike1_prf.
579 *
580 * It is used by ikeV1 to generate the various session keys used in the
581 * connection. It uses the initial key, an optional previous key, and a one byte
582 * key number to generate a unique key for each of the various session
583 * functions (encryption, decryption, mac). These keys expect a key size
584 * (as they may vary in length based on usage). If no length is provided,
585 * it will default to the length of the prf.
586 *
587 * This function returns either:
588 * prf(inKey, gxyKey || CKYi || CKYr || key_number)
589 * or
590 * prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number)
591 * depending on the stats of bHasPrevKey
592 *
593 * This is defined in rfc2409. For each of the following keys.
594 * inKey is SKEYID, gxyKey is g^xy
595 * for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0
596 * for outKey = SKEYID_a, prevKey= SKEYID_d, key_number = 1
597 * for outKey = SKEYID_e, prevKey= SKEYID_a, key_number = 2
598 */
599CK_RV
600sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
601 const CK_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
602 unsigned int keySize)
603{
604 SFTKAttribute *gxyKeyValue = NULL((void*)0);
605 SFTKObject *gxyKeyObj = NULL((void*)0);
606 SFTKAttribute *prevKeyValue = NULL((void*)0);
607 SFTKObject *prevKeyObj = NULL((void*)0);
608 SFTKSession *session;
609 unsigned char outKeyData[HASH_LENGTH_MAX64];
610 unsigned int macSize;
611 CK_RV crv;
612 prfContext context;
613
614 crv = prf_setup(&context, params->prfMechanism);
615 if (crv != CKR_OK0x00000000UL) {
616 return crv;
617 }
618 macSize = prf_length(&context);
619 if (keySize > macSize) {
620 return CKR_KEY_SIZE_RANGE0x00000062UL;
621 }
622 if (keySize == 0) {
623 keySize = macSize;
624 }
625
626 /* lookup the two keys from their passed in handles */
627 session = sftk_SessionFromHandle(hSession);
628 if (session == NULL((void*)0)) {
629 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
630 }
631 gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
632 if (params->bHasPrevKey) {
633 prevKeyObj = sftk_ObjectFromHandle(params->hPrevKey, session);
634 }
635 sftk_FreeSession(session);
636 if ((gxyKeyObj == NULL((void*)0)) || ((params->bHasPrevKey) &&
637 (prevKeyObj == NULL((void*)0)))) {
638 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
639 goto fail;
640 }
641 gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE0x00000011UL);
642 if (gxyKeyValue == NULL((void*)0)) {
643 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
644 goto fail;
645 }
646 if (prevKeyObj) {
647 prevKeyValue = sftk_FindAttribute(prevKeyObj, CKA_VALUE0x00000011UL);
648 if (prevKeyValue == NULL((void*)0)) {
649 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
650 goto fail;
651 }
652 }
653
654 /* outKey = prf(inKey, [prevKey|] gxyKey | CKYi | CKYr | keyNumber) */
655 crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
656 if (crv != CKR_OK0x00000000UL) {
657 goto fail;
658 }
659 if (prevKeyValue) {
660 crv = prf_update(&context, prevKeyValue->attrib.pValue,
661 prevKeyValue->attrib.ulValueLen);
662 if (crv != CKR_OK0x00000000UL) {
663 goto fail;
664 }
665 }
666 crv = prf_update(&context, gxyKeyValue->attrib.pValue,
667 gxyKeyValue->attrib.ulValueLen);
668 if (crv != CKR_OK0x00000000UL) {
669 goto fail;
670 }
671 crv = prf_update(&context, params->pCKYi, params->ulCKYiLen);
672 if (crv != CKR_OK0x00000000UL) {
673 goto fail;
674 }
675 crv = prf_update(&context, params->pCKYr, params->ulCKYrLen);
676 if (crv != CKR_OK0x00000000UL) {
677 goto fail;
678 }
679 crv = prf_update(&context, &params->keyNumber, 1);
680 if (crv != CKR_OK0x00000000UL) {
681 goto fail;
682 }
683 crv = prf_final(&context, outKeyData, macSize);
684 if (crv != CKR_OK0x00000000UL) {
685 goto fail;
686 }
687
688 crv = sftk_forceAttribute(outKey, CKA_VALUE0x00000011UL, outKeyData, keySize);
689fail:
690 if (gxyKeyValue) {
691 sftk_FreeAttribute(gxyKeyValue);
692 }
693 if (prevKeyValue) {
694 sftk_FreeAttribute(prevKeyValue);
695 }
696 if (gxyKeyObj) {
697 sftk_FreeObject(gxyKeyObj);
698 }
699 if (prevKeyObj) {
700 sftk_FreeObject(prevKeyObj);
701 }
702 PORT_Memsetmemset(outKeyData, 0, macSize);
703 prf_free(&context);
704 return crv;
705}
706
707/*
708 * The third flavor of ike prf is ike1_appendix_b.
709 *
710 * It is used by ikeV1 to generate longer key material from skeyid_e.
711 * Unlike ike1_prf, if no length is provided, this function
712 * will generate a KEY_RANGE_ERROR.
713 *
714 * This function returns (from rfc2409 appendix b):
715 * Ka = K1 | K2 | K3 | K4 |... Kn
716 * where:
717 * K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData
718 * ar not present.
719 * K2 = prf(K, K1|[gxyKey]|[extraData])
720 * K3 = prf(K, K2|[gxyKey]|[extraData])
721 * K4 = prf(K, K3|[gxyKey]|[extraData])
722 * .
723 * Kn = prf(K, K(n-1)|[gxyKey]|[extraData])
724 * K = inKey
725 */
726CK_RV
727sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
728 const CK_IKE1_EXTENDED_DERIVE_PARAMS *params,
729 SFTKObject *outKey, unsigned int keySize)
730{
731 SFTKAttribute *gxyKeyValue = NULL((void*)0);
732 SFTKObject *gxyKeyObj = NULL((void*)0);
733 unsigned char *outKeyData = NULL((void*)0);
734 unsigned char *thisKey = NULL((void*)0);
735 unsigned char *lastKey = NULL((void*)0);
736 unsigned int macSize;
737 unsigned int outKeySize;
738 unsigned int genKeySize;
739 PRBool quickMode = PR_FALSE0;
740 CK_RV crv;
741 prfContext context;
742
743 if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL((void*)0))) {
744 return CKR_ARGUMENTS_BAD0x00000007UL;
745 }
746 crv = prf_setup(&context, params->prfMechanism);
747 if (crv != CKR_OK0x00000000UL) {
748 return crv;
749 }
750
751 if (params->bHasKeygxy) {
752 SFTKSession *session;
753 session = sftk_SessionFromHandle(hSession);
754 if (session == NULL((void*)0)) {
755 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
756 }
757 gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
758 sftk_FreeSession(session);
759 if (gxyKeyObj == NULL((void*)0)) {
760 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
761 goto fail;
762 }
763 gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE0x00000011UL);
764 if (gxyKeyValue == NULL((void*)0)) {
765 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
766 goto fail;
767 }
768 quickMode = PR_TRUE1;
769 }
770
771 if (params->ulExtraDataLen != 0) {
772 quickMode = PR_TRUE1;
773 }
774
775 macSize = prf_length(&context);
776
777 if (keySize == 0) {
778 keySize = macSize;
779 }
780
781 /* In appendix B, we are just expanding or contracting a single key.
782 * If the input key is less than or equal to the the key size we want,
783 * just subset the original key. In quick mode we are actually getting
784 * new keys (salted with our seed data and our gxy key), so we want to
785 * run through our algorithm */
786 if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) {
787 return sftk_forceAttribute(outKey, CKA_VALUE0x00000011UL,
788 inKey->attrib.pValue, keySize);
789 }
790
791 outKeySize = PR_ROUNDUP(keySize, macSize)((((keySize) + ((macSize) - 1)) / (macSize)) * (macSize));
792 /* Reject if PR_ROUNDUP overflowed 32-bit unsigned arithmetic, which
793 * would yield an undersized allocation for the loop below. */
794 if (outKeySize < keySize) {
795 crv = CKR_KEY_SIZE_RANGE0x00000062UL;
796 goto fail;
797 }
798 outKeyData = PORT_AllocPORT_Alloc_Util(outKeySize);
799 if (outKeyData == NULL((void*)0)) {
800 crv = CKR_HOST_MEMORY0x00000002UL;
801 goto fail;
802 }
803
804 /*
805 * this loop generates on block of the prf, basically
806 * kn = prf(key, Kn-1 | [Keygxy] | [ExtraData])
807 * Kn is thisKey, Kn-1 is lastKey
808 * key is inKey
809 */
810 thisKey = outKeyData;
811 for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) {
812 PRBool hashedData = PR_FALSE0;
813 crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
814 if (crv != CKR_OK0x00000000UL) {
815 goto fail;
816 }
817 if (lastKey != NULL((void*)0)) {
818 crv = prf_update(&context, lastKey, macSize);
819 if (crv != CKR_OK0x00000000UL) {
820 goto fail;
821 }
822 hashedData = PR_TRUE1;
823 }
824 if (gxyKeyValue != NULL((void*)0)) {
825 crv = prf_update(&context, gxyKeyValue->attrib.pValue,
826 gxyKeyValue->attrib.ulValueLen);
827 if (crv != CKR_OK0x00000000UL) {
828 goto fail;
829 }
830 hashedData = PR_TRUE1;
831 }
832 if (params->ulExtraDataLen != 0) {
833 crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen);
834 if (crv != CKR_OK0x00000000UL) {
835 goto fail;
836 }
837 hashedData = PR_TRUE1;
838 }
839 /* if we haven't hashed anything yet, hash a zero */
840 if (hashedData == PR_FALSE0) {
841 const unsigned char zero = 0;
842 crv = prf_update(&context, &zero, 1);
843 if (crv != CKR_OK0x00000000UL) {
844 goto fail;
845 }
846 }
847 crv = prf_final(&context, thisKey, macSize);
848 if (crv != CKR_OK0x00000000UL) {
849 goto fail;
850 }
851 lastKey = thisKey;
852 thisKey += macSize;
853 }
854 crv = sftk_forceAttribute(outKey, CKA_VALUE0x00000011UL, outKeyData, keySize);
855fail:
856 if (gxyKeyValue) {
857 sftk_FreeAttribute(gxyKeyValue);
858 }
859 if (gxyKeyObj) {
860 sftk_FreeObject(gxyKeyObj);
861 }
862 if (outKeyData) {
863 PORT_ZFreePORT_ZFree_Util(outKeyData, outKeySize);
864 }
865 prf_free(&context);
866 return crv;
867}
868
869/*
870 * The final flavor of ike prf is ike_prf_plus
871 *
872 * It is used by ikeV2 to generate the various session keys used in the
873 * connection. It uses the initial key and a feedback version of the prf
874 * to generate sufficient bytes to cover all the session keys. The application
875 * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys.
876 * This function expects a key size to be set by the application to cover
877 * all the keys. Unlike ike1_prf, if no length is provided, this function
878 * will generate a KEY_RANGE_ERROR
879 *
880 * This function returns (from rfc5996):
881 * prfplus = T1 | T2 | T3 | T4 |... Tn
882 * where:
883 * T1 = prf(K, S | 0x01)
884 * T2 = prf(K, T1 | S | 0x02)
885 * T3 = prf(K, T3 | S | 0x03)
886 * T4 = prf(K, T4 | S | 0x04)
887 * .
888 * Tn = prf(K, T(n-1) | n)
889 * K = inKey, S = seedKey | seedData
890 */
891
892static CK_RV
893sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession,
894 const unsigned char *inKeyData, CK_ULONG inKeyLen,
895 const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params,
896 unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr,
897 unsigned int keySize)
898{
899 SFTKAttribute *seedValue = NULL((void*)0);
900 SFTKObject *seedKeyObj = NULL((void*)0);
901 unsigned char *outKeyData = NULL((void*)0);
902 unsigned int outKeySize;
903 unsigned char *thisKey;
904 unsigned char *lastKey = NULL((void*)0);
905 unsigned char currentByte = 0;
906 unsigned int getKeySize;
907 unsigned int macSize;
908 CK_RV crv;
909 prfContext context;
910
911 if (keySize == 0) {
912 return CKR_KEY_SIZE_RANGE0x00000062UL;
913 }
914
915 crv = prf_setup(&context, params->prfMechanism);
916 if (crv != CKR_OK0x00000000UL) {
917 return crv;
918 }
919 /* pull in optional seedKey */
920 if (params->bHasSeedKey) {
921 SFTKSession *session = sftk_SessionFromHandle(hSession);
922 if (session == NULL((void*)0)) {
923 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
924 }
925 seedKeyObj = sftk_ObjectFromHandle(params->hSeedKey, session);
926 sftk_FreeSession(session);
927 if (seedKeyObj == NULL((void*)0)) {
928 return CKR_KEY_HANDLE_INVALID0x00000060UL;
929 }
930 seedValue = sftk_FindAttribute(seedKeyObj, CKA_VALUE0x00000011UL);
931 if (seedValue == NULL((void*)0)) {
932 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
933 goto fail;
934 }
935 } else if (params->ulSeedDataLen == 0) {
936 crv = CKR_ARGUMENTS_BAD0x00000007UL;
937 goto fail;
938 }
939 macSize = prf_length(&context);
940 /* RFC 7296 limits prf+ to 255 blocks; enforcing this up front also
941 * prevents 32-bit overflow in PR_ROUNDUP below. */
942 if (keySize > 255 * macSize) {
943 crv = CKR_KEY_SIZE_RANGE0x00000062UL;
944 goto fail;
945 }
946 outKeySize = PR_ROUNDUP(keySize, macSize)((((keySize) + ((macSize) - 1)) / (macSize)) * (macSize));
947 outKeyData = PORT_AllocPORT_Alloc_Util(outKeySize);
948 if (outKeyData == NULL((void*)0)) {
949 crv = CKR_HOST_MEMORY0x00000002UL;
950 goto fail;
951 }
952
953 /*
954 * this loop generates on block of the prf, basically
955 * Tn = prf(key, Tn-1 | S | n)
956 * Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData,
957 * key is inKey. currentByte = n-1 on entry.
958 */
959 thisKey = outKeyData;
960 for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) {
961 /* if currentByte is 255, we'll overflow when we increment it below.
962 * This can only happen if keysize > 255*macSize. In that case
963 * the application has asked for too much key material, so return
964 * an error */
965 if (currentByte == 255) {
966 crv = CKR_KEY_SIZE_RANGE0x00000062UL;
967 goto fail;
968 }
969 crv = prf_init(&context, inKeyData, inKeyLen);
970 if (crv != CKR_OK0x00000000UL) {
971 goto fail;
972 }
973
974 if (lastKey) {
975 crv = prf_update(&context, lastKey, macSize);
976 if (crv != CKR_OK0x00000000UL) {
977 goto fail;
978 }
979 }
980 /* prf the key first */
981 if (seedValue) {
982 crv = prf_update(&context, seedValue->attrib.pValue,
983 seedValue->attrib.ulValueLen);
984 if (crv != CKR_OK0x00000000UL) {
985 goto fail;
986 }
987 }
988 /* then prf the data */
989 if (params->ulSeedDataLen != 0) {
990 crv = prf_update(&context, params->pSeedData,
991 params->ulSeedDataLen);
992 if (crv != CKR_OK0x00000000UL) {
993 goto fail;
994 }
995 }
996 currentByte++;
997 crv = prf_update(&context, &currentByte, 1);
998 if (crv != CKR_OK0x00000000UL) {
999 goto fail;
1000 }
1001 crv = prf_final(&context, thisKey, macSize);
1002 if (crv != CKR_OK0x00000000UL) {
1003 goto fail;
1004 }
1005 lastKey = thisKey;
1006 thisKey += macSize;
1007 }
1008 *outKeyDataPtr = outKeyData;
1009 *outKeySizePtr = outKeySize;
1010 outKeyData = NULL((void*)0); /* don't free it here, our caller will free it */
1011fail:
1012 if (outKeyData) {
1013 PORT_ZFreePORT_ZFree_Util(outKeyData, outKeySize);
1014 }
1015 if (seedValue) {
1016 sftk_FreeAttribute(seedValue);
1017 }
1018 if (seedKeyObj) {
1019 sftk_FreeObject(seedKeyObj);
1020 }
1021 prf_free(&context);
1022 return crv;
1023}
1024
1025/*
1026 * ike prf + with code to deliever results tosoftoken objects.
1027 */
1028CK_RV
1029sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
1030 const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
1031 unsigned int keySize)
1032{
1033 unsigned char *outKeyData = NULL((void*)0);
1034 unsigned int outKeySize;
1035 CK_RV crv;
1036
1037 crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue,
1038 inKey->attrib.ulValueLen, params,
1039 &outKeyData, &outKeySize, keySize);
1040 if (crv != CKR_OK0x00000000UL) {
1041 return crv;
1042 }
1043
1044 crv = sftk_forceAttribute(outKey, CKA_VALUE0x00000011UL, outKeyData, keySize);
1045 PORT_ZFreePORT_ZFree_Util(outKeyData, outKeySize);
1046 return crv;
1047}
1048
1049/* sftk_aes_xcbc_new_keys:
1050 *
1051 * aes xcbc creates 3 new keys from the input key. The first key will be the
1052 * base key of the underlying cbc. The sign code hooks directly into encrypt
1053 * so we'll have to create a full PKCS #11 key with handle for that key. The
1054 * caller needs to delete the key when it's through setting up the context.
1055 *
1056 * The other two keys will be stored in the sign context until we need them
1057 * at the end.
1058 */
1059CK_RV
1060sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
1061 CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
1062 unsigned char *k2, unsigned char *k3)
1063{
1064 SFTKObject *key = NULL((void*)0);
1065 SFTKSession *session = NULL((void*)0);
1066 SFTKObject *inKeyObj = NULL((void*)0);
1067 SFTKAttribute *inKeyValue = NULL((void*)0);
1068 CK_KEY_TYPE key_type = CKK_AES0x0000001FUL;
1069 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY0x00000004UL;
1070 CK_BBOOL ck_true = CK_TRUE1;
1071 CK_RV crv = CKR_OK0x00000000UL;
1072 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
1073 unsigned char buf[AES_BLOCK_SIZE16];
1074
1075 if (!slot) {
1076 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
1077 }
1078
1079 /* get the session */
1080 session = sftk_SessionFromHandle(hSession);
1081 if (session == NULL((void*)0)) {
1082 crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
1083 goto fail;
1084 }
1085
1086 inKeyObj = sftk_ObjectFromHandle(hKey, session);
1087 if (inKeyObj == NULL((void*)0)) {
1088 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
1089 goto fail;
1090 }
1091
1092 inKeyValue = sftk_FindAttribute(inKeyObj, CKA_VALUE0x00000011UL);
1093 if (inKeyValue == NULL((void*)0)) {
1094 crv = CKR_KEY_HANDLE_INVALID0x00000060UL;
1095 goto fail;
1096 }
1097
1098 crv = sftk_aes_xcbc_get_keys(inKeyValue->attrib.pValue,
1099 inKeyValue->attrib.ulValueLen, buf, k2, k3);
1100
1101 if (crv != CKR_OK0x00000000UL) {
1102 goto fail;
1103 }
1104
1105 /*
1106 * now lets create an object to hang the attributes off of
1107 */
1108 key = sftk_NewObject(slot); /* fill in the handle later */
1109 if (key == NULL((void*)0)) {
1110 crv = CKR_HOST_MEMORY0x00000002UL;
1111 goto fail;
1112 }
1113
1114 /* make sure we don't have any class, key_type, or value fields */
1115 sftk_DeleteAttributeType(key, CKA_CLASS0x00000000UL);
1116 sftk_DeleteAttributeType(key, CKA_KEY_TYPE0x00000100UL);
1117 sftk_DeleteAttributeType(key, CKA_VALUE0x00000011UL);
1118 sftk_DeleteAttributeType(key, CKA_SIGN0x00000108UL);
1119
1120 /* Add the class, key_type, and value */
1121 crv = sftk_AddAttributeType(key, CKA_CLASS0x00000000UL, &objclass, sizeof(CK_OBJECT_CLASS));
1122 if (crv != CKR_OK0x00000000UL) {
1123 goto fail;
1124 }
1125 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE0x00000100UL, &key_type, sizeof(CK_KEY_TYPE));
1126 if (crv != CKR_OK0x00000000UL) {
1127 goto fail;
1128 }
1129 crv = sftk_AddAttributeType(key, CKA_SIGN0x00000108UL, &ck_true, sizeof(CK_BBOOL));
1130 if (crv != CKR_OK0x00000000UL) {
1131 goto fail;
1132 }
1133 crv = sftk_AddAttributeType(key, CKA_VALUE0x00000011UL, buf, AES_BLOCK_SIZE16);
1134 if (crv != CKR_OK0x00000000UL) {
1135 goto fail;
1136 }
1137
1138 /*
1139 * finish filling in the key and link it with our global system.
1140 */
1141 crv = sftk_handleObject(key, session);
1142 if (crv != CKR_OK0x00000000UL) {
1143 goto fail;
1144 }
1145 *phKey = key->handle;
1146fail:
1147 if (session) {
1148 sftk_FreeSession(session);
1149 }
1150
1151 if (inKeyValue) {
1152 sftk_FreeAttribute(inKeyValue);
1153 }
1154 if (inKeyObj) {
1155 sftk_FreeObject(inKeyObj);
1156 }
1157 if (key) {
1158 sftk_FreeObject(key);
1159 }
1160 /* clear our CSPs */
1161 PORT_Memsetmemset(buf, 0, sizeof(buf));
1162 if (crv != CKR_OK0x00000000UL) {
1163 PORT_Memsetmemset(k2, 0, AES_BLOCK_SIZE16);
1164 PORT_Memsetmemset(k3, 0, AES_BLOCK_SIZE16);
1165 }
1166 return crv;
1167}
1168
1169/*
1170 * Helper function that tests a single prf test vector
1171 */
1172static SECStatus
1173prf_test(CK_MECHANISM_TYPE mech,
1174 const unsigned char *inKey, unsigned int inKeyLen,
1175 const unsigned char *plainText, unsigned int plainTextLen,
1176 const unsigned char *expectedResult, unsigned int expectedResultLen)
1177{
1178 PRUint8 ike_computed_mac[HASH_LENGTH_MAX64];
2
'ike_computed_mac' declared without an initial value
1179 prfContext context;
1180 unsigned int macSize;
1181 CK_RV crv;
1182
1183 crv = prf_setup(&context, mech);
1184 if (crv
2.1
'crv' is equal to CKR_OK
!= CKR_OK0x00000000UL) {
3
Taking false branch
1185 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1186 return SECFailure;
1187 }
1188 macSize = prf_length(&context);
1189 crv = prf_init(&context, inKey, inKeyLen);
1190 if (crv
3.1
'crv' is equal to CKR_OK
!= CKR_OK0x00000000UL) {
4
Taking false branch
1191 goto fail;
1192 }
1193 crv = prf_update(&context, plainText, plainTextLen);
1194 if (crv != CKR_OK0x00000000UL) {
5
Assuming 'crv' is equal to CKR_OK
6
Taking false branch
1195 goto fail;
1196 }
1197 crv = prf_final(&context, ike_computed_mac, macSize);
7
Calling 'prf_final'
15
Returning from 'prf_final'
1198 if (crv != CKR_OK0x00000000UL) {
16
Assuming 'crv' is equal to CKR_OK
17
Taking false branch
1199 goto fail;
1200 }
1201
1202 if (macSize
17.1
'macSize' is equal to 'expectedResultLen'
!= expectedResultLen) {
18
Taking false branch
1203 goto fail;
1204 }
1205 if (PORT_Memcmpmemcmp(expectedResult, ike_computed_mac, macSize) != 0) {
Other elements might also be undefined
19
The first element of the 2nd argument is undefined
1206 goto fail;
1207 }
1208
1209 /* only do the alignment if the plaintext is long enough */
1210 if (plainTextLen <= macSize) {
1211 return SECSuccess;
1212 }
1213 prf_free(&context);
1214 /* do it again, but this time tweak with the alignment */
1215 crv = prf_init(&context, inKey, inKeyLen);
1216 if (crv != CKR_OK0x00000000UL) {
1217 goto fail;
1218 }
1219 crv = prf_update(&context, plainText, 1);
1220 if (crv != CKR_OK0x00000000UL) {
1221 goto fail;
1222 }
1223 crv = prf_update(&context, &plainText[1], macSize);
1224 if (crv != CKR_OK0x00000000UL) {
1225 goto fail;
1226 }
1227 crv = prf_update(&context, &plainText[1 + macSize], plainTextLen - (macSize + 1));
1228 if (crv != CKR_OK0x00000000UL) {
1229 goto fail;
1230 }
1231 crv = prf_final(&context, ike_computed_mac, macSize);
1232 if (crv != CKR_OK0x00000000UL) {
1233 goto fail;
1234 }
1235 if (PORT_Memcmpmemcmp(expectedResult, ike_computed_mac, macSize) != 0) {
1236 goto fail;
1237 }
1238 prf_free(&context);
1239 return SECSuccess;
1240fail:
1241 prf_free(&context);
1242 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1243 return SECFailure;
1244}
1245
1246/*
1247 * FIPS Power up Self Tests for IKE. This is in this function so it
1248 * can access the private prf_ functions here. It's called out of fipstest.c
1249 */
1250SECStatus
1251sftk_fips_IKE_PowerUpSelfTests(void)
1252{
1253 /* PRF known test vectors */
1254 static const PRUint8 ike_xcbc_known_key[] = {
1255 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1256 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
1257 };
1258 static const PRUint8 ike_xcbc_known_plain_text[] = {
1259 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1260 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
1261 };
1262 static const PRUint8 ike_xcbc_known_mac[] = {
1263 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
1264 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63
1265 };
1266 /* test 2 uses the same key as test 1 */
1267 static const PRUint8 ike_xcbc_known_plain_text_2[] = {
1268 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1269 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1270 0x10, 0x11, 0x12, 0x13
1271 };
1272 static const PRUint8 ike_xcbc_known_mac_2[] = {
1273 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
1274 0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08
1275 };
1276 static const PRUint8 ike_xcbc_known_key_3[] = {
1277 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1278 0x08, 0x09
1279 };
1280 /* test 3 uses the same plaintest as test 2 */
1281 static const PRUint8 ike_xcbc_known_mac_3[] = {
1282 0x0f, 0xa0, 0x87, 0xaf, 0x7d, 0x86, 0x6e, 0x76,
1283 0x53, 0x43, 0x4e, 0x60, 0x2f, 0xdd, 0xe8, 0x35
1284 };
1285 static const PRUint8 ike_xcbc_known_key_4[] = {
1286 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1287 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1288 0xed, 0xcb
1289 };
1290 /* test 4 uses the same plaintest as test 2 */
1291 static const PRUint8 ike_xcbc_known_mac_4[] = {
1292 0x8c, 0xd3, 0xc9, 0x3a, 0xe5, 0x98, 0xa9, 0x80,
1293 0x30, 0x06, 0xff, 0xb6, 0x7c, 0x40, 0xe9, 0xe4
1294 };
1295 static const PRUint8 ike_sha1_known_key[] = {
1296 0x59, 0x98, 0x2b, 0x5b, 0xa5, 0x7e, 0x62, 0xc0,
1297 0x46, 0x0d, 0xef, 0xc7, 0x1e, 0x18, 0x64, 0x63
1298 };
1299 static const PRUint8 ike_sha1_known_plain_text[] = {
1300 0x1c, 0x07, 0x32, 0x1a, 0x9a, 0x7e, 0x41, 0xcd,
1301 0x88, 0x0c, 0xa3, 0x7a, 0xdb, 0x10, 0xc7, 0x3b,
1302 0xf0, 0x0e, 0x7a, 0xe3, 0xcf, 0xc6, 0xfd, 0x8b,
1303 0x51, 0xbc, 0xe2, 0xb9, 0x90, 0xe6, 0xf2, 0x01
1304 };
1305 static const PRUint8 ike_sha1_known_mac[] = {
1306 0x0c, 0x2a, 0xf3, 0x42, 0x97, 0x15, 0x62, 0x1d,
1307 0x2a, 0xad, 0xc9, 0x94, 0x5a, 0x90, 0x26, 0xfa,
1308 0xc7, 0x91, 0xe2, 0x4b
1309 };
1310 static const PRUint8 ike_sha256_known_key[] = {
1311 0x9d, 0xa2, 0xd5, 0x8f, 0x57, 0xf0, 0x39, 0xf9,
1312 0x20, 0x4e, 0x0d, 0xd0, 0xef, 0x04, 0xf3, 0x72
1313 };
1314 static const PRUint8 ike_sha256_known_plain_text[] = {
1315 0x33, 0xf1, 0x7a, 0xfc, 0xb6, 0x13, 0x4c, 0xbf,
1316 0x1c, 0xab, 0x59, 0x87, 0x7d, 0x42, 0xdb, 0x35,
1317 0x82, 0x22, 0x6e, 0xff, 0x74, 0xdd, 0x37, 0xeb,
1318 0x8b, 0x75, 0xe6, 0x75, 0x64, 0x5f, 0xc1, 0x69
1319 };
1320 static const PRUint8 ike_sha256_known_mac[] = {
1321 0x80, 0x4b, 0x4a, 0x1e, 0x0e, 0xc5, 0x93, 0xcf,
1322 0xb6, 0xe4, 0x54, 0x52, 0x41, 0x49, 0x39, 0x6d,
1323 0xe2, 0x34, 0xd0, 0xda, 0xe2, 0x9f, 0x34, 0xa8,
1324 0xfd, 0xb5, 0xf9, 0xaf, 0xe7, 0x6e, 0xa6, 0x52
1325 };
1326 static const PRUint8 ike_sha384_known_key[] = {
1327 0xce, 0xc8, 0x9d, 0x84, 0x5a, 0xdd, 0x83, 0xef,
1328 0xce, 0xbd, 0x43, 0xab, 0x71, 0xd1, 0x7d, 0xb9
1329 };
1330 static const PRUint8 ike_sha384_known_plain_text[] = {
1331 0x17, 0x24, 0xdb, 0xd8, 0x93, 0x52, 0x37, 0x64,
1332 0xbf, 0xef, 0x8c, 0x6f, 0xa9, 0x27, 0x85, 0x6f,
1333 0xcc, 0xfb, 0x77, 0xae, 0x25, 0x43, 0x58, 0xcc,
1334 0xe2, 0x9c, 0x27, 0x69, 0xa3, 0x29, 0x15, 0xc1
1335 };
1336 static const PRUint8 ike_sha384_known_mac[] = {
1337 0x6e, 0x45, 0x14, 0x61, 0x0b, 0xf8, 0x2d, 0x0a,
1338 0xb7, 0xbf, 0x02, 0x60, 0x09, 0x6f, 0x61, 0x46,
1339 0xa1, 0x53, 0xc7, 0x12, 0x07, 0x1a, 0xbb, 0x63,
1340 0x3c, 0xed, 0x81, 0x3c, 0x57, 0x21, 0x56, 0xc7,
1341 0x83, 0xe3, 0x68, 0x74, 0xa6, 0x5a, 0x64, 0x69,
1342 0x0c, 0xa7, 0x01, 0xd4, 0x0d, 0x56, 0xea, 0x18
1343 };
1344 static const PRUint8 ike_sha512_known_key[] = {
1345 0xac, 0xad, 0xc6, 0x31, 0x4a, 0x69, 0xcf, 0xcd,
1346 0x4e, 0x4a, 0xd1, 0x77, 0x18, 0xfe, 0xa7, 0xce
1347 };
1348 static const PRUint8 ike_sha512_known_plain_text[] = {
1349 0xb1, 0x5a, 0x9c, 0xfc, 0xe8, 0xc8, 0xd7, 0xea,
1350 0xb8, 0x79, 0xd6, 0x24, 0x30, 0x29, 0xd4, 0x01,
1351 0x88, 0xd3, 0xb7, 0x40, 0x87, 0x5a, 0x6a, 0xc6,
1352 0x2f, 0x56, 0xca, 0xc4, 0x37, 0x7e, 0x2e, 0xdd
1353 };
1354 static const PRUint8 ike_sha512_known_mac[] = {
1355 0xf0, 0x5a, 0xa0, 0x36, 0xdf, 0xce, 0x45, 0xa5,
1356 0x58, 0xd4, 0x04, 0x18, 0xde, 0xa9, 0x80, 0x96,
1357 0xe5, 0x19, 0xbc, 0x78, 0x41, 0xe3, 0xdb, 0x3d,
1358 0xd9, 0x36, 0x58, 0xd1, 0x18, 0xc3, 0xe8, 0x3b,
1359 0x50, 0x2f, 0x39, 0x8e, 0xcb, 0x13, 0x61, 0xec,
1360 0x77, 0xd3, 0x8a, 0x88, 0x55, 0xef, 0xff, 0x40,
1361 0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,
1362 0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b
1363 };
1364 static const PRUint8 ike_known_sha256_prf_plus[] = {
1365 0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72,
1366 0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb,
1367 0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b,
1368 0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d,
1369 0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3,
1370 0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5,
1371 0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4,
1372 0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39
1373 };
1374 SECStatus rv;
1375 CK_RV crv;
1376 unsigned char *outKeyData = NULL((void*)0);
1377 unsigned int outKeySize;
1378 CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike_params;
1379
1380 rv = prf_test(CKM_AES_XCBC_MAC0x0000108CUL,
1
Calling 'prf_test'
1381 ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
1382 ike_xcbc_known_plain_text, sizeof(ike_xcbc_known_plain_text),
1383 ike_xcbc_known_mac, sizeof(ike_xcbc_known_mac));
1384 if (rv != SECSuccess)
1385 return rv;
1386 rv = prf_test(CKM_AES_XCBC_MAC0x0000108CUL,
1387 ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
1388 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
1389 ike_xcbc_known_mac_2, sizeof(ike_xcbc_known_mac_2));
1390 if (rv != SECSuccess)
1391 return rv;
1392 rv = prf_test(CKM_AES_XCBC_MAC0x0000108CUL,
1393 ike_xcbc_known_key_3, sizeof(ike_xcbc_known_key_3),
1394 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
1395 ike_xcbc_known_mac_3, sizeof(ike_xcbc_known_mac_3));
1396 if (rv != SECSuccess)
1397 return rv;
1398 rv = prf_test(CKM_AES_XCBC_MAC0x0000108CUL,
1399 ike_xcbc_known_key_4, sizeof(ike_xcbc_known_key_4),
1400 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
1401 ike_xcbc_known_mac_4, sizeof(ike_xcbc_known_mac_4));
1402 if (rv != SECSuccess)
1403 return rv;
1404 rv = prf_test(CKM_SHA_1_HMAC0x00000221UL,
1405 ike_sha1_known_key, sizeof(ike_sha1_known_key),
1406 ike_sha1_known_plain_text, sizeof(ike_sha1_known_plain_text),
1407 ike_sha1_known_mac, sizeof(ike_sha1_known_mac));
1408 if (rv != SECSuccess)
1409 return rv;
1410 rv = prf_test(CKM_SHA256_HMAC0x00000251UL,
1411 ike_sha256_known_key, sizeof(ike_sha256_known_key),
1412 ike_sha256_known_plain_text,
1413 sizeof(ike_sha256_known_plain_text),
1414 ike_sha256_known_mac, sizeof(ike_sha256_known_mac));
1415 if (rv != SECSuccess)
1416 return rv;
1417 rv = prf_test(CKM_SHA384_HMAC0x00000261UL,
1418 ike_sha384_known_key, sizeof(ike_sha384_known_key),
1419 ike_sha384_known_plain_text,
1420 sizeof(ike_sha384_known_plain_text),
1421 ike_sha384_known_mac, sizeof(ike_sha384_known_mac));
1422 if (rv != SECSuccess)
1423 return rv;
1424 rv = prf_test(CKM_SHA512_HMAC0x00000271UL,
1425 ike_sha512_known_key, sizeof(ike_sha512_known_key),
1426 ike_sha512_known_plain_text,
1427 sizeof(ike_sha512_known_plain_text),
1428 ike_sha512_known_mac, sizeof(ike_sha512_known_mac));
1429
1430 ike_params.prfMechanism = CKM_SHA256_HMAC0x00000251UL;
1431 ike_params.bHasSeedKey = PR_FALSE0;
1432 ike_params.hSeedKey = CK_INVALID_HANDLE0;
1433 ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text;
1434 ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text);
1435 crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE0, ike_sha256_known_key,
1436 sizeof(ike_sha256_known_key), &ike_params,
1437 &outKeyData, &outKeySize, 64);
1438 if ((crv != CKR_OK0x00000000UL) ||
1439 (outKeySize != sizeof(ike_known_sha256_prf_plus)) ||
1440 (PORT_Memcmpmemcmp(outKeyData, ike_known_sha256_prf_plus,
1441 sizeof(ike_known_sha256_prf_plus)) != 0)) {
1442 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1443 return SECFailure;
1444 }
1445 PORT_ZFreePORT_ZFree_Util(outKeyData, outKeySize);
1446 return rv;
1447}