security/nss/lib/pk11wrap/pk11pbe.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial