p12local.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,326 行 · 第 1/3 页
C
1,326 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#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 "alghmac.h"#include "p12.h"#define SALT_LENGTH 16/* 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_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_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_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_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_PointerToAnyTemplate; break; case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING: theTemplate = 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; PRArenaPool *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; PRArenaPool *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; HMACContext *cx; 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 *)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) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?