| OLD | NEW |
| (Empty) |
| 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 #include "plarena.h" | |
| 6 | |
| 7 #include "seccomon.h" | |
| 8 #include "secitem.h" | |
| 9 #include "secport.h" | |
| 10 #include "hasht.h" | |
| 11 #include "pkcs11t.h" | |
| 12 #include "sechash.h" | |
| 13 #include "secasn1.h" | |
| 14 #include "secder.h" | |
| 15 #include "secoid.h" | |
| 16 #include "secerr.h" | |
| 17 #include "secmod.h" | |
| 18 #include "pk11func.h" | |
| 19 #include "secpkcs5.h" | |
| 20 #include "secmodi.h" | |
| 21 #include "secmodti.h" | |
| 22 #include "pkcs11.h" | |
| 23 #include "pk11func.h" | |
| 24 #include "secitem.h" | |
| 25 #include "key.h" | |
| 26 | |
| 27 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; | |
| 28 struct SEC_PKCS5PBEParameterStr { | |
| 29 PLArenaPool *poolp; | |
| 30 SECItem salt; /* octet string */ | |
| 31 SECItem iteration; /* integer */ | |
| 32 SECItem keyLength; /* PKCS5v2 only */ | |
| 33 SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */ | |
| 34 SECAlgorithmID prfAlgId; /* PKCS5v2 only */ | |
| 35 }; | |
| 36 | |
| 37 /* PKCS5 V2 has an algorithm ID for the encryption and for | |
| 38 * the key generation. This is valid for SEC_OID_PKCS5_PBES2 | |
| 39 * and SEC_OID_PKCS5_PBMAC1 | |
| 40 */ | |
| 41 struct sec_pkcs5V2ParameterStr { | |
| 42 PLArenaPool *poolp; | |
| 43 SECAlgorithmID pbeAlgId; /* real pbe algorithms */ | |
| 44 SECAlgorithmID cipherAlgId; /* encryption/mac */ | |
| 45 }; | |
| 46 | |
| 47 typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter; | |
| 48 | |
| 49 | |
| 50 /* template for PKCS 5 PBE Parameter. This template has been expanded | |
| 51 * based upon the additions in PKCS 12. This should eventually be moved | |
| 52 * if RSA updates PKCS 5. | |
| 53 */ | |
| 54 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = | |
| 55 { | |
| 56 { SEC_ASN1_SEQUENCE, | |
| 57 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
| 58 { SEC_ASN1_OCTET_STRING, | |
| 59 offsetof(SEC_PKCS5PBEParameter, salt) }, | |
| 60 { SEC_ASN1_INTEGER, | |
| 61 offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
| 62 { 0 } | |
| 63 }; | |
| 64 | |
| 65 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = | |
| 66 { | |
| 67 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
| 68 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, | |
| 69 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
| 70 { 0 } | |
| 71 }; | |
| 72 | |
| 73 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
| 74 | |
| 75 /* SECOID_PKCS5_PBKDF2 */ | |
| 76 const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] = | |
| 77 { | |
| 78 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
| 79 /* This is really a choice, but since we only understand this | |
| 80 * choice, just inline it */ | |
| 81 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, | |
| 82 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
| 83 { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL, | |
| 84 offsetof(SEC_PKCS5PBEParameter, keyLength) }, | |
| 85 { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, | |
| 86 offsetof(SEC_PKCS5PBEParameter, pPrfAlgId), | |
| 87 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 88 { 0 } | |
| 89 }; | |
| 90 | |
| 91 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */ | |
| 92 const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] = | |
| 93 { | |
| 94 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
| 95 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId), | |
| 96 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 97 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 98 offsetof(sec_pkcs5V2Parameter, cipherAlgId), | |
| 99 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 100 { 0 } | |
| 101 }; | |
| 102 | |
| 103 | |
| 104 /* | |
| 105 * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1 | |
| 106 * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2. | |
| 107 */ | |
| 108 SECOidTag | |
| 109 sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm) | |
| 110 { | |
| 111 switch(algorithm) | |
| 112 { | |
| 113 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
| 114 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
| 115 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: | |
| 116 return SEC_OID_DES_EDE3_CBC; | |
| 117 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: | |
| 118 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: | |
| 119 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: | |
| 120 return SEC_OID_DES_CBC; | |
| 121 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
| 122 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
| 123 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
| 124 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
| 125 return SEC_OID_RC2_CBC; | |
| 126 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
| 127 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
| 128 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
| 129 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
| 130 return SEC_OID_RC4; | |
| 131 case SEC_OID_PKCS5_PBKDF2: | |
| 132 case SEC_OID_PKCS5_PBES2: | |
| 133 case SEC_OID_PKCS5_PBMAC1: | |
| 134 return SEC_OID_PKCS5_PBKDF2; | |
| 135 default: | |
| 136 break; | |
| 137 } | |
| 138 | |
| 139 return SEC_OID_UNKNOWN; | |
| 140 } | |
| 141 | |
| 142 /* | |
| 143 * get a new PKCS5 V2 Parameter from the algorithm id. | |
| 144 * if arena is passed in, use it, otherwise create a new arena. | |
| 145 */ | |
| 146 sec_pkcs5V2Parameter * | |
| 147 sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid) | |
| 148 { | |
| 149 PLArenaPool *localArena = NULL; | |
| 150 sec_pkcs5V2Parameter *pbeV2_param; | |
| 151 SECStatus rv; | |
| 152 | |
| 153 if (arena == NULL) { | |
| 154 localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
| 155 if (arena == NULL) { | |
| 156 return NULL; | |
| 157 } | |
| 158 } | |
| 159 pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter); | |
| 160 if (pbeV2_param == NULL) { | |
| 161 goto loser; | |
| 162 } | |
| 163 | |
| 164 rv = SEC_ASN1DecodeItem(arena, pbeV2_param, | |
| 165 SEC_PKCS5V2ParameterTemplate, &algid->parameters); | |
| 166 if (rv == SECFailure) { | |
| 167 goto loser; | |
| 168 } | |
| 169 | |
| 170 pbeV2_param->poolp = arena; | |
| 171 return pbeV2_param; | |
| 172 loser: | |
| 173 if (localArena) { | |
| 174 PORT_FreeArena(arena, PR_FALSE); | |
| 175 } | |
| 176 return NULL; | |
| 177 } | |
| 178 | |
| 179 void | |
| 180 sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param) | |
| 181 { | |
| 182 if (param && param->poolp) { | |
| 183 PORT_FreeArena(param->poolp, PR_TRUE); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 | |
| 188 /* maps crypto algorithm from PBE algorithm. | |
| 189 */ | |
| 190 SECOidTag | |
| 191 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) | |
| 192 { | |
| 193 | |
| 194 SECOidTag pbeAlg; | |
| 195 SECOidTag cipherAlg; | |
| 196 | |
| 197 if(algid == NULL) | |
| 198 return SEC_OID_UNKNOWN; | |
| 199 | |
| 200 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
| 201 cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg); | |
| 202 if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) && | |
| 203 (pbeAlg != SEC_OID_PKCS5_PBKDF2)) { | |
| 204 sec_pkcs5V2Parameter *pbeV2_param; | |
| 205 cipherAlg = SEC_OID_UNKNOWN; | |
| 206 | |
| 207 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
| 208 if (pbeV2_param != NULL) { | |
| 209 cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId); | |
| 210 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 return cipherAlg; | |
| 215 } | |
| 216 | |
| 217 /* check to see if an oid is a pbe algorithm | |
| 218 */ | |
| 219 PRBool | |
| 220 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) | |
| 221 { | |
| 222 return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN); | |
| 223 } | |
| 224 | |
| 225 PRBool | |
| 226 SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag) | |
| 227 { | |
| 228 return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN); | |
| 229 } | |
| 230 | |
| 231 /* | |
| 232 * find the most appropriate PKCS5v2 overall oid tag from a regular | |
| 233 * cipher/hash algorithm tag. | |
| 234 */ | |
| 235 static SECOidTag | |
| 236 sec_pkcs5v2_get_pbe(SECOidTag algTag) | |
| 237 { | |
| 238 /* if it's a valid hash oid... */ | |
| 239 if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) { | |
| 240 /* use the MAC tag */ | |
| 241 return SEC_OID_PKCS5_PBMAC1; | |
| 242 } | |
| 243 if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) { | |
| 244 /* eliminate Hash algorithms */ | |
| 245 return SEC_OID_UNKNOWN; | |
| 246 } | |
| 247 if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) { | |
| 248 /* it's not a hash, if it has a PKCS #11 mechanism associated | |
| 249 * with it, assume it's a cipher. (NOTE this will generate | |
| 250 * some false positives). */ | |
| 251 return SEC_OID_PKCS5_PBES2; | |
| 252 } | |
| 253 return SEC_OID_UNKNOWN; | |
| 254 } | |
| 255 | |
| 256 /* | |
| 257 * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. | |
| 258 * input keyLen in bits. | |
| 259 */ | |
| 260 SECOidTag | |
| 261 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) | |
| 262 { | |
| 263 switch(algTag) | |
| 264 { | |
| 265 case SEC_OID_DES_EDE3_CBC: | |
| 266 switch(keyLen) { | |
| 267 case 168: | |
| 268 case 192: | |
| 269 case 0: | |
| 270 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_C
BC; | |
| 271 case 128: | |
| 272 case 92: | |
| 273 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_C
BC; | |
| 274 default: | |
| 275 break; | |
| 276 } | |
| 277 break; | |
| 278 case SEC_OID_DES_CBC: | |
| 279 return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; | |
| 280 case SEC_OID_RC2_CBC: | |
| 281 switch(keyLen) { | |
| 282 case 40: | |
| 283 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; | |
| 284 case 128: | |
| 285 case 0: | |
| 286 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; | |
| 287 default: | |
| 288 break; | |
| 289 } | |
| 290 break; | |
| 291 case SEC_OID_RC4: | |
| 292 switch(keyLen) { | |
| 293 case 40: | |
| 294 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; | |
| 295 case 128: | |
| 296 case 0: | |
| 297 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; | |
| 298 default: | |
| 299 break; | |
| 300 } | |
| 301 break; | |
| 302 default: | |
| 303 return sec_pkcs5v2_get_pbe(algTag); | |
| 304 } | |
| 305 | |
| 306 return SEC_OID_UNKNOWN; | |
| 307 } | |
| 308 | |
| 309 /* | |
| 310 * get the key length in bytes from a PKCS5 PBE | |
| 311 */ | |
| 312 int | |
| 313 sec_pkcs5v2_key_length(SECAlgorithmID *algid) | |
| 314 { | |
| 315 SECOidTag algorithm; | |
| 316 PLArenaPool *arena = NULL; | |
| 317 SEC_PKCS5PBEParameter p5_param; | |
| 318 SECStatus rv; | |
| 319 int length = -1; | |
| 320 | |
| 321 algorithm = SECOID_GetAlgorithmTag(algid); | |
| 322 /* sanity check, they should all be PBKDF2 here */ | |
| 323 if (algorithm != SEC_OID_PKCS5_PBKDF2) { | |
| 324 return -1; | |
| 325 } | |
| 326 | |
| 327 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
| 328 if (arena == NULL) { | |
| 329 goto loser; | |
| 330 } | |
| 331 PORT_Memset(&p5_param, 0, sizeof(p5_param)); | |
| 332 rv = SEC_ASN1DecodeItem(arena,&p5_param, | |
| 333 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); | |
| 334 if (rv != SECSuccess) { | |
| 335 goto loser; | |
| 336 } | |
| 337 | |
| 338 if (p5_param.keyLength.data != NULL) { | |
| 339 length = DER_GetInteger(&p5_param.keyLength); | |
| 340 } | |
| 341 | |
| 342 loser: | |
| 343 if (arena) { | |
| 344 PORT_FreeArena(arena, PR_FALSE); | |
| 345 } | |
| 346 return length; | |
| 347 } | |
| 348 | |
| 349 /* | |
| 350 * get the key length in bytes needed for the PBE algorithm | |
| 351 */ | |
| 352 int | |
| 353 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) | |
| 354 { | |
| 355 | |
| 356 SECOidTag algorithm; | |
| 357 | |
| 358 if(algid == NULL) | |
| 359 return SEC_OID_UNKNOWN; | |
| 360 | |
| 361 algorithm = SECOID_GetAlgorithmTag(algid); | |
| 362 | |
| 363 switch(algorithm) | |
| 364 { | |
| 365 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
| 366 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: | |
| 367 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
| 368 return 24; | |
| 369 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: | |
| 370 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: | |
| 371 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: | |
| 372 return 8; | |
| 373 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
| 374 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
| 375 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
| 376 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
| 377 return 5; | |
| 378 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
| 379 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
| 380 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
| 381 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
| 382 return 16; | |
| 383 case SEC_OID_PKCS5_PBKDF2: | |
| 384 return sec_pkcs5v2_key_length(algid); | |
| 385 case SEC_OID_PKCS5_PBES2: | |
| 386 case SEC_OID_PKCS5_PBMAC1: | |
| 387 { | |
| 388 sec_pkcs5V2Parameter *pbeV2_param; | |
| 389 int length = -1; | |
| 390 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
| 391 if (pbeV2_param != NULL) { | |
| 392 length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId); | |
| 393 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
| 394 } | |
| 395 return length; | |
| 396 } | |
| 397 | |
| 398 default: | |
| 399 break; | |
| 400 } | |
| 401 return -1; | |
| 402 } | |
| 403 | |
| 404 | |
| 405 /* the PKCS12 V2 algorithms only encode the salt, there is no iteration | |
| 406 * count so we need a check for V2 algorithm parameters. | |
| 407 */ | |
| 408 static PRBool | |
| 409 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) | |
| 410 { | |
| 411 switch(algorithm) | |
| 412 { | |
| 413 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
| 414 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
| 415 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
| 416 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
| 417 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
| 418 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
| 419 return PR_TRUE; | |
| 420 default: | |
| 421 break; | |
| 422 } | |
| 423 | |
| 424 return PR_FALSE; | |
| 425 } | |
| 426 | |
| 427 static PRBool | |
| 428 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm) | |
| 429 { | |
| 430 switch(algorithm) | |
| 431 { | |
| 432 case SEC_OID_PKCS5_PBES2: | |
| 433 case SEC_OID_PKCS5_PBMAC1: | |
| 434 case SEC_OID_PKCS5_PBKDF2: | |
| 435 return PR_TRUE; | |
| 436 default: | |
| 437 break; | |
| 438 } | |
| 439 | |
| 440 return PR_FALSE; | |
| 441 } | |
| 442 | |
| 443 /* destroy a pbe parameter. it assumes that the parameter was | |
| 444 * generated using the appropriate create function and therefor | |
| 445 * contains an arena pool. | |
| 446 */ | |
| 447 static void | |
| 448 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) | |
| 449 { | |
| 450 if(pbe_param != NULL) | |
| 451 PORT_FreeArena(pbe_param->poolp, PR_TRUE); | |
| 452 } | |
| 453 | |
| 454 /* creates a PBE parameter based on the PBE algorithm. the only required | |
| 455 * parameters are algorithm and interation. the return is a PBE parameter | |
| 456 * which conforms to PKCS 5 parameter unless an extended parameter is needed. | |
| 457 * this is primarily if keyLength and a variable key length algorithm are | |
| 458 * specified. | |
| 459 * salt - if null, a salt will be generated from random bytes. | |
| 460 * iteration - number of iterations to perform hashing. | |
| 461 * keyLength - only used in variable key length algorithms. if specified, | |
| 462 * should be in bytes. | |
| 463 * once a parameter is allocated, it should be destroyed calling | |
| 464 * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. | |
| 465 */ | |
| 466 #define DEFAULT_SALT_LENGTH 16 | |
| 467 static SEC_PKCS5PBEParameter * | |
| 468 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, | |
| 469 SECItem *salt, | |
| 470 int iteration, | |
| 471 int keyLength, | |
| 472 SECOidTag prfAlg) | |
| 473 { | |
| 474 PLArenaPool *poolp = NULL; | |
| 475 SEC_PKCS5PBEParameter *pbe_param = NULL; | |
| 476 SECStatus rv= SECSuccess; | |
| 477 void *dummy = NULL; | |
| 478 | |
| 479 if(iteration < 0) { | |
| 480 return NULL; | |
| 481 } | |
| 482 | |
| 483 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
| 484 if(poolp == NULL) | |
| 485 return NULL; | |
| 486 | |
| 487 pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, | |
| 488 sizeof(SEC_PKCS5PBEParameter)); | |
| 489 if(!pbe_param) { | |
| 490 PORT_FreeArena(poolp, PR_TRUE); | |
| 491 return NULL; | |
| 492 } | |
| 493 | |
| 494 pbe_param->poolp = poolp; | |
| 495 | |
| 496 rv = SECFailure; | |
| 497 if (salt && salt->data) { | |
| 498 rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); | |
| 499 } else { | |
| 500 /* sigh, the old interface generated salt on the fly, so we have to | |
| 501 * preserve the semantics */ | |
| 502 pbe_param->salt.len = DEFAULT_SALT_LENGTH; | |
| 503 pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH); | |
| 504 if (pbe_param->salt.data) { | |
| 505 rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH); | |
| 506 } | |
| 507 } | |
| 508 | |
| 509 if(rv != SECSuccess) { | |
| 510 PORT_FreeArena(poolp, PR_TRUE); | |
| 511 return NULL; | |
| 512 } | |
| 513 | |
| 514 /* encode the integer */ | |
| 515 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, | |
| 516 iteration); | |
| 517 rv = (dummy) ? SECSuccess : SECFailure; | |
| 518 | |
| 519 if(rv != SECSuccess) { | |
| 520 PORT_FreeArena(poolp, PR_FALSE); | |
| 521 return NULL; | |
| 522 } | |
| 523 | |
| 524 /* | |
| 525 * for PKCS5 v2 Add the keylength and the prf | |
| 526 */ | |
| 527 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
| 528 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength, | |
| 529 keyLength); | |
| 530 rv = (dummy) ? SECSuccess : SECFailure; | |
| 531 if (rv != SECSuccess) { | |
| 532 PORT_FreeArena(poolp, PR_FALSE); | |
| 533 return NULL; | |
| 534 } | |
| 535 rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL); | |
| 536 if (rv != SECSuccess) { | |
| 537 PORT_FreeArena(poolp, PR_FALSE); | |
| 538 return NULL; | |
| 539 } | |
| 540 pbe_param->pPrfAlgId = &pbe_param->prfAlgId; | |
| 541 } | |
| 542 | |
| 543 return pbe_param; | |
| 544 } | |
| 545 | |
| 546 /* creates a algorithm ID containing the PBE algorithm and appropriate | |
| 547 * parameters. the required parameter is the algorithm. if salt is | |
| 548 * not specified, it is generated randomly. | |
| 549 * | |
| 550 * the returned SECAlgorithmID should be destroyed using | |
| 551 * SECOID_DestroyAlgorithmID | |
| 552 */ | |
| 553 SECAlgorithmID * | |
| 554 sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, | |
| 555 SECOidTag cipherAlgorithm, | |
| 556 SECOidTag prfAlg, | |
| 557 SECOidTag *pPbeAlgorithm, | |
| 558 int keyLength, | |
| 559 SECItem *salt, | |
| 560 int iteration) | |
| 561 { | |
| 562 PLArenaPool *poolp = NULL; | |
| 563 SECAlgorithmID *algid, *ret_algid = NULL; | |
| 564 SECOidTag pbeAlgorithm = algorithm; | |
| 565 SECItem der_param; | |
| 566 void *dummy; | |
| 567 SECStatus rv = SECFailure; | |
| 568 SEC_PKCS5PBEParameter *pbe_param = NULL; | |
| 569 sec_pkcs5V2Parameter pbeV2_param; | |
| 570 | |
| 571 if(iteration <= 0) { | |
| 572 return NULL; | |
| 573 } | |
| 574 | |
| 575 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
| 576 if(!poolp) { | |
| 577 goto loser; | |
| 578 } | |
| 579 | |
| 580 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) || | |
| 581 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
| 582 /* use PKCS 5 v2 */ | |
| 583 SECItem *cipherParams; | |
| 584 | |
| 585 /* | |
| 586 * if we ask for pkcs5 Algorithms directly, then the | |
| 587 * application needs to supply the cipher algorithm, | |
| 588 * otherwise we are implicitly using pkcs5 v2 and the | |
| 589 * passed in algorithm is the encryption algorithm. | |
| 590 */ | |
| 591 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
| 592 if (cipherAlgorithm == SEC_OID_UNKNOWN) { | |
| 593 goto loser; | |
| 594 } | |
| 595 } else { | |
| 596 cipherAlgorithm = algorithm; | |
| 597 /* force algorithm to be chosen below */ | |
| 598 algorithm = SEC_OID_PKCS5_PBKDF2; | |
| 599 } | |
| 600 | |
| 601 pbeAlgorithm = SEC_OID_PKCS5_PBKDF2; | |
| 602 /* | |
| 603 * 'algorithm' is the overall algorithm oid tag used to wrap the | |
| 604 * entire algoithm ID block. For PKCS5v1 and PKCS12, this | |
| 605 * algorithm OID has encoded in it both the PBE KDF function | |
| 606 * and the encryption algorithm. For PKCS 5v2, PBE KDF and | |
| 607 * encryption/macing oids are encoded as parameters in | |
| 608 * the algorithm ID block. | |
| 609 * | |
| 610 * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11 | |
| 611 * mechanism, where as in PKCS 5v2, this alogithm tag does not map | |
| 612 * directly to a PKCS #11 mechanim, instead the 2 oids in the | |
| 613 * algorithm ID block map the the actual PKCS #11 mechanism. | |
| 614 * gorithm is). We use choose this algorithm oid based on the | |
| 615 * cipherAlgorithm to determine what this should be (MAC1 or PBES2). | |
| 616 */ | |
| 617 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
| 618 /* choose mac or pbes */ | |
| 619 algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm); | |
| 620 } | |
| 621 | |
| 622 /* set the PKCS5v2 specific parameters */ | |
| 623 if (keyLength == 0) { | |
| 624 SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm); | |
| 625 if (hashAlg != SEC_OID_UNKNOWN) { | |
| 626 keyLength = HASH_ResultLenByOidTag(hashAlg); | |
| 627 } else { | |
| 628 CK_MECHANISM_TYPE cryptoMech; | |
| 629 cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm); | |
| 630 if (cryptoMech == CKM_INVALID_MECHANISM) { | |
| 631 goto loser; | |
| 632 } | |
| 633 keyLength = PK11_GetMaxKeyLength(cryptoMech); | |
| 634 } | |
| 635 if (keyLength == 0) { | |
| 636 goto loser; | |
| 637 } | |
| 638 } | |
| 639 /* currently SEC_OID_HMAC_SHA1 is the default */ | |
| 640 if (prfAlg == SEC_OID_UNKNOWN) { | |
| 641 prfAlg = SEC_OID_HMAC_SHA1; | |
| 642 } | |
| 643 | |
| 644 /* build the PKCS5v2 cipher algorithm id */ | |
| 645 cipherParams = pk11_GenerateNewParamWithKeyLen( | |
| 646 PK11_AlgtagToMechanism(cipherAlgorithm), keyLength); | |
| 647 if (!cipherParams) { | |
| 648 goto loser; | |
| 649 } | |
| 650 | |
| 651 PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param)); | |
| 652 | |
| 653 rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, | |
| 654 poolp, &pbeV2_param.cipherAlgId); | |
| 655 SECITEM_FreeItem(cipherParams, PR_TRUE); | |
| 656 if (rv != SECSuccess) { | |
| 657 goto loser; | |
| 658 } | |
| 659 } | |
| 660 | |
| 661 | |
| 662 /* generate the parameter */ | |
| 663 pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration, | |
| 664 keyLength, prfAlg); | |
| 665 if(!pbe_param) { | |
| 666 goto loser; | |
| 667 } | |
| 668 | |
| 669 /* generate the algorithm id */ | |
| 670 algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); | |
| 671 if(algid == NULL) { | |
| 672 goto loser; | |
| 673 } | |
| 674 | |
| 675 der_param.data = NULL; | |
| 676 der_param.len = 0; | |
| 677 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
| 678 /* first encode the PBE algorithm ID */ | |
| 679 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
| 680 SEC_PKCS5V2PBEParameterTemplate); | |
| 681 if (dummy == NULL) { | |
| 682 goto loser; | |
| 683 } | |
| 684 rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId, | |
| 685 pbeAlgorithm, &der_param); | |
| 686 if (rv != SECSuccess) { | |
| 687 goto loser; | |
| 688 } | |
| 689 | |
| 690 /* now encode the Full PKCS 5 parameter */ | |
| 691 der_param.data = NULL; | |
| 692 der_param.len = 0; | |
| 693 dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param, | |
| 694 SEC_PKCS5V2ParameterTemplate); | |
| 695 } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { | |
| 696 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
| 697 SEC_PKCS5PBEParameterTemplate); | |
| 698 } else { | |
| 699 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
| 700 SEC_V2PKCS12PBEParameterTemplate); | |
| 701 } | |
| 702 if (dummy == NULL) { | |
| 703 goto loser; | |
| 704 } | |
| 705 | |
| 706 rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); | |
| 707 if (rv != SECSuccess) { | |
| 708 goto loser; | |
| 709 } | |
| 710 | |
| 711 ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); | |
| 712 if (ret_algid == NULL) { | |
| 713 goto loser; | |
| 714 } | |
| 715 | |
| 716 rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); | |
| 717 if (rv != SECSuccess) { | |
| 718 SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); | |
| 719 ret_algid = NULL; | |
| 720 } else if (pPbeAlgorithm) { | |
| 721 *pPbeAlgorithm = pbeAlgorithm; | |
| 722 } | |
| 723 | |
| 724 loser: | |
| 725 if (poolp != NULL) { | |
| 726 PORT_FreeArena(poolp, PR_TRUE); | |
| 727 algid = NULL; | |
| 728 } | |
| 729 | |
| 730 if (pbe_param) { | |
| 731 sec_pkcs5_destroy_pbe_param(pbe_param); | |
| 732 } | |
| 733 | |
| 734 return ret_algid; | |
| 735 } | |
| 736 | |
| 737 SECStatus | |
| 738 pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech) | |
| 739 { | |
| 740 SEC_PKCS5PBEParameter p5_param; | |
| 741 SECItem *salt = NULL; | |
| 742 SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); | |
| 743 PLArenaPool *arena = NULL; | |
| 744 SECStatus rv = SECFailure; | |
| 745 unsigned char *paramData = NULL; | |
| 746 unsigned char *pSalt = NULL; | |
| 747 CK_ULONG iterations; | |
| 748 int paramLen = 0; | |
| 749 int iv_len; | |
| 750 | |
| 751 | |
| 752 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
| 753 if (arena == NULL) { | |
| 754 goto loser; | |
| 755 } | |
| 756 | |
| 757 | |
| 758 /* | |
| 759 * decode the algid based on the pbe type | |
| 760 */ | |
| 761 PORT_Memset(&p5_param, 0, sizeof(p5_param)); | |
| 762 if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { | |
| 763 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); | |
| 764 rv = SEC_ASN1DecodeItem(arena, &p5_param, | |
| 765 SEC_V2PKCS12PBEParameterTemplate, &algid->parameters); | |
| 766 } else if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
| 767 iv_len = 0; | |
| 768 rv = SEC_ASN1DecodeItem(arena,&p5_param, | |
| 769 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); | |
| 770 } else { | |
| 771 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); | |
| 772 rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, | |
| 773 &algid->parameters); | |
| 774 } | |
| 775 | |
| 776 if (iv_len < 0) { | |
| 777 goto loser; | |
| 778 } | |
| 779 | |
| 780 if (rv != SECSuccess) { | |
| 781 goto loser; | |
| 782 } | |
| 783 | |
| 784 /* get salt */ | |
| 785 salt = &p5_param.salt; | |
| 786 iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration); | |
| 787 | |
| 788 /* allocate and fill in the PKCS #11 parameters | |
| 789 * based on the algorithm. */ | |
| 790 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
| 791 SECOidTag prfAlgTag; | |
| 792 CK_PKCS5_PBKD2_PARAMS *pbeV2_params = | |
| 793 (CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc( | |
| 794 sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len); | |
| 795 | |
| 796 if (pbeV2_params == NULL) { | |
| 797 goto loser; | |
| 798 } | |
| 799 paramData = (unsigned char *)pbeV2_params; | |
| 800 paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS); | |
| 801 | |
| 802 /* set the prf */ | |
| 803 prfAlgTag = SEC_OID_HMAC_SHA1; | |
| 804 if (p5_param.pPrfAlgId && | |
| 805 p5_param.pPrfAlgId->algorithm.data != 0) { | |
| 806 prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId); | |
| 807 } | |
| 808 switch (prfAlgTag) { | |
| 809 case SEC_OID_HMAC_SHA1: | |
| 810 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1; | |
| 811 break; | |
| 812 case SEC_OID_HMAC_SHA224: | |
| 813 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA224; | |
| 814 break; | |
| 815 case SEC_OID_HMAC_SHA256: | |
| 816 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA256; | |
| 817 break; | |
| 818 case SEC_OID_HMAC_SHA384: | |
| 819 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA384; | |
| 820 break; | |
| 821 case SEC_OID_HMAC_SHA512: | |
| 822 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA512; | |
| 823 break; | |
| 824 default: | |
| 825 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 826 goto loser; | |
| 827 } | |
| 828 | |
| 829 /* probably should fetch these from the prfAlgid */ | |
| 830 pbeV2_params->pPrfData = NULL; | |
| 831 pbeV2_params->ulPrfDataLen = 0; | |
| 832 pbeV2_params->saltSource = CKZ_SALT_SPECIFIED; | |
| 833 pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS); | |
| 834 PORT_Memcpy(pSalt, salt->data, salt->len); | |
| 835 pbeV2_params->pSaltSourceData = pSalt; | |
| 836 pbeV2_params->ulSaltSourceDataLen = salt->len; | |
| 837 pbeV2_params->iterations = iterations; | |
| 838 } else { | |
| 839 CK_PBE_PARAMS *pbe_params = NULL; | |
| 840 pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+ | |
| 841 salt->len+iv_len); | |
| 842 if (pbe_params == NULL) { | |
| 843 goto loser; | |
| 844 } | |
| 845 paramData = (unsigned char *)pbe_params; | |
| 846 paramLen = sizeof(CK_PBE_PARAMS); | |
| 847 | |
| 848 pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS); | |
| 849 pbe_params->pSalt = pSalt; | |
| 850 PORT_Memcpy(pSalt, salt->data, salt->len); | |
| 851 pbe_params->ulSaltLen = salt->len; | |
| 852 if (iv_len) { | |
| 853 pbe_params->pInitVector = | |
| 854 ((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len; | |
| 855 } | |
| 856 pbe_params->ulIteration = iterations; | |
| 857 } | |
| 858 | |
| 859 /* copy into the mechanism sec item */ | |
| 860 mech->data = paramData; | |
| 861 mech->len = paramLen; | |
| 862 if (arena) { | |
| 863 PORT_FreeArena(arena,PR_TRUE); | |
| 864 } | |
| 865 return SECSuccess; | |
| 866 | |
| 867 loser: | |
| 868 if (paramData) { | |
| 869 PORT_Free(paramData); | |
| 870 } | |
| 871 if (arena) { | |
| 872 PORT_FreeArena(arena,PR_TRUE); | |
| 873 } | |
| 874 return SECFailure; | |
| 875 } | |
| 876 | |
| 877 /* | |
| 878 * public, deprecated, not valid for pkcs5 v2 | |
| 879 * | |
| 880 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create | |
| 881 * PBE algorithmID's directly. | |
| 882 */ | |
| 883 SECStatus | |
| 884 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena, | |
| 885 SECAlgorithmID *algId) | |
| 886 { | |
| 887 CK_PBE_PARAMS *pbe_param; | |
| 888 SECItem pbeSalt; | |
| 889 SECAlgorithmID *pbeAlgID = NULL; | |
| 890 SECStatus rv; | |
| 891 | |
| 892 if(!param || !algId) { | |
| 893 return SECFailure; | |
| 894 } | |
| 895 | |
| 896 pbe_param = (CK_PBE_PARAMS *)param->data; | |
| 897 pbeSalt.data = (unsigned char *)pbe_param->pSalt; | |
| 898 pbeSalt.len = pbe_param->ulSaltLen; | |
| 899 pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, | |
| 900 SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration); | |
| 901 if(!pbeAlgID) { | |
| 902 return SECFailure; | |
| 903 } | |
| 904 | |
| 905 rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); | |
| 906 SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); | |
| 907 return rv; | |
| 908 } | |
| 909 | |
| 910 /* | |
| 911 * public, Deprecated, This function is only for binary compatibility with | |
| 912 * older applications. Does not support PKCS5v2. | |
| 913 * | |
| 914 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for | |
| 915 * iv values rather than generating PBE bits directly. | |
| 916 */ | |
| 917 PBEBitGenContext * | |
| 918 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, | |
| 919 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, | |
| 920 unsigned int iterations) | |
| 921 { | |
| 922 SECItem *context = NULL; | |
| 923 SECItem mechItem; | |
| 924 CK_PBE_PARAMS pbe_params; | |
| 925 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | |
| 926 PK11SlotInfo *slot; | |
| 927 PK11SymKey *symKey = NULL; | |
| 928 unsigned char ivData[8]; | |
| 929 | |
| 930 | |
| 931 /* use the purpose to select the low level keygen algorithm */ | |
| 932 switch (bitGenPurpose) { | |
| 933 case pbeBitGenIntegrityKey: | |
| 934 switch (hashAlgorithm) { | |
| 935 case SEC_OID_SHA1: | |
| 936 mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC; | |
| 937 break; | |
| 938 case SEC_OID_MD2: | |
| 939 mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; | |
| 940 break; | |
| 941 case SEC_OID_MD5: | |
| 942 mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; | |
| 943 break; | |
| 944 default: | |
| 945 break; | |
| 946 } | |
| 947 break; | |
| 948 case pbeBitGenCipherIV: | |
| 949 if (bitsNeeded > 64) { | |
| 950 break; | |
| 951 } | |
| 952 if (hashAlgorithm != SEC_OID_SHA1) { | |
| 953 break; | |
| 954 } | |
| 955 mechanism = CKM_PBE_SHA1_DES3_EDE_CBC; | |
| 956 break; | |
| 957 case pbeBitGenCipherKey: | |
| 958 if (hashAlgorithm != SEC_OID_SHA1) { | |
| 959 break; | |
| 960 } | |
| 961 switch (bitsNeeded) { | |
| 962 case 40: | |
| 963 mechanism = CKM_PBE_SHA1_RC4_40; | |
| 964 break; | |
| 965 case 128: | |
| 966 mechanism = CKM_PBE_SHA1_RC4_128; | |
| 967 break; | |
| 968 default: | |
| 969 break; | |
| 970 } | |
| 971 case pbeBitGenIDNull: | |
| 972 break; | |
| 973 } | |
| 974 | |
| 975 if (mechanism == CKM_INVALID_MECHANISM) { | |
| 976 /* we should set an error, but this is a deprecated function, and | |
| 977 * we are keeping bug for bug compatibility;)... */ | |
| 978 return NULL; | |
| 979 } | |
| 980 | |
| 981 pbe_params.pInitVector = ivData; | |
| 982 pbe_params.pPassword = pwitem->data; | |
| 983 pbe_params.ulPasswordLen = pwitem->len; | |
| 984 pbe_params.pSalt = salt->data; | |
| 985 pbe_params.ulSaltLen = salt->len; | |
| 986 pbe_params.ulIteration = iterations; | |
| 987 mechItem.data = (unsigned char *) &pbe_params; | |
| 988 mechItem.len = sizeof(pbe_params); | |
| 989 | |
| 990 | |
| 991 slot = PK11_GetInternalSlot(); | |
| 992 symKey = PK11_RawPBEKeyGen(slot,mechanism, | |
| 993 &mechItem, pwitem, PR_FALSE, NULL); | |
| 994 PK11_FreeSlot(slot); | |
| 995 if (symKey != NULL) { | |
| 996 if (bitGenPurpose == pbeBitGenCipherIV) { | |
| 997 /* NOTE: this assumes that bitsNeeded is a multiple of 8! */ | |
| 998 SECItem ivItem; | |
| 999 | |
| 1000 ivItem.data = ivData; | |
| 1001 ivItem.len = bitsNeeded/8; | |
| 1002 context = SECITEM_DupItem(&ivItem); | |
| 1003 } else { | |
| 1004 SECItem *keyData; | |
| 1005 PK11_ExtractKeyValue(symKey); | |
| 1006 keyData = PK11_GetKeyData(symKey); | |
| 1007 | |
| 1008 /* assert bitsNeeded with length? */ | |
| 1009 if (keyData) { | |
| 1010 context = SECITEM_DupItem(keyData); | |
| 1011 } | |
| 1012 } | |
| 1013 PK11_FreeSymKey(symKey); | |
| 1014 } | |
| 1015 | |
| 1016 return (PBEBitGenContext *)context; | |
| 1017 } | |
| 1018 | |
| 1019 /* | |
| 1020 * public, Deprecated, This function is only for binary compatibility with | |
| 1021 * older applications. Does not support PKCS5v2. | |
| 1022 * | |
| 1023 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for | |
| 1024 * iv values rather than generating PBE bits directly. | |
| 1025 */ | |
| 1026 SECItem * | |
| 1027 PBE_GenerateBits(PBEBitGenContext *context) | |
| 1028 { | |
| 1029 return (SECItem *)context; | |
| 1030 } | |
| 1031 | |
| 1032 /* | |
| 1033 * public, Deprecated, This function is only for binary compatibility with | |
| 1034 * older applications. Does not support PKCS5v2. | |
| 1035 * | |
| 1036 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for | |
| 1037 * iv values rather than generating PBE bits directly. | |
| 1038 */ | |
| 1039 void | |
| 1040 PBE_DestroyContext(PBEBitGenContext *context) | |
| 1041 { | |
| 1042 SECITEM_FreeItem((SECItem *)context,PR_TRUE); | |
| 1043 } | |
| 1044 | |
| 1045 /* | |
| 1046 * public, deprecated. Replaced with PK11_GetPBEIV(). | |
| 1047 */ | |
| 1048 SECItem * | |
| 1049 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) | |
| 1050 { | |
| 1051 /* pbe stuff */ | |
| 1052 CK_MECHANISM_TYPE type; | |
| 1053 SECItem *param = NULL; | |
| 1054 SECItem *iv = NULL; | |
| 1055 SECItem src; | |
| 1056 int iv_len = 0; | |
| 1057 PK11SymKey *symKey; | |
| 1058 PK11SlotInfo *slot; | |
| 1059 CK_PBE_PARAMS_PTR pPBEparams; | |
| 1060 SECOidTag pbeAlg; | |
| 1061 | |
| 1062 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
| 1063 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { | |
| 1064 unsigned char *ivData; | |
| 1065 sec_pkcs5V2Parameter *pbeV2_param = NULL; | |
| 1066 | |
| 1067 /* can only return the IV if the crypto Algorithm exists */ | |
| 1068 if (pbeAlg == SEC_OID_PKCS5_PBKDF2) { | |
| 1069 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1070 goto loser; | |
| 1071 } | |
| 1072 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
| 1073 if (pbeV2_param == NULL) { | |
| 1074 goto loser; | |
| 1075 } | |
| 1076 /* extract the IV from the cipher algid portion of our pkcs 5 v2 | |
| 1077 * algorithm id */ | |
| 1078 type = PK11_AlgtagToMechanism( | |
| 1079 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); | |
| 1080 param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId); | |
| 1081 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
| 1082 if (!param) { | |
| 1083 goto loser; | |
| 1084 } | |
| 1085 /* NOTE: NULL is a permissible return here */ | |
| 1086 ivData = PK11_IVFromParam(type, param, &iv_len); | |
| 1087 src.data = ivData; | |
| 1088 src.len = iv_len; | |
| 1089 goto done; | |
| 1090 } | |
| 1091 | |
| 1092 type = PK11_AlgtagToMechanism(pbeAlg); | |
| 1093 param = PK11_ParamFromAlgid(algid); | |
| 1094 if (param == NULL) { | |
| 1095 goto done; | |
| 1096 } | |
| 1097 slot = PK11_GetInternalSlot(); | |
| 1098 symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL); | |
| 1099 PK11_FreeSlot(slot); | |
| 1100 if (symKey == NULL) { | |
| 1101 goto loser; | |
| 1102 } | |
| 1103 PK11_FreeSymKey(symKey); | |
| 1104 pPBEparams = (CK_PBE_PARAMS_PTR)param->data; | |
| 1105 iv_len = PK11_GetIVLength(type); | |
| 1106 | |
| 1107 src.data = (unsigned char *)pPBEparams->pInitVector; | |
| 1108 src.len = iv_len; | |
| 1109 | |
| 1110 done: | |
| 1111 iv = SECITEM_DupItem(&src); | |
| 1112 | |
| 1113 loser: | |
| 1114 if (param) { | |
| 1115 SECITEM_ZfreeItem(param, PR_TRUE); | |
| 1116 } | |
| 1117 return iv; | |
| 1118 } | |
| 1119 | |
| 1120 /* | |
| 1121 * Subs from nss 3.x that are deprecated | |
| 1122 */ | |
| 1123 PBEBitGenContext * | |
| 1124 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, | |
| 1125 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, | |
| 1126 unsigned int iterations) | |
| 1127 { | |
| 1128 PORT_Assert("__PBE_CreateContext is Deprecated" == NULL); | |
| 1129 return NULL; | |
| 1130 } | |
| 1131 | |
| 1132 SECItem * | |
| 1133 __PBE_GenerateBits(PBEBitGenContext *context) | |
| 1134 { | |
| 1135 PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL); | |
| 1136 return NULL; | |
| 1137 } | |
| 1138 | |
| 1139 void | |
| 1140 __PBE_DestroyContext(PBEBitGenContext *context) | |
| 1141 { | |
| 1142 PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL); | |
| 1143 } | |
| 1144 | |
| 1145 SECStatus | |
| 1146 RSA_FormatBlock(SECItem *result, unsigned modulusLen, | |
| 1147 int blockType, SECItem *data) | |
| 1148 { | |
| 1149 PORT_Assert("RSA_FormatBlock is Deprecated" == NULL); | |
| 1150 return SECFailure; | |
| 1151 } | |
| 1152 | |
| 1153 /**************************************************************************** | |
| 1154 * | |
| 1155 * Now Do The PBE Functions Here... | |
| 1156 * | |
| 1157 ****************************************************************************/ | |
| 1158 | |
| 1159 static void | |
| 1160 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params) | |
| 1161 { | |
| 1162 if (pbe_params) { | |
| 1163 if (pbe_params->pPassword) | |
| 1164 PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen); | |
| 1165 if (pbe_params->pSalt) | |
| 1166 PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen); | |
| 1167 PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS)); | |
| 1168 } | |
| 1169 } | |
| 1170 | |
| 1171 /* | |
| 1172 * public, deprecated. use PK11_CreatePBEAlgorithmID or | |
| 1173 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters, | |
| 1174 * use PK11_ParamFromAlgid from the algorithm id you created using | |
| 1175 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID. | |
| 1176 */ | |
| 1177 SECItem * | |
| 1178 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations) | |
| 1179 { | |
| 1180 CK_PBE_PARAMS *pbe_params = NULL; | |
| 1181 SECItem *paramRV = NULL; | |
| 1182 | |
| 1183 paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS)); | |
| 1184 if (!paramRV ) { | |
| 1185 goto loser; | |
| 1186 } | |
| 1187 /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */ | |
| 1188 PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS)); | |
| 1189 | |
| 1190 pbe_params = (CK_PBE_PARAMS *)paramRV->data; | |
| 1191 pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len); | |
| 1192 if (!pbe_params->pPassword) { | |
| 1193 goto loser; | |
| 1194 } | |
| 1195 PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len); | |
| 1196 pbe_params->ulPasswordLen = pwd->len; | |
| 1197 | |
| 1198 pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len); | |
| 1199 if (!pbe_params->pSalt) { | |
| 1200 goto loser; | |
| 1201 } | |
| 1202 PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len); | |
| 1203 pbe_params->ulSaltLen = salt->len; | |
| 1204 | |
| 1205 pbe_params->ulIteration = (CK_ULONG)iterations; | |
| 1206 return paramRV; | |
| 1207 | |
| 1208 loser: | |
| 1209 if (pbe_params) | |
| 1210 pk11_destroy_ck_pbe_params(pbe_params); | |
| 1211 if (paramRV) | |
| 1212 PORT_ZFree(paramRV, sizeof(SECItem)); | |
| 1213 return NULL; | |
| 1214 } | |
| 1215 | |
| 1216 /* | |
| 1217 * public, deprecated. | |
| 1218 */ | |
| 1219 void | |
| 1220 PK11_DestroyPBEParams(SECItem *pItem) | |
| 1221 { | |
| 1222 if (pItem) { | |
| 1223 CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data); | |
| 1224 if (params) | |
| 1225 pk11_destroy_ck_pbe_params(params); | |
| 1226 PORT_ZFree(pItem, sizeof(SECItem)); | |
| 1227 } | |
| 1228 } | |
| 1229 | |
| 1230 /* | |
| 1231 * public, Partially supports PKCS5 V2 (some parameters are not controllable | |
| 1232 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need | |
| 1233 * finer control these. | |
| 1234 */ | |
| 1235 SECAlgorithmID * | |
| 1236 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt) | |
| 1237 { | |
| 1238 SECAlgorithmID *algid = NULL; | |
| 1239 algid = sec_pkcs5CreateAlgorithmID(algorithm, | |
| 1240 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration); | |
| 1241 return algid; | |
| 1242 } | |
| 1243 | |
| 1244 /* | |
| 1245 * public, fully support pkcs5v2. | |
| 1246 */ | |
| 1247 SECAlgorithmID * | |
| 1248 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag, | |
| 1249 SECOidTag prfAlgTag, int keyLength, int iteration, | |
| 1250 SECItem *salt) | |
| 1251 { | |
| 1252 SECAlgorithmID *algid = NULL; | |
| 1253 algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag, | |
| 1254 NULL, keyLength, salt, iteration); | |
| 1255 return algid; | |
| 1256 } | |
| 1257 | |
| 1258 /* | |
| 1259 * private. | |
| 1260 */ | |
| 1261 PK11SymKey * | |
| 1262 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 1263 SECItem *params, CK_KEY_TYPE keyType, int keyLen, | |
| 1264 SECItem *pwitem, void *wincx) | |
| 1265 { | |
| 1266 CK_ULONG pwLen; | |
| 1267 /* do some sanity checks */ | |
| 1268 if ((params == NULL) || (params->data == NULL)) { | |
| 1269 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1270 return NULL; | |
| 1271 } | |
| 1272 | |
| 1273 if (type == CKM_INVALID_MECHANISM) { | |
| 1274 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1275 return NULL; | |
| 1276 } | |
| 1277 | |
| 1278 /* set the password pointer in the parameters... */ | |
| 1279 if (type == CKM_PKCS5_PBKD2) { | |
| 1280 CK_PKCS5_PBKD2_PARAMS *pbev2_params; | |
| 1281 if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) { | |
| 1282 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1283 return NULL; | |
| 1284 } | |
| 1285 pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data; | |
| 1286 pbev2_params->pPassword = pwitem->data; | |
| 1287 pwLen = pwitem->len; | |
| 1288 pbev2_params->ulPasswordLen = &pwLen; | |
| 1289 } else { | |
| 1290 CK_PBE_PARAMS *pbe_params; | |
| 1291 if (params->len < sizeof(CK_PBE_PARAMS)) { | |
| 1292 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1293 return NULL; | |
| 1294 } | |
| 1295 pbe_params = (CK_PBE_PARAMS *)params->data; | |
| 1296 pbe_params->pPassword = pwitem->data; | |
| 1297 pbe_params->ulPasswordLen = pwitem->len; | |
| 1298 } | |
| 1299 | |
| 1300 /* generate the key (and sometimes the IV as a side effect...) */ | |
| 1301 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, | |
| 1302 keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, | |
| 1303 0, wincx); | |
| 1304 } | |
| 1305 | |
| 1306 /* | |
| 1307 * public, deprecated. use PK11_PBEKeyGen instead. | |
| 1308 */ | |
| 1309 PK11SymKey * | |
| 1310 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech, | |
| 1311 SECItem *pwitem, PRBool faulty3DES, void *wincx) | |
| 1312 { | |
| 1313 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { | |
| 1314 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; | |
| 1315 } | |
| 1316 return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx); | |
| 1317 } | |
| 1318 | |
| 1319 /* | |
| 1320 * pubic, supports pkcs5 v2. | |
| 1321 * | |
| 1322 * Create symkey from a PBE key. The algid can be created with | |
| 1323 * PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by | |
| 1324 * extraction of der data. | |
| 1325 */ | |
| 1326 PK11SymKey * | |
| 1327 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, | |
| 1328 PRBool faulty3DES, void *wincx) | |
| 1329 { | |
| 1330 CK_MECHANISM_TYPE type; | |
| 1331 SECItem *param = NULL; | |
| 1332 PK11SymKey *symKey = NULL; | |
| 1333 SECOidTag pbeAlg; | |
| 1334 CK_KEY_TYPE keyType = -1; | |
| 1335 int keyLen = 0; | |
| 1336 | |
| 1337 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
| 1338 /* if we're using PKCS5v2, extract the additional information we need | |
| 1339 * (key length, key type, and pbeAlg). */ | |
| 1340 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { | |
| 1341 CK_MECHANISM_TYPE cipherMech; | |
| 1342 sec_pkcs5V2Parameter *pbeV2_param; | |
| 1343 | |
| 1344 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
| 1345 if (pbeV2_param == NULL) { | |
| 1346 return NULL; | |
| 1347 } | |
| 1348 cipherMech = PK11_AlgtagToMechanism( | |
| 1349 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); | |
| 1350 pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId); | |
| 1351 param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId); | |
| 1352 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
| 1353 keyLen = SEC_PKCS5GetKeyLength(algid); | |
| 1354 if (keyLen == -1) { | |
| 1355 keyLen = 0; | |
| 1356 } | |
| 1357 keyType = PK11_GetKeyType(cipherMech, keyLen); | |
| 1358 } else { | |
| 1359 param = PK11_ParamFromAlgid(algid); | |
| 1360 } | |
| 1361 | |
| 1362 if(param == NULL) { | |
| 1363 goto loser; | |
| 1364 } | |
| 1365 | |
| 1366 type = PK11_AlgtagToMechanism(pbeAlg); | |
| 1367 if (type == CKM_INVALID_MECHANISM) { | |
| 1368 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1369 goto loser; | |
| 1370 } | |
| 1371 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { | |
| 1372 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; | |
| 1373 } | |
| 1374 symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen, | |
| 1375 pwitem, wincx); | |
| 1376 | |
| 1377 loser: | |
| 1378 if (param) { | |
| 1379 SECITEM_ZfreeItem(param, PR_TRUE); | |
| 1380 } | |
| 1381 return symKey; | |
| 1382 } | |
| 1383 | |
| 1384 /* | |
| 1385 * public, supports pkcs5v2 | |
| 1386 */ | |
| 1387 SECItem * | |
| 1388 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem) | |
| 1389 { | |
| 1390 return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE); | |
| 1391 } | |
| 1392 | |
| 1393 CK_MECHANISM_TYPE | |
| 1394 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, | |
| 1395 SECItem *pbe_pwd, PRBool faulty3DES) | |
| 1396 { | |
| 1397 int keyLen = 0; | |
| 1398 SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid); | |
| 1399 CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag); | |
| 1400 CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM; | |
| 1401 SECItem *iv = NULL; | |
| 1402 | |
| 1403 if (mech == CKM_INVALID_MECHANISM) { | |
| 1404 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1405 goto loser; | |
| 1406 } | |
| 1407 if (PK11_GetIVLength(mech)) { | |
| 1408 iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES); | |
| 1409 if (iv == NULL) { | |
| 1410 goto loser; | |
| 1411 } | |
| 1412 } | |
| 1413 | |
| 1414 keyLen = SEC_PKCS5GetKeyLength(algid); | |
| 1415 | |
| 1416 *param = pk11_ParamFromIVWithLen(mech, iv, keyLen); | |
| 1417 if (*param == NULL) { | |
| 1418 goto loser; | |
| 1419 } | |
| 1420 returnedMechanism = mech; | |
| 1421 | |
| 1422 loser: | |
| 1423 if (iv) { | |
| 1424 SECITEM_FreeItem(iv,PR_TRUE); | |
| 1425 } | |
| 1426 return returnedMechanism; | |
| 1427 } | |
| 1428 | |
| 1429 /* | |
| 1430 * Public, supports pkcs5 v2 | |
| 1431 * | |
| 1432 * Get the crypto mechanism directly from the pbe algorithmid. | |
| 1433 * | |
| 1434 * It's important to go directly from the algorithm id so that we can | |
| 1435 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases. | |
| 1436 * | |
| 1437 * This function returns both the mechanism and the parameter for the mechanism. | |
| 1438 * The caller is responsible for freeing the parameter. | |
| 1439 */ | |
| 1440 CK_MECHANISM_TYPE | |
| 1441 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, | |
| 1442 SECItem *pbe_pwd) | |
| 1443 { | |
| 1444 return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE); | |
| 1445 } | |
| OLD | NEW |