p12local.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,326 行 · 第 1/3 页

C
1,326
字号
	PORT_Free(mac);	return NULL;    }    /* compute MAC using HMAC */    cx = HMAC_Create(SEC_OID_SHA1, key->data, key->len);    if(cx != NULL) {	HMAC_Begin(cx);	HMAC_Update(cx, msg->data, msg->len);	res = HMAC_Finish(cx, mac->data, &mac->len, SHA1_LENGTH);	HMAC_Destroy(cx);    }    if(res != SECSuccess) {	SECITEM_ZfreeItem(mac, PR_TRUE);	mac = NULL;    }    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;    PRArenaPool *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 */PRBoolsec_pkcs12_convert_item_to_unicode(PRArenaPool *arena, SECItem *dest,				   SECItem *src, PRBool zeroTerm,				   PRBool asciiConvert, PRBool toUnicode){    PRBool success = PR_FALSE;    if(!src || !dest) {	return PR_FALSE;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?