1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11pbe.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1432 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "plarena.h" 1.9 + 1.10 +#include "seccomon.h" 1.11 +#include "secitem.h" 1.12 +#include "secport.h" 1.13 +#include "hasht.h" 1.14 +#include "pkcs11t.h" 1.15 +#include "sechash.h" 1.16 +#include "secasn1.h" 1.17 +#include "secder.h" 1.18 +#include "secoid.h" 1.19 +#include "secerr.h" 1.20 +#include "secmod.h" 1.21 +#include "pk11func.h" 1.22 +#include "secpkcs5.h" 1.23 +#include "secmodi.h" 1.24 +#include "secmodti.h" 1.25 +#include "pkcs11.h" 1.26 +#include "pk11func.h" 1.27 +#include "secitem.h" 1.28 +#include "key.h" 1.29 + 1.30 +typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; 1.31 +struct SEC_PKCS5PBEParameterStr { 1.32 + PLArenaPool *poolp; 1.33 + SECItem salt; /* octet string */ 1.34 + SECItem iteration; /* integer */ 1.35 + SECItem keyLength; /* PKCS5v2 only */ 1.36 + SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */ 1.37 + SECAlgorithmID prfAlgId; /* PKCS5v2 only */ 1.38 +}; 1.39 + 1.40 +/* PKCS5 V2 has an algorithm ID for the encryption and for 1.41 + * the key generation. This is valid for SEC_OID_PKCS5_PBES2 1.42 + * and SEC_OID_PKCS5_PBMAC1 1.43 + */ 1.44 +struct sec_pkcs5V2ParameterStr { 1.45 + PLArenaPool *poolp; 1.46 + SECAlgorithmID pbeAlgId; /* real pbe algorithms */ 1.47 + SECAlgorithmID cipherAlgId; /* encryption/mac */ 1.48 +}; 1.49 + 1.50 +typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter; 1.51 + 1.52 + 1.53 +/* template for PKCS 5 PBE Parameter. This template has been expanded 1.54 + * based upon the additions in PKCS 12. This should eventually be moved 1.55 + * if RSA updates PKCS 5. 1.56 + */ 1.57 +const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = 1.58 +{ 1.59 + { SEC_ASN1_SEQUENCE, 1.60 + 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, 1.61 + { SEC_ASN1_OCTET_STRING, 1.62 + offsetof(SEC_PKCS5PBEParameter, salt) }, 1.63 + { SEC_ASN1_INTEGER, 1.64 + offsetof(SEC_PKCS5PBEParameter, iteration) }, 1.65 + { 0 } 1.66 +}; 1.67 + 1.68 +const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = 1.69 +{ 1.70 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, 1.71 + { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, 1.72 + { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, 1.73 + { 0 } 1.74 +}; 1.75 + 1.76 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.77 + 1.78 +/* SECOID_PKCS5_PBKDF2 */ 1.79 +const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] = 1.80 +{ 1.81 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, 1.82 + /* This is really a choice, but since we only understand this 1.83 + * choice, just inline it */ 1.84 + { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, 1.85 + { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, 1.86 + { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL, 1.87 + offsetof(SEC_PKCS5PBEParameter, keyLength) }, 1.88 + { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, 1.89 + offsetof(SEC_PKCS5PBEParameter, pPrfAlgId), 1.90 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.91 + { 0 } 1.92 +}; 1.93 + 1.94 +/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */ 1.95 +const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] = 1.96 +{ 1.97 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, 1.98 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId), 1.99 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.100 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.101 + offsetof(sec_pkcs5V2Parameter, cipherAlgId), 1.102 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.103 + { 0 } 1.104 +}; 1.105 + 1.106 + 1.107 +/* 1.108 + * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1 1.109 + * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2. 1.110 + */ 1.111 +SECOidTag 1.112 +sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm) 1.113 +{ 1.114 + switch(algorithm) 1.115 + { 1.116 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: 1.117 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: 1.118 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: 1.119 + return SEC_OID_DES_EDE3_CBC; 1.120 + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: 1.121 + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: 1.122 + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: 1.123 + return SEC_OID_DES_CBC; 1.124 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.125 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.126 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.127 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.128 + return SEC_OID_RC2_CBC; 1.129 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.130 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.131 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.132 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.133 + return SEC_OID_RC4; 1.134 + case SEC_OID_PKCS5_PBKDF2: 1.135 + case SEC_OID_PKCS5_PBES2: 1.136 + case SEC_OID_PKCS5_PBMAC1: 1.137 + return SEC_OID_PKCS5_PBKDF2; 1.138 + default: 1.139 + break; 1.140 + } 1.141 + 1.142 + return SEC_OID_UNKNOWN; 1.143 +} 1.144 + 1.145 +/* 1.146 + * get a new PKCS5 V2 Parameter from the algorithm id. 1.147 + * if arena is passed in, use it, otherwise create a new arena. 1.148 + */ 1.149 +sec_pkcs5V2Parameter * 1.150 +sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid) 1.151 +{ 1.152 + PLArenaPool *localArena = NULL; 1.153 + sec_pkcs5V2Parameter *pbeV2_param; 1.154 + SECStatus rv; 1.155 + 1.156 + if (arena == NULL) { 1.157 + localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.158 + if (arena == NULL) { 1.159 + return NULL; 1.160 + } 1.161 + } 1.162 + pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter); 1.163 + if (pbeV2_param == NULL) { 1.164 + goto loser; 1.165 + } 1.166 + 1.167 + rv = SEC_ASN1DecodeItem(arena, pbeV2_param, 1.168 + SEC_PKCS5V2ParameterTemplate, &algid->parameters); 1.169 + if (rv == SECFailure) { 1.170 + goto loser; 1.171 + } 1.172 + 1.173 + pbeV2_param->poolp = arena; 1.174 + return pbeV2_param; 1.175 +loser: 1.176 + if (localArena) { 1.177 + PORT_FreeArena(arena, PR_FALSE); 1.178 + } 1.179 + return NULL; 1.180 +} 1.181 + 1.182 +void 1.183 +sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param) 1.184 +{ 1.185 + if (param && param->poolp) { 1.186 + PORT_FreeArena(param->poolp, PR_TRUE); 1.187 + } 1.188 +} 1.189 + 1.190 + 1.191 +/* maps crypto algorithm from PBE algorithm. 1.192 + */ 1.193 +SECOidTag 1.194 +SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) 1.195 +{ 1.196 + 1.197 + SECOidTag pbeAlg; 1.198 + SECOidTag cipherAlg; 1.199 + 1.200 + if(algid == NULL) 1.201 + return SEC_OID_UNKNOWN; 1.202 + 1.203 + pbeAlg = SECOID_GetAlgorithmTag(algid); 1.204 + cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg); 1.205 + if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) && 1.206 + (pbeAlg != SEC_OID_PKCS5_PBKDF2)) { 1.207 + sec_pkcs5V2Parameter *pbeV2_param; 1.208 + cipherAlg = SEC_OID_UNKNOWN; 1.209 + 1.210 + pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); 1.211 + if (pbeV2_param != NULL) { 1.212 + cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId); 1.213 + sec_pkcs5_v2_destroy_v2_param(pbeV2_param); 1.214 + } 1.215 + } 1.216 + 1.217 + return cipherAlg; 1.218 +} 1.219 + 1.220 +/* check to see if an oid is a pbe algorithm 1.221 + */ 1.222 +PRBool 1.223 +SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) 1.224 +{ 1.225 + return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN); 1.226 +} 1.227 + 1.228 +PRBool 1.229 +SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag) 1.230 +{ 1.231 + return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN); 1.232 +} 1.233 + 1.234 +/* 1.235 + * find the most appropriate PKCS5v2 overall oid tag from a regular 1.236 + * cipher/hash algorithm tag. 1.237 + */ 1.238 +static SECOidTag 1.239 +sec_pkcs5v2_get_pbe(SECOidTag algTag) 1.240 +{ 1.241 + /* if it's a valid hash oid... */ 1.242 + if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) { 1.243 + /* use the MAC tag */ 1.244 + return SEC_OID_PKCS5_PBMAC1; 1.245 + } 1.246 + if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) { 1.247 + /* eliminate Hash algorithms */ 1.248 + return SEC_OID_UNKNOWN; 1.249 + } 1.250 + if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) { 1.251 + /* it's not a hash, if it has a PKCS #11 mechanism associated 1.252 + * with it, assume it's a cipher. (NOTE this will generate 1.253 + * some false positives). */ 1.254 + return SEC_OID_PKCS5_PBES2; 1.255 + } 1.256 + return SEC_OID_UNKNOWN; 1.257 +} 1.258 + 1.259 +/* 1.260 + * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. 1.261 + * input keyLen in bits. 1.262 + */ 1.263 +SECOidTag 1.264 +SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) 1.265 +{ 1.266 + switch(algTag) 1.267 + { 1.268 + case SEC_OID_DES_EDE3_CBC: 1.269 + switch(keyLen) { 1.270 + case 168: 1.271 + case 192: 1.272 + case 0: 1.273 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; 1.274 + case 128: 1.275 + case 92: 1.276 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; 1.277 + default: 1.278 + break; 1.279 + } 1.280 + break; 1.281 + case SEC_OID_DES_CBC: 1.282 + return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; 1.283 + case SEC_OID_RC2_CBC: 1.284 + switch(keyLen) { 1.285 + case 40: 1.286 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; 1.287 + case 128: 1.288 + case 0: 1.289 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; 1.290 + default: 1.291 + break; 1.292 + } 1.293 + break; 1.294 + case SEC_OID_RC4: 1.295 + switch(keyLen) { 1.296 + case 40: 1.297 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; 1.298 + case 128: 1.299 + case 0: 1.300 + return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; 1.301 + default: 1.302 + break; 1.303 + } 1.304 + break; 1.305 + default: 1.306 + return sec_pkcs5v2_get_pbe(algTag); 1.307 + } 1.308 + 1.309 + return SEC_OID_UNKNOWN; 1.310 +} 1.311 + 1.312 +/* 1.313 + * get the key length in bytes from a PKCS5 PBE 1.314 + */ 1.315 +int 1.316 +sec_pkcs5v2_key_length(SECAlgorithmID *algid) 1.317 +{ 1.318 + SECOidTag algorithm; 1.319 + PLArenaPool *arena = NULL; 1.320 + SEC_PKCS5PBEParameter p5_param; 1.321 + SECStatus rv; 1.322 + int length = -1; 1.323 + 1.324 + algorithm = SECOID_GetAlgorithmTag(algid); 1.325 + /* sanity check, they should all be PBKDF2 here */ 1.326 + if (algorithm != SEC_OID_PKCS5_PBKDF2) { 1.327 + return -1; 1.328 + } 1.329 + 1.330 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.331 + if (arena == NULL) { 1.332 + goto loser; 1.333 + } 1.334 + PORT_Memset(&p5_param, 0, sizeof(p5_param)); 1.335 + rv = SEC_ASN1DecodeItem(arena,&p5_param, 1.336 + SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); 1.337 + if (rv != SECSuccess) { 1.338 + goto loser; 1.339 + } 1.340 + 1.341 + if (p5_param.keyLength.data != NULL) { 1.342 + length = DER_GetInteger(&p5_param.keyLength); 1.343 + } 1.344 + 1.345 +loser: 1.346 + if (arena) { 1.347 + PORT_FreeArena(arena, PR_FALSE); 1.348 + } 1.349 + return length; 1.350 +} 1.351 + 1.352 +/* 1.353 + * get the key length in bytes needed for the PBE algorithm 1.354 + */ 1.355 +int 1.356 +SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) 1.357 +{ 1.358 + 1.359 + SECOidTag algorithm; 1.360 + 1.361 + if(algid == NULL) 1.362 + return SEC_OID_UNKNOWN; 1.363 + 1.364 + algorithm = SECOID_GetAlgorithmTag(algid); 1.365 + 1.366 + switch(algorithm) 1.367 + { 1.368 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: 1.369 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: 1.370 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: 1.371 + return 24; 1.372 + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: 1.373 + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: 1.374 + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: 1.375 + return 8; 1.376 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.377 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.378 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.379 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.380 + return 5; 1.381 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.382 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.383 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.384 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.385 + return 16; 1.386 + case SEC_OID_PKCS5_PBKDF2: 1.387 + return sec_pkcs5v2_key_length(algid); 1.388 + case SEC_OID_PKCS5_PBES2: 1.389 + case SEC_OID_PKCS5_PBMAC1: 1.390 + { 1.391 + sec_pkcs5V2Parameter *pbeV2_param; 1.392 + int length = -1; 1.393 + pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); 1.394 + if (pbeV2_param != NULL) { 1.395 + length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId); 1.396 + sec_pkcs5_v2_destroy_v2_param(pbeV2_param); 1.397 + } 1.398 + return length; 1.399 + } 1.400 + 1.401 + default: 1.402 + break; 1.403 + } 1.404 + return -1; 1.405 +} 1.406 + 1.407 + 1.408 +/* the PKCS12 V2 algorithms only encode the salt, there is no iteration 1.409 + * count so we need a check for V2 algorithm parameters. 1.410 + */ 1.411 +static PRBool 1.412 +sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) 1.413 +{ 1.414 + switch(algorithm) 1.415 + { 1.416 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.417 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.418 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: 1.419 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: 1.420 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.421 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.422 + return PR_TRUE; 1.423 + default: 1.424 + break; 1.425 + } 1.426 + 1.427 + return PR_FALSE; 1.428 +} 1.429 + 1.430 +static PRBool 1.431 +sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm) 1.432 +{ 1.433 + switch(algorithm) 1.434 + { 1.435 + case SEC_OID_PKCS5_PBES2: 1.436 + case SEC_OID_PKCS5_PBMAC1: 1.437 + case SEC_OID_PKCS5_PBKDF2: 1.438 + return PR_TRUE; 1.439 + default: 1.440 + break; 1.441 + } 1.442 + 1.443 + return PR_FALSE; 1.444 +} 1.445 + 1.446 +/* destroy a pbe parameter. it assumes that the parameter was 1.447 + * generated using the appropriate create function and therefor 1.448 + * contains an arena pool. 1.449 + */ 1.450 +static void 1.451 +sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) 1.452 +{ 1.453 + if(pbe_param != NULL) 1.454 + PORT_FreeArena(pbe_param->poolp, PR_TRUE); 1.455 +} 1.456 + 1.457 +/* creates a PBE parameter based on the PBE algorithm. the only required 1.458 + * parameters are algorithm and interation. the return is a PBE parameter 1.459 + * which conforms to PKCS 5 parameter unless an extended parameter is needed. 1.460 + * this is primarily if keyLength and a variable key length algorithm are 1.461 + * specified. 1.462 + * salt - if null, a salt will be generated from random bytes. 1.463 + * iteration - number of iterations to perform hashing. 1.464 + * keyLength - only used in variable key length algorithms. if specified, 1.465 + * should be in bytes. 1.466 + * once a parameter is allocated, it should be destroyed calling 1.467 + * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. 1.468 + */ 1.469 +#define DEFAULT_SALT_LENGTH 16 1.470 +static SEC_PKCS5PBEParameter * 1.471 +sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, 1.472 + SECItem *salt, 1.473 + int iteration, 1.474 + int keyLength, 1.475 + SECOidTag prfAlg) 1.476 +{ 1.477 + PLArenaPool *poolp = NULL; 1.478 + SEC_PKCS5PBEParameter *pbe_param = NULL; 1.479 + SECStatus rv= SECSuccess; 1.480 + void *dummy = NULL; 1.481 + 1.482 + if(iteration < 0) { 1.483 + return NULL; 1.484 + } 1.485 + 1.486 + poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.487 + if(poolp == NULL) 1.488 + return NULL; 1.489 + 1.490 + pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, 1.491 + sizeof(SEC_PKCS5PBEParameter)); 1.492 + if(!pbe_param) { 1.493 + PORT_FreeArena(poolp, PR_TRUE); 1.494 + return NULL; 1.495 + } 1.496 + 1.497 + pbe_param->poolp = poolp; 1.498 + 1.499 + rv = SECFailure; 1.500 + if (salt && salt->data) { 1.501 + rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); 1.502 + } else { 1.503 + /* sigh, the old interface generated salt on the fly, so we have to 1.504 + * preserve the semantics */ 1.505 + pbe_param->salt.len = DEFAULT_SALT_LENGTH; 1.506 + pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH); 1.507 + if (pbe_param->salt.data) { 1.508 + rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH); 1.509 + } 1.510 + } 1.511 + 1.512 + if(rv != SECSuccess) { 1.513 + PORT_FreeArena(poolp, PR_TRUE); 1.514 + return NULL; 1.515 + } 1.516 + 1.517 + /* encode the integer */ 1.518 + dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, 1.519 + iteration); 1.520 + rv = (dummy) ? SECSuccess : SECFailure; 1.521 + 1.522 + if(rv != SECSuccess) { 1.523 + PORT_FreeArena(poolp, PR_FALSE); 1.524 + return NULL; 1.525 + } 1.526 + 1.527 + /* 1.528 + * for PKCS5 v2 Add the keylength and the prf 1.529 + */ 1.530 + if (algorithm == SEC_OID_PKCS5_PBKDF2) { 1.531 + dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength, 1.532 + keyLength); 1.533 + rv = (dummy) ? SECSuccess : SECFailure; 1.534 + if (rv != SECSuccess) { 1.535 + PORT_FreeArena(poolp, PR_FALSE); 1.536 + return NULL; 1.537 + } 1.538 + rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL); 1.539 + if (rv != SECSuccess) { 1.540 + PORT_FreeArena(poolp, PR_FALSE); 1.541 + return NULL; 1.542 + } 1.543 + pbe_param->pPrfAlgId = &pbe_param->prfAlgId; 1.544 + } 1.545 + 1.546 + return pbe_param; 1.547 +} 1.548 + 1.549 +/* creates a algorithm ID containing the PBE algorithm and appropriate 1.550 + * parameters. the required parameter is the algorithm. if salt is 1.551 + * not specified, it is generated randomly. 1.552 + * 1.553 + * the returned SECAlgorithmID should be destroyed using 1.554 + * SECOID_DestroyAlgorithmID 1.555 + */ 1.556 +SECAlgorithmID * 1.557 +sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, 1.558 + SECOidTag cipherAlgorithm, 1.559 + SECOidTag prfAlg, 1.560 + SECOidTag *pPbeAlgorithm, 1.561 + int keyLength, 1.562 + SECItem *salt, 1.563 + int iteration) 1.564 +{ 1.565 + PLArenaPool *poolp = NULL; 1.566 + SECAlgorithmID *algid, *ret_algid = NULL; 1.567 + SECOidTag pbeAlgorithm = algorithm; 1.568 + SECItem der_param; 1.569 + void *dummy; 1.570 + SECStatus rv = SECFailure; 1.571 + SEC_PKCS5PBEParameter *pbe_param = NULL; 1.572 + sec_pkcs5V2Parameter pbeV2_param; 1.573 + 1.574 + if(iteration <= 0) { 1.575 + return NULL; 1.576 + } 1.577 + 1.578 + poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.579 + if(!poolp) { 1.580 + goto loser; 1.581 + } 1.582 + 1.583 + if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) || 1.584 + sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { 1.585 + /* use PKCS 5 v2 */ 1.586 + SECItem *cipherParams; 1.587 + 1.588 + /* 1.589 + * if we ask for pkcs5 Algorithms directly, then the 1.590 + * application needs to supply the cipher algorithm, 1.591 + * otherwise we are implicitly using pkcs5 v2 and the 1.592 + * passed in algorithm is the encryption algorithm. 1.593 + */ 1.594 + if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { 1.595 + if (cipherAlgorithm == SEC_OID_UNKNOWN) { 1.596 + goto loser; 1.597 + } 1.598 + } else { 1.599 + cipherAlgorithm = algorithm; 1.600 + /* force algorithm to be chosen below */ 1.601 + algorithm = SEC_OID_PKCS5_PBKDF2; 1.602 + } 1.603 + 1.604 + pbeAlgorithm = SEC_OID_PKCS5_PBKDF2; 1.605 + /* 1.606 + * 'algorithm' is the overall algorithm oid tag used to wrap the 1.607 + * entire algoithm ID block. For PKCS5v1 and PKCS12, this 1.608 + * algorithm OID has encoded in it both the PBE KDF function 1.609 + * and the encryption algorithm. For PKCS 5v2, PBE KDF and 1.610 + * encryption/macing oids are encoded as parameters in 1.611 + * the algorithm ID block. 1.612 + * 1.613 + * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11 1.614 + * mechanism, where as in PKCS 5v2, this alogithm tag does not map 1.615 + * directly to a PKCS #11 mechanim, instead the 2 oids in the 1.616 + * algorithm ID block map the the actual PKCS #11 mechanism. 1.617 + * gorithm is). We use choose this algorithm oid based on the 1.618 + * cipherAlgorithm to determine what this should be (MAC1 or PBES2). 1.619 + */ 1.620 + if (algorithm == SEC_OID_PKCS5_PBKDF2) { 1.621 + /* choose mac or pbes */ 1.622 + algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm); 1.623 + } 1.624 + 1.625 + /* set the PKCS5v2 specific parameters */ 1.626 + if (keyLength == 0) { 1.627 + SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm); 1.628 + if (hashAlg != SEC_OID_UNKNOWN) { 1.629 + keyLength = HASH_ResultLenByOidTag(hashAlg); 1.630 + } else { 1.631 + CK_MECHANISM_TYPE cryptoMech; 1.632 + cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm); 1.633 + if (cryptoMech == CKM_INVALID_MECHANISM) { 1.634 + goto loser; 1.635 + } 1.636 + keyLength = PK11_GetMaxKeyLength(cryptoMech); 1.637 + } 1.638 + if (keyLength == 0) { 1.639 + goto loser; 1.640 + } 1.641 + } 1.642 + /* currently only SEC_OID_HMAC_SHA1 is defined */ 1.643 + if (prfAlg == SEC_OID_UNKNOWN) { 1.644 + prfAlg = SEC_OID_HMAC_SHA1; 1.645 + } 1.646 + 1.647 + /* build the PKCS5v2 cipher algorithm id */ 1.648 + cipherParams = pk11_GenerateNewParamWithKeyLen( 1.649 + PK11_AlgtagToMechanism(cipherAlgorithm), keyLength); 1.650 + if (!cipherParams) { 1.651 + goto loser; 1.652 + } 1.653 + 1.654 + PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param)); 1.655 + 1.656 + rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, 1.657 + poolp, &pbeV2_param.cipherAlgId); 1.658 + SECITEM_FreeItem(cipherParams, PR_TRUE); 1.659 + if (rv != SECSuccess) { 1.660 + goto loser; 1.661 + } 1.662 + } 1.663 + 1.664 + 1.665 + /* generate the parameter */ 1.666 + pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration, 1.667 + keyLength, prfAlg); 1.668 + if(!pbe_param) { 1.669 + goto loser; 1.670 + } 1.671 + 1.672 + /* generate the algorithm id */ 1.673 + algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); 1.674 + if(algid == NULL) { 1.675 + goto loser; 1.676 + } 1.677 + 1.678 + der_param.data = NULL; 1.679 + der_param.len = 0; 1.680 + if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { 1.681 + /* first encode the PBE algorithm ID */ 1.682 + dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, 1.683 + SEC_PKCS5V2PBEParameterTemplate); 1.684 + if (dummy == NULL) { 1.685 + goto loser; 1.686 + } 1.687 + rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId, 1.688 + pbeAlgorithm, &der_param); 1.689 + if (rv != SECSuccess) { 1.690 + goto loser; 1.691 + } 1.692 + 1.693 + /* now encode the Full PKCS 5 parameter */ 1.694 + der_param.data = NULL; 1.695 + der_param.len = 0; 1.696 + dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param, 1.697 + SEC_PKCS5V2ParameterTemplate); 1.698 + } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { 1.699 + dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, 1.700 + SEC_PKCS5PBEParameterTemplate); 1.701 + } else { 1.702 + dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, 1.703 + SEC_V2PKCS12PBEParameterTemplate); 1.704 + } 1.705 + if (dummy == NULL) { 1.706 + goto loser; 1.707 + } 1.708 + 1.709 + rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); 1.710 + if (rv != SECSuccess) { 1.711 + goto loser; 1.712 + } 1.713 + 1.714 + ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); 1.715 + if (ret_algid == NULL) { 1.716 + goto loser; 1.717 + } 1.718 + 1.719 + rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); 1.720 + if (rv != SECSuccess) { 1.721 + SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); 1.722 + ret_algid = NULL; 1.723 + } else if (pPbeAlgorithm) { 1.724 + *pPbeAlgorithm = pbeAlgorithm; 1.725 + } 1.726 + 1.727 +loser: 1.728 + if (poolp != NULL) { 1.729 + PORT_FreeArena(poolp, PR_TRUE); 1.730 + algid = NULL; 1.731 + } 1.732 + 1.733 + if (pbe_param) { 1.734 + sec_pkcs5_destroy_pbe_param(pbe_param); 1.735 + } 1.736 + 1.737 + return ret_algid; 1.738 +} 1.739 + 1.740 +SECStatus 1.741 +pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech) 1.742 +{ 1.743 + SEC_PKCS5PBEParameter p5_param; 1.744 + SECItem *salt = NULL; 1.745 + SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); 1.746 + PLArenaPool *arena = NULL; 1.747 + SECStatus rv = SECFailure; 1.748 + unsigned char *paramData = NULL; 1.749 + unsigned char *pSalt = NULL; 1.750 + CK_ULONG iterations; 1.751 + int paramLen = 0; 1.752 + int iv_len; 1.753 + 1.754 + 1.755 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.756 + if (arena == NULL) { 1.757 + goto loser; 1.758 + } 1.759 + 1.760 + 1.761 + /* 1.762 + * decode the algid based on the pbe type 1.763 + */ 1.764 + PORT_Memset(&p5_param, 0, sizeof(p5_param)); 1.765 + if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { 1.766 + iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); 1.767 + rv = SEC_ASN1DecodeItem(arena, &p5_param, 1.768 + SEC_V2PKCS12PBEParameterTemplate, &algid->parameters); 1.769 + } else if (algorithm == SEC_OID_PKCS5_PBKDF2) { 1.770 + iv_len = 0; 1.771 + rv = SEC_ASN1DecodeItem(arena,&p5_param, 1.772 + SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); 1.773 + } else { 1.774 + iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); 1.775 + rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, 1.776 + &algid->parameters); 1.777 + } 1.778 + 1.779 + if (iv_len < 0) { 1.780 + goto loser; 1.781 + } 1.782 + 1.783 + if (rv != SECSuccess) { 1.784 + goto loser; 1.785 + } 1.786 + 1.787 + /* get salt */ 1.788 + salt = &p5_param.salt; 1.789 + iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration); 1.790 + 1.791 + /* allocate and fill in the PKCS #11 parameters 1.792 + * based on the algorithm. */ 1.793 + if (algorithm == SEC_OID_PKCS5_PBKDF2) { 1.794 + SECOidTag prfAlgTag; 1.795 + CK_PKCS5_PBKD2_PARAMS *pbeV2_params = 1.796 + (CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc( 1.797 + sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len); 1.798 + 1.799 + if (pbeV2_params == NULL) { 1.800 + goto loser; 1.801 + } 1.802 + paramData = (unsigned char *)pbeV2_params; 1.803 + paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS); 1.804 + 1.805 + /* set the prf */ 1.806 + prfAlgTag = SEC_OID_HMAC_SHA1; 1.807 + if (p5_param.pPrfAlgId && 1.808 + p5_param.pPrfAlgId->algorithm.data != 0) { 1.809 + prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId); 1.810 + } 1.811 + if (prfAlgTag == SEC_OID_HMAC_SHA1) { 1.812 + pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1; 1.813 + } else { 1.814 + /* only SHA1_HMAC is currently supported by PKCS #11 */ 1.815 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.816 + goto loser; 1.817 + } 1.818 + 1.819 + /* probably should fetch these from the prfAlgid */ 1.820 + pbeV2_params->pPrfData = NULL; 1.821 + pbeV2_params->ulPrfDataLen = 0; 1.822 + pbeV2_params->saltSource = CKZ_SALT_SPECIFIED; 1.823 + pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS); 1.824 + PORT_Memcpy(pSalt, salt->data, salt->len); 1.825 + pbeV2_params->pSaltSourceData = pSalt; 1.826 + pbeV2_params->ulSaltSourceDataLen = salt->len; 1.827 + pbeV2_params->iterations = iterations; 1.828 + } else { 1.829 + CK_PBE_PARAMS *pbe_params = NULL; 1.830 + pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+ 1.831 + salt->len+iv_len); 1.832 + if (pbe_params == NULL) { 1.833 + goto loser; 1.834 + } 1.835 + paramData = (unsigned char *)pbe_params; 1.836 + paramLen = sizeof(CK_PBE_PARAMS); 1.837 + 1.838 + pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS); 1.839 + pbe_params->pSalt = pSalt; 1.840 + PORT_Memcpy(pSalt, salt->data, salt->len); 1.841 + pbe_params->ulSaltLen = salt->len; 1.842 + if (iv_len) { 1.843 + pbe_params->pInitVector = 1.844 + ((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len; 1.845 + } 1.846 + pbe_params->ulIteration = iterations; 1.847 + } 1.848 + 1.849 + /* copy into the mechanism sec item */ 1.850 + mech->data = paramData; 1.851 + mech->len = paramLen; 1.852 + if (arena) { 1.853 + PORT_FreeArena(arena,PR_TRUE); 1.854 + } 1.855 + return SECSuccess; 1.856 + 1.857 +loser: 1.858 + if (paramData) { 1.859 + PORT_Free(paramData); 1.860 + } 1.861 + if (arena) { 1.862 + PORT_FreeArena(arena,PR_TRUE); 1.863 + } 1.864 + return SECFailure; 1.865 +} 1.866 + 1.867 +/* 1.868 + * public, deprecated, not valid for pkcs5 v2 1.869 + * 1.870 + * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create 1.871 + * PBE algorithmID's directly. 1.872 + */ 1.873 +SECStatus 1.874 +PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena, 1.875 + SECAlgorithmID *algId) 1.876 +{ 1.877 + CK_PBE_PARAMS *pbe_param; 1.878 + SECItem pbeSalt; 1.879 + SECAlgorithmID *pbeAlgID = NULL; 1.880 + SECStatus rv; 1.881 + 1.882 + if(!param || !algId) { 1.883 + return SECFailure; 1.884 + } 1.885 + 1.886 + pbe_param = (CK_PBE_PARAMS *)param->data; 1.887 + pbeSalt.data = (unsigned char *)pbe_param->pSalt; 1.888 + pbeSalt.len = pbe_param->ulSaltLen; 1.889 + pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, 1.890 + SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration); 1.891 + if(!pbeAlgID) { 1.892 + return SECFailure; 1.893 + } 1.894 + 1.895 + rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); 1.896 + SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); 1.897 + return rv; 1.898 +} 1.899 + 1.900 +/* 1.901 + * public, Deprecated, This function is only for binary compatibility with 1.902 + * older applications. Does not support PKCS5v2. 1.903 + * 1.904 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for 1.905 + * iv values rather than generating PBE bits directly. 1.906 + */ 1.907 +PBEBitGenContext * 1.908 +PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, 1.909 + SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, 1.910 + unsigned int iterations) 1.911 +{ 1.912 + SECItem *context = NULL; 1.913 + SECItem mechItem; 1.914 + CK_PBE_PARAMS pbe_params; 1.915 + CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; 1.916 + PK11SlotInfo *slot; 1.917 + PK11SymKey *symKey = NULL; 1.918 + unsigned char ivData[8]; 1.919 + 1.920 + 1.921 + /* use the purpose to select the low level keygen algorithm */ 1.922 + switch (bitGenPurpose) { 1.923 + case pbeBitGenIntegrityKey: 1.924 + switch (hashAlgorithm) { 1.925 + case SEC_OID_SHA1: 1.926 + mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC; 1.927 + break; 1.928 + case SEC_OID_MD2: 1.929 + mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; 1.930 + break; 1.931 + case SEC_OID_MD5: 1.932 + mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; 1.933 + break; 1.934 + default: 1.935 + break; 1.936 + } 1.937 + break; 1.938 + case pbeBitGenCipherIV: 1.939 + if (bitsNeeded > 64) { 1.940 + break; 1.941 + } 1.942 + if (hashAlgorithm != SEC_OID_SHA1) { 1.943 + break; 1.944 + } 1.945 + mechanism = CKM_PBE_SHA1_DES3_EDE_CBC; 1.946 + break; 1.947 + case pbeBitGenCipherKey: 1.948 + if (hashAlgorithm != SEC_OID_SHA1) { 1.949 + break; 1.950 + } 1.951 + switch (bitsNeeded) { 1.952 + case 40: 1.953 + mechanism = CKM_PBE_SHA1_RC4_40; 1.954 + break; 1.955 + case 128: 1.956 + mechanism = CKM_PBE_SHA1_RC4_128; 1.957 + break; 1.958 + default: 1.959 + break; 1.960 + } 1.961 + case pbeBitGenIDNull: 1.962 + break; 1.963 + } 1.964 + 1.965 + if (mechanism == CKM_INVALID_MECHANISM) { 1.966 + /* we should set an error, but this is a deprecated function, and 1.967 + * we are keeping bug for bug compatibility;)... */ 1.968 + return NULL; 1.969 + } 1.970 + 1.971 + pbe_params.pInitVector = ivData; 1.972 + pbe_params.pPassword = pwitem->data; 1.973 + pbe_params.ulPasswordLen = pwitem->len; 1.974 + pbe_params.pSalt = salt->data; 1.975 + pbe_params.ulSaltLen = salt->len; 1.976 + pbe_params.ulIteration = iterations; 1.977 + mechItem.data = (unsigned char *) &pbe_params; 1.978 + mechItem.len = sizeof(pbe_params); 1.979 + 1.980 + 1.981 + slot = PK11_GetInternalSlot(); 1.982 + symKey = PK11_RawPBEKeyGen(slot,mechanism, 1.983 + &mechItem, pwitem, PR_FALSE, NULL); 1.984 + PK11_FreeSlot(slot); 1.985 + if (symKey != NULL) { 1.986 + if (bitGenPurpose == pbeBitGenCipherIV) { 1.987 + /* NOTE: this assumes that bitsNeeded is a multiple of 8! */ 1.988 + SECItem ivItem; 1.989 + 1.990 + ivItem.data = ivData; 1.991 + ivItem.len = bitsNeeded/8; 1.992 + context = SECITEM_DupItem(&ivItem); 1.993 + } else { 1.994 + SECItem *keyData; 1.995 + PK11_ExtractKeyValue(symKey); 1.996 + keyData = PK11_GetKeyData(symKey); 1.997 + 1.998 + /* assert bitsNeeded with length? */ 1.999 + if (keyData) { 1.1000 + context = SECITEM_DupItem(keyData); 1.1001 + } 1.1002 + } 1.1003 + PK11_FreeSymKey(symKey); 1.1004 + } 1.1005 + 1.1006 + return (PBEBitGenContext *)context; 1.1007 +} 1.1008 + 1.1009 +/* 1.1010 + * public, Deprecated, This function is only for binary compatibility with 1.1011 + * older applications. Does not support PKCS5v2. 1.1012 + * 1.1013 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for 1.1014 + * iv values rather than generating PBE bits directly. 1.1015 + */ 1.1016 +SECItem * 1.1017 +PBE_GenerateBits(PBEBitGenContext *context) 1.1018 +{ 1.1019 + return (SECItem *)context; 1.1020 +} 1.1021 + 1.1022 +/* 1.1023 + * public, Deprecated, This function is only for binary compatibility with 1.1024 + * older applications. Does not support PKCS5v2. 1.1025 + * 1.1026 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for 1.1027 + * iv values rather than generating PBE bits directly. 1.1028 + */ 1.1029 +void 1.1030 +PBE_DestroyContext(PBEBitGenContext *context) 1.1031 +{ 1.1032 + SECITEM_FreeItem((SECItem *)context,PR_TRUE); 1.1033 +} 1.1034 + 1.1035 +/* 1.1036 + * public, deprecated. Replaced with PK11_GetPBEIV(). 1.1037 + */ 1.1038 +SECItem * 1.1039 +SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) 1.1040 +{ 1.1041 + /* pbe stuff */ 1.1042 + CK_MECHANISM_TYPE type; 1.1043 + SECItem *param = NULL; 1.1044 + SECItem *iv = NULL; 1.1045 + SECItem src; 1.1046 + int iv_len = 0; 1.1047 + PK11SymKey *symKey; 1.1048 + PK11SlotInfo *slot; 1.1049 + CK_PBE_PARAMS_PTR pPBEparams; 1.1050 + SECOidTag pbeAlg; 1.1051 + 1.1052 + pbeAlg = SECOID_GetAlgorithmTag(algid); 1.1053 + if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { 1.1054 + unsigned char *ivData; 1.1055 + sec_pkcs5V2Parameter *pbeV2_param = NULL; 1.1056 + 1.1057 + /* can only return the IV if the crypto Algorithm exists */ 1.1058 + if (pbeAlg == SEC_OID_PKCS5_PBKDF2) { 1.1059 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1060 + goto loser; 1.1061 + } 1.1062 + pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); 1.1063 + if (pbeV2_param == NULL) { 1.1064 + goto loser; 1.1065 + } 1.1066 + /* extract the IV from the cipher algid portion of our pkcs 5 v2 1.1067 + * algorithm id */ 1.1068 + type = PK11_AlgtagToMechanism( 1.1069 + SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); 1.1070 + param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId); 1.1071 + sec_pkcs5_v2_destroy_v2_param(pbeV2_param); 1.1072 + if (!param) { 1.1073 + goto loser; 1.1074 + } 1.1075 + /* NOTE: NULL is a permissible return here */ 1.1076 + ivData = PK11_IVFromParam(type, param, &iv_len); 1.1077 + src.data = ivData; 1.1078 + src.len = iv_len; 1.1079 + goto done; 1.1080 + } 1.1081 + 1.1082 + type = PK11_AlgtagToMechanism(pbeAlg); 1.1083 + param = PK11_ParamFromAlgid(algid); 1.1084 + if (param == NULL) { 1.1085 + goto done; 1.1086 + } 1.1087 + slot = PK11_GetInternalSlot(); 1.1088 + symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL); 1.1089 + PK11_FreeSlot(slot); 1.1090 + if (symKey == NULL) { 1.1091 + goto loser; 1.1092 + } 1.1093 + PK11_FreeSymKey(symKey); 1.1094 + pPBEparams = (CK_PBE_PARAMS_PTR)param->data; 1.1095 + iv_len = PK11_GetIVLength(type); 1.1096 + 1.1097 + src.data = (unsigned char *)pPBEparams->pInitVector; 1.1098 + src.len = iv_len; 1.1099 + 1.1100 +done: 1.1101 + iv = SECITEM_DupItem(&src); 1.1102 + 1.1103 +loser: 1.1104 + if (param) { 1.1105 + SECITEM_ZfreeItem(param, PR_TRUE); 1.1106 + } 1.1107 + return iv; 1.1108 +} 1.1109 + 1.1110 +/* 1.1111 + * Subs from nss 3.x that are deprecated 1.1112 + */ 1.1113 +PBEBitGenContext * 1.1114 +__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, 1.1115 + SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, 1.1116 + unsigned int iterations) 1.1117 +{ 1.1118 + PORT_Assert("__PBE_CreateContext is Deprecated" == NULL); 1.1119 + return NULL; 1.1120 +} 1.1121 + 1.1122 +SECItem * 1.1123 +__PBE_GenerateBits(PBEBitGenContext *context) 1.1124 +{ 1.1125 + PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL); 1.1126 + return NULL; 1.1127 +} 1.1128 + 1.1129 +void 1.1130 +__PBE_DestroyContext(PBEBitGenContext *context) 1.1131 +{ 1.1132 + PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL); 1.1133 +} 1.1134 + 1.1135 +SECStatus 1.1136 +RSA_FormatBlock(SECItem *result, unsigned modulusLen, 1.1137 + int blockType, SECItem *data) 1.1138 +{ 1.1139 + PORT_Assert("RSA_FormatBlock is Deprecated" == NULL); 1.1140 + return SECFailure; 1.1141 +} 1.1142 + 1.1143 +/**************************************************************************** 1.1144 + * 1.1145 + * Now Do The PBE Functions Here... 1.1146 + * 1.1147 + ****************************************************************************/ 1.1148 + 1.1149 +static void 1.1150 +pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params) 1.1151 +{ 1.1152 + if (pbe_params) { 1.1153 + if (pbe_params->pPassword) 1.1154 + PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen); 1.1155 + if (pbe_params->pSalt) 1.1156 + PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen); 1.1157 + PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS)); 1.1158 + } 1.1159 +} 1.1160 + 1.1161 +/* 1.1162 + * public, deprecated. use PK11_CreatePBEAlgorithmID or 1.1163 + * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters, 1.1164 + * use PK11_ParamFromAlgid from the algorithm id you created using 1.1165 + * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID. 1.1166 + */ 1.1167 +SECItem * 1.1168 +PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations) 1.1169 +{ 1.1170 + CK_PBE_PARAMS *pbe_params = NULL; 1.1171 + SECItem *paramRV = NULL; 1.1172 + 1.1173 + paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS)); 1.1174 + if (!paramRV ) { 1.1175 + goto loser; 1.1176 + } 1.1177 + /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */ 1.1178 + PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS)); 1.1179 + 1.1180 + pbe_params = (CK_PBE_PARAMS *)paramRV->data; 1.1181 + pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len); 1.1182 + if (!pbe_params->pPassword) { 1.1183 + goto loser; 1.1184 + } 1.1185 + PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len); 1.1186 + pbe_params->ulPasswordLen = pwd->len; 1.1187 + 1.1188 + pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len); 1.1189 + if (!pbe_params->pSalt) { 1.1190 + goto loser; 1.1191 + } 1.1192 + PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len); 1.1193 + pbe_params->ulSaltLen = salt->len; 1.1194 + 1.1195 + pbe_params->ulIteration = (CK_ULONG)iterations; 1.1196 + return paramRV; 1.1197 + 1.1198 +loser: 1.1199 + if (pbe_params) 1.1200 + pk11_destroy_ck_pbe_params(pbe_params); 1.1201 + if (paramRV) 1.1202 + PORT_ZFree(paramRV, sizeof(SECItem)); 1.1203 + return NULL; 1.1204 +} 1.1205 + 1.1206 +/* 1.1207 + * public, deprecated. 1.1208 + */ 1.1209 +void 1.1210 +PK11_DestroyPBEParams(SECItem *pItem) 1.1211 +{ 1.1212 + if (pItem) { 1.1213 + CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data); 1.1214 + if (params) 1.1215 + pk11_destroy_ck_pbe_params(params); 1.1216 + PORT_ZFree(pItem, sizeof(SECItem)); 1.1217 + } 1.1218 +} 1.1219 + 1.1220 +/* 1.1221 + * public, Partially supports PKCS5 V2 (some parameters are not controllable 1.1222 + * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need 1.1223 + * finer control these. 1.1224 + */ 1.1225 +SECAlgorithmID * 1.1226 +PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt) 1.1227 +{ 1.1228 + SECAlgorithmID *algid = NULL; 1.1229 + algid = sec_pkcs5CreateAlgorithmID(algorithm, 1.1230 + SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration); 1.1231 + return algid; 1.1232 +} 1.1233 + 1.1234 +/* 1.1235 + * public, fully support pkcs5v2. 1.1236 + */ 1.1237 +SECAlgorithmID * 1.1238 +PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag, 1.1239 + SECOidTag prfAlgTag, int keyLength, int iteration, 1.1240 + SECItem *salt) 1.1241 +{ 1.1242 + SECAlgorithmID *algid = NULL; 1.1243 + algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag, 1.1244 + NULL, keyLength, salt, iteration); 1.1245 + return algid; 1.1246 +} 1.1247 + 1.1248 +/* 1.1249 + * private. 1.1250 + */ 1.1251 +PK11SymKey * 1.1252 +pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.1253 + SECItem *params, CK_KEY_TYPE keyType, int keyLen, 1.1254 + SECItem *pwitem, void *wincx) 1.1255 +{ 1.1256 + CK_ULONG pwLen; 1.1257 + /* do some sanity checks */ 1.1258 + if ((params == NULL) || (params->data == NULL)) { 1.1259 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1260 + return NULL; 1.1261 + } 1.1262 + 1.1263 + if (type == CKM_INVALID_MECHANISM) { 1.1264 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1265 + return NULL; 1.1266 + } 1.1267 + 1.1268 + /* set the password pointer in the parameters... */ 1.1269 + if (type == CKM_PKCS5_PBKD2) { 1.1270 + CK_PKCS5_PBKD2_PARAMS *pbev2_params; 1.1271 + if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) { 1.1272 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1273 + return NULL; 1.1274 + } 1.1275 + pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data; 1.1276 + pbev2_params->pPassword = pwitem->data; 1.1277 + pwLen = pwitem->len; 1.1278 + pbev2_params->ulPasswordLen = &pwLen; 1.1279 + } else { 1.1280 + CK_PBE_PARAMS *pbe_params; 1.1281 + if (params->len < sizeof(CK_PBE_PARAMS)) { 1.1282 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1283 + return NULL; 1.1284 + } 1.1285 + pbe_params = (CK_PBE_PARAMS *)params->data; 1.1286 + pbe_params->pPassword = pwitem->data; 1.1287 + pbe_params->ulPasswordLen = pwitem->len; 1.1288 + } 1.1289 + 1.1290 + /* generate the key (and sometimes the IV as a side effect...) */ 1.1291 + return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, 1.1292 + keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, 1.1293 + 0, wincx); 1.1294 +} 1.1295 + 1.1296 +/* 1.1297 + * public, deprecated. use PK11_PBEKeyGen instead. 1.1298 + */ 1.1299 +PK11SymKey * 1.1300 +PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech, 1.1301 + SECItem *pwitem, PRBool faulty3DES, void *wincx) 1.1302 +{ 1.1303 + if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { 1.1304 + type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; 1.1305 + } 1.1306 + return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx); 1.1307 +} 1.1308 + 1.1309 +/* 1.1310 + * pubic, supports pkcs5 v2. 1.1311 + * 1.1312 + * Create symkey from a PBE key. The algid can be created with 1.1313 + * PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by 1.1314 + * extraction of der data. 1.1315 + */ 1.1316 +PK11SymKey * 1.1317 +PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, 1.1318 + PRBool faulty3DES, void *wincx) 1.1319 +{ 1.1320 + CK_MECHANISM_TYPE type; 1.1321 + SECItem *param = NULL; 1.1322 + PK11SymKey *symKey = NULL; 1.1323 + SECOidTag pbeAlg; 1.1324 + CK_KEY_TYPE keyType = -1; 1.1325 + int keyLen = 0; 1.1326 + 1.1327 + pbeAlg = SECOID_GetAlgorithmTag(algid); 1.1328 + /* if we're using PKCS5v2, extract the additional information we need 1.1329 + * (key length, key type, and pbeAlg). */ 1.1330 + if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { 1.1331 + CK_MECHANISM_TYPE cipherMech; 1.1332 + sec_pkcs5V2Parameter *pbeV2_param; 1.1333 + 1.1334 + pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); 1.1335 + if (pbeV2_param == NULL) { 1.1336 + return NULL; 1.1337 + } 1.1338 + cipherMech = PK11_AlgtagToMechanism( 1.1339 + SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); 1.1340 + pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId); 1.1341 + param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId); 1.1342 + sec_pkcs5_v2_destroy_v2_param(pbeV2_param); 1.1343 + keyLen = SEC_PKCS5GetKeyLength(algid); 1.1344 + if (keyLen == -1) { 1.1345 + keyLen = 0; 1.1346 + } 1.1347 + keyType = PK11_GetKeyType(cipherMech, keyLen); 1.1348 + } else { 1.1349 + param = PK11_ParamFromAlgid(algid); 1.1350 + } 1.1351 + 1.1352 + if(param == NULL) { 1.1353 + goto loser; 1.1354 + } 1.1355 + 1.1356 + type = PK11_AlgtagToMechanism(pbeAlg); 1.1357 + if (type == CKM_INVALID_MECHANISM) { 1.1358 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1359 + goto loser; 1.1360 + } 1.1361 + if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { 1.1362 + type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; 1.1363 + } 1.1364 + symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen, 1.1365 + pwitem, wincx); 1.1366 + 1.1367 +loser: 1.1368 + if (param) { 1.1369 + SECITEM_ZfreeItem(param, PR_TRUE); 1.1370 + } 1.1371 + return symKey; 1.1372 +} 1.1373 + 1.1374 +/* 1.1375 + * public, supports pkcs5v2 1.1376 + */ 1.1377 +SECItem * 1.1378 +PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem) 1.1379 +{ 1.1380 + return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE); 1.1381 +} 1.1382 + 1.1383 +CK_MECHANISM_TYPE 1.1384 +pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 1.1385 + SECItem *pbe_pwd, PRBool faulty3DES) 1.1386 +{ 1.1387 + int keyLen = 0; 1.1388 + SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid); 1.1389 + CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag); 1.1390 + CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM; 1.1391 + SECItem *iv = NULL; 1.1392 + 1.1393 + if (mech == CKM_INVALID_MECHANISM) { 1.1394 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1395 + goto loser; 1.1396 + } 1.1397 + if (PK11_GetIVLength(mech)) { 1.1398 + iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES); 1.1399 + if (iv == NULL) { 1.1400 + goto loser; 1.1401 + } 1.1402 + } 1.1403 + 1.1404 + keyLen = SEC_PKCS5GetKeyLength(algid); 1.1405 + 1.1406 + *param = pk11_ParamFromIVWithLen(mech, iv, keyLen); 1.1407 + if (*param == NULL) { 1.1408 + goto loser; 1.1409 + } 1.1410 + returnedMechanism = mech; 1.1411 + 1.1412 +loser: 1.1413 + if (iv) { 1.1414 + SECITEM_FreeItem(iv,PR_TRUE); 1.1415 + } 1.1416 + return returnedMechanism; 1.1417 +} 1.1418 + 1.1419 +/* 1.1420 + * Public, supports pkcs5 v2 1.1421 + * 1.1422 + * Get the crypto mechanism directly from the pbe algorithmid. 1.1423 + * 1.1424 + * It's important to go directly from the algorithm id so that we can 1.1425 + * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases. 1.1426 + * 1.1427 + * This function returns both the mechanism and the parameter for the mechanism. 1.1428 + * The caller is responsible for freeing the parameter. 1.1429 + */ 1.1430 +CK_MECHANISM_TYPE 1.1431 +PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 1.1432 + SECItem *pbe_pwd) 1.1433 +{ 1.1434 + return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE); 1.1435 +}