1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/lowpbe.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1378 @@ 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 "blapi.h" 1.16 +#include "hasht.h" 1.17 +#include "secasn1.h" 1.18 +#include "secder.h" 1.19 +#include "lowpbe.h" 1.20 +#include "secoid.h" 1.21 +#include "alghmac.h" 1.22 +#include "softoken.h" 1.23 +#include "secerr.h" 1.24 + 1.25 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.26 + 1.27 +/* template for PKCS 5 PBE Parameter. This template has been expanded 1.28 + * based upon the additions in PKCS 12. This should eventually be moved 1.29 + * if RSA updates PKCS 5. 1.30 + */ 1.31 +static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = 1.32 +{ 1.33 + { SEC_ASN1_SEQUENCE, 1.34 + 0, NULL, sizeof(NSSPKCS5PBEParameter) }, 1.35 + { SEC_ASN1_OCTET_STRING, 1.36 + offsetof(NSSPKCS5PBEParameter, salt) }, 1.37 + { SEC_ASN1_INTEGER, 1.38 + offsetof(NSSPKCS5PBEParameter, iteration) }, 1.39 + { 0 } 1.40 +}; 1.41 + 1.42 +static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = 1.43 +{ 1.44 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) }, 1.45 + { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) }, 1.46 + { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) }, 1.47 + { 0 } 1.48 +}; 1.49 + 1.50 + 1.51 +/* PKCS5 v2 */ 1.52 + 1.53 +struct nsspkcs5V2PBEParameterStr { 1.54 + SECAlgorithmID keyParams; /* parameters of the key generation */ 1.55 + SECAlgorithmID algParams; /* parameters for the encryption or mac op */ 1.56 +}; 1.57 + 1.58 +typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter; 1.59 +#define PBKDF2 1.60 + 1.61 +#ifdef PBKDF2 1.62 +static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] = 1.63 +{ 1.64 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(nsspkcs5V2PBEParameter) }, 1.65 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.66 + offsetof(nsspkcs5V2PBEParameter, keyParams), 1.67 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.68 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.69 + offsetof(nsspkcs5V2PBEParameter, algParams), 1.70 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.71 + { 0 } 1.72 +}; 1.73 + 1.74 +static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] = 1.75 +{ 1.76 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) }, 1.77 + /* this is really a choice, but since we don't understand any other 1.78 + *choice, just inline it. */ 1.79 + { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) }, 1.80 + { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) }, 1.81 + { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, keyLength) }, 1.82 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.83 + offsetof(NSSPKCS5PBEParameter, prfAlg), 1.84 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.85 + { 0 } 1.86 +}; 1.87 +#endif 1.88 + 1.89 +SECStatus 1.90 +nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest, 1.91 + unsigned char *src, int len) 1.92 +{ 1.93 + void *ctx; 1.94 + unsigned int retLen; 1.95 + 1.96 + ctx = hashObj->create(); 1.97 + if(ctx == NULL) { 1.98 + return SECFailure; 1.99 + } 1.100 + hashObj->begin(ctx); 1.101 + hashObj->update(ctx, src, len); 1.102 + hashObj->end(ctx, dest, &retLen, hashObj->length); 1.103 + hashObj->destroy(ctx, PR_TRUE); 1.104 + return SECSuccess; 1.105 +} 1.106 + 1.107 +/* generate bits using any hash 1.108 + */ 1.109 +static SECItem * 1.110 +nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd, 1.111 + int iter, PRBool faulty3DES) 1.112 +{ 1.113 + SECItem *hash = NULL, *pre_hash = NULL; 1.114 + SECStatus rv = SECFailure; 1.115 + 1.116 + if((salt == NULL) || (pwd == NULL) || (iter < 0)) { 1.117 + return NULL; 1.118 + } 1.119 + 1.120 + hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.121 + pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.122 + 1.123 + if((hash != NULL) && (pre_hash != NULL)) { 1.124 + int i, ph_len; 1.125 + 1.126 + ph_len = hashObj->length; 1.127 + if((salt->len + pwd->len) > hashObj->length) { 1.128 + ph_len = salt->len + pwd->len; 1.129 + } 1.130 + 1.131 + rv = SECFailure; 1.132 + 1.133 + /* allocate buffers */ 1.134 + hash->len = hashObj->length; 1.135 + hash->data = (unsigned char *)PORT_ZAlloc(hash->len); 1.136 + pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); 1.137 + 1.138 + /* in pbeSHA1TripleDESCBC there was an allocation error that made 1.139 + * it into the caller. We do not want to propagate those errors 1.140 + * further, so we are doing it correctly, but reading the old method. 1.141 + */ 1.142 + if (faulty3DES) { 1.143 + pre_hash->len = ph_len; 1.144 + } else { 1.145 + pre_hash->len = salt->len + pwd->len; 1.146 + } 1.147 + 1.148 + /* preform hash */ 1.149 + if ((hash->data != NULL) && (pre_hash->data != NULL)) { 1.150 + rv = SECSuccess; 1.151 + /* check for 0 length password */ 1.152 + if(pwd->len > 0) { 1.153 + PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); 1.154 + } 1.155 + if(salt->len > 0) { 1.156 + PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); 1.157 + } 1.158 + for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) { 1.159 + rv = nsspkcs5_HashBuf(hashObj, hash->data, 1.160 + pre_hash->data, pre_hash->len); 1.161 + if(rv != SECFailure) { 1.162 + pre_hash->len = hashObj->length; 1.163 + PORT_Memcpy(pre_hash->data, hash->data, hashObj->length); 1.164 + } 1.165 + } 1.166 + } 1.167 + } 1.168 + 1.169 + if(pre_hash != NULL) { 1.170 + SECITEM_FreeItem(pre_hash, PR_TRUE); 1.171 + } 1.172 + 1.173 + if((rv != SECSuccess) && (hash != NULL)) { 1.174 + SECITEM_FreeItem(hash, PR_TRUE); 1.175 + hash = NULL; 1.176 + } 1.177 + 1.178 + return hash; 1.179 +} 1.180 + 1.181 +/* this bit generation routine is described in PKCS 12 and the proposed 1.182 + * extensions to PKCS 5. an initial hash is generated following the 1.183 + * instructions laid out in PKCS 5. If the number of bits generated is 1.184 + * insufficient, then the method discussed in the proposed extensions to 1.185 + * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC 1.186 + * function. And the P_Hash function from the TLS standard. 1.187 + */ 1.188 +static SECItem * 1.189 +nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, 1.190 + SECItem *init_hash, unsigned int bytes_needed) 1.191 +{ 1.192 + SECItem *ret_bits = NULL; 1.193 + int hash_size = 0; 1.194 + unsigned int i; 1.195 + unsigned int hash_iter; 1.196 + unsigned int dig_len; 1.197 + SECStatus rv = SECFailure; 1.198 + unsigned char *state = NULL; 1.199 + unsigned int state_len; 1.200 + HMACContext *cx = NULL; 1.201 + 1.202 + hash_size = hashObj->length; 1.203 + hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size; 1.204 + 1.205 + /* allocate return buffer */ 1.206 + ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.207 + if(ret_bits == NULL) 1.208 + return NULL; 1.209 + ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1); 1.210 + ret_bits->len = (hash_iter * hash_size); 1.211 + if(ret_bits->data == NULL) { 1.212 + PORT_Free(ret_bits); 1.213 + return NULL; 1.214 + } 1.215 + 1.216 + /* allocate intermediate hash buffer. 8 is for the 8 bytes of 1.217 + * data which are added based on iteration number 1.218 + */ 1.219 + 1.220 + if ((unsigned int)hash_size > pbe_param->salt.len) { 1.221 + state_len = hash_size; 1.222 + } else { 1.223 + state_len = pbe_param->salt.len; 1.224 + } 1.225 + state = (unsigned char *)PORT_ZAlloc(state_len); 1.226 + if(state == NULL) { 1.227 + rv = SECFailure; 1.228 + goto loser; 1.229 + } 1.230 + if(pbe_param->salt.len > 0) { 1.231 + PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len); 1.232 + } 1.233 + 1.234 + cx = HMAC_Create(hashObj, init_hash->data, init_hash->len, PR_TRUE); 1.235 + if (cx == NULL) { 1.236 + rv = SECFailure; 1.237 + goto loser; 1.238 + } 1.239 + 1.240 + for(i = 0; i < hash_iter; i++) { 1.241 + 1.242 + /* generate output bits */ 1.243 + HMAC_Begin(cx); 1.244 + HMAC_Update(cx, state, state_len); 1.245 + HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len); 1.246 + rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size), 1.247 + &dig_len, hash_size); 1.248 + if (rv != SECSuccess) 1.249 + goto loser; 1.250 + PORT_Assert((unsigned int)hash_size == dig_len); 1.251 + 1.252 + /* generate new state */ 1.253 + HMAC_Begin(cx); 1.254 + HMAC_Update(cx, state, state_len); 1.255 + rv = HMAC_Finish(cx, state, &state_len, state_len); 1.256 + if (rv != SECSuccess) 1.257 + goto loser; 1.258 + PORT_Assert(state_len == dig_len); 1.259 + } 1.260 + 1.261 +loser: 1.262 + if (state != NULL) 1.263 + PORT_ZFree(state, state_len); 1.264 + HMAC_Destroy(cx, PR_TRUE); 1.265 + 1.266 + if(rv != SECSuccess) { 1.267 + SECITEM_ZfreeItem(ret_bits, PR_TRUE); 1.268 + ret_bits = NULL; 1.269 + } 1.270 + 1.271 + return ret_bits; 1.272 +} 1.273 + 1.274 +/* generate bits for the key and iv determination. if enough bits 1.275 + * are not generated using PKCS 5, then we need to generate more bits 1.276 + * based on the extension proposed in PKCS 12 1.277 + */ 1.278 +static SECItem * 1.279 +nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj, 1.280 + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES) 1.281 +{ 1.282 + SECItem * hash = NULL; 1.283 + SECItem * newHash = NULL; 1.284 + int bytes_needed; 1.285 + int bytes_available; 1.286 + 1.287 + bytes_needed = pbe_param->ivLen + pbe_param->keyLen; 1.288 + bytes_available = hashObj->length; 1.289 + 1.290 + hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem, 1.291 + pbe_param->iter, faulty3DES); 1.292 + 1.293 + if(hash == NULL) { 1.294 + return NULL; 1.295 + } 1.296 + 1.297 + if(bytes_needed <= bytes_available) { 1.298 + return hash; 1.299 + } 1.300 + 1.301 + newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed); 1.302 + if (hash != newHash) 1.303 + SECITEM_FreeItem(hash, PR_TRUE); 1.304 + return newHash; 1.305 +} 1.306 + 1.307 +#ifdef PBKDF2 1.308 + 1.309 +/* 1.310 + * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS 1.311 + */ 1.312 +static void 1.313 +do_xor(unsigned char *dest, unsigned char *src, int len) 1.314 +{ 1.315 + /* use byt xor, not all platforms are happy about inaligned 1.316 + * integer fetches */ 1.317 + while (len--) { 1.318 + *dest = *dest ^ *src; 1.319 + dest++; 1.320 + src++; 1.321 + } 1.322 +} 1.323 + 1.324 +static SECStatus 1.325 +nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt, 1.326 + int iterations, unsigned int i, unsigned char *T) 1.327 +{ 1.328 + int j; 1.329 + HMACContext *cx = NULL; 1.330 + unsigned int hLen = hashobj->length; 1.331 + SECStatus rv = SECFailure; 1.332 + unsigned char *last = NULL; 1.333 + unsigned int lastLength = salt->len + 4; 1.334 + unsigned int lastBufLength; 1.335 + 1.336 + cx=HMAC_Create(hashobj,pwitem->data,pwitem->len,PR_FALSE); 1.337 + if (cx == NULL) { 1.338 + goto loser; 1.339 + } 1.340 + PORT_Memset(T,0,hLen); 1.341 + lastBufLength = PR_MAX(lastLength, hLen); 1.342 + last = PORT_Alloc(lastBufLength); 1.343 + if (last == NULL) { 1.344 + goto loser; 1.345 + } 1.346 + PORT_Memcpy(last,salt->data,salt->len); 1.347 + last[salt->len ] = (i >> 24) & 0xff; 1.348 + last[salt->len+1] = (i >> 16) & 0xff; 1.349 + last[salt->len+2] = (i >> 8) & 0xff; 1.350 + last[salt->len+3] = i & 0xff; 1.351 + 1.352 + /* NOTE: we need at least one iteration to return success! */ 1.353 + for (j=0; j < iterations; j++) { 1.354 + HMAC_Begin(cx); 1.355 + HMAC_Update(cx,last,lastLength); 1.356 + rv =HMAC_Finish(cx,last,&lastLength,hLen); 1.357 + if (rv !=SECSuccess) { 1.358 + break; 1.359 + } 1.360 + do_xor(T,last,hLen); 1.361 + } 1.362 +loser: 1.363 + if (cx) { 1.364 + HMAC_Destroy(cx, PR_TRUE); 1.365 + } 1.366 + if (last) { 1.367 + PORT_ZFree(last,lastBufLength); 1.368 + } 1.369 + return rv; 1.370 +} 1.371 + 1.372 +static SECItem * 1.373 +nsspkcs5_PBKDF2(const SECHashObject *hashobj, NSSPKCS5PBEParameter *pbe_param, 1.374 + SECItem *pwitem) 1.375 +{ 1.376 + int iterations = pbe_param->iter; 1.377 + int bytesNeeded = pbe_param->keyLen; 1.378 + unsigned int dkLen = bytesNeeded; 1.379 + unsigned int hLen = hashobj->length; 1.380 + unsigned int nblocks = (dkLen+hLen-1) / hLen; 1.381 + unsigned int i; 1.382 + unsigned char *rp; 1.383 + unsigned char *T = NULL; 1.384 + SECItem *result = NULL; 1.385 + SECItem *salt = &pbe_param->salt; 1.386 + SECStatus rv = SECFailure; 1.387 + 1.388 + result = SECITEM_AllocItem(NULL,NULL,nblocks*hLen); 1.389 + if (result == NULL) { 1.390 + return NULL; 1.391 + } 1.392 + 1.393 + T = PORT_Alloc(hLen); 1.394 + if (T == NULL) { 1.395 + goto loser; 1.396 + } 1.397 + 1.398 + for (i=1,rp=result->data; i <= nblocks ; i++, rp +=hLen) { 1.399 + rv = nsspkcs5_PBKFD2_F(hashobj,pwitem,salt,iterations,i,T); 1.400 + if (rv != SECSuccess) { 1.401 + break; 1.402 + } 1.403 + PORT_Memcpy(rp,T,hLen); 1.404 + } 1.405 + 1.406 +loser: 1.407 + if (T) { 1.408 + PORT_ZFree(T,hLen); 1.409 + } 1.410 + if (rv != SECSuccess) { 1.411 + SECITEM_FreeItem(result,PR_TRUE); 1.412 + result = NULL; 1.413 + } else { 1.414 + result->len = dkLen; 1.415 + } 1.416 + 1.417 + return result; 1.418 +} 1.419 +#endif 1.420 + 1.421 +#define HMAC_BUFFER 64 1.422 +#define NSSPBE_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) 1.423 +#define NSSPBE_MIN(x,y) ((x) < (y) ? (x) : (y)) 1.424 +/* 1.425 + * This is the extended PBE function defined by the final PKCS #12 spec. 1.426 + */ 1.427 +static SECItem * 1.428 +nsspkcs5_PKCS12PBE(const SECHashObject *hashObject, 1.429 + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, 1.430 + PBEBitGenID bitGenPurpose, unsigned int bytesNeeded) 1.431 +{ 1.432 + PLArenaPool *arena = NULL; 1.433 + unsigned int SLen,PLen; 1.434 + unsigned int hashLength = hashObject->length; 1.435 + unsigned char *S, *P; 1.436 + SECItem *A = NULL, B, D, I; 1.437 + SECItem *salt = &pbe_param->salt; 1.438 + unsigned int c,i = 0; 1.439 + unsigned int hashLen; 1.440 + int iter; 1.441 + unsigned char *iterBuf; 1.442 + void *hash = NULL; 1.443 + 1.444 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.445 + if(!arena) { 1.446 + return NULL; 1.447 + } 1.448 + 1.449 + /* how many hash object lengths are needed */ 1.450 + c = (bytesNeeded + (hashLength-1))/hashLength; 1.451 + 1.452 + /* initialize our buffers */ 1.453 + D.len = HMAC_BUFFER; 1.454 + /* B and D are the same length, use one alloc go get both */ 1.455 + D.data = (unsigned char*)PORT_ArenaZAlloc(arena, D.len*2); 1.456 + B.len = D.len; 1.457 + B.data = D.data + D.len; 1.458 + 1.459 + /* if all goes well, A will be returned, so don't use our temp arena */ 1.460 + A = SECITEM_AllocItem(NULL,NULL,c*hashLength); 1.461 + if (A == NULL) { 1.462 + goto loser; 1.463 + } 1.464 + 1.465 + SLen = NSSPBE_ROUNDUP(salt->len,HMAC_BUFFER); 1.466 + PLen = NSSPBE_ROUNDUP(pwitem->len,HMAC_BUFFER); 1.467 + I.len = SLen+PLen; 1.468 + I.data = (unsigned char*)PORT_ArenaZAlloc(arena, I.len); 1.469 + if (I.data == NULL) { 1.470 + goto loser; 1.471 + } 1.472 + 1.473 + /* S & P are only used to initialize I */ 1.474 + S = I.data; 1.475 + P = S + SLen; 1.476 + 1.477 + PORT_Memset(D.data, (char)bitGenPurpose, D.len); 1.478 + if (SLen) { 1.479 + for (i=0; i < SLen; i += salt->len) { 1.480 + PORT_Memcpy(S+i, salt->data, NSSPBE_MIN(SLen-i,salt->len)); 1.481 + } 1.482 + } 1.483 + if (PLen) { 1.484 + for (i=0; i < PLen; i += pwitem->len) { 1.485 + PORT_Memcpy(P+i, pwitem->data, NSSPBE_MIN(PLen-i,pwitem->len)); 1.486 + } 1.487 + } 1.488 + 1.489 + iterBuf = (unsigned char*)PORT_ArenaZAlloc(arena,hashLength); 1.490 + if (iterBuf == NULL) { 1.491 + goto loser; 1.492 + } 1.493 + 1.494 + hash = hashObject->create(); 1.495 + if(!hash) { 1.496 + goto loser; 1.497 + } 1.498 + /* calculate the PBE now */ 1.499 + for(i = 0; i < c; i++) { 1.500 + int Bidx; /* must be signed or the for loop won't terminate */ 1.501 + unsigned int k, j; 1.502 + unsigned char *Ai = A->data+i*hashLength; 1.503 + 1.504 + 1.505 + for(iter = 0; iter < pbe_param->iter; iter++) { 1.506 + hashObject->begin(hash); 1.507 + 1.508 + if (iter) { 1.509 + hashObject->update(hash, iterBuf, hashLen); 1.510 + } else { 1.511 + hashObject->update(hash, D.data, D.len); 1.512 + hashObject->update(hash, I.data, I.len); 1.513 + } 1.514 + 1.515 + hashObject->end(hash, iterBuf, &hashLen, hashObject->length); 1.516 + if(hashLen != hashObject->length) { 1.517 + break; 1.518 + } 1.519 + } 1.520 + 1.521 + PORT_Memcpy(Ai, iterBuf, hashLength); 1.522 + for (Bidx = 0; Bidx < B.len; Bidx += hashLength) { 1.523 + PORT_Memcpy(B.data+Bidx,iterBuf,NSSPBE_MIN(B.len-Bidx,hashLength)); 1.524 + } 1.525 + 1.526 + k = I.len/B.len; 1.527 + for(j = 0; j < k; j++) { 1.528 + unsigned int q, carryBit; 1.529 + unsigned char *Ij = I.data + j*B.len; 1.530 + 1.531 + /* (Ij = Ij+B+1) */ 1.532 + for (Bidx = (B.len-1), q=1, carryBit=0; Bidx >= 0; Bidx--,q=0) { 1.533 + q += (unsigned int)Ij[Bidx]; 1.534 + q += (unsigned int)B.data[Bidx]; 1.535 + q += carryBit; 1.536 + 1.537 + carryBit = (q > 0xff); 1.538 + Ij[Bidx] = (unsigned char)(q & 0xff); 1.539 + } 1.540 + } 1.541 + } 1.542 +loser: 1.543 + if (hash) { 1.544 + hashObject->destroy(hash, PR_TRUE); 1.545 + } 1.546 + if(arena) { 1.547 + PORT_FreeArena(arena, PR_TRUE); 1.548 + } 1.549 + 1.550 + if (A) { 1.551 + /* if i != c, then we didn't complete the loop above and must of failed 1.552 + * somwhere along the way */ 1.553 + if (i != c) { 1.554 + SECITEM_ZfreeItem(A,PR_TRUE); 1.555 + A = NULL; 1.556 + } else { 1.557 + A->len = bytesNeeded; 1.558 + } 1.559 + } 1.560 + 1.561 + return A; 1.562 +} 1.563 + 1.564 +/* 1.565 + * generate key as per PKCS 5 1.566 + */ 1.567 +SECItem * 1.568 +nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, 1.569 + SECItem *iv, PRBool faulty3DES) 1.570 +{ 1.571 + SECItem *hash = NULL, *key = NULL; 1.572 + const SECHashObject *hashObj; 1.573 + PRBool getIV = PR_FALSE; 1.574 + 1.575 + if((pbe_param == NULL) || (pwitem == NULL)) { 1.576 + return NULL; 1.577 + } 1.578 + 1.579 + key = SECITEM_AllocItem(NULL,NULL,pbe_param->keyLen); 1.580 + if (key == NULL) { 1.581 + return NULL; 1.582 + } 1.583 + 1.584 + if (iv && (pbe_param->ivLen) && (iv->data == NULL)) { 1.585 + getIV = PR_TRUE; 1.586 + iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen); 1.587 + if (iv->data == NULL) { 1.588 + goto loser; 1.589 + } 1.590 + iv->len = pbe_param->ivLen; 1.591 + } 1.592 + 1.593 + hashObj = HASH_GetRawHashObject(pbe_param->hashType); 1.594 + switch (pbe_param->pbeType) { 1.595 + case NSSPKCS5_PBKDF1: 1.596 + hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES); 1.597 + if (hash == NULL) { 1.598 + goto loser; 1.599 + } 1.600 + PORT_Assert(hash->len >= key->len+(getIV ? iv->len : 0)); 1.601 + if (getIV) { 1.602 + PORT_Memcpy(iv->data, hash->data+(hash->len - iv->len),iv->len); 1.603 + } 1.604 + 1.605 + break; 1.606 +#ifdef PBKDF2 1.607 + case NSSPKCS5_PBKDF2: 1.608 + hash = nsspkcs5_PBKDF2(hashObj,pbe_param,pwitem); 1.609 + if (getIV) { 1.610 + PORT_Memcpy(iv->data, pbe_param->ivData, iv->len); 1.611 + } 1.612 + break; 1.613 +#endif 1.614 + case NSSPKCS5_PKCS12_V2: 1.615 + if (getIV) { 1.616 + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, 1.617 + pbeBitGenCipherIV,iv->len); 1.618 + if (hash == NULL) { 1.619 + goto loser; 1.620 + } 1.621 + PORT_Memcpy(iv->data,hash->data,iv->len); 1.622 + SECITEM_ZfreeItem(hash,PR_TRUE); 1.623 + hash = NULL; 1.624 + } 1.625 + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, 1.626 + pbe_param->keyID,key->len); 1.627 + default: 1.628 + break; 1.629 + } 1.630 + 1.631 + if (hash == NULL) { 1.632 + goto loser; 1.633 + } 1.634 + 1.635 + if (pbe_param->is2KeyDES) { 1.636 + PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3); 1.637 + PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data, 1.638 + key->len / 3); 1.639 + } else { 1.640 + PORT_Memcpy(key->data, hash->data, key->len); 1.641 + } 1.642 + 1.643 + SECITEM_ZfreeItem(hash, PR_TRUE); 1.644 + return key; 1.645 + 1.646 +loser: 1.647 + if (getIV && iv->data) { 1.648 + PORT_ZFree(iv->data,iv->len); 1.649 + iv->data = NULL; 1.650 + } 1.651 + 1.652 + SECITEM_ZfreeItem(key, PR_TRUE); 1.653 + return NULL; 1.654 +} 1.655 + 1.656 +static SECStatus 1.657 +nsspkcs5_FillInParam(SECOidTag algorithm, NSSPKCS5PBEParameter *pbe_param) 1.658 +{ 1.659 + PRBool skipType = PR_FALSE; 1.660 + 1.661 + pbe_param->keyLen = 5; 1.662 + pbe_param->ivLen = 8; 1.663 + pbe_param->hashType = HASH_AlgSHA1; 1.664 + pbe_param->pbeType = NSSPKCS5_PBKDF1; 1.665 + pbe_param->encAlg = SEC_OID_RC2_CBC; 1.666 + pbe_param->is2KeyDES = PR_FALSE; 1.667 + switch(algorithm) { 1.668 + /* DES3 Algorithms */ 1.669 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: 1.670 + pbe_param->is2KeyDES = PR_TRUE; 1.671 + /* fall through */ 1.672 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: 1.673 + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; 1.674 + /* fall through */ 1.675 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: 1.676 + pbe_param->keyLen = 24; 1.677 + pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; 1.678 + break; 1.679 + 1.680 + /* DES Algorithms */ 1.681 + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: 1.682 + pbe_param->hashType = HASH_AlgMD2; 1.683 + goto finish_des; 1.684 + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: 1.685 + pbe_param->hashType = HASH_AlgMD5; 1.686 + /* fall through */ 1.687 + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: 1.688 +finish_des: 1.689 + pbe_param->keyLen = 8; 1.690 + pbe_param->encAlg = SEC_OID_DES_CBC; 1.691 + break; 1.692 + 1.693 + /* RC2 Algorithms */ 1.694 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.695 + pbe_param->keyLen = 16; 1.696 + /* fall through */ 1.697 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.698 + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; 1.699 + break; 1.700 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: 1.701 + pbe_param->keyLen = 16; 1.702 + /* fall through */ 1.703 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: 1.704 + break; 1.705 + 1.706 + /* RC4 algorithms */ 1.707 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.708 + skipType = PR_TRUE; 1.709 + /* fall through */ 1.710 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: 1.711 + pbe_param->keyLen = 16; 1.712 + /* fall through */ 1.713 + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.714 + if (!skipType) { 1.715 + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; 1.716 + } 1.717 + /* fall through */ 1.718 + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: 1.719 + pbe_param->ivLen = 0; 1.720 + pbe_param->encAlg = SEC_OID_RC4; 1.721 + break; 1.722 + 1.723 +#ifdef PBKDF2 1.724 + case SEC_OID_PKCS5_PBKDF2: 1.725 + case SEC_OID_PKCS5_PBES2: 1.726 + case SEC_OID_PKCS5_PBMAC1: 1.727 + /* everything else will be filled in by the template */ 1.728 + pbe_param->ivLen = 0; 1.729 + pbe_param->pbeType = NSSPKCS5_PBKDF2; 1.730 + pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2; 1.731 + pbe_param->keyLen = 0; /* needs to be set by caller after return */ 1.732 + break; 1.733 +#endif 1.734 + 1.735 + default: 1.736 + return SECFailure; 1.737 + } 1.738 + 1.739 + return SECSuccess; 1.740 +} 1.741 + 1.742 +/* decode the algid and generate a PKCS 5 parameter from it 1.743 + */ 1.744 +NSSPKCS5PBEParameter * 1.745 +nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator) 1.746 +{ 1.747 + PLArenaPool *arena = NULL; 1.748 + NSSPKCS5PBEParameter *pbe_param = NULL; 1.749 + SECStatus rv = SECFailure; 1.750 + 1.751 + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.752 + if (arena == NULL) 1.753 + return NULL; 1.754 + 1.755 + /* allocate memory for the parameter */ 1.756 + pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, 1.757 + sizeof(NSSPKCS5PBEParameter)); 1.758 + 1.759 + if (pbe_param == NULL) { 1.760 + goto loser; 1.761 + } 1.762 + 1.763 + pbe_param->poolp = arena; 1.764 + 1.765 + rv = nsspkcs5_FillInParam(alg, pbe_param); 1.766 + if (rv != SECSuccess) { 1.767 + goto loser; 1.768 + } 1.769 + 1.770 + pbe_param->iter = iterator; 1.771 + if (salt) { 1.772 + rv = SECITEM_CopyItem(arena,&pbe_param->salt,salt); 1.773 + } 1.774 + 1.775 + /* default key gen */ 1.776 + pbe_param->keyID = pbeBitGenCipherKey; 1.777 + 1.778 +loser: 1.779 + if (rv != SECSuccess) { 1.780 + PORT_FreeArena(arena, PR_TRUE); 1.781 + pbe_param = NULL; 1.782 + } 1.783 + 1.784 + return pbe_param; 1.785 +} 1.786 + 1.787 +/* 1.788 + * find the hash type needed to implement a specific HMAC. 1.789 + * OID definitions are from pkcs 5 v2.0 and 2.1 1.790 + */ 1.791 +HASH_HashType 1.792 +HASH_FromHMACOid(SECOidTag hmac) 1.793 +{ 1.794 + switch (hmac) { 1.795 + case SEC_OID_HMAC_SHA1: 1.796 + return HASH_AlgSHA1; 1.797 + case SEC_OID_HMAC_SHA256: 1.798 + return HASH_AlgSHA256; 1.799 + case SEC_OID_HMAC_SHA384: 1.800 + return HASH_AlgSHA384; 1.801 + case SEC_OID_HMAC_SHA512: 1.802 + return HASH_AlgSHA512; 1.803 + case SEC_OID_HMAC_SHA224: 1.804 + default: 1.805 + break; 1.806 + } 1.807 + return HASH_AlgNULL; 1.808 +} 1.809 + 1.810 +/* decode the algid and generate a PKCS 5 parameter from it 1.811 + */ 1.812 +NSSPKCS5PBEParameter * 1.813 +nsspkcs5_AlgidToParam(SECAlgorithmID *algid) 1.814 +{ 1.815 + NSSPKCS5PBEParameter *pbe_param = NULL; 1.816 + nsspkcs5V2PBEParameter pbev2_param; 1.817 + SECOidTag algorithm; 1.818 + SECStatus rv = SECFailure; 1.819 + 1.820 + if (algid == NULL) { 1.821 + return NULL; 1.822 + } 1.823 + 1.824 + algorithm = SECOID_GetAlgorithmTag(algid); 1.825 + if (algorithm == SEC_OID_UNKNOWN) { 1.826 + goto loser; 1.827 + } 1.828 + 1.829 + pbe_param = nsspkcs5_NewParam(algorithm, NULL, 1); 1.830 + if (pbe_param == NULL) { 1.831 + goto loser; 1.832 + } 1.833 + 1.834 + /* decode parameter */ 1.835 + rv = SECFailure; 1.836 + switch (pbe_param->pbeType) { 1.837 + case NSSPKCS5_PBKDF1: 1.838 + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, 1.839 + NSSPKCS5PBEParameterTemplate, &algid->parameters); 1.840 + break; 1.841 + case NSSPKCS5_PKCS12_V2: 1.842 + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, 1.843 + NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters); 1.844 + break; 1.845 +#ifdef PBKDF2 1.846 + case NSSPKCS5_PBKDF2: 1.847 + PORT_Memset(&pbev2_param,0, sizeof(pbev2_param)); 1.848 + /* just the PBE */ 1.849 + if (algorithm == SEC_OID_PKCS5_PBKDF2) { 1.850 + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, 1.851 + NSSPKCS5V2PBEParameterTemplate, &algid->parameters); 1.852 + } else { 1.853 + /* PBE data an others */ 1.854 + rv = SEC_ASN1DecodeItem(pbe_param->poolp, &pbev2_param, 1.855 + NSSPKCS5V2PBES2ParameterTemplate, &algid->parameters); 1.856 + if (rv != SECSuccess) { 1.857 + break; 1.858 + } 1.859 + pbe_param->encAlg = SECOID_GetAlgorithmTag(&pbev2_param.algParams); 1.860 + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, 1.861 + NSSPKCS5V2PBEParameterTemplate, 1.862 + &pbev2_param.keyParams.parameters); 1.863 + if (rv != SECSuccess) { 1.864 + break; 1.865 + } 1.866 + pbe_param->keyLen = DER_GetInteger(&pbe_param->keyLength); 1.867 + } 1.868 + /* we we are encrypting, save any iv's */ 1.869 + if (algorithm == SEC_OID_PKCS5_PBES2) { 1.870 + pbe_param->ivLen = pbev2_param.algParams.parameters.len; 1.871 + pbe_param->ivData = pbev2_param.algParams.parameters.data; 1.872 + } 1.873 + pbe_param->hashType = 1.874 + HASH_FromHMACOid(SECOID_GetAlgorithmTag(&pbe_param->prfAlg)); 1.875 + if (pbe_param->hashType == HASH_AlgNULL) { 1.876 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.877 + rv = SECFailure; 1.878 + } 1.879 + break; 1.880 +#endif 1.881 + } 1.882 + 1.883 +loser: 1.884 + if (rv == SECSuccess) { 1.885 + pbe_param->iter = DER_GetInteger(&pbe_param->iteration); 1.886 + } else { 1.887 + nsspkcs5_DestroyPBEParameter(pbe_param); 1.888 + pbe_param = NULL; 1.889 + } 1.890 + 1.891 + return pbe_param; 1.892 +} 1.893 + 1.894 +/* destroy a pbe parameter. it assumes that the parameter was 1.895 + * generated using the appropriate create function and therefor 1.896 + * contains an arena pool. 1.897 + */ 1.898 +void 1.899 +nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param) 1.900 +{ 1.901 + if (pbe_param != NULL) { 1.902 + PORT_FreeArena(pbe_param->poolp, PR_FALSE); 1.903 + } 1.904 +} 1.905 + 1.906 + 1.907 +/* crypto routines */ 1.908 +/* perform DES encryption and decryption. these routines are called 1.909 + * by nsspkcs5_CipherData. In the case of an error, NULL is returned. 1.910 + */ 1.911 +static SECItem * 1.912 +sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, 1.913 + PRBool encrypt) 1.914 +{ 1.915 + SECItem *dest; 1.916 + SECItem *dup_src; 1.917 + SECStatus rv = SECFailure; 1.918 + int pad; 1.919 + 1.920 + if((src == NULL) || (key == NULL) || (iv == NULL)) 1.921 + return NULL; 1.922 + 1.923 + dup_src = SECITEM_DupItem(src); 1.924 + if(dup_src == NULL) { 1.925 + return NULL; 1.926 + } 1.927 + 1.928 + if(encrypt != PR_FALSE) { 1.929 + void *dummy; 1.930 + 1.931 + dummy = CBC_PadBuffer(NULL, dup_src->data, 1.932 + dup_src->len, &dup_src->len, 8 /* DES_BLOCK_SIZE */); 1.933 + if(dummy == NULL) { 1.934 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.935 + return NULL; 1.936 + } 1.937 + dup_src->data = (unsigned char*)dummy; 1.938 + } 1.939 + 1.940 + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.941 + if(dest != NULL) { 1.942 + /* allocate with over flow */ 1.943 + dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); 1.944 + if(dest->data != NULL) { 1.945 + DESContext *ctxt; 1.946 + ctxt = DES_CreateContext(key->data, iv->data, 1.947 + (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC), 1.948 + encrypt); 1.949 + 1.950 + if(ctxt != NULL) { 1.951 + rv = (encrypt ? DES_Encrypt : DES_Decrypt)( 1.952 + ctxt, dest->data, &dest->len, 1.953 + dup_src->len + 64, dup_src->data, dup_src->len); 1.954 + 1.955 + /* remove padding -- assumes 64 bit blocks */ 1.956 + if((encrypt == PR_FALSE) && (rv == SECSuccess)) { 1.957 + pad = dest->data[dest->len-1]; 1.958 + if((pad > 0) && (pad <= 8)) { 1.959 + if(dest->data[dest->len-pad] != pad) { 1.960 + rv = SECFailure; 1.961 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.962 + } else { 1.963 + dest->len -= pad; 1.964 + } 1.965 + } else { 1.966 + rv = SECFailure; 1.967 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.968 + } 1.969 + } 1.970 + DES_DestroyContext(ctxt, PR_TRUE); 1.971 + } 1.972 + } 1.973 + } 1.974 + 1.975 + if(rv == SECFailure) { 1.976 + if(dest != NULL) { 1.977 + SECITEM_FreeItem(dest, PR_TRUE); 1.978 + } 1.979 + dest = NULL; 1.980 + } 1.981 + 1.982 + if(dup_src != NULL) { 1.983 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.984 + } 1.985 + 1.986 + return dest; 1.987 +} 1.988 + 1.989 +/* perform aes encryption/decryption if an error occurs, NULL is returned 1.990 + */ 1.991 +static SECItem * 1.992 +sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, 1.993 + PRBool encrypt) 1.994 +{ 1.995 + SECItem *dest; 1.996 + SECItem *dup_src; 1.997 + SECStatus rv = SECFailure; 1.998 + int pad; 1.999 + 1.1000 + if((src == NULL) || (key == NULL) || (iv == NULL)) 1.1001 + return NULL; 1.1002 + 1.1003 + dup_src = SECITEM_DupItem(src); 1.1004 + if(dup_src == NULL) { 1.1005 + return NULL; 1.1006 + } 1.1007 + 1.1008 + if(encrypt != PR_FALSE) { 1.1009 + void *dummy; 1.1010 + 1.1011 + dummy = CBC_PadBuffer(NULL, dup_src->data, 1.1012 + dup_src->len, &dup_src->len,AES_BLOCK_SIZE); 1.1013 + if(dummy == NULL) { 1.1014 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.1015 + return NULL; 1.1016 + } 1.1017 + dup_src->data = (unsigned char*)dummy; 1.1018 + } 1.1019 + 1.1020 + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.1021 + if(dest != NULL) { 1.1022 + /* allocate with over flow */ 1.1023 + dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); 1.1024 + if(dest->data != NULL) { 1.1025 + AESContext *ctxt; 1.1026 + ctxt = AES_CreateContext(key->data, iv->data, 1.1027 + NSS_AES_CBC, encrypt, key->len, 16); 1.1028 + 1.1029 + if(ctxt != NULL) { 1.1030 + rv = (encrypt ? AES_Encrypt : AES_Decrypt)( 1.1031 + ctxt, dest->data, &dest->len, 1.1032 + dup_src->len + 64, dup_src->data, dup_src->len); 1.1033 + 1.1034 + /* remove padding -- assumes 64 bit blocks */ 1.1035 + if((encrypt == PR_FALSE) && (rv == SECSuccess)) { 1.1036 + pad = dest->data[dest->len-1]; 1.1037 + if((pad > 0) && (pad <= 16)) { 1.1038 + if(dest->data[dest->len-pad] != pad) { 1.1039 + rv = SECFailure; 1.1040 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.1041 + } else { 1.1042 + dest->len -= pad; 1.1043 + } 1.1044 + } else { 1.1045 + rv = SECFailure; 1.1046 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.1047 + } 1.1048 + } 1.1049 + AES_DestroyContext(ctxt, PR_TRUE); 1.1050 + } 1.1051 + } 1.1052 + } 1.1053 + 1.1054 + if(rv == SECFailure) { 1.1055 + if(dest != NULL) { 1.1056 + SECITEM_FreeItem(dest, PR_TRUE); 1.1057 + } 1.1058 + dest = NULL; 1.1059 + } 1.1060 + 1.1061 + if(dup_src != NULL) { 1.1062 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.1063 + } 1.1064 + 1.1065 + return dest; 1.1066 +} 1.1067 + 1.1068 +/* perform rc2 encryption/decryption if an error occurs, NULL is returned 1.1069 + */ 1.1070 +static SECItem * 1.1071 +sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, 1.1072 + PRBool encrypt) 1.1073 +{ 1.1074 + SECItem *dest; 1.1075 + SECItem *dup_src; 1.1076 + SECStatus rv = SECFailure; 1.1077 + int pad; 1.1078 + 1.1079 + if((src == NULL) || (key == NULL) || (iv == NULL)) { 1.1080 + return NULL; 1.1081 + } 1.1082 + 1.1083 + dup_src = SECITEM_DupItem(src); 1.1084 + if(dup_src == NULL) { 1.1085 + return NULL; 1.1086 + } 1.1087 + 1.1088 + if(encrypt != PR_FALSE) { 1.1089 + void *dummy; 1.1090 + 1.1091 + dummy = CBC_PadBuffer(NULL, dup_src->data, 1.1092 + dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */); 1.1093 + if(dummy == NULL) { 1.1094 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.1095 + return NULL; 1.1096 + } 1.1097 + dup_src->data = (unsigned char*)dummy; 1.1098 + } 1.1099 + 1.1100 + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.1101 + if(dest != NULL) { 1.1102 + dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64); 1.1103 + if(dest->data != NULL) { 1.1104 + RC2Context *ctxt; 1.1105 + 1.1106 + ctxt = RC2_CreateContext(key->data, key->len, iv->data, 1.1107 + NSS_RC2_CBC, key->len); 1.1108 + 1.1109 + if(ctxt != NULL) { 1.1110 + rv = (encrypt ? RC2_Encrypt: RC2_Decrypt)( 1.1111 + ctxt, dest->data, &dest->len, 1.1112 + dup_src->len + 64, dup_src->data, dup_src->len); 1.1113 + 1.1114 + /* assumes 8 byte blocks -- remove padding */ 1.1115 + if((rv == SECSuccess) && (encrypt != PR_TRUE)) { 1.1116 + pad = dest->data[dest->len-1]; 1.1117 + if((pad > 0) && (pad <= 8)) { 1.1118 + if(dest->data[dest->len-pad] != pad) { 1.1119 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.1120 + rv = SECFailure; 1.1121 + } else { 1.1122 + dest->len -= pad; 1.1123 + } 1.1124 + } else { 1.1125 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); 1.1126 + rv = SECFailure; 1.1127 + } 1.1128 + } 1.1129 + 1.1130 + } 1.1131 + } 1.1132 + } 1.1133 + 1.1134 + if((rv != SECSuccess) && (dest != NULL)) { 1.1135 + SECITEM_FreeItem(dest, PR_TRUE); 1.1136 + dest = NULL; 1.1137 + } 1.1138 + 1.1139 + if(dup_src != NULL) { 1.1140 + SECITEM_FreeItem(dup_src, PR_TRUE); 1.1141 + } 1.1142 + 1.1143 + return dest; 1.1144 +} 1.1145 + 1.1146 +/* perform rc4 encryption and decryption */ 1.1147 +static SECItem * 1.1148 +sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op, 1.1149 + PRBool encrypt) 1.1150 +{ 1.1151 + SECItem *dest; 1.1152 + SECStatus rv = SECFailure; 1.1153 + 1.1154 + if((src == NULL) || (key == NULL) || (iv == NULL)) { 1.1155 + return NULL; 1.1156 + } 1.1157 + 1.1158 + dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.1159 + if(dest != NULL) { 1.1160 + dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * 1.1161 + (src->len + 64)); 1.1162 + if(dest->data != NULL) { 1.1163 + RC4Context *ctxt; 1.1164 + 1.1165 + ctxt = RC4_CreateContext(key->data, key->len); 1.1166 + if(ctxt) { 1.1167 + rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)( 1.1168 + ctxt, dest->data, &dest->len, 1.1169 + src->len + 64, src->data, src->len); 1.1170 + RC4_DestroyContext(ctxt, PR_TRUE); 1.1171 + } 1.1172 + } 1.1173 + } 1.1174 + 1.1175 + if((rv != SECSuccess) && (dest)) { 1.1176 + SECITEM_FreeItem(dest, PR_TRUE); 1.1177 + dest = NULL; 1.1178 + } 1.1179 + 1.1180 + return dest; 1.1181 +} 1.1182 +/* function pointer template for crypto functions */ 1.1183 +typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, 1.1184 + SECItem *src, PRBool op1, PRBool op2); 1.1185 + 1.1186 +/* performs the cipher operation on the src and returns the result. 1.1187 + * if an error occurs, NULL is returned. 1.1188 + * 1.1189 + * a null length password is allowed. this corresponds to encrypting 1.1190 + * the data with ust the salt. 1.1191 + */ 1.1192 +/* change this to use PKCS 11? */ 1.1193 +SECItem * 1.1194 +nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, 1.1195 + SECItem *src, PRBool encrypt, PRBool *update) 1.1196 +{ 1.1197 + SECItem *key = NULL, iv; 1.1198 + SECItem *dest = NULL; 1.1199 + PRBool tripleDES = PR_TRUE; 1.1200 + pkcs5_crypto_func cryptof; 1.1201 + 1.1202 + iv.data = NULL; 1.1203 + 1.1204 + if (update) { 1.1205 + *update = PR_FALSE; 1.1206 + } 1.1207 + 1.1208 + if ((pwitem == NULL) || (src == NULL)) { 1.1209 + return NULL; 1.1210 + } 1.1211 + 1.1212 + /* get key, and iv */ 1.1213 + key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE); 1.1214 + if(key == NULL) { 1.1215 + return NULL; 1.1216 + } 1.1217 + 1.1218 + switch(pbe_param->encAlg) { 1.1219 + /* PKCS 5 v2 only */ 1.1220 + case SEC_OID_AES_128_CBC: 1.1221 + case SEC_OID_AES_192_CBC: 1.1222 + case SEC_OID_AES_256_CBC: 1.1223 + cryptof = sec_pkcs5_aes; 1.1224 + break; 1.1225 + case SEC_OID_DES_EDE3_CBC: 1.1226 + cryptof = sec_pkcs5_des; 1.1227 + tripleDES = PR_TRUE; 1.1228 + break; 1.1229 + case SEC_OID_DES_CBC: 1.1230 + cryptof = sec_pkcs5_des; 1.1231 + tripleDES = PR_FALSE; 1.1232 + break; 1.1233 + case SEC_OID_RC2_CBC: 1.1234 + cryptof = sec_pkcs5_rc2; 1.1235 + break; 1.1236 + case SEC_OID_RC4: 1.1237 + cryptof = sec_pkcs5_rc4; 1.1238 + break; 1.1239 + default: 1.1240 + cryptof = NULL; 1.1241 + break; 1.1242 + } 1.1243 + 1.1244 + if (cryptof == NULL) { 1.1245 + goto loser; 1.1246 + } 1.1247 + 1.1248 + dest = (*cryptof)(key, &iv, src, tripleDES, encrypt); 1.1249 + /* 1.1250 + * it's possible for some keys and keydb's to claim to 1.1251 + * be triple des when they're really des. In this case 1.1252 + * we simply try des. If des works we set the update flag 1.1253 + * so the key db knows it needs to update all it's entries. 1.1254 + * The case can only happen on decrypted of a 1.1255 + * SEC_OID_DES_EDE3_CBD. 1.1256 + */ 1.1257 + if ((dest == NULL) && (encrypt == PR_FALSE) && 1.1258 + (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) { 1.1259 + dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt); 1.1260 + if (update && (dest != NULL)) *update = PR_TRUE; 1.1261 + } 1.1262 + 1.1263 +loser: 1.1264 + if (key != NULL) { 1.1265 + SECITEM_ZfreeItem(key, PR_TRUE); 1.1266 + } 1.1267 + if (iv.data != NULL) { 1.1268 + SECITEM_ZfreeItem(&iv, PR_FALSE); 1.1269 + } 1.1270 + 1.1271 + return dest; 1.1272 +} 1.1273 + 1.1274 +/* creates a algorithm ID containing the PBE algorithm and appropriate 1.1275 + * parameters. the required parameter is the algorithm. if salt is 1.1276 + * not specified, it is generated randomly. if IV is specified, it overrides 1.1277 + * the PKCS 5 generation of the IV. 1.1278 + * 1.1279 + * the returned SECAlgorithmID should be destroyed using 1.1280 + * SECOID_DestroyAlgorithmID 1.1281 + */ 1.1282 +SECAlgorithmID * 1.1283 +nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm, 1.1284 + NSSPKCS5PBEParameter *pbe_param) 1.1285 +{ 1.1286 + SECAlgorithmID *algid, *ret_algid = NULL; 1.1287 + SECItem der_param; 1.1288 + nsspkcs5V2PBEParameter pkcs5v2_param; 1.1289 + 1.1290 + SECStatus rv = SECFailure; 1.1291 + void *dummy = NULL; 1.1292 + 1.1293 + if (arena == NULL) { 1.1294 + return NULL; 1.1295 + } 1.1296 + 1.1297 + der_param.data = NULL; 1.1298 + der_param.len = 0; 1.1299 + 1.1300 + /* generate the algorithm id */ 1.1301 + algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID)); 1.1302 + if (algid == NULL) { 1.1303 + goto loser; 1.1304 + } 1.1305 + 1.1306 + if (pbe_param->iteration.data == NULL) { 1.1307 + dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,&pbe_param->iteration, 1.1308 + pbe_param->iter); 1.1309 + if (dummy == NULL) { 1.1310 + goto loser; 1.1311 + } 1.1312 + } 1.1313 + switch (pbe_param->pbeType) { 1.1314 + case NSSPKCS5_PBKDF1: 1.1315 + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, 1.1316 + NSSPKCS5PBEParameterTemplate); 1.1317 + break; 1.1318 + case NSSPKCS5_PKCS12_V2: 1.1319 + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, 1.1320 + NSSPKCS5PKCS12V2PBEParameterTemplate); 1.1321 + break; 1.1322 +#ifdef PBKDF2 1.1323 + case NSSPKCS5_PBKDF2: 1.1324 + if (pbe_param->keyLength.data == NULL) { 1.1325 + dummy = SEC_ASN1EncodeInteger(pbe_param->poolp, 1.1326 + &pbe_param->keyLength, pbe_param->keyLen); 1.1327 + if (dummy == NULL) { 1.1328 + goto loser; 1.1329 + } 1.1330 + } 1.1331 + PORT_Memset(&pkcs5v2_param, 0, sizeof(pkcs5v2_param)); 1.1332 + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, 1.1333 + NSSPKCS5V2PBEParameterTemplate); 1.1334 + if (dummy == NULL) { 1.1335 + break; 1.1336 + } 1.1337 + dummy = NULL; 1.1338 + rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.keyParams, 1.1339 + SEC_OID_PKCS5_PBKDF2, &der_param); 1.1340 + if (rv != SECSuccess) { 1.1341 + break; 1.1342 + } 1.1343 + der_param.data = pbe_param->ivData; 1.1344 + der_param.len = pbe_param->ivLen; 1.1345 + rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams, 1.1346 + pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL); 1.1347 + if (rv != SECSuccess) { 1.1348 + break; 1.1349 + } 1.1350 + dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param, 1.1351 + NSSPKCS5V2PBES2ParameterTemplate); 1.1352 + break; 1.1353 +#endif 1.1354 + default: 1.1355 + break; 1.1356 + } 1.1357 + 1.1358 + if (dummy == NULL) { 1.1359 + goto loser; 1.1360 + } 1.1361 + 1.1362 + rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param); 1.1363 + if (rv != SECSuccess) { 1.1364 + goto loser; 1.1365 + } 1.1366 + 1.1367 + ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); 1.1368 + if (ret_algid == NULL) { 1.1369 + goto loser; 1.1370 + } 1.1371 + 1.1372 + rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); 1.1373 + if (rv != SECSuccess) { 1.1374 + SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); 1.1375 + ret_algid = NULL; 1.1376 + } 1.1377 + 1.1378 +loser: 1.1379 + 1.1380 + return ret_algid; 1.1381 +}