Back to index

lightning-sunbird  0.9+nobinonly
p12local.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nssrenam.h"
00038 #include "pkcs12.h"
00039 #include "secpkcs7.h"
00040 #include "secasn1.h"
00041 #include "seccomon.h"
00042 #include "secoid.h"
00043 #include "sechash.h"
00044 #include "secitem.h"
00045 #include "secerr.h"
00046 #include "pk11func.h"
00047 #include "p12local.h"
00048 #include "p12.h"
00049 
00050 #define SALT_LENGTH  16
00051 
00052 SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate)
00053 SEC_ASN1_MKSUB(sgn_DigestInfoTemplate)
00054 
00055 CK_MECHANISM_TYPE
00056 sec_pkcs12_algtag_to_mech(SECOidTag algtag)
00057 {
00058     switch (algtag) {
00059     case SEC_OID_MD2:
00060        return CKM_MD2_HMAC;
00061     case SEC_OID_MD5:
00062        return CKM_MD5_HMAC;
00063     case SEC_OID_SHA1:
00064        return CKM_SHA_1_HMAC;
00065     case SEC_OID_SHA256:
00066        return CKM_SHA256_HMAC;
00067     case SEC_OID_SHA384:
00068        return CKM_SHA384_HMAC;
00069     case SEC_OID_SHA512:
00070        return CKM_SHA512_HMAC;
00071     default:
00072        break;
00073     }
00074     return CKM_INVALID_MECHANISM;
00075 }
00076 
00077 /* helper functions */
00078 /* returns proper bag type template based upon object type tag */
00079 const SEC_ASN1Template *
00080 sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding)
00081 {
00082     const SEC_ASN1Template *theTemplate;
00083     SEC_PKCS12SafeBag *safebag;
00084     SECOidData *oiddata;
00085 
00086     if (src_or_dest == NULL) {
00087        return NULL;
00088     }
00089 
00090     safebag = (SEC_PKCS12SafeBag*)src_or_dest;
00091 
00092     oiddata = safebag->safeBagTypeTag;
00093     if (oiddata == NULL) {
00094        oiddata = SECOID_FindOID(&safebag->safeBagType);
00095        safebag->safeBagTypeTag = oiddata;
00096     }
00097 
00098     switch (oiddata->offset) {
00099        default:
00100            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
00101            break;
00102        case SEC_OID_PKCS12_KEY_BAG_ID:
00103            theTemplate = SEC_PointerToPKCS12KeyBagTemplate;
00104            break;
00105        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
00106            theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD;
00107            break;
00108         case SEC_OID_PKCS12_SECRET_BAG_ID:
00109            theTemplate = SEC_PointerToPKCS12SecretBagTemplate;
00110            break;
00111     }
00112     return theTemplate;
00113 }
00114 
00115 const SEC_ASN1Template *
00116 sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding)
00117 {
00118     const SEC_ASN1Template *theTemplate;
00119     SEC_PKCS12SafeBag *safebag;
00120     SECOidData *oiddata;
00121 
00122     if (src_or_dest == NULL) {
00123        return NULL;
00124     }
00125 
00126     safebag = (SEC_PKCS12SafeBag*)src_or_dest;
00127 
00128     oiddata = safebag->safeBagTypeTag;
00129     if (oiddata == NULL) {
00130        oiddata = SECOID_FindOID(&safebag->safeBagType);
00131        safebag->safeBagTypeTag = oiddata;
00132     }
00133 
00134     switch (oiddata->offset) {
00135        default:
00136            theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
00137            break;
00138        case SEC_OID_PKCS12_KEY_BAG_ID:
00139            theTemplate = SEC_PKCS12PrivateKeyBagTemplate;
00140            break;
00141        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
00142            theTemplate = SEC_PKCS12CertAndCRLBagTemplate;
00143            break;
00144         case SEC_OID_PKCS12_SECRET_BAG_ID:
00145            theTemplate = SEC_PKCS12SecretBagTemplate;
00146            break;
00147     }
00148     return theTemplate;
00149 }
00150 
00151 /* returns proper cert crl template based upon type tag */
00152 const SEC_ASN1Template *
00153 sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding)
00154 {
00155     const SEC_ASN1Template *theTemplate;
00156     SEC_PKCS12CertAndCRL *certbag;
00157     SECOidData *oiddata;
00158 
00159     if (src_or_dest == NULL) {
00160        return NULL;
00161     }
00162 
00163     certbag = (SEC_PKCS12CertAndCRL*)src_or_dest;
00164     oiddata = certbag->BagTypeTag;
00165     if (oiddata == NULL) {
00166        oiddata = SECOID_FindOID(&certbag->BagID);
00167        certbag->BagTypeTag = oiddata;
00168     }
00169 
00170     switch (oiddata->offset) {
00171        default:
00172            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
00173            break;
00174        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
00175            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD;
00176            break;
00177        case SEC_OID_PKCS12_SDSI_CERT_BAG:
00178            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
00179            break;
00180     }
00181     return theTemplate;
00182 }
00183 
00184 const SEC_ASN1Template *
00185 sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding)
00186 {
00187     const SEC_ASN1Template *theTemplate;
00188     SEC_PKCS12CertAndCRL *certbag;
00189     SECOidData *oiddata;
00190 
00191     if (src_or_dest == NULL) {
00192        return NULL;
00193     }
00194 
00195     certbag = (SEC_PKCS12CertAndCRL*)src_or_dest;
00196     oiddata = certbag->BagTypeTag;
00197     if (oiddata == NULL) {
00198        oiddata = SECOID_FindOID(&certbag->BagID);
00199        certbag->BagTypeTag = oiddata;
00200     }
00201 
00202     switch (oiddata->offset) {
00203        default:
00204            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
00205            break;
00206        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
00207            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate;
00208            break;
00209        case SEC_OID_PKCS12_SDSI_CERT_BAG:
00210            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
00211            break;
00212     }
00213     return theTemplate;
00214 }
00215 
00216 /* returns appropriate shroud template based on object type tag */
00217 const SEC_ASN1Template *
00218 sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding)
00219 {
00220     const SEC_ASN1Template *theTemplate;
00221     SEC_PKCS12ESPVKItem *espvk;
00222     SECOidData *oiddata;
00223 
00224     if (src_or_dest == NULL) {
00225        return NULL;
00226     }
00227 
00228     espvk = (SEC_PKCS12ESPVKItem*)src_or_dest;
00229     oiddata = espvk->espvkTag;
00230     if (oiddata == NULL) {
00231        oiddata = SECOID_FindOID(&espvk->espvkOID);
00232        espvk->espvkTag = oiddata;
00233     }
00234 
00235     switch (oiddata->offset) {
00236        default:
00237            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
00238            break;
00239        case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING:
00240           theTemplate = 
00241               SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate);
00242            break;
00243     }
00244     return theTemplate;
00245 }
00246 
00247 /* generate SALT  placing it into the character array passed in.
00248  * it is assumed that salt_dest is an array of appropriate size
00249  * XXX We might want to generate our own random context
00250  */
00251 SECItem *
00252 sec_pkcs12_generate_salt(void)
00253 {
00254     SECItem *salt;
00255 
00256     salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
00257     if(salt == NULL) {
00258        PORT_SetError(SEC_ERROR_NO_MEMORY);
00259        return NULL;
00260     }
00261     salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * 
00262                                          SALT_LENGTH);
00263     salt->len = SALT_LENGTH;
00264     if(salt->data == NULL) {
00265        PORT_SetError(SEC_ERROR_NO_MEMORY);
00266        SECITEM_ZfreeItem(salt, PR_TRUE);
00267        return NULL;
00268     }
00269 
00270     PK11_GenerateRandom(salt->data, salt->len);
00271 
00272     return salt;
00273 }
00274 
00275 /* generate KEYS -- as per PKCS12 section 7.  
00276  * only used for MAC
00277  */
00278 SECItem *
00279 sec_pkcs12_generate_key_from_password(SECOidTag algorithm, 
00280                                   SECItem *salt, 
00281                                   SECItem *password) 
00282 {
00283     unsigned char *pre_hash=NULL;
00284     unsigned char *hash_dest=NULL;
00285     SECStatus res;
00286     PRArenaPool *poolp;
00287     SECItem *key = NULL;
00288     int key_len = 0;
00289 
00290     if((salt == NULL) || (password == NULL)) {
00291        return NULL;
00292     }
00293 
00294     poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00295     if(poolp == NULL) {
00296        PORT_SetError(SEC_ERROR_NO_MEMORY);
00297        return NULL;
00298     }
00299 
00300     pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * 
00301                                            (salt->len+password->len));
00302     if(pre_hash == NULL) {
00303        PORT_SetError(SEC_ERROR_NO_MEMORY);
00304        goto loser;
00305     }
00306 
00307     hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp, 
00308                                    sizeof(unsigned char) * SHA1_LENGTH);
00309     if(hash_dest == NULL) {
00310        PORT_SetError(SEC_ERROR_NO_MEMORY);
00311        goto loser;
00312     }
00313 
00314     PORT_Memcpy(pre_hash, salt->data, salt->len);
00315     /* handle password of 0 length case */
00316     if(password->len > 0) {
00317        PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
00318     }
00319 
00320     res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash, 
00321                        (salt->len+password->len));
00322     if(res == SECFailure) {
00323        PORT_SetError(SEC_ERROR_NO_MEMORY);
00324        goto loser;
00325     }
00326 
00327     switch(algorithm) {
00328        case SEC_OID_SHA1:
00329            if(key_len == 0)
00330               key_len = 16;
00331            key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
00332            if(key == NULL) {
00333               PORT_SetError(SEC_ERROR_NO_MEMORY);
00334               goto loser;
00335            }
00336            key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) 
00337                                                * key_len);
00338            if(key->data == NULL) {
00339               PORT_SetError(SEC_ERROR_NO_MEMORY);
00340               goto loser;
00341            }
00342            key->len = key_len;
00343            PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH-key->len], key->len);
00344            break;
00345        default:
00346            goto loser;
00347            break;
00348     }
00349 
00350     PORT_FreeArena(poolp, PR_TRUE);
00351     return key;
00352 
00353 loser:
00354     PORT_FreeArena(poolp, PR_TRUE);
00355     if(key != NULL) {
00356        SECITEM_ZfreeItem(key, PR_TRUE);
00357     }
00358     return NULL;
00359 }
00360 
00361 /* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
00362  * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
00363  * because it is not known how long the message actually is.  String
00364  * manipulation routines will not necessarily work because msg may have
00365  * imbedded NULLs
00366  */
00367 static SECItem *
00368 sec_pkcs12_generate_old_mac(SECItem *key, 
00369                          SECItem *msg)
00370 {
00371     SECStatus res;
00372     PRArenaPool *temparena = NULL;
00373     unsigned char *hash_dest=NULL, *hash_src1=NULL, *hash_src2 = NULL;
00374     int i;
00375     SECItem *mac = NULL;
00376 
00377     if((key == NULL) || (msg == NULL))
00378         goto loser;
00379 
00380     /* allocate return item */
00381     mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
00382     if(mac == NULL)
00383        return NULL;
00384     mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char)
00385        * SHA1_LENGTH);
00386     mac->len = SHA1_LENGTH;
00387     if(mac->data == NULL)
00388        goto loser;
00389 
00390     /* allocate temporary items */
00391     temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00392     if(temparena == NULL)
00393        goto loser;
00394 
00395     hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
00396        sizeof(unsigned char) * (16+msg->len));
00397     if(hash_src1 == NULL)
00398         goto loser;
00399 
00400     hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
00401        sizeof(unsigned char) * (SHA1_LENGTH+16));
00402     if(hash_src2 == NULL)
00403         goto loser;
00404 
00405     hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena, 
00406        sizeof(unsigned char) * SHA1_LENGTH);
00407     if(hash_dest == NULL)
00408         goto loser;
00409 
00410     /* perform mac'ing as per PKCS 12 */
00411 
00412     /* first round of hashing */
00413     for(i = 0; i < 16; i++)
00414        hash_src1[i] = key->data[i] ^ 0x36;
00415     PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
00416     res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16+msg->len));
00417     if(res == SECFailure)
00418        goto loser;
00419 
00420     /* second round of hashing */
00421     for(i = 0; i < 16; i++)
00422        hash_src2[i] = key->data[i] ^ 0x5c;
00423     PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
00424     res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH+16);
00425     if(res == SECFailure)
00426        goto loser;
00427 
00428     PORT_FreeArena(temparena, PR_TRUE);
00429     return mac;
00430 
00431 loser:
00432     if(temparena != NULL)
00433        PORT_FreeArena(temparena, PR_TRUE);
00434     if(mac != NULL)
00435        SECITEM_ZfreeItem(mac, PR_TRUE);
00436     return NULL;
00437 }
00438 
00439 /* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
00440  * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
00441  * because it is not known how long the message actually is.  String
00442  * manipulation routines will not necessarily work because msg may have
00443  * imbedded NULLs
00444  */
00445 SECItem *
00446 sec_pkcs12_generate_mac(SECItem *key, 
00447                      SECItem *msg,
00448                      PRBool old_method)
00449 {
00450     SECStatus res = SECFailure;
00451     SECItem *mac = NULL;
00452     PK11Context *pk11cx = NULL;    
00453     SECItem ignore = {0};
00454 
00455     if((key == NULL) || (msg == NULL)) {
00456        return NULL;
00457     }
00458 
00459     if(old_method == PR_TRUE) {
00460        return sec_pkcs12_generate_old_mac(key, msg);
00461     }
00462 
00463     /* allocate return item */
00464     mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH);
00465     if (mac == NULL) {
00466        return NULL;
00467     }
00468 
00469     pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive,
00470                                         CKA_SIGN, key, &ignore, NULL);
00471     if (pk11cx == NULL) {
00472        goto loser;
00473     }
00474 
00475     res = PK11_DigestBegin(pk11cx);
00476     if (res == SECFailure) {
00477        goto loser;
00478     }
00479 
00480     res = PK11_DigestOp(pk11cx, msg->data, msg->len);
00481     if (res == SECFailure) {
00482        goto loser;
00483     }
00484 
00485     res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH);
00486     if (res == SECFailure) {
00487        goto loser;
00488     }
00489 
00490     PK11_DestroyContext(pk11cx, PR_TRUE);
00491     pk11cx = NULL;
00492 
00493 loser:
00494 
00495     if(res != SECSuccess) {
00496        SECITEM_ZfreeItem(mac, PR_TRUE);
00497        mac = NULL;
00498        if (pk11cx) {
00499            PK11_DestroyContext(pk11cx, PR_TRUE);
00500        }
00501     }
00502 
00503     return mac;
00504 }
00505 
00506 /* compute the thumbprint of the DER cert and create a digest info
00507  * to store it in and return the digest info.
00508  * a return of NULL indicates an error.
00509  */
00510 SGNDigestInfo *
00511 sec_pkcs12_compute_thumbprint(SECItem *der_cert)
00512 {
00513     SGNDigestInfo *thumb = NULL;
00514     SECItem digest;
00515     PRArenaPool *temparena = NULL;
00516     SECStatus rv = SECFailure;
00517 
00518     if(der_cert == NULL)
00519        return NULL;
00520 
00521     temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
00522     if(temparena == NULL) {
00523        return NULL;
00524     }
00525 
00526     digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
00527                                               sizeof(unsigned char) * 
00528                                               SHA1_LENGTH);
00529     /* digest data and create digest info */
00530     if(digest.data != NULL) {
00531        digest.len = SHA1_LENGTH;
00532        rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data, 
00533                          der_cert->len);
00534        if(rv == SECSuccess) {
00535            thumb = SGN_CreateDigestInfo(SEC_OID_SHA1, 
00536                                     digest.data, 
00537                                     digest.len);
00538        } else {
00539            PORT_SetError(SEC_ERROR_NO_MEMORY);
00540        }
00541     } else {
00542        PORT_SetError(SEC_ERROR_NO_MEMORY);
00543     }
00544 
00545     PORT_FreeArena(temparena, PR_TRUE);
00546 
00547     return thumb;
00548 }
00549 
00550 /* create a virtual password per PKCS 12, the password is converted
00551  * to unicode, the salt is prepended to it, and then the whole thing
00552  * is returned */
00553 SECItem *
00554 sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt,
00555                                PRBool swap)
00556 {
00557     SECItem uniPwd = {siBuffer, NULL,0}, *retPwd = NULL;
00558 
00559     if((password == NULL) || (salt == NULL)) {
00560        return NULL;
00561     }
00562 
00563     if(password->len == 0) {
00564        uniPwd.data = (unsigned char*)PORT_ZAlloc(2);
00565        uniPwd.len = 2;
00566        if(!uniPwd.data) {
00567            return NULL;
00568        }
00569     } else {
00570        uniPwd.data = (unsigned char*)PORT_ZAlloc(password->len * 3);
00571        uniPwd.len = password->len * 3;
00572        if(!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
00573                             uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
00574            SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
00575            return NULL;
00576        }
00577     }
00578 
00579     retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
00580     if(retPwd == NULL) {
00581        goto loser;
00582     }
00583 
00584     /* allocate space and copy proper data */
00585     retPwd->len = uniPwd.len + salt->len;
00586     retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len);
00587     if(retPwd->data == NULL) {
00588        PORT_Free(retPwd);
00589        goto loser;
00590     }
00591 
00592     PORT_Memcpy(retPwd->data, salt->data, salt->len);
00593     PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len);
00594 
00595     SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
00596 
00597     return retPwd;
00598 
00599 loser:
00600     PORT_SetError(SEC_ERROR_NO_MEMORY);
00601     SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
00602     return NULL;
00603 }
00604 
00605 /* appends a shrouded key to a key bag.  this is used for exporting
00606  * to store externally wrapped keys.  it is used when importing to convert
00607  * old items to new
00608  */
00609 SECStatus 
00610 sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag,
00611                             SEC_PKCS12ESPVKItem *espvk)
00612 {
00613     int size;
00614     void *mark = NULL, *dummy = NULL;
00615 
00616     if((bag == NULL) || (espvk == NULL))
00617        return SECFailure;
00618 
00619     mark = PORT_ArenaMark(bag->poolp);
00620 
00621     /* grow the list */
00622     size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *);
00623     dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp,
00624                                    bag->espvks, size, 
00625                                    size + sizeof(SEC_PKCS12ESPVKItem *));
00626     bag->espvks = (SEC_PKCS12ESPVKItem**)dummy;
00627     if(dummy == NULL) {
00628        PORT_SetError(SEC_ERROR_NO_MEMORY);
00629        goto loser;
00630     }
00631 
00632     bag->espvks[bag->nEspvks] = espvk;
00633     bag->nEspvks++;
00634     bag->espvks[bag->nEspvks] = NULL;
00635 
00636     PORT_ArenaUnmark(bag->poolp, mark);
00637     return SECSuccess;
00638 
00639 loser:
00640     PORT_ArenaRelease(bag->poolp, mark);
00641     return SECFailure;
00642 }
00643 
00644 /* search a certificate list for a nickname, a thumbprint, or both
00645  * within a certificate bag.  if the certificate could not be
00646  * found or an error occurs, NULL is returned;
00647  */
00648 static SEC_PKCS12CertAndCRL *
00649 sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
00650                             SECItem *nickname, SGNDigestInfo *thumbprint)
00651 {
00652     PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
00653     int i, j;
00654 
00655     if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
00656        return NULL;
00657     }
00658 
00659     if(thumbprint && nickname) {
00660        search_both = PR_TRUE;
00661     }
00662 
00663     if(nickname) {
00664        search_nickname = PR_TRUE;
00665     }
00666 
00667 search_again:  
00668     i = 0;
00669     while(certbag->certAndCRLs[i] != NULL) {
00670        SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];
00671 
00672        if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {
00673 
00674            /* check nicknames */
00675            if(search_nickname) {
00676               if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
00677                   return cert;
00678               }
00679            } else {
00680            /* check thumbprints */
00681               SECItem **derCertList;
00682 
00683               /* get pointer to certificate list, does not need to
00684                * be freed since it is within the arena which will
00685                * be freed later.
00686                */
00687               derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
00688               j = 0;
00689               if(derCertList != NULL) {
00690                   while(derCertList[j] != NULL) {
00691                      SECComparison eq;
00692                      SGNDigestInfo *di;
00693                      di = sec_pkcs12_compute_thumbprint(derCertList[j]);
00694                      if(di) {
00695                          eq = SGN_CompareDigestInfo(thumbprint, di);
00696                          SGN_DestroyDigestInfo(di);
00697                          if(eq == SECEqual) {
00698                             /* copy the derCert for later reference */
00699                             cert->value.x509->derLeafCert = derCertList[j];
00700                             return cert;
00701                          }
00702                      } else {
00703                          /* an error occurred */
00704                          return NULL;
00705                      }
00706                      j++;
00707                   }
00708               }
00709            }
00710        }
00711 
00712        i++;
00713     }
00714 
00715     if(search_both) {
00716        search_both = PR_FALSE;
00717        search_nickname = PR_FALSE;
00718        goto search_again;
00719     }
00720 
00721     return NULL;
00722 }
00723 
00724 /* search a key list for a nickname, a thumbprint, or both
00725  * within a key bag.  if the key could not be
00726  * found or an error occurs, NULL is returned;
00727  */
00728 static SEC_PKCS12PrivateKey *
00729 sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag,
00730                            SECItem *nickname, SGNDigestInfo *thumbprint)
00731 {
00732     PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
00733     int i, j;
00734 
00735     if((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
00736        return NULL;
00737     }
00738 
00739     if(keybag->privateKeys == NULL) {
00740        return NULL;
00741     }
00742 
00743     if(thumbprint && nickname) {
00744        search_both = PR_TRUE;
00745     }
00746 
00747     if(nickname) {
00748        search_nickname = PR_TRUE;
00749     }
00750 
00751 search_again:  
00752     i = 0;
00753     while(keybag->privateKeys[i] != NULL) {
00754        SEC_PKCS12PrivateKey *key = keybag->privateKeys[i];
00755 
00756        /* check nicknames */
00757        if(search_nickname) {
00758            if(SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) {
00759               return key;
00760            }
00761        } else {
00762            /* check digests */
00763            SGNDigestInfo **assocCerts = key->pvkData.assocCerts;
00764            if((assocCerts == NULL) || (assocCerts[0] == NULL)) {
00765               return NULL;
00766            }
00767 
00768            j = 0;
00769            while(assocCerts[j] != NULL) {
00770               SECComparison eq;
00771               eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]);
00772               if(eq == SECEqual) {
00773                   return key;
00774               }
00775               j++;
00776            }
00777        }
00778        i++;
00779     }
00780 
00781     if(search_both) {
00782        search_both = PR_FALSE;
00783        search_nickname = PR_FALSE;
00784        goto search_again;
00785     }
00786 
00787     return NULL;
00788 }
00789 
00790 /* seach the safe first then try the baggage bag 
00791  *  safe and bag contain certs and keys to search
00792  *  objType is the object type to look for
00793  *  bagType is the type of bag that was found by sec_pkcs12_find_object
00794  *  index is the entity in safe->safeContents or bag->unencSecrets which
00795  *    is being searched
00796  *  nickname and thumbprint are the search criteria
00797  * 
00798  * a return of null indicates no match
00799  */
00800 static void *
00801 sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe,
00802                 SEC_PKCS12BaggageItem *bag,
00803                 SECOidTag objType, SECOidTag bagType, int index,
00804                 SECItem *nickname, SGNDigestInfo *thumbprint)
00805 {
00806     PRBool searchSafe;
00807     int i = index;
00808 
00809     if((safe == NULL) && (bag == NULL)) {
00810        return NULL;
00811     }
00812 
00813     searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE);
00814     switch(objType) {
00815        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
00816            if(objType == bagType) {
00817               SEC_PKCS12CertAndCRLBag *certBag;
00818 
00819               if(searchSafe) {
00820                   certBag = safe->contents[i]->safeContent.certAndCRLBag;
00821               } else {
00822                   certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag;
00823               }
00824               return sec_pkcs12_find_cert_in_certbag(certBag, nickname, 
00825                                                  thumbprint);
00826            }
00827            break;
00828        case SEC_OID_PKCS12_KEY_BAG_ID:
00829            if(objType == bagType) {
00830               SEC_PKCS12PrivateKeyBag *keyBag;
00831 
00832               if(searchSafe) {
00833                   keyBag = safe->contents[i]->safeContent.keyBag;
00834               } else {
00835                   keyBag = bag->unencSecrets[i]->safeContent.keyBag;
00836               }
00837               return sec_pkcs12_find_key_in_keybag(keyBag, nickname, 
00838                                                   thumbprint);
00839            }
00840            break;
00841        default:
00842            break;
00843     }
00844 
00845     return NULL;
00846 }
00847 
00848 /* searches both the baggage and the safe areas looking for
00849  * object of specified type matching either the nickname or the 
00850  * thumbprint specified.
00851  *
00852  * safe and baggage store certs and keys
00853  * objType is the OID for the bag type to be searched:
00854  *   SEC_OID_PKCS12_KEY_BAG_ID, or 
00855  *   SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID
00856  * nickname and thumbprint are the search criteria
00857  * 
00858  * if no match found, NULL returned and error set
00859  */
00860 void *
00861 sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe,
00862                      SEC_PKCS12Baggage *baggage,
00863                      SECOidTag objType,
00864                      SECItem *nickname,
00865                      SGNDigestInfo *thumbprint)
00866 {
00867     int i, j;
00868     void *retItem;
00869    
00870     if(((safe == NULL) && (thumbprint == NULL)) ||
00871        ((nickname == NULL) && (thumbprint == NULL))) {
00872        return NULL;
00873     }    
00874 
00875     i = 0;
00876     if((safe != NULL) && (safe->contents != NULL)) {
00877        while(safe->contents[i] != NULL) {
00878            SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType);
00879            retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i,
00880                                      nickname, thumbprint);
00881            if(retItem != NULL) {
00882               return retItem;
00883            }
00884            i++;
00885        }
00886     }
00887 
00888     if((baggage != NULL) && (baggage->bags != NULL)) {
00889        i = 0;
00890        while(baggage->bags[i] != NULL) {
00891            SEC_PKCS12BaggageItem *xbag = baggage->bags[i];
00892            j = 0;
00893            if(xbag->unencSecrets != NULL) {
00894               while(xbag->unencSecrets[j] != NULL) {
00895                   SECOidTag bagType;
00896                   bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType);
00897                   retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType,
00898                                             j, nickname, thumbprint);
00899                   if(retItem != NULL) {
00900                      return retItem;
00901                   }
00902                   j++;
00903               }
00904            }
00905            i++;
00906        }
00907     }
00908 
00909     PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);
00910     return NULL;
00911 }
00912 
00913 /* this function converts a password to unicode and encures that the 
00914  * required double 0 byte be placed at the end of the string
00915  */
00916 PRBool
00917 sec_pkcs12_convert_item_to_unicode(PRArenaPool *arena, SECItem *dest,
00918                                SECItem *src, PRBool zeroTerm,
00919                                PRBool asciiConvert, PRBool toUnicode)
00920 {
00921     PRBool success = PR_FALSE;
00922     if(!src || !dest) {
00923        return PR_FALSE;
00924     }
00925 
00926     dest->len = src->len * 3 + 2;
00927     if(arena) {
00928        dest->data = (unsigned char*)PORT_ArenaZAlloc(arena, dest->len);
00929     } else {
00930        dest->data = (unsigned char*)PORT_ZAlloc(dest->len);
00931     }
00932 
00933     if(!dest->data) {
00934        dest->len = 0;
00935        return PR_FALSE;
00936     }
00937 
00938     if(!asciiConvert) {
00939        success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data,
00940                                       dest->len, &dest->len);
00941     } else {
00942 #ifndef IS_LITTLE_ENDIAN
00943        PRBool swapUnicode = PR_FALSE;
00944 #else
00945        PRBool swapUnicode = PR_TRUE;
00946 #endif
00947        success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data,
00948                                        dest->len, &dest->len, swapUnicode);
00949     }
00950 
00951     if(!success) {
00952        if(!arena) {
00953            PORT_Free(dest->data);
00954            dest->data = NULL;
00955            dest->len = 0;
00956        }
00957        return PR_FALSE;
00958     }
00959 
00960     if((dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) {
00961        if(dest->len + 2 > 3 * src->len) {
00962            if(arena) {
00963               dest->data = (unsigned char*)PORT_ArenaGrow(arena, 
00964                                                dest->data, dest->len,
00965                                                dest->len + 2);
00966            } else {
00967               dest->data = (unsigned char*)PORT_Realloc(dest->data, 
00968                                                    dest->len + 2);
00969            }
00970 
00971            if(!dest->data) {
00972               return PR_FALSE;
00973            }
00974        }
00975        dest->len += 2;
00976        dest->data[dest->len-1] = dest->data[dest->len-2] = 0;
00977     }
00978 
00979     return PR_TRUE;
00980 }
00981 
00982 /* pkcs 12 templates */
00983 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
00984     sec_pkcs12_choose_shroud_type;
00985 
00986 const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] =
00987 {
00988     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
00989     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
00990     { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) },
00991     { 0 }
00992 };
00993 
00994 const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] =
00995 {
00996     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
00997     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
00998     { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) },
00999     { 0 }
01000 };
01001 
01002 const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] =
01003 {
01004     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
01005        SEC_PKCS12CodedCertBagTemplate },
01006 };
01007 
01008 const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] = 
01009 {
01010     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
01011     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
01012     { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
01013        SEC_PKCS12PVKSupportingDataTemplate_OLD },
01014     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
01015        SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
01016        &sec_pkcs12_shroud_chooser },
01017     { 0 }
01018 };
01019 
01020 const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] = 
01021 {
01022     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
01023     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
01024     { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
01025        SEC_PKCS12PVKSupportingDataTemplate },
01026     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
01027        SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
01028        &sec_pkcs12_shroud_chooser },
01029     { 0 }
01030 };
01031 
01032 const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] =
01033 {
01034     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) },
01035     { SEC_ASN1_OBJECT_ID, 
01036        offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) },
01037     { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
01038        offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) },
01039     { 0 }
01040 };
01041 
01042 const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] =
01043 {
01044     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
01045     { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , 
01046         offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
01047        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
01048     { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, 
01049        offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
01050     { SEC_ASN1_PRINTABLE_STRING, 
01051        offsetof(SEC_PKCS12PVKSupportingData, nickname) },
01052     { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
01053        offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
01054     { 0 }
01055 };
01056 
01057 const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] =
01058 {
01059     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
01060     { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , 
01061         offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
01062        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
01063     { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, 
01064        offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
01065     { SEC_ASN1_BMP_STRING, 
01066        offsetof(SEC_PKCS12PVKSupportingData, uniNickName) },
01067     { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
01068        offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
01069     { 0 }
01070 };
01071 
01072 const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] =
01073 {
01074     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) },
01075     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks),
01076        SEC_PKCS12ESPVKItemTemplate },
01077     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
01078        SEC_PKCS12SafeBagTemplate },
01079     /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
01080        SEC_PKCS12CodedSafeBagTemplate }, */
01081     { 0 }
01082 };
01083 
01084 const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] =
01085 {
01086     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags),
01087        SEC_PKCS12BaggageItemTemplate },
01088 };
01089 
01090 const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] =
01091 {
01092     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks),
01093        SEC_PKCS12ESPVKItemTemplate_OLD },
01094 };
01095 
01096 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser =
01097        sec_pkcs12_choose_bag_type;
01098 
01099 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old =
01100        sec_pkcs12_choose_bag_type_old;
01101 
01102 const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] =
01103 {
01104     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
01105     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
01106     { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
01107        SEC_ASN1_CONTEXT_SPECIFIC | 0,
01108         offsetof(SEC_PKCS12SafeBag, safeContent),
01109        &sec_pkcs12_bag_chooser_old },
01110     { 0 }
01111 };
01112 
01113 const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] =
01114 {
01115     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
01116     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
01117     { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER,
01118         offsetof(SEC_PKCS12SafeBag, safeContent),
01119        &sec_pkcs12_bag_chooser },
01120     { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING,
01121        offsetof(SEC_PKCS12SafeBag, uniSafeBagName) },
01122     { 0 }
01123 };
01124 
01125 const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] =
01126 {
01127     { SEC_ASN1_SET_OF,
01128        offsetof(SEC_PKCS12SafeContents, contents),
01129        SEC_PKCS12SafeBagTemplate_OLD }
01130 };
01131 
01132 const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] =
01133 {
01134     { SEC_ASN1_SET_OF,
01135        offsetof(SEC_PKCS12SafeContents, contents),
01136        SEC_PKCS12SafeBagTemplate }  /* here */
01137 };
01138 
01139 const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] =
01140 {
01141     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) },
01142     { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData),
01143        SEC_PKCS12PVKSupportingDataTemplate },
01144     { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 
01145         offsetof(SEC_PKCS12PrivateKey, pkcs8data),
01146        SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) },
01147     { 0 }
01148 };
01149 
01150 const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] =
01151 {
01152     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) },
01153     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys),
01154        SEC_PKCS12PrivateKeyTemplate },
01155     { 0 }
01156 };
01157 
01158 const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] =
01159 {
01160     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
01161     { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
01162        sec_PKCS7ContentInfoTemplate },
01163     { SEC_ASN1_INLINE | SEC_ASN1_XTRN , 
01164         offsetof(SEC_PKCS12X509CertCRL, thumbprint),
01165        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
01166     { 0 }
01167 };
01168 
01169 const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] =
01170 {
01171     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
01172     { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
01173        sec_PKCS7ContentInfoTemplate },
01174     { 0 }
01175 };
01176 
01177 const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] =
01178 {
01179     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
01180     { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) },
01181     { 0 }
01182 };
01183 
01184 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old =
01185        sec_pkcs12_choose_cert_crl_type_old;
01186 
01187 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser =
01188        sec_pkcs12_choose_cert_crl_type;
01189 
01190 const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] =
01191 {
01192     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
01193     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
01194     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT |
01195        SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0,
01196        offsetof(SEC_PKCS12CertAndCRL, value),
01197        &sec_pkcs12_cert_crl_chooser_old },
01198     { 0 }
01199 };
01200 
01201 const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] =
01202 {
01203     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
01204     { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
01205     { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
01206        SEC_ASN1_CONTEXT_SPECIFIC | 0, 
01207        offsetof(SEC_PKCS12CertAndCRL, value),
01208        &sec_pkcs12_cert_crl_chooser },
01209     { 0 }
01210 };
01211 
01212 const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] =
01213 {
01214     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
01215        SEC_PKCS12CertAndCRLTemplate },
01216 };
01217 
01218 const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] =
01219 {
01220     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) },
01221     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
01222        SEC_PKCS12CertAndCRLTemplate_OLD },
01223     { 0 }
01224 };
01225 
01226 const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] =
01227 {
01228     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) },
01229     { SEC_ASN1_OBJECT_ID,
01230        offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) },
01231     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT,
01232        offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) },
01233     { 0 }
01234 };
01235 
01236 const SEC_ASN1Template SEC_PKCS12SecretTemplate[] =
01237 {
01238     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
01239     { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) },
01240     { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) },
01241     { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
01242        offsetof(SEC_PKCS12Secret, secretAdditional),
01243        SEC_PKCS12SecretAdditionalTemplate },
01244     { 0 }
01245 };
01246 
01247 const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] = 
01248 {
01249     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
01250     { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0,
01251        offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate },
01252     { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1,
01253        offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate },
01254     { 0 }
01255 };
01256 
01257 const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] =
01258 {
01259     { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets),
01260        SEC_PKCS12SecretItemTemplate },
01261 };
01262 
01263 const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] =
01264 {
01265     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
01266     { SEC_ASN1_INLINE | SEC_ASN1_XTRN , offsetof(SEC_PKCS12MacData, safeMac),
01267        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
01268     { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) },
01269     { 0 }
01270 };
01271 
01272 const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] =
01273 {
01274     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
01275     { SEC_ASN1_OPTIONAL |
01276        SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
01277        offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate },
01278     { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
01279        offsetof(SEC_PKCS12PFXItem, authSafe), 
01280        sec_PKCS7ContentInfoTemplate },
01281     { 0 }
01282 };
01283 
01284 const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] =
01285 {
01286     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
01287     { SEC_ASN1_OPTIONAL |
01288        SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 
01289        offsetof(SEC_PKCS12PFXItem, old_safeMac), 
01290        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
01291     { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING,
01292        offsetof(SEC_PKCS12PFXItem, old_macSalt) },
01293     { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
01294        offsetof(SEC_PKCS12PFXItem, authSafe), 
01295        sec_PKCS7ContentInfoTemplate },
01296     { 0 }
01297 };
01298 
01299 const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] =
01300 {
01301     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
01302     { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, 
01303        offsetof(SEC_PKCS12AuthenticatedSafe, version) }, 
01304     { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID,
01305        offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
01306     { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
01307        offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
01308     { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF, 
01309        offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags), 
01310        SEC_PKCS12BaggageItemTemplate },
01311     { SEC_ASN1_POINTER,
01312        offsetof(SEC_PKCS12AuthenticatedSafe, safe),
01313        sec_PKCS7ContentInfoTemplate },
01314     { 0 }
01315 };
01316 
01317 const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] =
01318 {
01319     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
01320     { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, 
01321        offsetof(SEC_PKCS12AuthenticatedSafe, version) }, 
01322     { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
01323        offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
01324     { SEC_ASN1_BIT_STRING,
01325        offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
01326     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | 
01327        SEC_ASN1_CONTEXT_SPECIFIC | 0, 
01328        offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage), 
01329        SEC_PKCS12BaggageTemplate_OLD },
01330     { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
01331        offsetof(SEC_PKCS12AuthenticatedSafe, old_safe),
01332        sec_PKCS7ContentInfoTemplate },
01333     { 0 }
01334 };
01335 
01336 const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] =
01337 {
01338     { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate }
01339 };
01340 
01341 const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] =
01342 {
01343     { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD }
01344 };
01345 
01346 const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] =
01347 {
01348     { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate }
01349 };
01350 
01351 const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] =
01352 {
01353     { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate }
01354 };
01355 
01356 const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] =
01357 {
01358     { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD }
01359 };
01360 
01361 const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] =
01362 {
01363     { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate }
01364 };
01365 
01366 const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] =
01367 {
01368     { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate }
01369 };
01370 
01371