1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pkcs12/p12local.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1342 @@ 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 "nssrenam.h" 1.9 +#include "pkcs12.h" 1.10 +#include "secpkcs7.h" 1.11 +#include "secasn1.h" 1.12 +#include "seccomon.h" 1.13 +#include "secoid.h" 1.14 +#include "sechash.h" 1.15 +#include "secitem.h" 1.16 +#include "secerr.h" 1.17 +#include "pk11func.h" 1.18 +#include "p12local.h" 1.19 +#include "p12.h" 1.20 + 1.21 +#define SALT_LENGTH 16 1.22 + 1.23 +SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate) 1.24 +SEC_ASN1_MKSUB(sgn_DigestInfoTemplate) 1.25 + 1.26 +CK_MECHANISM_TYPE 1.27 +sec_pkcs12_algtag_to_mech(SECOidTag algtag) 1.28 +{ 1.29 + switch (algtag) { 1.30 + case SEC_OID_MD2: 1.31 + return CKM_MD2_HMAC; 1.32 + case SEC_OID_MD5: 1.33 + return CKM_MD5_HMAC; 1.34 + case SEC_OID_SHA1: 1.35 + return CKM_SHA_1_HMAC; 1.36 + case SEC_OID_SHA224: 1.37 + return CKM_SHA224_HMAC; 1.38 + case SEC_OID_SHA256: 1.39 + return CKM_SHA256_HMAC; 1.40 + case SEC_OID_SHA384: 1.41 + return CKM_SHA384_HMAC; 1.42 + case SEC_OID_SHA512: 1.43 + return CKM_SHA512_HMAC; 1.44 + default: 1.45 + break; 1.46 + } 1.47 + return CKM_INVALID_MECHANISM; 1.48 +} 1.49 + 1.50 +/* helper functions */ 1.51 +/* returns proper bag type template based upon object type tag */ 1.52 +const SEC_ASN1Template * 1.53 +sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding) 1.54 +{ 1.55 + const SEC_ASN1Template *theTemplate; 1.56 + SEC_PKCS12SafeBag *safebag; 1.57 + SECOidData *oiddata; 1.58 + 1.59 + if (src_or_dest == NULL) { 1.60 + return NULL; 1.61 + } 1.62 + 1.63 + safebag = (SEC_PKCS12SafeBag*)src_or_dest; 1.64 + 1.65 + oiddata = safebag->safeBagTypeTag; 1.66 + if (oiddata == NULL) { 1.67 + oiddata = SECOID_FindOID(&safebag->safeBagType); 1.68 + safebag->safeBagTypeTag = oiddata; 1.69 + } 1.70 + 1.71 + switch (oiddata->offset) { 1.72 + default: 1.73 + theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); 1.74 + break; 1.75 + case SEC_OID_PKCS12_KEY_BAG_ID: 1.76 + theTemplate = SEC_PointerToPKCS12KeyBagTemplate; 1.77 + break; 1.78 + case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: 1.79 + theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD; 1.80 + break; 1.81 + case SEC_OID_PKCS12_SECRET_BAG_ID: 1.82 + theTemplate = SEC_PointerToPKCS12SecretBagTemplate; 1.83 + break; 1.84 + } 1.85 + return theTemplate; 1.86 +} 1.87 + 1.88 +const SEC_ASN1Template * 1.89 +sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding) 1.90 +{ 1.91 + const SEC_ASN1Template *theTemplate; 1.92 + SEC_PKCS12SafeBag *safebag; 1.93 + SECOidData *oiddata; 1.94 + 1.95 + if (src_or_dest == NULL) { 1.96 + return NULL; 1.97 + } 1.98 + 1.99 + safebag = (SEC_PKCS12SafeBag*)src_or_dest; 1.100 + 1.101 + oiddata = safebag->safeBagTypeTag; 1.102 + if (oiddata == NULL) { 1.103 + oiddata = SECOID_FindOID(&safebag->safeBagType); 1.104 + safebag->safeBagTypeTag = oiddata; 1.105 + } 1.106 + 1.107 + switch (oiddata->offset) { 1.108 + default: 1.109 + theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); 1.110 + break; 1.111 + case SEC_OID_PKCS12_KEY_BAG_ID: 1.112 + theTemplate = SEC_PKCS12PrivateKeyBagTemplate; 1.113 + break; 1.114 + case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: 1.115 + theTemplate = SEC_PKCS12CertAndCRLBagTemplate; 1.116 + break; 1.117 + case SEC_OID_PKCS12_SECRET_BAG_ID: 1.118 + theTemplate = SEC_PKCS12SecretBagTemplate; 1.119 + break; 1.120 + } 1.121 + return theTemplate; 1.122 +} 1.123 + 1.124 +/* returns proper cert crl template based upon type tag */ 1.125 +const SEC_ASN1Template * 1.126 +sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding) 1.127 +{ 1.128 + const SEC_ASN1Template *theTemplate; 1.129 + SEC_PKCS12CertAndCRL *certbag; 1.130 + SECOidData *oiddata; 1.131 + 1.132 + if (src_or_dest == NULL) { 1.133 + return NULL; 1.134 + } 1.135 + 1.136 + certbag = (SEC_PKCS12CertAndCRL*)src_or_dest; 1.137 + oiddata = certbag->BagTypeTag; 1.138 + if (oiddata == NULL) { 1.139 + oiddata = SECOID_FindOID(&certbag->BagID); 1.140 + certbag->BagTypeTag = oiddata; 1.141 + } 1.142 + 1.143 + switch (oiddata->offset) { 1.144 + default: 1.145 + theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); 1.146 + break; 1.147 + case SEC_OID_PKCS12_X509_CERT_CRL_BAG: 1.148 + theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD; 1.149 + break; 1.150 + case SEC_OID_PKCS12_SDSI_CERT_BAG: 1.151 + theTemplate = SEC_PointerToPKCS12SDSICertTemplate; 1.152 + break; 1.153 + } 1.154 + return theTemplate; 1.155 +} 1.156 + 1.157 +const SEC_ASN1Template * 1.158 +sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding) 1.159 +{ 1.160 + const SEC_ASN1Template *theTemplate; 1.161 + SEC_PKCS12CertAndCRL *certbag; 1.162 + SECOidData *oiddata; 1.163 + 1.164 + if (src_or_dest == NULL) { 1.165 + return NULL; 1.166 + } 1.167 + 1.168 + certbag = (SEC_PKCS12CertAndCRL*)src_or_dest; 1.169 + oiddata = certbag->BagTypeTag; 1.170 + if (oiddata == NULL) { 1.171 + oiddata = SECOID_FindOID(&certbag->BagID); 1.172 + certbag->BagTypeTag = oiddata; 1.173 + } 1.174 + 1.175 + switch (oiddata->offset) { 1.176 + default: 1.177 + theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); 1.178 + break; 1.179 + case SEC_OID_PKCS12_X509_CERT_CRL_BAG: 1.180 + theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate; 1.181 + break; 1.182 + case SEC_OID_PKCS12_SDSI_CERT_BAG: 1.183 + theTemplate = SEC_PointerToPKCS12SDSICertTemplate; 1.184 + break; 1.185 + } 1.186 + return theTemplate; 1.187 +} 1.188 + 1.189 +/* returns appropriate shroud template based on object type tag */ 1.190 +const SEC_ASN1Template * 1.191 +sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding) 1.192 +{ 1.193 + const SEC_ASN1Template *theTemplate; 1.194 + SEC_PKCS12ESPVKItem *espvk; 1.195 + SECOidData *oiddata; 1.196 + 1.197 + if (src_or_dest == NULL) { 1.198 + return NULL; 1.199 + } 1.200 + 1.201 + espvk = (SEC_PKCS12ESPVKItem*)src_or_dest; 1.202 + oiddata = espvk->espvkTag; 1.203 + if (oiddata == NULL) { 1.204 + oiddata = SECOID_FindOID(&espvk->espvkOID); 1.205 + espvk->espvkTag = oiddata; 1.206 + } 1.207 + 1.208 + switch (oiddata->offset) { 1.209 + default: 1.210 + theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); 1.211 + break; 1.212 + case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING: 1.213 + theTemplate = 1.214 + SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate); 1.215 + break; 1.216 + } 1.217 + return theTemplate; 1.218 +} 1.219 + 1.220 +/* generate SALT placing it into the character array passed in. 1.221 + * it is assumed that salt_dest is an array of appropriate size 1.222 + * XXX We might want to generate our own random context 1.223 + */ 1.224 +SECItem * 1.225 +sec_pkcs12_generate_salt(void) 1.226 +{ 1.227 + SECItem *salt; 1.228 + 1.229 + salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.230 + if(salt == NULL) { 1.231 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.232 + return NULL; 1.233 + } 1.234 + salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * 1.235 + SALT_LENGTH); 1.236 + salt->len = SALT_LENGTH; 1.237 + if(salt->data == NULL) { 1.238 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.239 + SECITEM_ZfreeItem(salt, PR_TRUE); 1.240 + return NULL; 1.241 + } 1.242 + 1.243 + PK11_GenerateRandom(salt->data, salt->len); 1.244 + 1.245 + return salt; 1.246 +} 1.247 + 1.248 +/* generate KEYS -- as per PKCS12 section 7. 1.249 + * only used for MAC 1.250 + */ 1.251 +SECItem * 1.252 +sec_pkcs12_generate_key_from_password(SECOidTag algorithm, 1.253 + SECItem *salt, 1.254 + SECItem *password) 1.255 +{ 1.256 + unsigned char *pre_hash=NULL; 1.257 + unsigned char *hash_dest=NULL; 1.258 + SECStatus res; 1.259 + PLArenaPool *poolp; 1.260 + SECItem *key = NULL; 1.261 + int key_len = 0; 1.262 + 1.263 + if((salt == NULL) || (password == NULL)) { 1.264 + return NULL; 1.265 + } 1.266 + 1.267 + poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.268 + if(poolp == NULL) { 1.269 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.270 + return NULL; 1.271 + } 1.272 + 1.273 + pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * 1.274 + (salt->len+password->len)); 1.275 + if(pre_hash == NULL) { 1.276 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.277 + goto loser; 1.278 + } 1.279 + 1.280 + hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp, 1.281 + sizeof(unsigned char) * SHA1_LENGTH); 1.282 + if(hash_dest == NULL) { 1.283 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.284 + goto loser; 1.285 + } 1.286 + 1.287 + PORT_Memcpy(pre_hash, salt->data, salt->len); 1.288 + /* handle password of 0 length case */ 1.289 + if(password->len > 0) { 1.290 + PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len); 1.291 + } 1.292 + 1.293 + res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash, 1.294 + (salt->len+password->len)); 1.295 + if(res == SECFailure) { 1.296 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.297 + goto loser; 1.298 + } 1.299 + 1.300 + switch(algorithm) { 1.301 + case SEC_OID_SHA1: 1.302 + if(key_len == 0) 1.303 + key_len = 16; 1.304 + key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.305 + if(key == NULL) { 1.306 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.307 + goto loser; 1.308 + } 1.309 + key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) 1.310 + * key_len); 1.311 + if(key->data == NULL) { 1.312 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.313 + goto loser; 1.314 + } 1.315 + key->len = key_len; 1.316 + PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH-key->len], key->len); 1.317 + break; 1.318 + default: 1.319 + goto loser; 1.320 + break; 1.321 + } 1.322 + 1.323 + PORT_FreeArena(poolp, PR_TRUE); 1.324 + return key; 1.325 + 1.326 +loser: 1.327 + PORT_FreeArena(poolp, PR_TRUE); 1.328 + if(key != NULL) { 1.329 + SECITEM_ZfreeItem(key, PR_TRUE); 1.330 + } 1.331 + return NULL; 1.332 +} 1.333 + 1.334 +/* MAC is generated per PKCS 12 section 6. It is expected that key, msg 1.335 + * and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in 1.336 + * because it is not known how long the message actually is. String 1.337 + * manipulation routines will not necessarily work because msg may have 1.338 + * imbedded NULLs 1.339 + */ 1.340 +static SECItem * 1.341 +sec_pkcs12_generate_old_mac(SECItem *key, 1.342 + SECItem *msg) 1.343 +{ 1.344 + SECStatus res; 1.345 + PLArenaPool *temparena = NULL; 1.346 + unsigned char *hash_dest=NULL, *hash_src1=NULL, *hash_src2 = NULL; 1.347 + int i; 1.348 + SECItem *mac = NULL; 1.349 + 1.350 + if((key == NULL) || (msg == NULL)) 1.351 + goto loser; 1.352 + 1.353 + /* allocate return item */ 1.354 + mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.355 + if(mac == NULL) 1.356 + return NULL; 1.357 + mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) 1.358 + * SHA1_LENGTH); 1.359 + mac->len = SHA1_LENGTH; 1.360 + if(mac->data == NULL) 1.361 + goto loser; 1.362 + 1.363 + /* allocate temporary items */ 1.364 + temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.365 + if(temparena == NULL) 1.366 + goto loser; 1.367 + 1.368 + hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena, 1.369 + sizeof(unsigned char) * (16+msg->len)); 1.370 + if(hash_src1 == NULL) 1.371 + goto loser; 1.372 + 1.373 + hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena, 1.374 + sizeof(unsigned char) * (SHA1_LENGTH+16)); 1.375 + if(hash_src2 == NULL) 1.376 + goto loser; 1.377 + 1.378 + hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena, 1.379 + sizeof(unsigned char) * SHA1_LENGTH); 1.380 + if(hash_dest == NULL) 1.381 + goto loser; 1.382 + 1.383 + /* perform mac'ing as per PKCS 12 */ 1.384 + 1.385 + /* first round of hashing */ 1.386 + for(i = 0; i < 16; i++) 1.387 + hash_src1[i] = key->data[i] ^ 0x36; 1.388 + PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len); 1.389 + res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16+msg->len)); 1.390 + if(res == SECFailure) 1.391 + goto loser; 1.392 + 1.393 + /* second round of hashing */ 1.394 + for(i = 0; i < 16; i++) 1.395 + hash_src2[i] = key->data[i] ^ 0x5c; 1.396 + PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH); 1.397 + res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH+16); 1.398 + if(res == SECFailure) 1.399 + goto loser; 1.400 + 1.401 + PORT_FreeArena(temparena, PR_TRUE); 1.402 + return mac; 1.403 + 1.404 +loser: 1.405 + if(temparena != NULL) 1.406 + PORT_FreeArena(temparena, PR_TRUE); 1.407 + if(mac != NULL) 1.408 + SECITEM_ZfreeItem(mac, PR_TRUE); 1.409 + return NULL; 1.410 +} 1.411 + 1.412 +/* MAC is generated per PKCS 12 section 6. It is expected that key, msg 1.413 + * and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in 1.414 + * because it is not known how long the message actually is. String 1.415 + * manipulation routines will not necessarily work because msg may have 1.416 + * imbedded NULLs 1.417 + */ 1.418 +SECItem * 1.419 +sec_pkcs12_generate_mac(SECItem *key, 1.420 + SECItem *msg, 1.421 + PRBool old_method) 1.422 +{ 1.423 + SECStatus res = SECFailure; 1.424 + SECItem *mac = NULL; 1.425 + PK11Context *pk11cx = NULL; 1.426 + SECItem ignore = {0}; 1.427 + 1.428 + if((key == NULL) || (msg == NULL)) { 1.429 + return NULL; 1.430 + } 1.431 + 1.432 + if(old_method == PR_TRUE) { 1.433 + return sec_pkcs12_generate_old_mac(key, msg); 1.434 + } 1.435 + 1.436 + /* allocate return item */ 1.437 + mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); 1.438 + if (mac == NULL) { 1.439 + return NULL; 1.440 + } 1.441 + 1.442 + pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive, 1.443 + CKA_SIGN, key, &ignore, NULL); 1.444 + if (pk11cx == NULL) { 1.445 + goto loser; 1.446 + } 1.447 + 1.448 + res = PK11_DigestBegin(pk11cx); 1.449 + if (res == SECFailure) { 1.450 + goto loser; 1.451 + } 1.452 + 1.453 + res = PK11_DigestOp(pk11cx, msg->data, msg->len); 1.454 + if (res == SECFailure) { 1.455 + goto loser; 1.456 + } 1.457 + 1.458 + res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH); 1.459 + if (res == SECFailure) { 1.460 + goto loser; 1.461 + } 1.462 + 1.463 + PK11_DestroyContext(pk11cx, PR_TRUE); 1.464 + pk11cx = NULL; 1.465 + 1.466 +loser: 1.467 + 1.468 + if(res != SECSuccess) { 1.469 + SECITEM_ZfreeItem(mac, PR_TRUE); 1.470 + mac = NULL; 1.471 + if (pk11cx) { 1.472 + PK11_DestroyContext(pk11cx, PR_TRUE); 1.473 + } 1.474 + } 1.475 + 1.476 + return mac; 1.477 +} 1.478 + 1.479 +/* compute the thumbprint of the DER cert and create a digest info 1.480 + * to store it in and return the digest info. 1.481 + * a return of NULL indicates an error. 1.482 + */ 1.483 +SGNDigestInfo * 1.484 +sec_pkcs12_compute_thumbprint(SECItem *der_cert) 1.485 +{ 1.486 + SGNDigestInfo *thumb = NULL; 1.487 + SECItem digest; 1.488 + PLArenaPool *temparena = NULL; 1.489 + SECStatus rv = SECFailure; 1.490 + 1.491 + if(der_cert == NULL) 1.492 + return NULL; 1.493 + 1.494 + temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.495 + if(temparena == NULL) { 1.496 + return NULL; 1.497 + } 1.498 + 1.499 + digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena, 1.500 + sizeof(unsigned char) * 1.501 + SHA1_LENGTH); 1.502 + /* digest data and create digest info */ 1.503 + if(digest.data != NULL) { 1.504 + digest.len = SHA1_LENGTH; 1.505 + rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data, 1.506 + der_cert->len); 1.507 + if(rv == SECSuccess) { 1.508 + thumb = SGN_CreateDigestInfo(SEC_OID_SHA1, 1.509 + digest.data, 1.510 + digest.len); 1.511 + } else { 1.512 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.513 + } 1.514 + } else { 1.515 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.516 + } 1.517 + 1.518 + PORT_FreeArena(temparena, PR_TRUE); 1.519 + 1.520 + return thumb; 1.521 +} 1.522 + 1.523 +/* create a virtual password per PKCS 12, the password is converted 1.524 + * to unicode, the salt is prepended to it, and then the whole thing 1.525 + * is returned */ 1.526 +SECItem * 1.527 +sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt, 1.528 + PRBool swap) 1.529 +{ 1.530 + SECItem uniPwd = {siBuffer, NULL,0}, *retPwd = NULL; 1.531 + 1.532 + if((password == NULL) || (salt == NULL)) { 1.533 + return NULL; 1.534 + } 1.535 + 1.536 + if(password->len == 0) { 1.537 + uniPwd.data = (unsigned char*)PORT_ZAlloc(2); 1.538 + uniPwd.len = 2; 1.539 + if(!uniPwd.data) { 1.540 + return NULL; 1.541 + } 1.542 + } else { 1.543 + uniPwd.data = (unsigned char*)PORT_ZAlloc(password->len * 3); 1.544 + uniPwd.len = password->len * 3; 1.545 + if(!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len, 1.546 + uniPwd.data, uniPwd.len, &uniPwd.len, swap)) { 1.547 + SECITEM_ZfreeItem(&uniPwd, PR_FALSE); 1.548 + return NULL; 1.549 + } 1.550 + } 1.551 + 1.552 + retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1.553 + if(retPwd == NULL) { 1.554 + goto loser; 1.555 + } 1.556 + 1.557 + /* allocate space and copy proper data */ 1.558 + retPwd->len = uniPwd.len + salt->len; 1.559 + retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len); 1.560 + if(retPwd->data == NULL) { 1.561 + PORT_Free(retPwd); 1.562 + goto loser; 1.563 + } 1.564 + 1.565 + PORT_Memcpy(retPwd->data, salt->data, salt->len); 1.566 + PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len); 1.567 + 1.568 + SECITEM_ZfreeItem(&uniPwd, PR_FALSE); 1.569 + 1.570 + return retPwd; 1.571 + 1.572 +loser: 1.573 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.574 + SECITEM_ZfreeItem(&uniPwd, PR_FALSE); 1.575 + return NULL; 1.576 +} 1.577 + 1.578 +/* appends a shrouded key to a key bag. this is used for exporting 1.579 + * to store externally wrapped keys. it is used when importing to convert 1.580 + * old items to new 1.581 + */ 1.582 +SECStatus 1.583 +sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag, 1.584 + SEC_PKCS12ESPVKItem *espvk) 1.585 +{ 1.586 + int size; 1.587 + void *mark = NULL, *dummy = NULL; 1.588 + 1.589 + if((bag == NULL) || (espvk == NULL)) 1.590 + return SECFailure; 1.591 + 1.592 + mark = PORT_ArenaMark(bag->poolp); 1.593 + 1.594 + /* grow the list */ 1.595 + size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *); 1.596 + dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp, 1.597 + bag->espvks, size, 1.598 + size + sizeof(SEC_PKCS12ESPVKItem *)); 1.599 + bag->espvks = (SEC_PKCS12ESPVKItem**)dummy; 1.600 + if(dummy == NULL) { 1.601 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.602 + goto loser; 1.603 + } 1.604 + 1.605 + bag->espvks[bag->nEspvks] = espvk; 1.606 + bag->nEspvks++; 1.607 + bag->espvks[bag->nEspvks] = NULL; 1.608 + 1.609 + PORT_ArenaUnmark(bag->poolp, mark); 1.610 + return SECSuccess; 1.611 + 1.612 +loser: 1.613 + PORT_ArenaRelease(bag->poolp, mark); 1.614 + return SECFailure; 1.615 +} 1.616 + 1.617 +/* search a certificate list for a nickname, a thumbprint, or both 1.618 + * within a certificate bag. if the certificate could not be 1.619 + * found or an error occurs, NULL is returned; 1.620 + */ 1.621 +static SEC_PKCS12CertAndCRL * 1.622 +sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag, 1.623 + SECItem *nickname, SGNDigestInfo *thumbprint) 1.624 +{ 1.625 + PRBool search_both = PR_FALSE, search_nickname = PR_FALSE; 1.626 + int i, j; 1.627 + 1.628 + if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) { 1.629 + return NULL; 1.630 + } 1.631 + 1.632 + if(thumbprint && nickname) { 1.633 + search_both = PR_TRUE; 1.634 + } 1.635 + 1.636 + if(nickname) { 1.637 + search_nickname = PR_TRUE; 1.638 + } 1.639 + 1.640 +search_again: 1.641 + i = 0; 1.642 + while(certbag->certAndCRLs[i] != NULL) { 1.643 + SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i]; 1.644 + 1.645 + if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { 1.646 + 1.647 + /* check nicknames */ 1.648 + if(search_nickname) { 1.649 + if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) { 1.650 + return cert; 1.651 + } 1.652 + } else { 1.653 + /* check thumbprints */ 1.654 + SECItem **derCertList; 1.655 + 1.656 + /* get pointer to certificate list, does not need to 1.657 + * be freed since it is within the arena which will 1.658 + * be freed later. 1.659 + */ 1.660 + derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL); 1.661 + j = 0; 1.662 + if(derCertList != NULL) { 1.663 + while(derCertList[j] != NULL) { 1.664 + SECComparison eq; 1.665 + SGNDigestInfo *di; 1.666 + di = sec_pkcs12_compute_thumbprint(derCertList[j]); 1.667 + if(di) { 1.668 + eq = SGN_CompareDigestInfo(thumbprint, di); 1.669 + SGN_DestroyDigestInfo(di); 1.670 + if(eq == SECEqual) { 1.671 + /* copy the derCert for later reference */ 1.672 + cert->value.x509->derLeafCert = derCertList[j]; 1.673 + return cert; 1.674 + } 1.675 + } else { 1.676 + /* an error occurred */ 1.677 + return NULL; 1.678 + } 1.679 + j++; 1.680 + } 1.681 + } 1.682 + } 1.683 + } 1.684 + 1.685 + i++; 1.686 + } 1.687 + 1.688 + if(search_both) { 1.689 + search_both = PR_FALSE; 1.690 + search_nickname = PR_FALSE; 1.691 + goto search_again; 1.692 + } 1.693 + 1.694 + return NULL; 1.695 +} 1.696 + 1.697 +/* search a key list for a nickname, a thumbprint, or both 1.698 + * within a key bag. if the key could not be 1.699 + * found or an error occurs, NULL is returned; 1.700 + */ 1.701 +static SEC_PKCS12PrivateKey * 1.702 +sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag, 1.703 + SECItem *nickname, SGNDigestInfo *thumbprint) 1.704 +{ 1.705 + PRBool search_both = PR_FALSE, search_nickname = PR_FALSE; 1.706 + int i, j; 1.707 + 1.708 + if((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) { 1.709 + return NULL; 1.710 + } 1.711 + 1.712 + if(keybag->privateKeys == NULL) { 1.713 + return NULL; 1.714 + } 1.715 + 1.716 + if(thumbprint && nickname) { 1.717 + search_both = PR_TRUE; 1.718 + } 1.719 + 1.720 + if(nickname) { 1.721 + search_nickname = PR_TRUE; 1.722 + } 1.723 + 1.724 +search_again: 1.725 + i = 0; 1.726 + while(keybag->privateKeys[i] != NULL) { 1.727 + SEC_PKCS12PrivateKey *key = keybag->privateKeys[i]; 1.728 + 1.729 + /* check nicknames */ 1.730 + if(search_nickname) { 1.731 + if(SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) { 1.732 + return key; 1.733 + } 1.734 + } else { 1.735 + /* check digests */ 1.736 + SGNDigestInfo **assocCerts = key->pvkData.assocCerts; 1.737 + if((assocCerts == NULL) || (assocCerts[0] == NULL)) { 1.738 + return NULL; 1.739 + } 1.740 + 1.741 + j = 0; 1.742 + while(assocCerts[j] != NULL) { 1.743 + SECComparison eq; 1.744 + eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]); 1.745 + if(eq == SECEqual) { 1.746 + return key; 1.747 + } 1.748 + j++; 1.749 + } 1.750 + } 1.751 + i++; 1.752 + } 1.753 + 1.754 + if(search_both) { 1.755 + search_both = PR_FALSE; 1.756 + search_nickname = PR_FALSE; 1.757 + goto search_again; 1.758 + } 1.759 + 1.760 + return NULL; 1.761 +} 1.762 + 1.763 +/* seach the safe first then try the baggage bag 1.764 + * safe and bag contain certs and keys to search 1.765 + * objType is the object type to look for 1.766 + * bagType is the type of bag that was found by sec_pkcs12_find_object 1.767 + * index is the entity in safe->safeContents or bag->unencSecrets which 1.768 + * is being searched 1.769 + * nickname and thumbprint are the search criteria 1.770 + * 1.771 + * a return of null indicates no match 1.772 + */ 1.773 +static void * 1.774 +sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe, 1.775 + SEC_PKCS12BaggageItem *bag, 1.776 + SECOidTag objType, SECOidTag bagType, int index, 1.777 + SECItem *nickname, SGNDigestInfo *thumbprint) 1.778 +{ 1.779 + PRBool searchSafe; 1.780 + int i = index; 1.781 + 1.782 + if((safe == NULL) && (bag == NULL)) { 1.783 + return NULL; 1.784 + } 1.785 + 1.786 + searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE); 1.787 + switch(objType) { 1.788 + case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: 1.789 + if(objType == bagType) { 1.790 + SEC_PKCS12CertAndCRLBag *certBag; 1.791 + 1.792 + if(searchSafe) { 1.793 + certBag = safe->contents[i]->safeContent.certAndCRLBag; 1.794 + } else { 1.795 + certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag; 1.796 + } 1.797 + return sec_pkcs12_find_cert_in_certbag(certBag, nickname, 1.798 + thumbprint); 1.799 + } 1.800 + break; 1.801 + case SEC_OID_PKCS12_KEY_BAG_ID: 1.802 + if(objType == bagType) { 1.803 + SEC_PKCS12PrivateKeyBag *keyBag; 1.804 + 1.805 + if(searchSafe) { 1.806 + keyBag = safe->contents[i]->safeContent.keyBag; 1.807 + } else { 1.808 + keyBag = bag->unencSecrets[i]->safeContent.keyBag; 1.809 + } 1.810 + return sec_pkcs12_find_key_in_keybag(keyBag, nickname, 1.811 + thumbprint); 1.812 + } 1.813 + break; 1.814 + default: 1.815 + break; 1.816 + } 1.817 + 1.818 + return NULL; 1.819 +} 1.820 + 1.821 +/* searches both the baggage and the safe areas looking for 1.822 + * object of specified type matching either the nickname or the 1.823 + * thumbprint specified. 1.824 + * 1.825 + * safe and baggage store certs and keys 1.826 + * objType is the OID for the bag type to be searched: 1.827 + * SEC_OID_PKCS12_KEY_BAG_ID, or 1.828 + * SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID 1.829 + * nickname and thumbprint are the search criteria 1.830 + * 1.831 + * if no match found, NULL returned and error set 1.832 + */ 1.833 +void * 1.834 +sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe, 1.835 + SEC_PKCS12Baggage *baggage, 1.836 + SECOidTag objType, 1.837 + SECItem *nickname, 1.838 + SGNDigestInfo *thumbprint) 1.839 +{ 1.840 + int i, j; 1.841 + void *retItem; 1.842 + 1.843 + if(((safe == NULL) && (thumbprint == NULL)) || 1.844 + ((nickname == NULL) && (thumbprint == NULL))) { 1.845 + return NULL; 1.846 + } 1.847 + 1.848 + i = 0; 1.849 + if((safe != NULL) && (safe->contents != NULL)) { 1.850 + while(safe->contents[i] != NULL) { 1.851 + SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); 1.852 + retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i, 1.853 + nickname, thumbprint); 1.854 + if(retItem != NULL) { 1.855 + return retItem; 1.856 + } 1.857 + i++; 1.858 + } 1.859 + } 1.860 + 1.861 + if((baggage != NULL) && (baggage->bags != NULL)) { 1.862 + i = 0; 1.863 + while(baggage->bags[i] != NULL) { 1.864 + SEC_PKCS12BaggageItem *xbag = baggage->bags[i]; 1.865 + j = 0; 1.866 + if(xbag->unencSecrets != NULL) { 1.867 + while(xbag->unencSecrets[j] != NULL) { 1.868 + SECOidTag bagType; 1.869 + bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType); 1.870 + retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType, 1.871 + j, nickname, thumbprint); 1.872 + if(retItem != NULL) { 1.873 + return retItem; 1.874 + } 1.875 + j++; 1.876 + } 1.877 + } 1.878 + i++; 1.879 + } 1.880 + } 1.881 + 1.882 + PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); 1.883 + return NULL; 1.884 +} 1.885 + 1.886 +/* this function converts a password to unicode and encures that the 1.887 + * required double 0 byte be placed at the end of the string 1.888 + */ 1.889 +PRBool 1.890 +sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest, 1.891 + SECItem *src, PRBool zeroTerm, 1.892 + PRBool asciiConvert, PRBool toUnicode) 1.893 +{ 1.894 + PRBool success = PR_FALSE; 1.895 + if(!src || !dest) { 1.896 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.897 + return PR_FALSE; 1.898 + } 1.899 + 1.900 + dest->len = src->len * 3 + 2; 1.901 + if(arena) { 1.902 + dest->data = (unsigned char*)PORT_ArenaZAlloc(arena, dest->len); 1.903 + } else { 1.904 + dest->data = (unsigned char*)PORT_ZAlloc(dest->len); 1.905 + } 1.906 + 1.907 + if(!dest->data) { 1.908 + dest->len = 0; 1.909 + return PR_FALSE; 1.910 + } 1.911 + 1.912 + if(!asciiConvert) { 1.913 + success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data, 1.914 + dest->len, &dest->len); 1.915 + } else { 1.916 +#ifndef IS_LITTLE_ENDIAN 1.917 + PRBool swapUnicode = PR_FALSE; 1.918 +#else 1.919 + PRBool swapUnicode = PR_TRUE; 1.920 +#endif 1.921 + success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data, 1.922 + dest->len, &dest->len, swapUnicode); 1.923 + } 1.924 + 1.925 + if(!success) { 1.926 + if(!arena) { 1.927 + PORT_Free(dest->data); 1.928 + dest->data = NULL; 1.929 + dest->len = 0; 1.930 + } 1.931 + return PR_FALSE; 1.932 + } 1.933 + 1.934 + if((dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) { 1.935 + if(dest->len + 2 > 3 * src->len) { 1.936 + if(arena) { 1.937 + dest->data = (unsigned char*)PORT_ArenaGrow(arena, 1.938 + dest->data, dest->len, 1.939 + dest->len + 2); 1.940 + } else { 1.941 + dest->data = (unsigned char*)PORT_Realloc(dest->data, 1.942 + dest->len + 2); 1.943 + } 1.944 + 1.945 + if(!dest->data) { 1.946 + return PR_FALSE; 1.947 + } 1.948 + } 1.949 + dest->len += 2; 1.950 + dest->data[dest->len-1] = dest->data[dest->len-2] = 0; 1.951 + } 1.952 + 1.953 + return PR_TRUE; 1.954 +} 1.955 + 1.956 +/* pkcs 12 templates */ 1.957 +static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser = 1.958 + sec_pkcs12_choose_shroud_type; 1.959 + 1.960 +const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] = 1.961 +{ 1.962 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, 1.963 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, 1.964 + { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) }, 1.965 + { 0 } 1.966 +}; 1.967 + 1.968 +const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] = 1.969 +{ 1.970 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, 1.971 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, 1.972 + { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) }, 1.973 + { 0 } 1.974 +}; 1.975 + 1.976 +const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] = 1.977 +{ 1.978 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), 1.979 + SEC_PKCS12CodedCertBagTemplate }, 1.980 +}; 1.981 + 1.982 +const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] = 1.983 +{ 1.984 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) }, 1.985 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) }, 1.986 + { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData), 1.987 + SEC_PKCS12PVKSupportingDataTemplate_OLD }, 1.988 + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1.989 + SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText), 1.990 + &sec_pkcs12_shroud_chooser }, 1.991 + { 0 } 1.992 +}; 1.993 + 1.994 +const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] = 1.995 +{ 1.996 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) }, 1.997 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) }, 1.998 + { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData), 1.999 + SEC_PKCS12PVKSupportingDataTemplate }, 1.1000 + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1.1001 + SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText), 1.1002 + &sec_pkcs12_shroud_chooser }, 1.1003 + { 0 } 1.1004 +}; 1.1005 + 1.1006 +const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] = 1.1007 +{ 1.1008 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) }, 1.1009 + { SEC_ASN1_OBJECT_ID, 1.1010 + offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) }, 1.1011 + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1012 + offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) }, 1.1013 + { 0 } 1.1014 +}; 1.1015 + 1.1016 +const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] = 1.1017 +{ 1.1018 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) }, 1.1019 + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , 1.1020 + offsetof(SEC_PKCS12PVKSupportingData, assocCerts), 1.1021 + SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, 1.1022 + { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, 1.1023 + offsetof(SEC_PKCS12PVKSupportingData, regenerable) }, 1.1024 + { SEC_ASN1_PRINTABLE_STRING, 1.1025 + offsetof(SEC_PKCS12PVKSupportingData, nickname) }, 1.1026 + { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, 1.1027 + offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) }, 1.1028 + { 0 } 1.1029 +}; 1.1030 + 1.1031 +const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] = 1.1032 +{ 1.1033 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) }, 1.1034 + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , 1.1035 + offsetof(SEC_PKCS12PVKSupportingData, assocCerts), 1.1036 + SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, 1.1037 + { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, 1.1038 + offsetof(SEC_PKCS12PVKSupportingData, regenerable) }, 1.1039 + { SEC_ASN1_BMP_STRING, 1.1040 + offsetof(SEC_PKCS12PVKSupportingData, uniNickName) }, 1.1041 + { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, 1.1042 + offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) }, 1.1043 + { 0 } 1.1044 +}; 1.1045 + 1.1046 +const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] = 1.1047 +{ 1.1048 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) }, 1.1049 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks), 1.1050 + SEC_PKCS12ESPVKItemTemplate }, 1.1051 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets), 1.1052 + SEC_PKCS12SafeBagTemplate }, 1.1053 + /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets), 1.1054 + SEC_PKCS12CodedSafeBagTemplate }, */ 1.1055 + { 0 } 1.1056 +}; 1.1057 + 1.1058 +const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] = 1.1059 +{ 1.1060 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags), 1.1061 + SEC_PKCS12BaggageItemTemplate }, 1.1062 +}; 1.1063 + 1.1064 +const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] = 1.1065 +{ 1.1066 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks), 1.1067 + SEC_PKCS12ESPVKItemTemplate_OLD }, 1.1068 +}; 1.1069 + 1.1070 +static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser = 1.1071 + sec_pkcs12_choose_bag_type; 1.1072 + 1.1073 +static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old = 1.1074 + sec_pkcs12_choose_bag_type_old; 1.1075 + 1.1076 +const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] = 1.1077 +{ 1.1078 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, 1.1079 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, 1.1080 + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.1081 + SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1082 + offsetof(SEC_PKCS12SafeBag, safeContent), 1.1083 + &sec_pkcs12_bag_chooser_old }, 1.1084 + { 0 } 1.1085 +}; 1.1086 + 1.1087 +const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] = 1.1088 +{ 1.1089 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, 1.1090 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, 1.1091 + { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER, 1.1092 + offsetof(SEC_PKCS12SafeBag, safeContent), 1.1093 + &sec_pkcs12_bag_chooser }, 1.1094 + { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING, 1.1095 + offsetof(SEC_PKCS12SafeBag, uniSafeBagName) }, 1.1096 + { 0 } 1.1097 +}; 1.1098 + 1.1099 +const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] = 1.1100 +{ 1.1101 + { SEC_ASN1_SET_OF, 1.1102 + offsetof(SEC_PKCS12SafeContents, contents), 1.1103 + SEC_PKCS12SafeBagTemplate_OLD } 1.1104 +}; 1.1105 + 1.1106 +const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] = 1.1107 +{ 1.1108 + { SEC_ASN1_SET_OF, 1.1109 + offsetof(SEC_PKCS12SafeContents, contents), 1.1110 + SEC_PKCS12SafeBagTemplate } /* here */ 1.1111 +}; 1.1112 + 1.1113 +const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] = 1.1114 +{ 1.1115 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) }, 1.1116 + { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData), 1.1117 + SEC_PKCS12PVKSupportingDataTemplate }, 1.1118 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.1119 + offsetof(SEC_PKCS12PrivateKey, pkcs8data), 1.1120 + SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) }, 1.1121 + { 0 } 1.1122 +}; 1.1123 + 1.1124 +const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] = 1.1125 +{ 1.1126 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) }, 1.1127 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys), 1.1128 + SEC_PKCS12PrivateKeyTemplate }, 1.1129 + { 0 } 1.1130 +}; 1.1131 + 1.1132 +const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] = 1.1133 +{ 1.1134 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, 1.1135 + { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL), 1.1136 + sec_PKCS7ContentInfoTemplate }, 1.1137 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN , 1.1138 + offsetof(SEC_PKCS12X509CertCRL, thumbprint), 1.1139 + SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, 1.1140 + { 0 } 1.1141 +}; 1.1142 + 1.1143 +const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] = 1.1144 +{ 1.1145 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, 1.1146 + { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL), 1.1147 + sec_PKCS7ContentInfoTemplate }, 1.1148 + { 0 } 1.1149 +}; 1.1150 + 1.1151 +const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] = 1.1152 +{ 1.1153 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, 1.1154 + { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) }, 1.1155 + { 0 } 1.1156 +}; 1.1157 + 1.1158 +static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old = 1.1159 + sec_pkcs12_choose_cert_crl_type_old; 1.1160 + 1.1161 +static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser = 1.1162 + sec_pkcs12_choose_cert_crl_type; 1.1163 + 1.1164 +const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] = 1.1165 +{ 1.1166 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, 1.1167 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, 1.1168 + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT | 1.1169 + SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0, 1.1170 + offsetof(SEC_PKCS12CertAndCRL, value), 1.1171 + &sec_pkcs12_cert_crl_chooser_old }, 1.1172 + { 0 } 1.1173 +}; 1.1174 + 1.1175 +const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] = 1.1176 +{ 1.1177 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, 1.1178 + { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, 1.1179 + { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.1180 + SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1181 + offsetof(SEC_PKCS12CertAndCRL, value), 1.1182 + &sec_pkcs12_cert_crl_chooser }, 1.1183 + { 0 } 1.1184 +}; 1.1185 + 1.1186 +const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] = 1.1187 +{ 1.1188 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), 1.1189 + SEC_PKCS12CertAndCRLTemplate }, 1.1190 +}; 1.1191 + 1.1192 +const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] = 1.1193 +{ 1.1194 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) }, 1.1195 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), 1.1196 + SEC_PKCS12CertAndCRLTemplate_OLD }, 1.1197 + { 0 } 1.1198 +}; 1.1199 + 1.1200 +const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] = 1.1201 +{ 1.1202 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) }, 1.1203 + { SEC_ASN1_OBJECT_ID, 1.1204 + offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) }, 1.1205 + { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT, 1.1206 + offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) }, 1.1207 + { 0 } 1.1208 +}; 1.1209 + 1.1210 +const SEC_ASN1Template SEC_PKCS12SecretTemplate[] = 1.1211 +{ 1.1212 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) }, 1.1213 + { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) }, 1.1214 + { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) }, 1.1215 + { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, 1.1216 + offsetof(SEC_PKCS12Secret, secretAdditional), 1.1217 + SEC_PKCS12SecretAdditionalTemplate }, 1.1218 + { 0 } 1.1219 +}; 1.1220 + 1.1221 +const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] = 1.1222 +{ 1.1223 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) }, 1.1224 + { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1225 + offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate }, 1.1226 + { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.1227 + offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate }, 1.1228 + { 0 } 1.1229 +}; 1.1230 + 1.1231 +const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] = 1.1232 +{ 1.1233 + { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets), 1.1234 + SEC_PKCS12SecretItemTemplate }, 1.1235 +}; 1.1236 + 1.1237 +const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] = 1.1238 +{ 1.1239 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, 1.1240 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN , offsetof(SEC_PKCS12MacData, safeMac), 1.1241 + SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, 1.1242 + { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) }, 1.1243 + { 0 } 1.1244 +}; 1.1245 + 1.1246 +const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] = 1.1247 +{ 1.1248 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, 1.1249 + { SEC_ASN1_OPTIONAL | 1.1250 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1251 + offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate }, 1.1252 + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.1253 + offsetof(SEC_PKCS12PFXItem, authSafe), 1.1254 + sec_PKCS7ContentInfoTemplate }, 1.1255 + { 0 } 1.1256 +}; 1.1257 + 1.1258 +const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] = 1.1259 +{ 1.1260 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, 1.1261 + { SEC_ASN1_OPTIONAL | 1.1262 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 1.1263 + offsetof(SEC_PKCS12PFXItem, old_safeMac), 1.1264 + SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, 1.1265 + { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING, 1.1266 + offsetof(SEC_PKCS12PFXItem, old_macSalt) }, 1.1267 + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.1268 + offsetof(SEC_PKCS12PFXItem, authSafe), 1.1269 + sec_PKCS7ContentInfoTemplate }, 1.1270 + { 0 } 1.1271 +}; 1.1272 + 1.1273 +const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] = 1.1274 +{ 1.1275 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) }, 1.1276 + { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, 1.1277 + offsetof(SEC_PKCS12AuthenticatedSafe, version) }, 1.1278 + { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID, 1.1279 + offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) }, 1.1280 + { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL, 1.1281 + offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) }, 1.1282 + { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF, 1.1283 + offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags), 1.1284 + SEC_PKCS12BaggageItemTemplate }, 1.1285 + { SEC_ASN1_POINTER, 1.1286 + offsetof(SEC_PKCS12AuthenticatedSafe, safe), 1.1287 + sec_PKCS7ContentInfoTemplate }, 1.1288 + { 0 } 1.1289 +}; 1.1290 + 1.1291 +const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] = 1.1292 +{ 1.1293 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) }, 1.1294 + { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, 1.1295 + offsetof(SEC_PKCS12AuthenticatedSafe, version) }, 1.1296 + { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, 1.1297 + offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) }, 1.1298 + { SEC_ASN1_BIT_STRING, 1.1299 + offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) }, 1.1300 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 1.1301 + SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.1302 + offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage), 1.1303 + SEC_PKCS12BaggageTemplate_OLD }, 1.1304 + { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.1305 + offsetof(SEC_PKCS12AuthenticatedSafe, old_safe), 1.1306 + sec_PKCS7ContentInfoTemplate }, 1.1307 + { 0 } 1.1308 +}; 1.1309 + 1.1310 +const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] = 1.1311 +{ 1.1312 + { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate } 1.1313 +}; 1.1314 + 1.1315 +const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] = 1.1316 +{ 1.1317 + { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD } 1.1318 +}; 1.1319 + 1.1320 +const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] = 1.1321 +{ 1.1322 + { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate } 1.1323 +}; 1.1324 + 1.1325 +const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] = 1.1326 +{ 1.1327 + { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate } 1.1328 +}; 1.1329 + 1.1330 +const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] = 1.1331 +{ 1.1332 + { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD } 1.1333 +}; 1.1334 + 1.1335 +const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] = 1.1336 +{ 1.1337 + { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate } 1.1338 +}; 1.1339 + 1.1340 +const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] = 1.1341 +{ 1.1342 + { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate } 1.1343 +}; 1.1344 + 1.1345 +