p12dec.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 693 行 · 第 1/2 页
C
693 行
return NULL;}/* validates the safe within the authenticated safe item. * in order to be valid: * 1. the privacy salt must be present * 2. the encryption algorithm must be supported (including * export policy) * PR_FALSE indicates an error, PR_TRUE indicates a valid safe */static PRBool sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe){ PRBool valid = PR_FALSE; SECAlgorithmID *algid; if(asafe == NULL) { return PR_FALSE; } /* if mode is password privacy, then privacySalt is assumed * to be non-zero. */ if(asafe->privacySalt.len != 0) { valid = PR_TRUE; asafe->privacySalt.len /= 8; } else { PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); return PR_FALSE; } /* until spec changes, content will have between 2 and 8 bytes depending * upon the algorithm used if certs are unencrypted... * also want to support case where content is empty -- which we produce */ if(SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE) { asafe->emptySafe = PR_TRUE; return PR_TRUE; } asafe->emptySafe = PR_FALSE; /* make sure that a pbe algorithm is being used */ algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe); if(algid != NULL) { if(SEC_PKCS5IsAlgorithmPBEAlg(algid)) { valid = SEC_PKCS12DecryptionAllowed(algid); if(valid == PR_FALSE) { PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM); } } else { PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM); valid = PR_FALSE; } } else { valid = PR_FALSE; PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM); } return valid;}/* validates authenticates safe: * 1. checks that the version is supported * 2. checks that only password privacy mode is used (currently) * 3. further, makes sure safe has appropriate policies per above function * PR_FALSE indicates failure. */static PRBool sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe){ PRBool valid = PR_TRUE; SECOidTag safe_type; int version; if(asafe == NULL) { return PR_FALSE; } /* check version, since it is default it may not be present. * therefore, assume ok */ if((asafe->version.len > 0) && (asafe->old == PR_FALSE)) { version = DER_GetInteger(&asafe->version); if(version > SEC_PKCS12_PFX_VERSION) { PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION); return PR_FALSE; } } /* validate password mode is being used */ safe_type = SEC_PKCS7ContentType(asafe->safe); switch(safe_type) { case SEC_OID_PKCS7_ENCRYPTED_DATA: valid = sec_pkcs12_validate_encrypted_safe(asafe); break; case SEC_OID_PKCS7_ENVELOPED_DATA: default: PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE); valid = PR_FALSE; break; } return valid;}/* retrieves the authenticated safe item from the PFX item * before returning the authenticated safe, the validity of the * authenticated safe is checked and if valid, returned. * a return of NULL indicates that an error occured. */static SEC_PKCS12AuthenticatedSafe *sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx){ SEC_PKCS12AuthenticatedSafe *asafe; PRBool valid_safe; if(pfx == NULL) { return NULL; } asafe = sec_pkcs12_decode_authenticated_safe(pfx); if(asafe == NULL) { return NULL; } valid_safe = sec_pkcs12_validate_auth_safe(asafe); if(valid_safe != PR_TRUE) { asafe = NULL; } else if(asafe) { asafe->baggage.poolp = asafe->poolp; } return asafe;}/* decrypts the authenticated safe. * a return of anything but SECSuccess indicates an error. the * password is not known to be valid until the call to the * function sec_pkcs12_get_safe_contents. If decoding the safe * fails, it is assumed the password was incorrect and the error * is set then. any failure here is assumed to be due to * internal problems in SEC_PKCS7DecryptContents or below. */static SECStatussec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe, SECItem *pwitem, void *wincx){ SECStatus rv = SECFailure; SECItem *vpwd = NULL; if((asafe == NULL) || (pwitem == NULL)) { return SECFailure; } if(asafe->old == PR_FALSE) { vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt, asafe->swapUnicode); if(vpwd == NULL) { return SECFailure; } } rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe, (asafe->old ? pwitem : vpwd), wincx); if(asafe->old == PR_FALSE) { SECITEM_ZfreeItem(vpwd, PR_TRUE); } return rv;}/* extract the safe from the authenticated safe. * if we are unable to decode the safe, then it is likely that the * safe has not been decrypted or the password used to decrypt * the safe was invalid. we assume that the password was invalid and * set an error accordingly. * a return of NULL indicates that an error occurred. */static SEC_PKCS12SafeContents *sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe){ SECItem *src = NULL; SEC_PKCS12SafeContents *safe = NULL; SECStatus rv = SECFailure; if(asafe == NULL) { return NULL; } safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(asafe->poolp, sizeof(SEC_PKCS12SafeContents)); if(safe == NULL) { return NULL; } safe->poolp = asafe->poolp; safe->old = asafe->old; safe->swapUnicode = asafe->swapUnicode; src = SEC_PKCS7GetContent(asafe->safe); if(src != NULL) { const SEC_ASN1Template *theTemplate; if(asafe->old != PR_TRUE) { theTemplate = SEC_PKCS12SafeContentsTemplate; } else { theTemplate = SEC_PKCS12SafeContentsTemplate_OLD; } rv = SEC_ASN1DecodeItem(asafe->poolp, safe, theTemplate, src); /* if we could not decode the item, password was probably invalid */ if(rv != SECSuccess) { safe = NULL; PORT_SetError(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT); } } else { PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); rv = SECFailure; } return safe;}/* import PFX item * der_pfx is the der encoded pfx structure * pbef and pbearg are the integrity/encryption password call back * ncCall is the nickname collision calllback * slot is the destination token * wincx window handler * * on error, error code set and SECFailure returned */SECStatusSEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem, SEC_PKCS12NicknameCollisionCallback ncCall, PK11SlotInfo *slot, void *wincx){ SEC_PKCS12PFXItem *pfx; SEC_PKCS12AuthenticatedSafe *asafe; SEC_PKCS12SafeContents *safe_contents = NULL; SECStatus rv; if(!der_pfx || !pwitem || !slot) { return SECFailure; } /* decode and validate each section */ rv = SECFailure; pfx = sec_pkcs12_get_pfx(der_pfx, pwitem); if(pfx != NULL) { asafe = sec_pkcs12_get_auth_safe(pfx); if(asafe != NULL) { /* decrypt safe -- only if not empty */ if(asafe->emptySafe != PR_TRUE) { rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx); if(rv == SECSuccess) { safe_contents = sec_pkcs12_get_safe_contents(asafe); if(safe_contents == NULL) { rv = SECFailure; } } } else { safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp); safe_contents->swapUnicode = pfx->swapUnicode; if(safe_contents == NULL) { rv = SECFailure; } else { rv = SECSuccess; } } /* get safe contents and begin import */ if(rv == SECSuccess) { SEC_PKCS12DecoderContext *p12dcx; p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot, pfx->swapUnicode, pwitem, wincx, safe_contents, &asafe->baggage); if(!p12dcx) { rv = SECFailure; goto loser; } if(SEC_PKCS12DecoderValidateBags(p12dcx, ncCall) != SECSuccess) { rv = SECFailure; goto loser; } rv = SEC_PKCS12DecoderImportBags(p12dcx); } } }loser: if(pfx) { SEC_PKCS12DestroyPFX(pfx); } return rv;}PRBool SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength){ int lengthLength; PRBool valid = PR_FALSE; if(buf == NULL) { return PR_FALSE; } /* check for constructed sequence identifier tag */ if(*buf == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) { totalLength--; /* header byte taken care of */ buf++; lengthLength = (long int)SEC_ASN1LengthLength(totalLength - 1); if(totalLength > 0x7f) { lengthLength--; *buf &= 0x7f; /* remove bit 8 indicator */ if((*buf - (char)lengthLength) == 0) { valid = PR_TRUE; } } else { lengthLength--; if((*buf - (char)lengthLength) == 0) { valid = PR_TRUE; } } } return valid;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?