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