mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-10 18:00:15 +01:00
a572ea8ca3
bug1095307, bug1073330(backout), bug1084986, bug1050069, bug942172, bug1054547, bug532081, bug1096348, bug1058870, bug1093940, bug1102985, bug1112461, bug1094492, bug112029, bug1119983, bug1120685, bug1120691, bug1113632, bug863076, bug1082973, bug1124539, bug1117617, bug1117621, bug1121273, bug753136, bug921684, bug1132818, bug1125375, bug647690, bug1055441, bug1134455, bug975010, bug950369, bug1128367, bug1129573, bug1136095, bug1117897, bug1113453, bug1061725, bug1073330, bug1111901, bug1083900, bug1136095, bug1138820, bug1096741, bug1134548, bug345725, bug950348, bug950344, bug1151037, bug991783, bug1153994
1344 lines
36 KiB
C
1344 lines
36 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nssrenam.h"
|
|
#include "pkcs12.h"
|
|
#include "secpkcs7.h"
|
|
#include "secasn1.h"
|
|
#include "seccomon.h"
|
|
#include "secoid.h"
|
|
#include "sechash.h"
|
|
#include "secitem.h"
|
|
#include "secerr.h"
|
|
#include "pk11func.h"
|
|
#include "p12local.h"
|
|
#include "p12.h"
|
|
|
|
#define SALT_LENGTH 16
|
|
|
|
SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate)
|
|
SEC_ASN1_MKSUB(sgn_DigestInfoTemplate)
|
|
|
|
CK_MECHANISM_TYPE
|
|
sec_pkcs12_algtag_to_mech(SECOidTag algtag)
|
|
{
|
|
switch (algtag) {
|
|
case SEC_OID_MD2:
|
|
return CKM_MD2_HMAC;
|
|
case SEC_OID_MD5:
|
|
return CKM_MD5_HMAC;
|
|
case SEC_OID_SHA1:
|
|
return CKM_SHA_1_HMAC;
|
|
case SEC_OID_SHA224:
|
|
return CKM_SHA224_HMAC;
|
|
case SEC_OID_SHA256:
|
|
return CKM_SHA256_HMAC;
|
|
case SEC_OID_SHA384:
|
|
return CKM_SHA384_HMAC;
|
|
case SEC_OID_SHA512:
|
|
return CKM_SHA512_HMAC;
|
|
default:
|
|
break;
|
|
}
|
|
return CKM_INVALID_MECHANISM;
|
|
}
|
|
|
|
/* helper functions */
|
|
/* returns proper bag type template based upon object type tag */
|
|
const SEC_ASN1Template *
|
|
sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding)
|
|
{
|
|
const SEC_ASN1Template *theTemplate;
|
|
SEC_PKCS12SafeBag *safebag;
|
|
SECOidData *oiddata;
|
|
|
|
if (src_or_dest == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
safebag = (SEC_PKCS12SafeBag*)src_or_dest;
|
|
|
|
oiddata = safebag->safeBagTypeTag;
|
|
if (oiddata == NULL) {
|
|
oiddata = SECOID_FindOID(&safebag->safeBagType);
|
|
safebag->safeBagTypeTag = oiddata;
|
|
}
|
|
|
|
switch (oiddata->offset) {
|
|
default:
|
|
theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
|
break;
|
|
case SEC_OID_PKCS12_KEY_BAG_ID:
|
|
theTemplate = SEC_PointerToPKCS12KeyBagTemplate;
|
|
break;
|
|
case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
|
|
theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD;
|
|
break;
|
|
case SEC_OID_PKCS12_SECRET_BAG_ID:
|
|
theTemplate = SEC_PointerToPKCS12SecretBagTemplate;
|
|
break;
|
|
}
|
|
return theTemplate;
|
|
}
|
|
|
|
const SEC_ASN1Template *
|
|
sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding)
|
|
{
|
|
const SEC_ASN1Template *theTemplate;
|
|
SEC_PKCS12SafeBag *safebag;
|
|
SECOidData *oiddata;
|
|
|
|
if (src_or_dest == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
safebag = (SEC_PKCS12SafeBag*)src_or_dest;
|
|
|
|
oiddata = safebag->safeBagTypeTag;
|
|
if (oiddata == NULL) {
|
|
oiddata = SECOID_FindOID(&safebag->safeBagType);
|
|
safebag->safeBagTypeTag = oiddata;
|
|
}
|
|
|
|
switch (oiddata->offset) {
|
|
default:
|
|
theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
|
|
break;
|
|
case SEC_OID_PKCS12_KEY_BAG_ID:
|
|
theTemplate = SEC_PKCS12PrivateKeyBagTemplate;
|
|
break;
|
|
case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
|
|
theTemplate = SEC_PKCS12CertAndCRLBagTemplate;
|
|
break;
|
|
case SEC_OID_PKCS12_SECRET_BAG_ID:
|
|
theTemplate = SEC_PKCS12SecretBagTemplate;
|
|
break;
|
|
}
|
|
return theTemplate;
|
|
}
|
|
|
|
/* returns proper cert crl template based upon type tag */
|
|
const SEC_ASN1Template *
|
|
sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding)
|
|
{
|
|
const SEC_ASN1Template *theTemplate;
|
|
SEC_PKCS12CertAndCRL *certbag;
|
|
SECOidData *oiddata;
|
|
|
|
if (src_or_dest == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
certbag = (SEC_PKCS12CertAndCRL*)src_or_dest;
|
|
oiddata = certbag->BagTypeTag;
|
|
if (oiddata == NULL) {
|
|
oiddata = SECOID_FindOID(&certbag->BagID);
|
|
certbag->BagTypeTag = oiddata;
|
|
}
|
|
|
|
switch (oiddata->offset) {
|
|
default:
|
|
theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
|
break;
|
|
case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
|
|
theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD;
|
|
break;
|
|
case SEC_OID_PKCS12_SDSI_CERT_BAG:
|
|
theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
|
|
break;
|
|
}
|
|
return theTemplate;
|
|
}
|
|
|
|
const SEC_ASN1Template *
|
|
sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding)
|
|
{
|
|
const SEC_ASN1Template *theTemplate;
|
|
SEC_PKCS12CertAndCRL *certbag;
|
|
SECOidData *oiddata;
|
|
|
|
if (src_or_dest == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
certbag = (SEC_PKCS12CertAndCRL*)src_or_dest;
|
|
oiddata = certbag->BagTypeTag;
|
|
if (oiddata == NULL) {
|
|
oiddata = SECOID_FindOID(&certbag->BagID);
|
|
certbag->BagTypeTag = oiddata;
|
|
}
|
|
|
|
switch (oiddata->offset) {
|
|
default:
|
|
theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
|
break;
|
|
case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
|
|
theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate;
|
|
break;
|
|
case SEC_OID_PKCS12_SDSI_CERT_BAG:
|
|
theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
|
|
break;
|
|
}
|
|
return theTemplate;
|
|
}
|
|
|
|
/* returns appropriate shroud template based on object type tag */
|
|
const SEC_ASN1Template *
|
|
sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding)
|
|
{
|
|
const SEC_ASN1Template *theTemplate;
|
|
SEC_PKCS12ESPVKItem *espvk;
|
|
SECOidData *oiddata;
|
|
|
|
if (src_or_dest == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
espvk = (SEC_PKCS12ESPVKItem*)src_or_dest;
|
|
oiddata = espvk->espvkTag;
|
|
if (oiddata == NULL) {
|
|
oiddata = SECOID_FindOID(&espvk->espvkOID);
|
|
espvk->espvkTag = oiddata;
|
|
}
|
|
|
|
switch (oiddata->offset) {
|
|
default:
|
|
theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
|
break;
|
|
case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING:
|
|
theTemplate =
|
|
SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate);
|
|
break;
|
|
}
|
|
return theTemplate;
|
|
}
|
|
|
|
/* generate SALT placing it into the character array passed in.
|
|
* it is assumed that salt_dest is an array of appropriate size
|
|
* XXX We might want to generate our own random context
|
|
*/
|
|
SECItem *
|
|
sec_pkcs12_generate_salt(void)
|
|
{
|
|
SECItem *salt;
|
|
|
|
salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
|
|
if(salt == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
return NULL;
|
|
}
|
|
salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
|
|
SALT_LENGTH);
|
|
salt->len = SALT_LENGTH;
|
|
if(salt->data == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
SECITEM_ZfreeItem(salt, PR_TRUE);
|
|
return NULL;
|
|
}
|
|
|
|
PK11_GenerateRandom(salt->data, salt->len);
|
|
|
|
return salt;
|
|
}
|
|
|
|
/* generate KEYS -- as per PKCS12 section 7.
|
|
* only used for MAC
|
|
*/
|
|
SECItem *
|
|
sec_pkcs12_generate_key_from_password(SECOidTag algorithm,
|
|
SECItem *salt,
|
|
SECItem *password)
|
|
{
|
|
unsigned char *pre_hash=NULL;
|
|
unsigned char *hash_dest=NULL;
|
|
SECStatus res;
|
|
PLArenaPool *poolp;
|
|
SECItem *key = NULL;
|
|
int key_len = 0;
|
|
|
|
if((salt == NULL) || (password == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if(poolp == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
return NULL;
|
|
}
|
|
|
|
pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) *
|
|
(salt->len+password->len));
|
|
if(pre_hash == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
|
|
hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp,
|
|
sizeof(unsigned char) * SHA1_LENGTH);
|
|
if(hash_dest == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
|
|
PORT_Memcpy(pre_hash, salt->data, salt->len);
|
|
/* handle password of 0 length case */
|
|
if(password->len > 0) {
|
|
PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
|
|
}
|
|
|
|
res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash,
|
|
(salt->len+password->len));
|
|
if(res == SECFailure) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
|
|
switch(algorithm) {
|
|
case SEC_OID_SHA1:
|
|
if(key_len == 0)
|
|
key_len = 16;
|
|
key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
|
|
if(key == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char)
|
|
* key_len);
|
|
if(key->data == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
key->len = key_len;
|
|
PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH-key->len], key->len);
|
|
break;
|
|
default:
|
|
goto loser;
|
|
break;
|
|
}
|
|
|
|
PORT_FreeArena(poolp, PR_TRUE);
|
|
return key;
|
|
|
|
loser:
|
|
PORT_FreeArena(poolp, PR_TRUE);
|
|
if(key != NULL) {
|
|
SECITEM_ZfreeItem(key, PR_TRUE);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* MAC is generated per PKCS 12 section 6. It is expected that key, msg
|
|
* and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in
|
|
* because it is not known how long the message actually is. String
|
|
* manipulation routines will not necessarily work because msg may have
|
|
* imbedded NULLs
|
|
*/
|
|
static SECItem *
|
|
sec_pkcs12_generate_old_mac(SECItem *key,
|
|
SECItem *msg)
|
|
{
|
|
SECStatus res;
|
|
PLArenaPool *temparena = NULL;
|
|
unsigned char *hash_dest=NULL, *hash_src1=NULL, *hash_src2 = NULL;
|
|
int i;
|
|
SECItem *mac = NULL;
|
|
|
|
if((key == NULL) || (msg == NULL))
|
|
goto loser;
|
|
|
|
/* allocate return item */
|
|
mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
|
|
if(mac == NULL)
|
|
return NULL;
|
|
mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char)
|
|
* SHA1_LENGTH);
|
|
mac->len = SHA1_LENGTH;
|
|
if(mac->data == NULL)
|
|
goto loser;
|
|
|
|
/* allocate temporary items */
|
|
temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if(temparena == NULL)
|
|
goto loser;
|
|
|
|
hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
|
|
sizeof(unsigned char) * (16+msg->len));
|
|
if(hash_src1 == NULL)
|
|
goto loser;
|
|
|
|
hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
|
|
sizeof(unsigned char) * (SHA1_LENGTH+16));
|
|
if(hash_src2 == NULL)
|
|
goto loser;
|
|
|
|
hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena,
|
|
sizeof(unsigned char) * SHA1_LENGTH);
|
|
if(hash_dest == NULL)
|
|
goto loser;
|
|
|
|
/* perform mac'ing as per PKCS 12 */
|
|
|
|
/* first round of hashing */
|
|
for(i = 0; i < 16; i++)
|
|
hash_src1[i] = key->data[i] ^ 0x36;
|
|
PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
|
|
res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16+msg->len));
|
|
if(res == SECFailure)
|
|
goto loser;
|
|
|
|
/* second round of hashing */
|
|
for(i = 0; i < 16; i++)
|
|
hash_src2[i] = key->data[i] ^ 0x5c;
|
|
PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
|
|
res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH+16);
|
|
if(res == SECFailure)
|
|
goto loser;
|
|
|
|
PORT_FreeArena(temparena, PR_TRUE);
|
|
return mac;
|
|
|
|
loser:
|
|
if(temparena != NULL)
|
|
PORT_FreeArena(temparena, PR_TRUE);
|
|
if(mac != NULL)
|
|
SECITEM_ZfreeItem(mac, PR_TRUE);
|
|
return NULL;
|
|
}
|
|
|
|
/* MAC is generated per PKCS 12 section 6. It is expected that key, msg
|
|
* and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in
|
|
* because it is not known how long the message actually is. String
|
|
* manipulation routines will not necessarily work because msg may have
|
|
* imbedded NULLs
|
|
*/
|
|
SECItem *
|
|
sec_pkcs12_generate_mac(SECItem *key,
|
|
SECItem *msg,
|
|
PRBool old_method)
|
|
{
|
|
SECStatus res = SECFailure;
|
|
SECItem *mac = NULL;
|
|
PK11Context *pk11cx = NULL;
|
|
SECItem ignore = {0};
|
|
|
|
if((key == NULL) || (msg == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
if(old_method == PR_TRUE) {
|
|
return sec_pkcs12_generate_old_mac(key, msg);
|
|
}
|
|
|
|
/* allocate return item */
|
|
mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH);
|
|
if (mac == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive,
|
|
CKA_SIGN, key, &ignore, NULL);
|
|
if (pk11cx == NULL) {
|
|
goto loser;
|
|
}
|
|
|
|
res = PK11_DigestBegin(pk11cx);
|
|
if (res == SECFailure) {
|
|
goto loser;
|
|
}
|
|
|
|
res = PK11_DigestOp(pk11cx, msg->data, msg->len);
|
|
if (res == SECFailure) {
|
|
goto loser;
|
|
}
|
|
|
|
res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH);
|
|
if (res == SECFailure) {
|
|
goto loser;
|
|
}
|
|
|
|
PK11_DestroyContext(pk11cx, PR_TRUE);
|
|
pk11cx = NULL;
|
|
|
|
loser:
|
|
|
|
if(res != SECSuccess) {
|
|
SECITEM_ZfreeItem(mac, PR_TRUE);
|
|
mac = NULL;
|
|
if (pk11cx) {
|
|
PK11_DestroyContext(pk11cx, PR_TRUE);
|
|
}
|
|
}
|
|
|
|
return mac;
|
|
}
|
|
|
|
/* compute the thumbprint of the DER cert and create a digest info
|
|
* to store it in and return the digest info.
|
|
* a return of NULL indicates an error.
|
|
*/
|
|
SGNDigestInfo *
|
|
sec_pkcs12_compute_thumbprint(SECItem *der_cert)
|
|
{
|
|
SGNDigestInfo *thumb = NULL;
|
|
SECItem digest;
|
|
PLArenaPool *temparena = NULL;
|
|
SECStatus rv = SECFailure;
|
|
|
|
if(der_cert == NULL)
|
|
return NULL;
|
|
|
|
temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
|
|
if(temparena == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
|
|
sizeof(unsigned char) *
|
|
SHA1_LENGTH);
|
|
/* digest data and create digest info */
|
|
if(digest.data != NULL) {
|
|
digest.len = SHA1_LENGTH;
|
|
rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data,
|
|
der_cert->len);
|
|
if(rv == SECSuccess) {
|
|
thumb = SGN_CreateDigestInfo(SEC_OID_SHA1,
|
|
digest.data,
|
|
digest.len);
|
|
} else {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
}
|
|
} else {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
}
|
|
|
|
PORT_FreeArena(temparena, PR_TRUE);
|
|
|
|
return thumb;
|
|
}
|
|
|
|
/* create a virtual password per PKCS 12, the password is converted
|
|
* to unicode, the salt is prepended to it, and then the whole thing
|
|
* is returned */
|
|
SECItem *
|
|
sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt,
|
|
PRBool swap)
|
|
{
|
|
SECItem uniPwd = {siBuffer, NULL,0}, *retPwd = NULL;
|
|
|
|
if((password == NULL) || (salt == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
if(password->len == 0) {
|
|
uniPwd.data = (unsigned char*)PORT_ZAlloc(2);
|
|
uniPwd.len = 2;
|
|
if(!uniPwd.data) {
|
|
return NULL;
|
|
}
|
|
} else {
|
|
uniPwd.data = (unsigned char*)PORT_ZAlloc(password->len * 3);
|
|
uniPwd.len = password->len * 3;
|
|
if(!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
|
|
uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
|
|
SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
|
|
if(retPwd == NULL) {
|
|
goto loser;
|
|
}
|
|
|
|
/* allocate space and copy proper data */
|
|
retPwd->len = uniPwd.len + salt->len;
|
|
retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len);
|
|
if(retPwd->data == NULL) {
|
|
PORT_Free(retPwd);
|
|
goto loser;
|
|
}
|
|
|
|
PORT_Memcpy(retPwd->data, salt->data, salt->len);
|
|
PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len);
|
|
|
|
SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
|
|
|
|
return retPwd;
|
|
|
|
loser:
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
/* appends a shrouded key to a key bag. this is used for exporting
|
|
* to store externally wrapped keys. it is used when importing to convert
|
|
* old items to new
|
|
*/
|
|
SECStatus
|
|
sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag,
|
|
SEC_PKCS12ESPVKItem *espvk)
|
|
{
|
|
int size;
|
|
void *mark = NULL, *dummy = NULL;
|
|
|
|
if((bag == NULL) || (espvk == NULL))
|
|
return SECFailure;
|
|
|
|
mark = PORT_ArenaMark(bag->poolp);
|
|
|
|
/* grow the list */
|
|
size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *);
|
|
dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp,
|
|
bag->espvks, size,
|
|
size + sizeof(SEC_PKCS12ESPVKItem *));
|
|
bag->espvks = (SEC_PKCS12ESPVKItem**)dummy;
|
|
if(dummy == NULL) {
|
|
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
|
goto loser;
|
|
}
|
|
|
|
bag->espvks[bag->nEspvks] = espvk;
|
|
bag->nEspvks++;
|
|
bag->espvks[bag->nEspvks] = NULL;
|
|
|
|
PORT_ArenaUnmark(bag->poolp, mark);
|
|
return SECSuccess;
|
|
|
|
loser:
|
|
PORT_ArenaRelease(bag->poolp, mark);
|
|
return SECFailure;
|
|
}
|
|
|
|
/* search a certificate list for a nickname, a thumbprint, or both
|
|
* within a certificate bag. if the certificate could not be
|
|
* found or an error occurs, NULL is returned;
|
|
*/
|
|
static SEC_PKCS12CertAndCRL *
|
|
sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
|
|
SECItem *nickname, SGNDigestInfo *thumbprint)
|
|
{
|
|
PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
|
|
int i, j;
|
|
|
|
if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
|
|
return NULL;
|
|
}
|
|
|
|
if(thumbprint && nickname) {
|
|
search_both = PR_TRUE;
|
|
}
|
|
|
|
if(nickname) {
|
|
search_nickname = PR_TRUE;
|
|
}
|
|
|
|
search_again:
|
|
i = 0;
|
|
while(certbag->certAndCRLs[i] != NULL) {
|
|
SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];
|
|
|
|
if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {
|
|
|
|
/* check nicknames */
|
|
if(search_nickname) {
|
|
if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
|
|
return cert;
|
|
}
|
|
} else {
|
|
/* check thumbprints */
|
|
SECItem **derCertList;
|
|
|
|
/* get pointer to certificate list, does not need to
|
|
* be freed since it is within the arena which will
|
|
* be freed later.
|
|
*/
|
|
derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
|
|
j = 0;
|
|
if(derCertList != NULL) {
|
|
while(derCertList[j] != NULL) {
|
|
SECComparison eq;
|
|
SGNDigestInfo *di;
|
|
di = sec_pkcs12_compute_thumbprint(derCertList[j]);
|
|
if(di) {
|
|
eq = SGN_CompareDigestInfo(thumbprint, di);
|
|
SGN_DestroyDigestInfo(di);
|
|
if(eq == SECEqual) {
|
|
/* copy the derCert for later reference */
|
|
cert->value.x509->derLeafCert = derCertList[j];
|
|
return cert;
|
|
}
|
|
} else {
|
|
/* an error occurred */
|
|
return NULL;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
if(search_both) {
|
|
search_both = PR_FALSE;
|
|
search_nickname = PR_FALSE;
|
|
goto search_again;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* search a key list for a nickname, a thumbprint, or both
|
|
* within a key bag. if the key could not be
|
|
* found or an error occurs, NULL is returned;
|
|
*/
|
|
static SEC_PKCS12PrivateKey *
|
|
sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag,
|
|
SECItem *nickname, SGNDigestInfo *thumbprint)
|
|
{
|
|
PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
|
|
int i, j;
|
|
|
|
if((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
|
|
return NULL;
|
|
}
|
|
|
|
if(keybag->privateKeys == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if(thumbprint && nickname) {
|
|
search_both = PR_TRUE;
|
|
}
|
|
|
|
if(nickname) {
|
|
search_nickname = PR_TRUE;
|
|
}
|
|
|
|
search_again:
|
|
i = 0;
|
|
while(keybag->privateKeys[i] != NULL) {
|
|
SEC_PKCS12PrivateKey *key = keybag->privateKeys[i];
|
|
|
|
/* check nicknames */
|
|
if(search_nickname) {
|
|
if(SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) {
|
|
return key;
|
|
}
|
|
} else {
|
|
/* check digests */
|
|
SGNDigestInfo **assocCerts = key->pvkData.assocCerts;
|
|
if((assocCerts == NULL) || (assocCerts[0] == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
j = 0;
|
|
while(assocCerts[j] != NULL) {
|
|
SECComparison eq;
|
|
eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]);
|
|
if(eq == SECEqual) {
|
|
return key;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if(search_both) {
|
|
search_both = PR_FALSE;
|
|
search_nickname = PR_FALSE;
|
|
goto search_again;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* seach the safe first then try the baggage bag
|
|
* safe and bag contain certs and keys to search
|
|
* objType is the object type to look for
|
|
* bagType is the type of bag that was found by sec_pkcs12_find_object
|
|
* index is the entity in safe->safeContents or bag->unencSecrets which
|
|
* is being searched
|
|
* nickname and thumbprint are the search criteria
|
|
*
|
|
* a return of null indicates no match
|
|
*/
|
|
static void *
|
|
sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe,
|
|
SEC_PKCS12BaggageItem *bag,
|
|
SECOidTag objType, SECOidTag bagType, int index,
|
|
SECItem *nickname, SGNDigestInfo *thumbprint)
|
|
{
|
|
PRBool searchSafe;
|
|
int i = index;
|
|
|
|
if((safe == NULL) && (bag == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE);
|
|
switch(objType) {
|
|
case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
|
|
if(objType == bagType) {
|
|
SEC_PKCS12CertAndCRLBag *certBag;
|
|
|
|
if(searchSafe) {
|
|
certBag = safe->contents[i]->safeContent.certAndCRLBag;
|
|
} else {
|
|
certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag;
|
|
}
|
|
return sec_pkcs12_find_cert_in_certbag(certBag, nickname,
|
|
thumbprint);
|
|
}
|
|
break;
|
|
case SEC_OID_PKCS12_KEY_BAG_ID:
|
|
if(objType == bagType) {
|
|
SEC_PKCS12PrivateKeyBag *keyBag;
|
|
|
|
if(searchSafe) {
|
|
keyBag = safe->contents[i]->safeContent.keyBag;
|
|
} else {
|
|
keyBag = bag->unencSecrets[i]->safeContent.keyBag;
|
|
}
|
|
return sec_pkcs12_find_key_in_keybag(keyBag, nickname,
|
|
thumbprint);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* searches both the baggage and the safe areas looking for
|
|
* object of specified type matching either the nickname or the
|
|
* thumbprint specified.
|
|
*
|
|
* safe and baggage store certs and keys
|
|
* objType is the OID for the bag type to be searched:
|
|
* SEC_OID_PKCS12_KEY_BAG_ID, or
|
|
* SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID
|
|
* nickname and thumbprint are the search criteria
|
|
*
|
|
* if no match found, NULL returned and error set
|
|
*/
|
|
void *
|
|
sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe,
|
|
SEC_PKCS12Baggage *baggage,
|
|
SECOidTag objType,
|
|
SECItem *nickname,
|
|
SGNDigestInfo *thumbprint)
|
|
{
|
|
int i, j;
|
|
void *retItem;
|
|
|
|
if(((safe == NULL) && (thumbprint == NULL)) ||
|
|
((nickname == NULL) && (thumbprint == NULL))) {
|
|
return NULL;
|
|
}
|
|
|
|
i = 0;
|
|
if((safe != NULL) && (safe->contents != NULL)) {
|
|
while(safe->contents[i] != NULL) {
|
|
SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType);
|
|
retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i,
|
|
nickname, thumbprint);
|
|
if(retItem != NULL) {
|
|
return retItem;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if((baggage != NULL) && (baggage->bags != NULL)) {
|
|
i = 0;
|
|
while(baggage->bags[i] != NULL) {
|
|
SEC_PKCS12BaggageItem *xbag = baggage->bags[i];
|
|
j = 0;
|
|
if(xbag->unencSecrets != NULL) {
|
|
while(xbag->unencSecrets[j] != NULL) {
|
|
SECOidTag bagType;
|
|
bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType);
|
|
retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType,
|
|
j, nickname, thumbprint);
|
|
if(retItem != NULL) {
|
|
return retItem;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);
|
|
return NULL;
|
|
}
|
|
|
|
/* this function converts a password to unicode and encures that the
|
|
* required double 0 byte be placed at the end of the string
|
|
*/
|
|
PRBool
|
|
sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest,
|
|
SECItem *src, PRBool zeroTerm,
|
|
PRBool asciiConvert, PRBool toUnicode)
|
|
{
|
|
PRBool success = PR_FALSE;
|
|
if(!src || !dest) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
return PR_FALSE;
|
|
}
|
|
|
|
dest->len = src->len * 3 + 2;
|
|
if(arena) {
|
|
dest->data = (unsigned char*)PORT_ArenaZAlloc(arena, dest->len);
|
|
} else {
|
|
dest->data = (unsigned char*)PORT_ZAlloc(dest->len);
|
|
}
|
|
|
|
if(!dest->data) {
|
|
dest->len = 0;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
if(!asciiConvert) {
|
|
success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data,
|
|
dest->len, &dest->len);
|
|
} else {
|
|
#ifndef IS_LITTLE_ENDIAN
|
|
PRBool swapUnicode = PR_FALSE;
|
|
#else
|
|
PRBool swapUnicode = PR_TRUE;
|
|
#endif
|
|
success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data,
|
|
dest->len, &dest->len, swapUnicode);
|
|
}
|
|
|
|
if(!success) {
|
|
if(!arena) {
|
|
PORT_Free(dest->data);
|
|
dest->data = NULL;
|
|
dest->len = 0;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
if ((dest->len >= 2) &&
|
|
(dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) {
|
|
if(dest->len + 2 > 3 * src->len) {
|
|
if(arena) {
|
|
dest->data = (unsigned char*)PORT_ArenaGrow(arena,
|
|
dest->data, dest->len,
|
|
dest->len + 2);
|
|
} else {
|
|
dest->data = (unsigned char*)PORT_Realloc(dest->data,
|
|
dest->len + 2);
|
|
}
|
|
|
|
if(!dest->data) {
|
|
return PR_FALSE;
|
|
}
|
|
}
|
|
dest->len += 2;
|
|
dest->data[dest->len-1] = dest->data[dest->len-2] = 0;
|
|
}
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
/* pkcs 12 templates */
|
|
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
|
|
sec_pkcs12_choose_shroud_type;
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
|
|
{ SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
|
|
{ SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
|
|
SEC_PKCS12CodedCertBagTemplate },
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
|
|
{ SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
|
|
SEC_PKCS12PVKSupportingDataTemplate_OLD },
|
|
{ SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
|
|
SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
|
|
&sec_pkcs12_shroud_chooser },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
|
|
{ SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
|
|
SEC_PKCS12PVKSupportingDataTemplate },
|
|
{ SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
|
|
SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
|
|
&sec_pkcs12_shroud_chooser },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) },
|
|
{ SEC_ASN1_OBJECT_ID,
|
|
offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) },
|
|
{ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
|
|
{ SEC_ASN1_SET_OF | SEC_ASN1_XTRN ,
|
|
offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
|
|
SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
|
|
offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
|
|
{ SEC_ASN1_PRINTABLE_STRING,
|
|
offsetof(SEC_PKCS12PVKSupportingData, nickname) },
|
|
{ SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
|
|
offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
|
|
{ SEC_ASN1_SET_OF | SEC_ASN1_XTRN ,
|
|
offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
|
|
SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
|
|
offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
|
|
{ SEC_ASN1_BMP_STRING,
|
|
offsetof(SEC_PKCS12PVKSupportingData, uniNickName) },
|
|
{ SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
|
|
offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) },
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks),
|
|
SEC_PKCS12ESPVKItemTemplate },
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
|
|
SEC_PKCS12SafeBagTemplate },
|
|
/*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
|
|
SEC_PKCS12CodedSafeBagTemplate }, */
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags),
|
|
SEC_PKCS12BaggageItemTemplate },
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks),
|
|
SEC_PKCS12ESPVKItemTemplate_OLD },
|
|
};
|
|
|
|
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser =
|
|
sec_pkcs12_choose_bag_type;
|
|
|
|
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old =
|
|
sec_pkcs12_choose_bag_type_old;
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
|
|
{ SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
|
SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12SafeBag, safeContent),
|
|
&sec_pkcs12_bag_chooser_old },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
|
|
{ SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER,
|
|
offsetof(SEC_PKCS12SafeBag, safeContent),
|
|
&sec_pkcs12_bag_chooser },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING,
|
|
offsetof(SEC_PKCS12SafeBag, uniSafeBagName) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF,
|
|
offsetof(SEC_PKCS12SafeContents, contents),
|
|
SEC_PKCS12SafeBagTemplate_OLD }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF,
|
|
offsetof(SEC_PKCS12SafeContents, contents),
|
|
SEC_PKCS12SafeBagTemplate } /* here */
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) },
|
|
{ SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData),
|
|
SEC_PKCS12PVKSupportingDataTemplate },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
|
|
offsetof(SEC_PKCS12PrivateKey, pkcs8data),
|
|
SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) },
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys),
|
|
SEC_PKCS12PrivateKeyTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
|
|
{ SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN ,
|
|
offsetof(SEC_PKCS12X509CertCRL, thumbprint),
|
|
SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
|
|
{ SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
|
|
{ SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) },
|
|
{ 0 }
|
|
};
|
|
|
|
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old =
|
|
sec_pkcs12_choose_cert_crl_type_old;
|
|
|
|
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser =
|
|
sec_pkcs12_choose_cert_crl_type;
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
|
|
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT |
|
|
SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0,
|
|
offsetof(SEC_PKCS12CertAndCRL, value),
|
|
&sec_pkcs12_cert_crl_chooser_old },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
|
|
{ SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
|
|
{ SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
|
|
SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12CertAndCRL, value),
|
|
&sec_pkcs12_cert_crl_chooser },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
|
|
SEC_PKCS12CertAndCRLTemplate },
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) },
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
|
|
SEC_PKCS12CertAndCRLTemplate_OLD },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) },
|
|
{ SEC_ASN1_OBJECT_ID,
|
|
offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) },
|
|
{ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT,
|
|
offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SecretTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
|
|
{ SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) },
|
|
{ SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
|
|
offsetof(SEC_PKCS12Secret, secretAdditional),
|
|
SEC_PKCS12SecretAdditionalTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
|
offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets),
|
|
SEC_PKCS12SecretItemTemplate },
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
|
|
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN , offsetof(SEC_PKCS12MacData, safeMac),
|
|
SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
|
|
{ SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
|
|
{ SEC_ASN1_OPTIONAL |
|
|
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate },
|
|
{ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
|
offsetof(SEC_PKCS12PFXItem, authSafe),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
|
|
{ SEC_ASN1_OPTIONAL |
|
|
SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
|
|
offsetof(SEC_PKCS12PFXItem, old_safeMac),
|
|
SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING,
|
|
offsetof(SEC_PKCS12PFXItem, old_macSalt) },
|
|
{ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
|
offsetof(SEC_PKCS12PFXItem, authSafe),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, version) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
|
|
{ SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags),
|
|
SEC_PKCS12BaggageItemTemplate },
|
|
{ SEC_ASN1_POINTER,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, safe),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, version) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
|
|
{ SEC_ASN1_BIT_STRING,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
|
|
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
|
|
SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage),
|
|
SEC_PKCS12BaggageTemplate_OLD },
|
|
{ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
|
|
offsetof(SEC_PKCS12AuthenticatedSafe, old_safe),
|
|
sec_PKCS7ContentInfoTemplate },
|
|
{ 0 }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate }
|
|
};
|
|
|
|
const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] =
|
|
{
|
|
{ SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate }
|
|
};
|
|
|
|
|