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 + -
显示快捷键?