sftkike.c (48907B)
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 */ 45 typedef 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_SIZE]; 52 unsigned char macBuf[AES_BLOCK_SIZE]; 53 unsigned char k1[AES_BLOCK_SIZE]; 54 unsigned char k2[AES_BLOCK_SIZE]; 55 unsigned char k3[AES_BLOCK_SIZE]; 56 } prfContext; 57 58 /* iv full of zeros used in several places in aes xcbc */ 59 static 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 */ 69 static CK_RV 70 sftk_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; 77 unsigned char newKey[AES_BLOCK_SIZE]; 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_SIZE) { 117 PORT_Memcpy(newKey, keyValue, keyLen); 118 PORT_Memset(&newKey[keyLen], 0, AES_BLOCK_SIZE - keyLen); 119 keyValue = newKey; 120 } else if (keyLen > AES_BLOCK_SIZE) { 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_CBC, 130 PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE); 131 /* we know the following loop will execute at least once */ 132 while (keyLen > AES_BLOCK_SIZE) { 133 rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE, 134 keyValue, AES_BLOCK_SIZE); 135 if (rv != SECSuccess) { 136 goto fail; 137 } 138 keyValue += AES_BLOCK_SIZE; 139 keyLen -= AES_BLOCK_SIZE; 140 } 141 PORT_Memcpy(newKey, keyValue, keyLen); 142 sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE, k2_0, k3_0); 143 rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE, 144 newKey, AES_BLOCK_SIZE); 145 if (rv != SECSuccess) { 146 goto fail; 147 } 148 keyValue = newKey; 149 AES_DestroyContext(aes_context, PR_TRUE); 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_AES, PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE); 157 if (aes_context == NULL) { 158 goto fail; 159 } 160 rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE, 161 k1data, sizeof(k1data)); 162 if (rv != SECSuccess) { 163 goto fail; 164 } 165 rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE, 166 k2data, sizeof(k2data)); 167 if (rv != SECSuccess) { 168 goto fail; 169 } 170 rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE, 171 k3data, sizeof(k3data)); 172 if (rv != SECSuccess) { 173 goto fail; 174 } 175 AES_DestroyContext(aes_context, PR_TRUE); 176 PORT_Memset(newKey, 0, AES_BLOCK_SIZE); 177 return CKR_OK; 178 fail: 179 crv = sftk_MapCryptError(PORT_GetError()); 180 if (aes_context) { 181 AES_DestroyContext(aes_context, PR_TRUE); 182 } 183 PORT_Memset(k1, 0, AES_BLOCK_SIZE); 184 PORT_Memset(k2, 0, AES_BLOCK_SIZE); 185 PORT_Memset(k3, 0, AES_BLOCK_SIZE); 186 PORT_Memset(newKey, 0, AES_BLOCK_SIZE); 187 return crv; 188 } 189 190 /* encode the final pad block of aes xcbc, padBuf is modified */ 191 CK_RV 192 sftk_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_OK; 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 */ 216 static HASH_HashType 217 sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type) 218 { 219 switch (type) { 220 case CKM_SHA_1_HMAC: 221 case CKM_SHA_1: 222 return HASH_AlgSHA1; 223 case CKM_MD5_HMAC: 224 case CKM_MD5: 225 return HASH_AlgMD5; 226 case CKM_MD2_HMAC: 227 case CKM_MD2: 228 return HASH_AlgMD2; 229 case CKM_SHA224_HMAC: 230 case CKM_SHA224: 231 return HASH_AlgSHA224; 232 case CKM_SHA256_HMAC: 233 case CKM_SHA256: 234 return HASH_AlgSHA256; 235 case CKM_SHA384_HMAC: 236 case CKM_SHA384: 237 return HASH_AlgSHA384; 238 case CKM_SHA512_HMAC: 239 case CKM_SHA512: 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 */ 254 static CK_RV 255 prf_setup(prfContext *context, CK_MECHANISM_TYPE mech) 256 { 257 context->hashType = sftk_map_hmac_to_hash(mech); 258 context->hashObj = NULL; 259 context->hmac = NULL; 260 context->aes = NULL; 261 if (context->hashType != HASH_AlgNULL) { 262 context->hashObj = HASH_GetRawHashObject(context->hashType); 263 if (context->hashObj == NULL) { 264 return CKR_GENERAL_ERROR; 265 } 266 return CKR_OK; 267 } else if (mech == CKM_AES_XCBC_MAC) { 268 return CKR_OK; 269 } 270 return CKR_MECHANISM_PARAM_INVALID; 271 } 272 273 /* return the underlying prf length for this context. This will 274 * function once the context is setup */ 275 static CK_RV 276 prf_length(prfContext *context) 277 { 278 if (context->hashObj) { 279 return context->hashObj->length; 280 } 281 return AES_BLOCK_SIZE; /* 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 */ 288 static CK_RV 289 prf_init(prfContext *context, const unsigned char *keyValue, 290 unsigned int keyLen) 291 { 292 CK_RV crv; 293 294 context->hmac = NULL; 295 if (context->hashObj) { 296 context->hmac = HMAC_Create(context->hashObj, 297 keyValue, keyLen, PR_FALSE); 298 if (context->hmac == NULL) { 299 return sftk_MapCryptError(PORT_GetError()); 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_OK) 306 return crv; 307 context->nextChar = 0; 308 context->aes = AES_CreateContext(context->k1, iv_zero, NSS_AES_CBC, 309 PR_TRUE, sizeof(context->k1), AES_BLOCK_SIZE); 310 if (context->aes == NULL) { 311 crv = sftk_MapCryptError(PORT_GetError()); 312 PORT_Memset(context->k1, 0, sizeof(context->k1)); 313 PORT_Memset(context->k2, 0, sizeof(context->k2)); 314 PORT_Memset(context->k3, 0, sizeof(context->k2)); 315 return crv; 316 } 317 } 318 return CKR_OK; 319 } 320 321 /* 322 * process input to the prf 323 */ 324 static CK_RV 325 prf_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_SIZE) { 338 if (context->nextChar != 0) { 339 /* first handle fill in any partial blocks in the buffer */ 340 unsigned int left = AES_BLOCK_SIZE - context->nextChar; 341 /* note: left can be zero */ 342 PORT_Memcpy(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_GetError()); 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_SIZE); 362 if (rv != SECSuccess) { 363 return sftk_MapCryptError(PORT_GetError()); 364 } 365 len -= AES_BLOCK_SIZE; 366 buf += AES_BLOCK_SIZE; 367 } 368 } 369 PORT_Memcpy(context->padBuf + context->nextChar, buf, len); 370 context->nextChar += len; 371 } 372 return CKR_OK; 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 */ 382 static void 383 prf_free(prfContext *context) 384 { 385 if (context->hmac) { 386 HMAC_Destroy(context->hmac, PR_TRUE); 387 context->hmac = NULL; 388 } 389 if (context->aes) { 390 PORT_Memset(context->k1, 0, sizeof(context->k1)); 391 PORT_Memset(context->k2, 0, sizeof(context->k2)); 392 PORT_Memset(context->k3, 0, sizeof(context->k2)); 393 PORT_Memset(context->padBuf, 0, sizeof(context->padBuf)); 394 PORT_Memset(context->macBuf, 0, sizeof(context->macBuf)); 395 AES_DestroyContext(context->aes, PR_TRUE); 396 context->aes = NULL; 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 */ 404 static CK_RV 405 prf_final(prfContext *context, unsigned char *buf, unsigned int len) 406 { 407 unsigned int tmpLen; 408 SECStatus rv; 409 410 if (context->hmac) { 411 unsigned int outLen; 412 HMAC_Finish(context->hmac, buf, &outLen, len); 413 if (outLen != len) { 414 return CKR_GENERAL_ERROR; 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_SIZE, context->k2, context->k3); 422 if (crv != CKR_OK) { 423 return crv; 424 } 425 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen, 426 sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE); 427 if (rv != SECSuccess) { 428 return sftk_MapCryptError(PORT_GetError()); 429 } 430 PORT_Memcpy(buf, context->macBuf, len); 431 } 432 prf_free(context); 433 return CKR_OK; 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 */ 460 CK_RV 461 sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, 462 const CK_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey) 463 { 464 SFTKAttribute *newKeyValue = NULL; 465 SFTKObject *newKeyObj = NULL; 466 unsigned char outKeyData[HASH_LENGTH_MAX]; 467 unsigned char *newInKey = NULL; 468 unsigned int newInKeySize = 0; 469 unsigned int macSize; 470 CK_RV crv = CKR_OK; 471 prfContext context; 472 473 crv = prf_setup(&context, params->prfMechanism); 474 if (crv != CKR_OK) { 475 return crv; 476 } 477 macSize = prf_length(&context); 478 if ((params->bDataAsKey) && (params->bRekey)) { 479 return CKR_ARGUMENTS_BAD; 480 } 481 if (params->bRekey) { 482 /* lookup the value of new key from the session and key handle */ 483 SFTKSession *session = sftk_SessionFromHandle(hSession); 484 if (session == NULL) { 485 return CKR_SESSION_HANDLE_INVALID; 486 } 487 newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session); 488 sftk_FreeSession(session); 489 if (newKeyObj == NULL) { 490 return CKR_KEY_HANDLE_INVALID; 491 } 492 newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE); 493 if (newKeyValue == NULL) { 494 crv = CKR_KEY_HANDLE_INVALID; 495 goto fail; 496 } 497 } 498 if (params->bDataAsKey) { 499 /* The key is Ni || Np, so we need to concatenate them together first */ 500 newInKeySize = params->ulNiLen + params->ulNrLen; 501 newInKey = PORT_Alloc(newInKeySize); 502 if (newInKey == NULL) { 503 crv = CKR_HOST_MEMORY; 504 goto fail; 505 } 506 PORT_Memcpy(newInKey, params->pNi, params->ulNiLen); 507 PORT_Memcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen); 508 crv = prf_init(&context, newInKey, newInKeySize); 509 if (crv != CKR_OK) { 510 goto fail; 511 } 512 /* key as the data */ 513 crv = prf_update(&context, inKey->attrib.pValue, 514 inKey->attrib.ulValueLen); 515 if (crv != CKR_OK) { 516 goto fail; 517 } 518 } else { 519 crv = prf_init(&context, inKey->attrib.pValue, 520 inKey->attrib.ulValueLen); 521 if (crv != CKR_OK) { 522 goto fail; 523 } 524 if (newKeyValue) { 525 crv = prf_update(&context, newKeyValue->attrib.pValue, 526 newKeyValue->attrib.ulValueLen); 527 if (crv != CKR_OK) { 528 goto fail; 529 } 530 } 531 crv = prf_update(&context, params->pNi, params->ulNiLen); 532 if (crv != CKR_OK) { 533 goto fail; 534 } 535 crv = prf_update(&context, params->pNr, params->ulNrLen); 536 if (crv != CKR_OK) { 537 goto fail; 538 } 539 } 540 crv = prf_final(&context, outKeyData, macSize); 541 if (crv != CKR_OK) { 542 goto fail; 543 } 544 545 crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize); 546 fail: 547 if (newInKey) { 548 PORT_ZFree(newInKey, newInKeySize); 549 } 550 if (newKeyValue) { 551 sftk_FreeAttribute(newKeyValue); 552 } 553 if (newKeyObj) { 554 sftk_FreeObject(newKeyObj); 555 } 556 PORT_Memset(outKeyData, 0, macSize); 557 prf_free(&context); 558 return crv; 559 } 560 561 /* 562 * The second flavor of ike prf is ike1_prf. 563 * 564 * It is used by ikeV1 to generate the various session keys used in the 565 * connection. It uses the initial key, an optional previous key, and a one byte 566 * key number to generate a unique key for each of the various session 567 * functions (encryption, decryption, mac). These keys expect a key size 568 * (as they may vary in length based on usage). If no length is provided, 569 * it will default to the length of the prf. 570 * 571 * This function returns either: 572 * prf(inKey, gxyKey || CKYi || CKYr || key_number) 573 * or 574 * prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number) 575 * depending on the stats of bHasPrevKey 576 * 577 * This is defined in rfc2409. For each of the following keys. 578 * inKey is SKEYID, gxyKey is g^xy 579 * for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0 580 * for outKey = SKEYID_a, prevKey= SKEYID_d, key_number = 1 581 * for outKey = SKEYID_e, prevKey= SKEYID_a, key_number = 2 582 */ 583 CK_RV 584 sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, 585 const CK_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey, 586 unsigned int keySize) 587 { 588 SFTKAttribute *gxyKeyValue = NULL; 589 SFTKObject *gxyKeyObj = NULL; 590 SFTKAttribute *prevKeyValue = NULL; 591 SFTKObject *prevKeyObj = NULL; 592 SFTKSession *session; 593 unsigned char outKeyData[HASH_LENGTH_MAX]; 594 unsigned int macSize; 595 CK_RV crv; 596 prfContext context; 597 598 crv = prf_setup(&context, params->prfMechanism); 599 if (crv != CKR_OK) { 600 return crv; 601 } 602 macSize = prf_length(&context); 603 if (keySize > macSize) { 604 return CKR_KEY_SIZE_RANGE; 605 } 606 if (keySize == 0) { 607 keySize = macSize; 608 } 609 610 /* lookup the two keys from their passed in handles */ 611 session = sftk_SessionFromHandle(hSession); 612 if (session == NULL) { 613 return CKR_SESSION_HANDLE_INVALID; 614 } 615 gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session); 616 if (params->bHasPrevKey) { 617 prevKeyObj = sftk_ObjectFromHandle(params->hPrevKey, session); 618 } 619 sftk_FreeSession(session); 620 if ((gxyKeyObj == NULL) || ((params->bHasPrevKey) && 621 (prevKeyObj == NULL))) { 622 crv = CKR_KEY_HANDLE_INVALID; 623 goto fail; 624 } 625 gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE); 626 if (gxyKeyValue == NULL) { 627 crv = CKR_KEY_HANDLE_INVALID; 628 goto fail; 629 } 630 if (prevKeyObj) { 631 prevKeyValue = sftk_FindAttribute(prevKeyObj, CKA_VALUE); 632 if (prevKeyValue == NULL) { 633 crv = CKR_KEY_HANDLE_INVALID; 634 goto fail; 635 } 636 } 637 638 /* outKey = prf(inKey, [prevKey|] gxyKey | CKYi | CKYr | keyNumber) */ 639 crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen); 640 if (crv != CKR_OK) { 641 goto fail; 642 } 643 if (prevKeyValue) { 644 crv = prf_update(&context, prevKeyValue->attrib.pValue, 645 prevKeyValue->attrib.ulValueLen); 646 if (crv != CKR_OK) { 647 goto fail; 648 } 649 } 650 crv = prf_update(&context, gxyKeyValue->attrib.pValue, 651 gxyKeyValue->attrib.ulValueLen); 652 if (crv != CKR_OK) { 653 goto fail; 654 } 655 crv = prf_update(&context, params->pCKYi, params->ulCKYiLen); 656 if (crv != CKR_OK) { 657 goto fail; 658 } 659 crv = prf_update(&context, params->pCKYr, params->ulCKYrLen); 660 if (crv != CKR_OK) { 661 goto fail; 662 } 663 crv = prf_update(&context, ¶ms->keyNumber, 1); 664 if (crv != CKR_OK) { 665 goto fail; 666 } 667 crv = prf_final(&context, outKeyData, macSize); 668 if (crv != CKR_OK) { 669 goto fail; 670 } 671 672 crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize); 673 fail: 674 if (gxyKeyValue) { 675 sftk_FreeAttribute(gxyKeyValue); 676 } 677 if (prevKeyValue) { 678 sftk_FreeAttribute(prevKeyValue); 679 } 680 if (gxyKeyObj) { 681 sftk_FreeObject(gxyKeyObj); 682 } 683 if (prevKeyObj) { 684 sftk_FreeObject(prevKeyObj); 685 } 686 PORT_Memset(outKeyData, 0, macSize); 687 prf_free(&context); 688 return crv; 689 } 690 691 /* 692 * The third flavor of ike prf is ike1_appendix_b. 693 * 694 * It is used by ikeV1 to generate longer key material from skeyid_e. 695 * Unlike ike1_prf, if no length is provided, this function 696 * will generate a KEY_RANGE_ERROR. 697 * 698 * This function returns (from rfc2409 appendix b): 699 * Ka = K1 | K2 | K3 | K4 |... Kn 700 * where: 701 * K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData 702 * ar not present. 703 * K2 = prf(K, K1|[gxyKey]|[extraData]) 704 * K3 = prf(K, K2|[gxyKey]|[extraData]) 705 * K4 = prf(K, K3|[gxyKey]|[extraData]) 706 * . 707 * Kn = prf(K, K(n-1)|[gxyKey]|[extraData]) 708 * K = inKey 709 */ 710 CK_RV 711 sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, 712 const CK_IKE1_EXTENDED_DERIVE_PARAMS *params, 713 SFTKObject *outKey, unsigned int keySize) 714 { 715 SFTKAttribute *gxyKeyValue = NULL; 716 SFTKObject *gxyKeyObj = NULL; 717 unsigned char *outKeyData = NULL; 718 unsigned char *thisKey = NULL; 719 unsigned char *lastKey = NULL; 720 unsigned int macSize; 721 unsigned int outKeySize; 722 unsigned int genKeySize; 723 PRBool quickMode = PR_FALSE; 724 CK_RV crv; 725 prfContext context; 726 727 if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL)) { 728 return CKR_ARGUMENTS_BAD; 729 } 730 crv = prf_setup(&context, params->prfMechanism); 731 if (crv != CKR_OK) { 732 return crv; 733 } 734 735 if (params->bHasKeygxy) { 736 SFTKSession *session; 737 session = sftk_SessionFromHandle(hSession); 738 if (session == NULL) { 739 return CKR_SESSION_HANDLE_INVALID; 740 } 741 gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session); 742 sftk_FreeSession(session); 743 if (gxyKeyObj == NULL) { 744 crv = CKR_KEY_HANDLE_INVALID; 745 goto fail; 746 } 747 gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE); 748 if (gxyKeyValue == NULL) { 749 crv = CKR_KEY_HANDLE_INVALID; 750 goto fail; 751 } 752 quickMode = PR_TRUE; 753 } 754 755 if (params->ulExtraDataLen != 0) { 756 quickMode = PR_TRUE; 757 } 758 759 macSize = prf_length(&context); 760 761 if (keySize == 0) { 762 keySize = macSize; 763 } 764 765 /* In appendix B, we are just expanding or contracting a single key. 766 * If the input key is less than or equal to the the key size we want, 767 * just subset the original key. In quick mode we are actually getting 768 * new keys (salted with our seed data and our gxy key), so we want to 769 * run through our algorithm */ 770 if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) { 771 return sftk_forceAttribute(outKey, CKA_VALUE, 772 inKey->attrib.pValue, keySize); 773 } 774 775 outKeySize = PR_ROUNDUP(keySize, macSize); 776 outKeyData = PORT_Alloc(outKeySize); 777 if (outKeyData == NULL) { 778 crv = CKR_HOST_MEMORY; 779 goto fail; 780 } 781 782 /* 783 * this loop generates on block of the prf, basically 784 * kn = prf(key, Kn-1 | [Keygxy] | [ExtraData]) 785 * Kn is thisKey, Kn-1 is lastKey 786 * key is inKey 787 */ 788 thisKey = outKeyData; 789 for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) { 790 PRBool hashedData = PR_FALSE; 791 crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen); 792 if (crv != CKR_OK) { 793 goto fail; 794 } 795 if (lastKey != NULL) { 796 crv = prf_update(&context, lastKey, macSize); 797 if (crv != CKR_OK) { 798 goto fail; 799 } 800 hashedData = PR_TRUE; 801 } 802 if (gxyKeyValue != NULL) { 803 crv = prf_update(&context, gxyKeyValue->attrib.pValue, 804 gxyKeyValue->attrib.ulValueLen); 805 if (crv != CKR_OK) { 806 goto fail; 807 } 808 hashedData = PR_TRUE; 809 } 810 if (params->ulExtraDataLen != 0) { 811 crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen); 812 if (crv != CKR_OK) { 813 goto fail; 814 } 815 hashedData = PR_TRUE; 816 } 817 /* if we haven't hashed anything yet, hash a zero */ 818 if (hashedData == PR_FALSE) { 819 const unsigned char zero = 0; 820 crv = prf_update(&context, &zero, 1); 821 if (crv != CKR_OK) { 822 goto fail; 823 } 824 } 825 crv = prf_final(&context, thisKey, macSize); 826 if (crv != CKR_OK) { 827 goto fail; 828 } 829 lastKey = thisKey; 830 thisKey += macSize; 831 } 832 crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize); 833 fail: 834 if (gxyKeyValue) { 835 sftk_FreeAttribute(gxyKeyValue); 836 } 837 if (gxyKeyObj) { 838 sftk_FreeObject(gxyKeyObj); 839 } 840 if (outKeyData) { 841 PORT_ZFree(outKeyData, outKeySize); 842 } 843 prf_free(&context); 844 return crv; 845 } 846 847 /* 848 * The final flavor of ike prf is ike_prf_plus 849 * 850 * It is used by ikeV2 to generate the various session keys used in the 851 * connection. It uses the initial key and a feedback version of the prf 852 * to generate sufficient bytes to cover all the session keys. The application 853 * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys. 854 * This function expects a key size to be set by the application to cover 855 * all the keys. Unlike ike1_prf, if no length is provided, this function 856 * will generate a KEY_RANGE_ERROR 857 * 858 * This function returns (from rfc5996): 859 * prfplus = T1 | T2 | T3 | T4 |... Tn 860 * where: 861 * T1 = prf(K, S | 0x01) 862 * T2 = prf(K, T1 | S | 0x02) 863 * T3 = prf(K, T3 | S | 0x03) 864 * T4 = prf(K, T4 | S | 0x04) 865 * . 866 * Tn = prf(K, T(n-1) | n) 867 * K = inKey, S = seedKey | seedData 868 */ 869 870 static CK_RV 871 sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession, 872 const unsigned char *inKeyData, CK_ULONG inKeyLen, 873 const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params, 874 unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr, 875 unsigned int keySize) 876 { 877 SFTKAttribute *seedValue = NULL; 878 SFTKObject *seedKeyObj = NULL; 879 unsigned char *outKeyData = NULL; 880 unsigned int outKeySize; 881 unsigned char *thisKey; 882 unsigned char *lastKey = NULL; 883 unsigned char currentByte = 0; 884 unsigned int getKeySize; 885 unsigned int macSize; 886 CK_RV crv; 887 prfContext context; 888 889 if (keySize == 0) { 890 return CKR_KEY_SIZE_RANGE; 891 } 892 893 crv = prf_setup(&context, params->prfMechanism); 894 if (crv != CKR_OK) { 895 return crv; 896 } 897 /* pull in optional seedKey */ 898 if (params->bHasSeedKey) { 899 SFTKSession *session = sftk_SessionFromHandle(hSession); 900 if (session == NULL) { 901 return CKR_SESSION_HANDLE_INVALID; 902 } 903 seedKeyObj = sftk_ObjectFromHandle(params->hSeedKey, session); 904 sftk_FreeSession(session); 905 if (seedKeyObj == NULL) { 906 return CKR_KEY_HANDLE_INVALID; 907 } 908 seedValue = sftk_FindAttribute(seedKeyObj, CKA_VALUE); 909 if (seedValue == NULL) { 910 crv = CKR_KEY_HANDLE_INVALID; 911 goto fail; 912 } 913 } else if (params->ulSeedDataLen == 0) { 914 crv = CKR_ARGUMENTS_BAD; 915 goto fail; 916 } 917 macSize = prf_length(&context); 918 outKeySize = PR_ROUNDUP(keySize, macSize); 919 outKeyData = PORT_Alloc(outKeySize); 920 if (outKeyData == NULL) { 921 crv = CKR_HOST_MEMORY; 922 goto fail; 923 } 924 925 /* 926 * this loop generates on block of the prf, basically 927 * Tn = prf(key, Tn-1 | S | n) 928 * Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData, 929 * key is inKey. currentByte = n-1 on entry. 930 */ 931 thisKey = outKeyData; 932 for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) { 933 /* if currentByte is 255, we'll overflow when we increment it below. 934 * This can only happen if keysize > 255*macSize. In that case 935 * the application has asked for too much key material, so return 936 * an error */ 937 if (currentByte == 255) { 938 crv = CKR_KEY_SIZE_RANGE; 939 goto fail; 940 } 941 crv = prf_init(&context, inKeyData, inKeyLen); 942 if (crv != CKR_OK) { 943 goto fail; 944 } 945 946 if (lastKey) { 947 crv = prf_update(&context, lastKey, macSize); 948 if (crv != CKR_OK) { 949 goto fail; 950 } 951 } 952 /* prf the key first */ 953 if (seedValue) { 954 crv = prf_update(&context, seedValue->attrib.pValue, 955 seedValue->attrib.ulValueLen); 956 if (crv != CKR_OK) { 957 goto fail; 958 } 959 } 960 /* then prf the data */ 961 if (params->ulSeedDataLen != 0) { 962 crv = prf_update(&context, params->pSeedData, 963 params->ulSeedDataLen); 964 if (crv != CKR_OK) { 965 goto fail; 966 } 967 } 968 currentByte++; 969 crv = prf_update(&context, ¤tByte, 1); 970 if (crv != CKR_OK) { 971 goto fail; 972 } 973 crv = prf_final(&context, thisKey, macSize); 974 if (crv != CKR_OK) { 975 goto fail; 976 } 977 lastKey = thisKey; 978 thisKey += macSize; 979 } 980 *outKeyDataPtr = outKeyData; 981 *outKeySizePtr = outKeySize; 982 outKeyData = NULL; /* don't free it here, our caller will free it */ 983 fail: 984 if (outKeyData) { 985 PORT_ZFree(outKeyData, outKeySize); 986 } 987 if (seedValue) { 988 sftk_FreeAttribute(seedValue); 989 } 990 if (seedKeyObj) { 991 sftk_FreeObject(seedKeyObj); 992 } 993 prf_free(&context); 994 return crv; 995 } 996 997 /* 998 * ike prf + with code to deliever results tosoftoken objects. 999 */ 1000 CK_RV 1001 sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey, 1002 const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey, 1003 unsigned int keySize) 1004 { 1005 unsigned char *outKeyData = NULL; 1006 unsigned int outKeySize; 1007 CK_RV crv; 1008 1009 crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue, 1010 inKey->attrib.ulValueLen, params, 1011 &outKeyData, &outKeySize, keySize); 1012 if (crv != CKR_OK) { 1013 return crv; 1014 } 1015 1016 crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize); 1017 PORT_ZFree(outKeyData, outKeySize); 1018 return crv; 1019 } 1020 1021 /* sftk_aes_xcbc_new_keys: 1022 * 1023 * aes xcbc creates 3 new keys from the input key. The first key will be the 1024 * base key of the underlying cbc. The sign code hooks directly into encrypt 1025 * so we'll have to create a full PKCS #11 key with handle for that key. The 1026 * caller needs to delete the key when it's through setting up the context. 1027 * 1028 * The other two keys will be stored in the sign context until we need them 1029 * at the end. 1030 */ 1031 CK_RV 1032 sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession, 1033 CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey, 1034 unsigned char *k2, unsigned char *k3) 1035 { 1036 SFTKObject *key = NULL; 1037 SFTKSession *session = NULL; 1038 SFTKObject *inKeyObj = NULL; 1039 SFTKAttribute *inKeyValue = NULL; 1040 CK_KEY_TYPE key_type = CKK_AES; 1041 CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; 1042 CK_BBOOL ck_true = CK_TRUE; 1043 CK_RV crv = CKR_OK; 1044 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1045 unsigned char buf[AES_BLOCK_SIZE]; 1046 1047 if (!slot) { 1048 return CKR_SESSION_HANDLE_INVALID; 1049 } 1050 1051 /* get the session */ 1052 session = sftk_SessionFromHandle(hSession); 1053 if (session == NULL) { 1054 crv = CKR_SESSION_HANDLE_INVALID; 1055 goto fail; 1056 } 1057 1058 inKeyObj = sftk_ObjectFromHandle(hKey, session); 1059 if (inKeyObj == NULL) { 1060 crv = CKR_KEY_HANDLE_INVALID; 1061 goto fail; 1062 } 1063 1064 inKeyValue = sftk_FindAttribute(inKeyObj, CKA_VALUE); 1065 if (inKeyValue == NULL) { 1066 crv = CKR_KEY_HANDLE_INVALID; 1067 goto fail; 1068 } 1069 1070 crv = sftk_aes_xcbc_get_keys(inKeyValue->attrib.pValue, 1071 inKeyValue->attrib.ulValueLen, buf, k2, k3); 1072 1073 if (crv != CKR_OK) { 1074 goto fail; 1075 } 1076 1077 /* 1078 * now lets create an object to hang the attributes off of 1079 */ 1080 key = sftk_NewObject(slot); /* fill in the handle later */ 1081 if (key == NULL) { 1082 crv = CKR_HOST_MEMORY; 1083 goto fail; 1084 } 1085 1086 /* make sure we don't have any class, key_type, or value fields */ 1087 sftk_DeleteAttributeType(key, CKA_CLASS); 1088 sftk_DeleteAttributeType(key, CKA_KEY_TYPE); 1089 sftk_DeleteAttributeType(key, CKA_VALUE); 1090 sftk_DeleteAttributeType(key, CKA_SIGN); 1091 1092 /* Add the class, key_type, and value */ 1093 crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); 1094 if (crv != CKR_OK) { 1095 goto fail; 1096 } 1097 crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); 1098 if (crv != CKR_OK) { 1099 goto fail; 1100 } 1101 crv = sftk_AddAttributeType(key, CKA_SIGN, &ck_true, sizeof(CK_BBOOL)); 1102 if (crv != CKR_OK) { 1103 goto fail; 1104 } 1105 crv = sftk_AddAttributeType(key, CKA_VALUE, buf, AES_BLOCK_SIZE); 1106 if (crv != CKR_OK) { 1107 goto fail; 1108 } 1109 1110 /* 1111 * finish filling in the key and link it with our global system. 1112 */ 1113 crv = sftk_handleObject(key, session); 1114 if (crv != CKR_OK) { 1115 goto fail; 1116 } 1117 *phKey = key->handle; 1118 fail: 1119 if (session) { 1120 sftk_FreeSession(session); 1121 } 1122 1123 if (inKeyValue) { 1124 sftk_FreeAttribute(inKeyValue); 1125 } 1126 if (inKeyObj) { 1127 sftk_FreeObject(inKeyObj); 1128 } 1129 if (key) { 1130 sftk_FreeObject(key); 1131 } 1132 /* clear our CSPs */ 1133 PORT_Memset(buf, 0, sizeof(buf)); 1134 if (crv != CKR_OK) { 1135 PORT_Memset(k2, 0, AES_BLOCK_SIZE); 1136 PORT_Memset(k3, 0, AES_BLOCK_SIZE); 1137 } 1138 return crv; 1139 } 1140 1141 /* 1142 * Helper function that tests a single prf test vector 1143 */ 1144 static SECStatus 1145 prf_test(CK_MECHANISM_TYPE mech, 1146 const unsigned char *inKey, unsigned int inKeyLen, 1147 const unsigned char *plainText, unsigned int plainTextLen, 1148 const unsigned char *expectedResult, unsigned int expectedResultLen) 1149 { 1150 PRUint8 ike_computed_mac[HASH_LENGTH_MAX]; 1151 prfContext context; 1152 unsigned int macSize; 1153 CK_RV crv; 1154 1155 crv = prf_setup(&context, mech); 1156 if (crv != CKR_OK) { 1157 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1158 return SECFailure; 1159 } 1160 macSize = prf_length(&context); 1161 crv = prf_init(&context, inKey, inKeyLen); 1162 if (crv != CKR_OK) { 1163 goto fail; 1164 } 1165 crv = prf_update(&context, plainText, plainTextLen); 1166 if (crv != CKR_OK) { 1167 goto fail; 1168 } 1169 crv = prf_final(&context, ike_computed_mac, macSize); 1170 if (crv != CKR_OK) { 1171 goto fail; 1172 } 1173 1174 if (macSize != expectedResultLen) { 1175 goto fail; 1176 } 1177 if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) { 1178 goto fail; 1179 } 1180 1181 /* only do the alignment if the plaintext is long enough */ 1182 if (plainTextLen <= macSize) { 1183 return SECSuccess; 1184 } 1185 prf_free(&context); 1186 /* do it again, but this time tweak with the alignment */ 1187 crv = prf_init(&context, inKey, inKeyLen); 1188 if (crv != CKR_OK) { 1189 goto fail; 1190 } 1191 crv = prf_update(&context, plainText, 1); 1192 if (crv != CKR_OK) { 1193 goto fail; 1194 } 1195 crv = prf_update(&context, &plainText[1], macSize); 1196 if (crv != CKR_OK) { 1197 goto fail; 1198 } 1199 crv = prf_update(&context, &plainText[1 + macSize], plainTextLen - (macSize + 1)); 1200 if (crv != CKR_OK) { 1201 goto fail; 1202 } 1203 crv = prf_final(&context, ike_computed_mac, macSize); 1204 if (crv != CKR_OK) { 1205 goto fail; 1206 } 1207 if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) { 1208 goto fail; 1209 } 1210 prf_free(&context); 1211 return SECSuccess; 1212 fail: 1213 prf_free(&context); 1214 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1215 return SECFailure; 1216 } 1217 1218 /* 1219 * FIPS Power up Self Tests for IKE. This is in this function so it 1220 * can access the private prf_ functions here. It's called out of fipstest.c 1221 */ 1222 SECStatus 1223 sftk_fips_IKE_PowerUpSelfTests(void) 1224 { 1225 /* PRF known test vectors */ 1226 static const PRUint8 ike_xcbc_known_key[] = { 1227 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1228 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 1229 }; 1230 static const PRUint8 ike_xcbc_known_plain_text[] = { 1231 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1232 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 1233 }; 1234 static const PRUint8 ike_xcbc_known_mac[] = { 1235 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, 1236 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 1237 }; 1238 /* test 2 uses the same key as test 1 */ 1239 static const PRUint8 ike_xcbc_known_plain_text_2[] = { 1240 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1241 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 1242 0x10, 0x11, 0x12, 0x13 1243 }; 1244 static const PRUint8 ike_xcbc_known_mac_2[] = { 1245 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15, 1246 0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 1247 }; 1248 static const PRUint8 ike_xcbc_known_key_3[] = { 1249 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1250 0x08, 0x09 1251 }; 1252 /* test 3 uses the same plaintest as test 2 */ 1253 static const PRUint8 ike_xcbc_known_mac_3[] = { 1254 0x0f, 0xa0, 0x87, 0xaf, 0x7d, 0x86, 0x6e, 0x76, 1255 0x53, 0x43, 0x4e, 0x60, 0x2f, 0xdd, 0xe8, 0x35 1256 }; 1257 static const PRUint8 ike_xcbc_known_key_4[] = { 1258 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 1259 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 1260 0xed, 0xcb 1261 }; 1262 /* test 4 uses the same plaintest as test 2 */ 1263 static const PRUint8 ike_xcbc_known_mac_4[] = { 1264 0x8c, 0xd3, 0xc9, 0x3a, 0xe5, 0x98, 0xa9, 0x80, 1265 0x30, 0x06, 0xff, 0xb6, 0x7c, 0x40, 0xe9, 0xe4 1266 }; 1267 static const PRUint8 ike_sha1_known_key[] = { 1268 0x59, 0x98, 0x2b, 0x5b, 0xa5, 0x7e, 0x62, 0xc0, 1269 0x46, 0x0d, 0xef, 0xc7, 0x1e, 0x18, 0x64, 0x63 1270 }; 1271 static const PRUint8 ike_sha1_known_plain_text[] = { 1272 0x1c, 0x07, 0x32, 0x1a, 0x9a, 0x7e, 0x41, 0xcd, 1273 0x88, 0x0c, 0xa3, 0x7a, 0xdb, 0x10, 0xc7, 0x3b, 1274 0xf0, 0x0e, 0x7a, 0xe3, 0xcf, 0xc6, 0xfd, 0x8b, 1275 0x51, 0xbc, 0xe2, 0xb9, 0x90, 0xe6, 0xf2, 0x01 1276 }; 1277 static const PRUint8 ike_sha1_known_mac[] = { 1278 0x0c, 0x2a, 0xf3, 0x42, 0x97, 0x15, 0x62, 0x1d, 1279 0x2a, 0xad, 0xc9, 0x94, 0x5a, 0x90, 0x26, 0xfa, 1280 0xc7, 0x91, 0xe2, 0x4b 1281 }; 1282 static const PRUint8 ike_sha256_known_key[] = { 1283 0x9d, 0xa2, 0xd5, 0x8f, 0x57, 0xf0, 0x39, 0xf9, 1284 0x20, 0x4e, 0x0d, 0xd0, 0xef, 0x04, 0xf3, 0x72 1285 }; 1286 static const PRUint8 ike_sha256_known_plain_text[] = { 1287 0x33, 0xf1, 0x7a, 0xfc, 0xb6, 0x13, 0x4c, 0xbf, 1288 0x1c, 0xab, 0x59, 0x87, 0x7d, 0x42, 0xdb, 0x35, 1289 0x82, 0x22, 0x6e, 0xff, 0x74, 0xdd, 0x37, 0xeb, 1290 0x8b, 0x75, 0xe6, 0x75, 0x64, 0x5f, 0xc1, 0x69 1291 }; 1292 static const PRUint8 ike_sha256_known_mac[] = { 1293 0x80, 0x4b, 0x4a, 0x1e, 0x0e, 0xc5, 0x93, 0xcf, 1294 0xb6, 0xe4, 0x54, 0x52, 0x41, 0x49, 0x39, 0x6d, 1295 0xe2, 0x34, 0xd0, 0xda, 0xe2, 0x9f, 0x34, 0xa8, 1296 0xfd, 0xb5, 0xf9, 0xaf, 0xe7, 0x6e, 0xa6, 0x52 1297 }; 1298 static const PRUint8 ike_sha384_known_key[] = { 1299 0xce, 0xc8, 0x9d, 0x84, 0x5a, 0xdd, 0x83, 0xef, 1300 0xce, 0xbd, 0x43, 0xab, 0x71, 0xd1, 0x7d, 0xb9 1301 }; 1302 static const PRUint8 ike_sha384_known_plain_text[] = { 1303 0x17, 0x24, 0xdb, 0xd8, 0x93, 0x52, 0x37, 0x64, 1304 0xbf, 0xef, 0x8c, 0x6f, 0xa9, 0x27, 0x85, 0x6f, 1305 0xcc, 0xfb, 0x77, 0xae, 0x25, 0x43, 0x58, 0xcc, 1306 0xe2, 0x9c, 0x27, 0x69, 0xa3, 0x29, 0x15, 0xc1 1307 }; 1308 static const PRUint8 ike_sha384_known_mac[] = { 1309 0x6e, 0x45, 0x14, 0x61, 0x0b, 0xf8, 0x2d, 0x0a, 1310 0xb7, 0xbf, 0x02, 0x60, 0x09, 0x6f, 0x61, 0x46, 1311 0xa1, 0x53, 0xc7, 0x12, 0x07, 0x1a, 0xbb, 0x63, 1312 0x3c, 0xed, 0x81, 0x3c, 0x57, 0x21, 0x56, 0xc7, 1313 0x83, 0xe3, 0x68, 0x74, 0xa6, 0x5a, 0x64, 0x69, 1314 0x0c, 0xa7, 0x01, 0xd4, 0x0d, 0x56, 0xea, 0x18 1315 }; 1316 static const PRUint8 ike_sha512_known_key[] = { 1317 0xac, 0xad, 0xc6, 0x31, 0x4a, 0x69, 0xcf, 0xcd, 1318 0x4e, 0x4a, 0xd1, 0x77, 0x18, 0xfe, 0xa7, 0xce 1319 }; 1320 static const PRUint8 ike_sha512_known_plain_text[] = { 1321 0xb1, 0x5a, 0x9c, 0xfc, 0xe8, 0xc8, 0xd7, 0xea, 1322 0xb8, 0x79, 0xd6, 0x24, 0x30, 0x29, 0xd4, 0x01, 1323 0x88, 0xd3, 0xb7, 0x40, 0x87, 0x5a, 0x6a, 0xc6, 1324 0x2f, 0x56, 0xca, 0xc4, 0x37, 0x7e, 0x2e, 0xdd 1325 }; 1326 static const PRUint8 ike_sha512_known_mac[] = { 1327 0xf0, 0x5a, 0xa0, 0x36, 0xdf, 0xce, 0x45, 0xa5, 1328 0x58, 0xd4, 0x04, 0x18, 0xde, 0xa9, 0x80, 0x96, 1329 0xe5, 0x19, 0xbc, 0x78, 0x41, 0xe3, 0xdb, 0x3d, 1330 0xd9, 0x36, 0x58, 0xd1, 0x18, 0xc3, 0xe8, 0x3b, 1331 0x50, 0x2f, 0x39, 0x8e, 0xcb, 0x13, 0x61, 0xec, 1332 0x77, 0xd3, 0x8a, 0x88, 0x55, 0xef, 0xff, 0x40, 1333 0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e, 1334 0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b 1335 }; 1336 static const PRUint8 ike_known_sha256_prf_plus[] = { 1337 0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72, 1338 0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb, 1339 0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b, 1340 0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d, 1341 0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3, 1342 0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5, 1343 0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4, 1344 0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39 1345 }; 1346 SECStatus rv; 1347 CK_RV crv; 1348 unsigned char *outKeyData = NULL; 1349 unsigned int outKeySize; 1350 CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike_params; 1351 1352 rv = prf_test(CKM_AES_XCBC_MAC, 1353 ike_xcbc_known_key, sizeof(ike_xcbc_known_key), 1354 ike_xcbc_known_plain_text, sizeof(ike_xcbc_known_plain_text), 1355 ike_xcbc_known_mac, sizeof(ike_xcbc_known_mac)); 1356 if (rv != SECSuccess) 1357 return rv; 1358 rv = prf_test(CKM_AES_XCBC_MAC, 1359 ike_xcbc_known_key, sizeof(ike_xcbc_known_key), 1360 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2), 1361 ike_xcbc_known_mac_2, sizeof(ike_xcbc_known_mac_2)); 1362 if (rv != SECSuccess) 1363 return rv; 1364 rv = prf_test(CKM_AES_XCBC_MAC, 1365 ike_xcbc_known_key_3, sizeof(ike_xcbc_known_key_3), 1366 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2), 1367 ike_xcbc_known_mac_3, sizeof(ike_xcbc_known_mac_3)); 1368 if (rv != SECSuccess) 1369 return rv; 1370 rv = prf_test(CKM_AES_XCBC_MAC, 1371 ike_xcbc_known_key_4, sizeof(ike_xcbc_known_key_4), 1372 ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2), 1373 ike_xcbc_known_mac_4, sizeof(ike_xcbc_known_mac_4)); 1374 if (rv != SECSuccess) 1375 return rv; 1376 rv = prf_test(CKM_SHA_1_HMAC, 1377 ike_sha1_known_key, sizeof(ike_sha1_known_key), 1378 ike_sha1_known_plain_text, sizeof(ike_sha1_known_plain_text), 1379 ike_sha1_known_mac, sizeof(ike_sha1_known_mac)); 1380 if (rv != SECSuccess) 1381 return rv; 1382 rv = prf_test(CKM_SHA256_HMAC, 1383 ike_sha256_known_key, sizeof(ike_sha256_known_key), 1384 ike_sha256_known_plain_text, 1385 sizeof(ike_sha256_known_plain_text), 1386 ike_sha256_known_mac, sizeof(ike_sha256_known_mac)); 1387 if (rv != SECSuccess) 1388 return rv; 1389 rv = prf_test(CKM_SHA384_HMAC, 1390 ike_sha384_known_key, sizeof(ike_sha384_known_key), 1391 ike_sha384_known_plain_text, 1392 sizeof(ike_sha384_known_plain_text), 1393 ike_sha384_known_mac, sizeof(ike_sha384_known_mac)); 1394 if (rv != SECSuccess) 1395 return rv; 1396 rv = prf_test(CKM_SHA512_HMAC, 1397 ike_sha512_known_key, sizeof(ike_sha512_known_key), 1398 ike_sha512_known_plain_text, 1399 sizeof(ike_sha512_known_plain_text), 1400 ike_sha512_known_mac, sizeof(ike_sha512_known_mac)); 1401 1402 ike_params.prfMechanism = CKM_SHA256_HMAC; 1403 ike_params.bHasSeedKey = PR_FALSE; 1404 ike_params.hSeedKey = CK_INVALID_HANDLE; 1405 ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text; 1406 ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text); 1407 crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE, ike_sha256_known_key, 1408 sizeof(ike_sha256_known_key), &ike_params, 1409 &outKeyData, &outKeySize, 64); 1410 if ((crv != CKR_OK) || 1411 (outKeySize != sizeof(ike_known_sha256_prf_plus)) || 1412 (PORT_Memcmp(outKeyData, ike_known_sha256_prf_plus, 1413 sizeof(ike_known_sha256_prf_plus)) != 0)) { 1414 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1415 return SECFailure; 1416 } 1417 PORT_ZFree(outKeyData, outKeySize); 1418 return rv; 1419 }