p12exp.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,408 行 · 第 1/3 页
C
1,408 行
*rBaggage = baggage; *rSafe = safe; return rv;}/* DER encode the safe contents and return a SECItem. if an error * occurs, NULL is returned. */static SECItem *sec_pkcs12_encode_safe_contents(SEC_PKCS12SafeContents *safe){ SECItem *dsafe = NULL, *tsafe; void *dummy = NULL; PRArenaPool *arena; if(safe == NULL) { return NULL; }/* rv = sec_pkcs12_prepare_for_der_code_safe(safe, PR_TRUE); if(rv != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; }*/ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if(arena == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } tsafe = (SECItem *)PORT_ArenaZAlloc(arena, sizeof(SECItem)); if(tsafe != NULL) { dummy = SEC_ASN1EncodeItem(arena, tsafe, safe, SEC_PKCS12SafeContentsTemplate); if(dummy != NULL) { dsafe = SECITEM_DupItem(tsafe); } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } PORT_FreeArena(arena, PR_TRUE); return dsafe;}/* prepare the authenicated safe for encoding and encode it. * baggage is copied to the appropriate area, safe is encoded and * encrypted. the version and transport mode are set on the asafe. * the whole ball of wax is then der encoded and packaged up into * data content info * safe -- container of certs and keys, is encrypted. * baggage -- container of certs and keys, keys assumed to be encrypted by * another method, certs are in the clear * algorithm -- algorithm by which to encrypt safe * pwitem -- password for encryption * wincx - window handle * * return of NULL is an error condition. */static SEC_PKCS7ContentInfo *sec_pkcs12_get_auth_safe(SEC_PKCS12SafeContents *safe, SEC_PKCS12Baggage *baggage, SECOidTag algorithm, SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn, void *wincx){ SECItem *src = NULL, *dest = NULL, *psalt = NULL; PRArenaPool *poolp; SEC_PKCS12AuthenticatedSafe *asafe; SEC_PKCS7ContentInfo *safe_cinfo = NULL; SEC_PKCS7ContentInfo *asafe_cinfo = NULL; void *dummy; SECStatus rv = SECSuccess; PRBool swapUnicodeBytes = PR_FALSE;#ifdef IS_LITTLE_ENDIAN swapUnicodeBytes = PR_TRUE;#endif if(((safe != NULL) && (pwitem == NULL)) && (baggage == NULL)) return NULL; poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if(poolp == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } /* prepare authenticated safe for encode */ asafe = sec_pkcs12_new_asafe(poolp); if(asafe != NULL) { /* set version */ dummy = SEC_ASN1EncodeInteger(asafe->poolp, &asafe->version, SEC_PKCS12_PFX_VERSION); if(dummy == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); rv = SECFailure; goto loser; } /* generate the privacy salt used to create virtual pwd */ psalt = sec_pkcs12_generate_salt(); if(psalt != NULL) { rv = SECITEM_CopyItem(asafe->poolp, &asafe->privacySalt, psalt); if(rv == SECSuccess) { asafe->privacySalt.len *= 8; } else { SECITEM_ZfreeItem(psalt, PR_TRUE); PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } } if((psalt == NULL) || (rv == SECFailure)) { PORT_SetError(SEC_ERROR_NO_MEMORY); rv = SECFailure; goto loser; } /* package up safe contents */ if(safe != NULL) { safe_cinfo = SEC_PKCS7CreateEncryptedData(algorithm, NULL, wincx); if((safe_cinfo != NULL) && (safe->safe_size > 0)) { /* encode the safe and encrypt the contents of the * content info */ src = sec_pkcs12_encode_safe_contents(safe); if(src != NULL) { rv = SEC_PKCS7SetContent(safe_cinfo, (char *)src->data, src->len); SECITEM_ZfreeItem(src, PR_TRUE); if(rv == SECSuccess) { SECItem *vpwd; vpwd = sec_pkcs12_create_virtual_password(pwitem, psalt, unicodeFn, swapUnicodeBytes); if(vpwd != NULL) { rv = SEC_PKCS7EncryptContents(NULL, safe_cinfo, vpwd, wincx); SECITEM_ZfreeItem(vpwd, PR_TRUE); } else { rv = SECFailure; PORT_SetError(SEC_ERROR_NO_MEMORY); } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } } else { rv = SECFailure; } } else if(safe->safe_size > 0) { PORT_SetError(SEC_ERROR_NO_MEMORY); goto loser; } else { /* case where there is NULL content in the safe contents */ rv = SEC_PKCS7SetContent(safe_cinfo, NULL, 0); if(rv != SECFailure) { PORT_SetError(SEC_ERROR_NO_MEMORY); } } if(rv != SECSuccess) { SEC_PKCS7DestroyContentInfo(safe_cinfo); safe_cinfo = NULL; goto loser; } asafe->safe = safe_cinfo; /* PORT_Memcpy(&asafe->safe, safe_cinfo, sizeof(*safe_cinfo)); */ } /* copy the baggage to the authenticated safe baggage if present */ if(baggage != NULL) { PORT_Memcpy(&asafe->baggage, baggage, sizeof(*baggage)); } /* encode authenticated safe and store it in a Data content info */ dest = (SECItem *)PORT_ArenaZAlloc(poolp, sizeof(SECItem)); if(dest != NULL) { dummy = SEC_ASN1EncodeItem(poolp, dest, asafe, SEC_PKCS12AuthenticatedSafeTemplate); if(dummy != NULL) { asafe_cinfo = SEC_PKCS7CreateData(); if(asafe_cinfo != NULL) { rv = SEC_PKCS7SetContent(asafe_cinfo, (char *)dest->data, dest->len); if(rv != SECSuccess) { PORT_SetError(SEC_ERROR_NO_MEMORY); SEC_PKCS7DestroyContentInfo(asafe_cinfo); asafe_cinfo = NULL; } } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); rv = SECFailure; } } }loser: PORT_FreeArena(poolp, PR_TRUE); if(safe_cinfo != NULL) { SEC_PKCS7DestroyContentInfo(safe_cinfo); } if(psalt != NULL) { SECITEM_ZfreeItem(psalt, PR_TRUE); } if(rv == SECFailure) { return NULL; } return asafe_cinfo;}/* generates the PFX and computes the mac on the authenticated safe * NULL implies an error */static SEC_PKCS12PFXItem *sec_pkcs12_get_pfx(SEC_PKCS7ContentInfo *cinfo, PRBool do_mac, SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn){ SECItem *dest = NULL, *mac = NULL, *salt = NULL, *key = NULL; SEC_PKCS12PFXItem *pfx; SECStatus rv = SECFailure; SGNDigestInfo *di; SECItem *vpwd; PRBool swapUnicodeBytes = PR_FALSE;#ifdef IS_LITTLE_ENDIAN swapUnicodeBytes = PR_TRUE;#endif if((cinfo == NULL) || ((do_mac == PR_TRUE) && (pwitem == NULL))) { return NULL; } /* allocate new pfx structure */ pfx = sec_pkcs12_new_pfx(); if(pfx == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } PORT_Memcpy(&pfx->authSafe, cinfo, sizeof(*cinfo)); if(do_mac == PR_TRUE) { /* salt for computing mac */ salt = sec_pkcs12_generate_salt(); if(salt != NULL) { rv = SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, salt); pfx->macData.macSalt.len *= 8; vpwd = sec_pkcs12_create_virtual_password(pwitem, salt, unicodeFn, swapUnicodeBytes); if(vpwd == NULL) { rv = SECFailure; key = NULL; } else { key = sec_pkcs12_generate_key_from_password(SEC_OID_SHA1, salt, vpwd); SECITEM_ZfreeItem(vpwd, PR_TRUE); } if((key != NULL) && (rv == SECSuccess)) { dest = SEC_PKCS7GetContent(cinfo); if(dest != NULL) { /* compute mac on data -- for password integrity mode */ mac = sec_pkcs12_generate_mac(key, dest, PR_FALSE); if(mac != NULL) { di = SGN_CreateDigestInfo(SEC_OID_SHA1, mac->data, mac->len); if(di != NULL) { rv = SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, di); SGN_DestroyDigestInfo(di); } else { PORT_SetError(SEC_ERROR_NO_MEMORY); } SECITEM_ZfreeItem(mac, PR_TRUE); } } else { rv = SECFailure; } } else { PORT_SetError(SEC_ERROR_NO_MEMORY); rv = SECFailure; } if(key != NULL) { SECITEM_ZfreeItem(key, PR_TRUE); } SECITEM_ZfreeItem(salt, PR_TRUE); } } if(rv == SECFailure) { SEC_PKCS12DestroyPFX(pfx); pfx = NULL; } return pfx;}/* der encode the pfx */static SECItem *sec_pkcs12_encode_pfx(SEC_PKCS12PFXItem *pfx){ SECItem *dest; void *dummy; if(pfx == NULL) { return NULL; } dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); if(dest == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return NULL; } dummy = SEC_ASN1EncodeItem(NULL, dest, pfx, SEC_PKCS12PFXItemTemplate); if(dummy == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); SECITEM_ZfreeItem(dest, PR_TRUE); dest = NULL; } return dest;}SECItem *SEC_PKCS12GetPFX(char **nicknames, CERTCertificate **ref_certs, PRBool shroud_keys, SEC_PKCS5GetPBEPassword pbef, void *pbearg, PKCS12UnicodeConvertFunction unicodeFn, void *wincx){ SECItem **nicks = NULL; SEC_PKCS12PFXItem *pfx = NULL; SEC_PKCS12Baggage *baggage = NULL; SEC_PKCS12SafeContents *safe = NULL; SEC_PKCS7ContentInfo *cinfo = NULL; SECStatus rv = SECFailure; SECItem *dest = NULL, *pwitem = NULL; PRBool problem = PR_FALSE; PRBool unencryptedCerts; SECOidTag shroud_alg, safe_alg; /* how should we encrypt certs ? */ unencryptedCerts = !SEC_PKCS12IsEncryptionAllowed(); if(!unencryptedCerts) { safe_alg = SEC_PKCS12GetPreferredEncryptionAlgorithm(); if(safe_alg == SEC_OID_UNKNOWN) { safe_alg = SEC_PKCS12GetStrongestAllowedAlgorithm(); } if(safe_alg == SEC_OID_UNKNOWN) { unencryptedCerts = PR_TRUE; /* for export where no encryption is allowed, we still need * to encrypt the NULL contents per the spec. encrypted info * is known plaintext, so it shouldn't be a problem. */ safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; } } else { /* for export where no encryption is allowed, we still need * to encrypt the NULL contents per the spec. encrypted info * is known plaintext, so it shouldn't be a problem. */ safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; } /* keys are always stored with triple DES */ shroud_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; /* check for FIPS, if so, do not encrypt certs */ if(PK11_IsFIPS() && !unencryptedCerts) { unencryptedCerts = PR_TRUE; } if((nicknames == NULL) || (pbef == NULL) || (ref_certs == NULL)) { problem = PR_TRUE; goto loser; } /* get password */ pwitem = (*pbef)(pbearg); if(pwitem == NULL) { problem = PR_TRUE; goto loser; } nicks = sec_pkcs12_convert_nickname_list(nicknames); /* get safe and baggage */ rv = sec_pkcs12_package_certs_and_keys(nicks, ref_certs, unencryptedCerts, &safe, &baggage, shroud_keys, shroud_alg, pwitem, unicodeFn, wincx); if(rv == SECFailure) { problem = PR_TRUE; } if((safe != NULL) && (problem == PR_FALSE)) { /* copy thumbprints */ rv = sec_pkcs12_propagate_thumbprints(nicks, ref_certs, safe, baggage); /* package everything up into AuthenticatedSafe */ cinfo = sec_pkcs12_get_auth_safe(safe, baggage, safe_alg, pwitem, unicodeFn, wincx); sec_pkcs12_destroy_cert_content_infos(safe, baggage); /* get the pfx and mac it */ if(cinfo != NULL) { pfx = sec_pkcs12_get_pfx(cinfo, PR_TRUE, pwitem, unicodeFn); if(pfx != NULL) { dest = sec_pkcs12_encode_pfx(pfx); SEC_PKCS12DestroyPFX(pfx); } SEC_PKCS7DestroyContentInfo(cinfo); } if(safe != NULL) { PORT_FreeArena(safe->poolp, PR_TRUE); } } else { if(safe != NULL) { PORT_FreeArena(safe->poolp, PR_TRUE); } }loser: if(nicks != NULL) { sec_pkcs12_destroy_nickname_list(nicks); } if(ref_certs != NULL) { sec_pkcs12_destroy_certificate_list(ref_certs); } if(pwitem != NULL) { SECITEM_ZfreeItem(pwitem, PR_TRUE); } if(problem == PR_TRUE) { dest = NULL; } return dest;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?