p12e.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,255 行 · 第 1/4 页
C
2,255 行
* it. * * p12ctxt - the export context * safe - the safeInfo to place the key in * nestedDest - the nested safeContents to place a key * cert - the certificate which the key belongs to * shroudKey - encrypt the private key for export. This value should * always be true. lower level code will not allow the export * of unencrypted private keys. * algorithm - the algorithm with which to encrypt the private key * pwitem - the password to encrypted the private key with * keyId - the keyID attribute * nickName - the nickname attribute */static SECStatusSEC_PKCS12AddEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, SECKEYEncryptedPrivateKeyInfo *epki, SEC_PKCS12SafeInfo *safe, void *nestedDest, SECItem *keyId, SECItem *nickName){ void *mark; void *keyItem; SECOidTag keyType; SECStatus rv = SECFailure; sec_PKCS12SafeBag *returnBag; if(!p12ctxt || !safe || !epki) { return SECFailure; } mark = PORT_ArenaMark(p12ctxt->arena); keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYEncryptedPrivateKeyInfo)); if(!keyItem) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, (SECKEYEncryptedPrivateKeyInfo *)keyItem, epki); keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID; if(rv != SECSuccess) { goto loser; } /* create the safe bag and set any attributes */ returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem); if(!returnBag) { rv = SECFailure; goto loser; } if(nickName) { if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_FRIENDLY_NAME, nickName) != SECSuccess) { goto loser; } } if(keyId) { if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_LOCAL_KEY_ID, keyId) != SECSuccess) { goto loser; } } if(nestedDest) { rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, (sec_PKCS12SafeContents*)nestedDest, returnBag); } else { rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag); }loser: if (rv != SECSuccess) { PORT_ArenaRelease(p12ctxt->arena, mark); } else { PORT_ArenaUnmark(p12ctxt->arena, mark); } return rv;}/* SEC_PKCS12AddKeyForCert * Extracts the key associated with a particular certificate and exports * it. * * p12ctxt - the export context * safe - the safeInfo to place the key in * nestedDest - the nested safeContents to place a key * cert - the certificate which the key belongs to * shroudKey - encrypt the private key for export. This value should * always be true. lower level code will not allow the export * of unencrypted private keys. * algorithm - the algorithm with which to encrypt the private key * pwitem - the password to encrypt the private key with * keyId - the keyID attribute * nickName - the nickname attribute */SECStatusSEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, void *nestedDest, CERTCertificate *cert, PRBool shroudKey, SECOidTag algorithm, SECItem *pwitem, SECItem *keyId, SECItem *nickName){ void *mark; void *keyItem; SECOidTag keyType; SECStatus rv = SECFailure; SECItem nickname = {siBuffer,NULL,0}, uniPwitem = {siBuffer, NULL, 0}; sec_PKCS12SafeBag *returnBag; if(!p12ctxt || !cert || !safe) { return SECFailure; } mark = PORT_ArenaMark(p12ctxt->arena); /* retrieve the key based upon the type that it is and * specify the type of safeBag to store the key in */ if(!shroudKey) { /* extract the key unencrypted. this will most likely go away */ SECKEYPrivateKeyInfo *pki = PK11_ExportPrivateKeyInfo(cert, p12ctxt->wincx); if(!pki) { PORT_ArenaRelease(p12ctxt->arena, mark); PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); return SECFailure; } keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYPrivateKeyInfo)); if(!keyItem) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } rv = SECKEY_CopyPrivateKeyInfo(p12ctxt->arena, (SECKEYPrivateKeyInfo *)keyItem, pki); keyType = SEC_OID_PKCS12_V1_KEY_BAG_ID; SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); } else { /* extract the key encrypted */ SECKEYEncryptedPrivateKeyInfo *epki = NULL; PK11SlotInfo *slot = p12ctxt->slot; if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, &uniPwitem, pwitem, PR_TRUE, PR_TRUE, PR_TRUE)) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } /* we want to make sure to take the key out of the key slot */ if(PK11_IsInternal(p12ctxt->slot)) { slot = PK11_GetInternalKeySlot(); } epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, &uniPwitem, cert, 1, p12ctxt->wincx); if(PK11_IsInternal(p12ctxt->slot)) { PK11_FreeSlot(slot); } keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYEncryptedPrivateKeyInfo)); if(!keyItem) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } if(!epki) { PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); return SECFailure; } rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, (SECKEYEncryptedPrivateKeyInfo *)keyItem, epki); keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID; SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); } if(rv != SECSuccess) { goto loser; } /* if no nickname specified, let's see if the certificate has a * nickname. */ if(!nickName) { if(cert->nickname) { nickname.data = (unsigned char *)cert->nickname; nickname.len = PORT_Strlen(cert->nickname); nickName = &nickname; } } /* create the safe bag and set any attributes */ returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem); if(!returnBag) { rv = SECFailure; goto loser; } if(nickName) { if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_FRIENDLY_NAME, nickName) != SECSuccess) { goto loser; } } if(keyId) { if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_LOCAL_KEY_ID, keyId) != SECSuccess) { goto loser; } } if(nestedDest) { rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, (sec_PKCS12SafeContents*)nestedDest, returnBag); } else { rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag); }loser: if (rv != SECSuccess) { PORT_ArenaRelease(p12ctxt->arena, mark); } else { PORT_ArenaUnmark(p12ctxt->arena, mark); } return rv;}/* SEC_PKCS12AddCertAndEncryptedKey * Add a certificate and key pair to be exported. * * p12ctxt - the export context * certSafe - the safeInfo where the cert is stored * certNestedDest - the nested safeContents to store the cert * keySafe - the safeInfo where the key is stored * keyNestedDest - the nested safeContents to store the key * shroudKey - extract the private key encrypted? * pwitem - the password with which the key is encrypted * algorithm - the algorithm with which the key is encrypted */SECStatusSEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, void *certSafe, void *certNestedDest, SECItem *derCert, void *keySafe, void *keyNestedDest, SECKEYEncryptedPrivateKeyInfo *epki, char *nickname){ SECStatus rv = SECFailure; SGNDigestInfo *digest = NULL; void *mark = NULL; CERTCertificate *cert; SECItem nick = {siBuffer, NULL,0}, *nickPtr = NULL; if(!p12ctxt || !certSafe || !keySafe || !derCert) { return SECFailure; } mark = PORT_ArenaMark(p12ctxt->arena); cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, PR_FALSE, PR_TRUE); if(!cert) { PORT_ArenaRelease(p12ctxt->arena, mark); PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; } cert->nickname = nickname; /* generate the thumbprint of the cert to use as a keyId */ digest = sec_pkcs12_compute_thumbprint(&cert->derCert); if(!digest) { CERT_DestroyCertificate(cert); return SECFailure; } /* add the certificate */ rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, certNestedDest, cert, NULL, &digest->digest, PR_FALSE); if(rv != SECSuccess) { goto loser; } if(nickname) { nick.data = (unsigned char *)nickname; nick.len = PORT_Strlen(nickname); nickPtr = &nick; } else { nickPtr = NULL; } /* add the key */ rv = SEC_PKCS12AddEncryptedKey(p12ctxt, epki, (SEC_PKCS12SafeInfo*)keySafe, keyNestedDest, &digest->digest, nickPtr ); if(rv != SECSuccess) { goto loser; } SGN_DestroyDigestInfo(digest); PORT_ArenaUnmark(p12ctxt->arena, mark); return SECSuccess;loser: SGN_DestroyDigestInfo(digest); CERT_DestroyCertificate(cert); PORT_ArenaRelease(p12ctxt->arena, mark); return SECFailure; }/* SEC_PKCS12AddCertAndKey * Add a certificate and key pair to be exported. * * p12ctxt - the export context * certSafe - the safeInfo where the cert is stored * certNestedDest - the nested safeContents to store the cert * keySafe - the safeInfo where the key is stored * keyNestedDest - the nested safeContents to store the key * shroudKey - extract the private key encrypted? * pwitem - the password with which the key is encrypted * algorithm - the algorithm with which the key is encrypted */SECStatusSEC_PKCS12AddCertAndKey(SEC_PKCS12ExportContext *p12ctxt, void *certSafe, void *certNestedDest, CERTCertificate *cert, CERTCertDBHandle *certDb, void *keySafe, void *keyNestedDest, PRBool shroudKey, SECItem *pwitem, SECOidTag algorithm){ SECStatus rv = SECFailure; SGNDigestInfo *digest = NULL; void *mark = NULL; if(!p12ctxt || !certSafe || !keySafe || !cert) { return SECFailure; } mark = PORT_ArenaMark(p12ctxt->arena); /* generate the thumbprint of the cert to use as a keyId */ digest = sec_pkcs12_compute_thumbprint(&cert->derCert); if(!digest) { PORT_ArenaRelease(p12ctxt->arena, mark); return SECFailure; } /* add the certificate */ rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, (SEC_PKCS12SafeInfo*)certNestedDest, cert, certDb, &digest->digest, PR_TRUE); if(rv != SECSuccess) { goto loser; } /* add the key */ rv = SEC_PKCS12AddKeyForCert(p12ctxt, (SEC_PKCS12SafeInfo*)keySafe, keyNestedDest, cert, shroudKey, algorithm, pwitem, &digest->digest, NULL ); if(rv != SECSuccess) { goto loser; } SGN_DestroyDigestInfo(digest); PORT_ArenaUnmark(p12ctxt->arena, mark); return SECSuccess;loser: SGN_DestroyDigestInfo(digest); PORT_ArenaRelease(p12ctxt->arena, mark); return SECFailure; }/* SEC_PKCS12CreateNestedSafeContents * Allows nesting of safe contents to be implemented. No limit imposed on * depth. * * p12ctxt - the export context * baseSafe - the base safeInfo * nestedDest - a parent safeContents (?) */void *SEC_PKCS12CreateNestedSafeContents(SEC_PKCS12ExportContext *p12ctxt, void *baseSafe, void *nestedDest){ sec_PKCS12SafeContents *newSafe; sec_PKCS12SafeBag *safeContentsBag; void *mark; SECStatus rv; if(!p12ctxt || !baseSafe) { return NULL; } mark = PORT_ArenaMark(p12ctxt->arena); newSafe = sec_PKCS12CreateSafeContents(p12ctxt->arena); if(!newSafe) { PORT_ArenaRelease(p12ctxt->arena, mark); PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } /* create the safeContents safeBag */ safeContentsBag = sec_PKCS12CreateSafeBag(p12ctxt, SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID, newSafe); if(!safeContentsBag) { goto loser; } /* append the safeContents to the appropriate area */ if(nestedDest) { rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, (sec_PKCS12SafeContents*)nestedDest, safeContentsBag); } else { rv = sec_pkcs12_append_bag(p12ctxt, (SEC_PKCS12SafeInfo*)baseSafe, safeContentsBag); } if(rv != SECSuccess) { goto loser; } PORT_ArenaUnmark(p12ctxt->arena, mark); return newSafe;loser: PORT_ArenaRelease(p12ctxt->arena, mark); return NULL;}/********************************* * Encoding routines *********************************//* set up the encoder context based on information in the export context * and return the newly allocated enocoder context. A return of NULL * indicates an error occurred. */sec_PKCS12EncoderContext *sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp){ sec_PKCS12EncoderContext *p12enc = NULL; unsigned int i, nonEmptyCnt; if(!p12exp || !p12exp->safeInfos) { return NULL; } /* check for any empty safes and skip them */ i = nonEmptyCnt = 0; while(p12exp->safeInfos[i]) { if(p12exp->safeInfos[i]->itemCount) { nonEmptyCnt++; } i++; } if(nonEmptyCnt == 0) { return NULL; } p12exp->authSafe.encodedSafes[nonEmptyCnt] = NULL; /* allocate the encoder context */ p12enc = (sec_PKCS12EncoderContext*)PORT_ArenaZAlloc(p12exp->arena, sizeof(sec_PKCS12EncoderContext)); if(!p12enc) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } p12enc->arena = p12exp->arena; p12enc->p12exp = p12exp; /* set up the PFX version and information */ PORT_Memset(&p12enc->pfx, 0, sizeof(sec_PKCS12PFXItem)); if(!SEC_ASN1EncodeInteger(p12exp->arena, &(p12enc->pfx.version), SEC_PKCS12_VERSION) ) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } /* set up the authenticated safe content info based on the * type of integrity being used. this should be changed to * enforce integrity mode, but will not be implemented until * it is confirmed that integrity must be in place */ if(p12exp->integrityEnabled && !p12exp->pwdIntegrity) { SECStatus rv; /* create public key integrity mode */ p12enc->aSafeCinfo = SEC_PKCS7CreateSignedData( p12exp->integrityInfo.pubkeyInfo.cert, certUsageEmailSigner, p12exp->integrityInfo.pubkeyInfo.certDb, p12exp->integrityInfo.pubkeyInfo.algorithm, NULL, p12exp->pwfn, p12exp->pwfnarg); if(!p12enc->aSafeCinfo) { goto loser; } if(SEC_PKCS7IncludeCertChain(p12enc->aSafeCinfo,NULL) != SECSuccess) { SEC_PKCS7DestroyContentInfo(p12enc->aSafeCinfo); goto loser; } rv = SEC_PKCS7AddSigningTime(p12enc->aSafeCinfo); PORT_Assert(rv == SECSuccess); } else { p12enc->aSafeCinfo = SEC_PKCS7CreateData(); /* init password pased integrity mode */ if(p12exp->integrityEnabled) { SECItem pwd = {siBuffer,NULL, 0}, *key; SECItem *salt = sec_pkcs12_generate_salt(); PBEBitGenContext *pbeCtxt = NULL; /* zero out macData and set values */ PORT_Memset(&p12enc->mac, 0, sizeof(sec_PKCS12MacData)); if(!salt) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } if(SECITEM_CopyItem(p12exp->arena, &(p12enc->mac.macSalt), salt) != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } SECITEM_ZfreeItem(salt, PR_TRUE); /* generate HMAC key */ if(!sec_pkcs12_convert_item_to_unicode(p12exp->arena, &pwd, p12exp->integrityInfo.pwdInfo.password, PR_TRUE, PR_TRUE, PR_TRUE)) { goto loser; } pbeCtxt = PBE_CreateContext(p12exp->integrityInfo.pwdInfo.algorithm, pbeBitGenIntegrityKey, &pwd, &(p12enc->mac.macSalt), 160, 1); if(!pbeCtxt) { goto loser; } key = PBE_GenerateBits(pbeCtxt); PBE_DestroyContext(pbeCtxt); if(!key) { goto loser;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?