| Index: nss_pkcs12/p12dec.c
|
| ===================================================================
|
| --- nss_pkcs12/p12dec.c (revision 26000)
|
| +++ nss_pkcs12/p12dec.c (working copy)
|
| @@ -1,664 +0,0 @@
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -
|
| -#include "pkcs12.h"
|
| -#include "plarena.h"
|
| -#include "secpkcs7.h"
|
| -#include "p12local.h"
|
| -#include "secoid.h"
|
| -#include "secitem.h"
|
| -#include "secport.h"
|
| -#include "secasn1.h"
|
| -#include "secder.h"
|
| -#include "secerr.h"
|
| -#include "cert.h"
|
| -#include "certdb.h"
|
| -#include "p12plcy.h"
|
| -#include "p12.h"
|
| -#include "secpkcs5.h"
|
| -
|
| -/* PFX extraction and validation routines */
|
| -
|
| -/* decode the DER encoded PFX item. if unable to decode, check to see if it
|
| - * is an older PFX item. If that fails, assume the file was not a valid
|
| - * pfx file.
|
| - * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX
|
| - */
|
| -static SEC_PKCS12PFXItem *
|
| -sec_pkcs12_decode_pfx(SECItem *der_pfx)
|
| -{
|
| - SEC_PKCS12PFXItem *pfx;
|
| - SECStatus rv;
|
| -
|
| - if(der_pfx == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - /* allocate the space for a new PFX item */
|
| - pfx = sec_pkcs12_new_pfx();
|
| - if(pfx == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate,
|
| - der_pfx);
|
| -
|
| - /* if a failure occurred, check for older version...
|
| - * we also get rid of the old pfx structure, because we don't
|
| - * know where it failed and what data in may contain
|
| - */
|
| - if(rv != SECSuccess) {
|
| - SEC_PKCS12DestroyPFX(pfx);
|
| - pfx = sec_pkcs12_new_pfx();
|
| - if(pfx == NULL) {
|
| - return NULL;
|
| - }
|
| - rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD,
|
| - der_pfx);
|
| - if(rv != SECSuccess) {
|
| - PORT_SetError(SEC_ERROR_PKCS12_DECODING_PFX);
|
| - PORT_FreeArena(pfx->poolp, PR_TRUE);
|
| - return NULL;
|
| - }
|
| - pfx->old = PR_TRUE;
|
| - SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac);
|
| - SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt);
|
| - } else {
|
| - pfx->old = PR_FALSE;
|
| - }
|
| -
|
| - /* convert bit string from bits to bytes */
|
| - pfx->macData.macSalt.len /= 8;
|
| -
|
| - return pfx;
|
| -}
|
| -
|
| -/* validate the integrity MAC used in the PFX. The MAC is generated
|
| - * per the PKCS 12 document. If the MAC is incorrect, it is most likely
|
| - * due to an invalid password.
|
| - * pwitem is the integrity password
|
| - * pfx is the decoded pfx item
|
| - */
|
| -static PRBool
|
| -sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx,
|
| - SECItem *pwitem)
|
| -{
|
| - SECItem *key = NULL, *mac = NULL, *data = NULL;
|
| - SECItem *vpwd = NULL;
|
| - SECOidTag algorithm;
|
| - PRBool ret = PR_FALSE;
|
| -
|
| - if(pfx == NULL) {
|
| - return PR_FALSE;
|
| - }
|
| -
|
| - algorithm = SECOID_GetAlgorithmTag(&pfx->macData.safeMac.digestAlgorithm);
|
| - switch(algorithm) {
|
| - /* only SHA1 hashing supported as a MACing algorithm */
|
| - case SEC_OID_SHA1:
|
| - if(pfx->old == PR_FALSE) {
|
| - pfx->swapUnicode = PR_FALSE;
|
| - }
|
| -
|
| -recheckUnicodePassword:
|
| - vpwd = sec_pkcs12_create_virtual_password(pwitem,
|
| - &pfx->macData.macSalt,
|
| - pfx->swapUnicode);
|
| - if(vpwd == NULL) {
|
| - return PR_FALSE;
|
| - }
|
| -
|
| - key = sec_pkcs12_generate_key_from_password(algorithm,
|
| - &pfx->macData.macSalt,
|
| - (pfx->old ? pwitem : vpwd));
|
| - /* free vpwd only for newer PFX */
|
| - if(vpwd) {
|
| - SECITEM_ZfreeItem(vpwd, PR_TRUE);
|
| - }
|
| - if(key == NULL) {
|
| - return PR_FALSE;
|
| - }
|
| -
|
| - data = SEC_PKCS7GetContent(&pfx->authSafe);
|
| - if(data == NULL) {
|
| - break;
|
| - }
|
| -
|
| - /* check MAC */
|
| - mac = sec_pkcs12_generate_mac(key, data, pfx->old);
|
| - ret = PR_TRUE;
|
| - if(mac) {
|
| - SECItem *safeMac = &pfx->macData.safeMac.digest;
|
| - if(SECITEM_CompareItem(mac, safeMac) != SECEqual) {
|
| -
|
| - /* if we encounter an invalid mac, lets invert the
|
| - * password in case of unicode changes
|
| - */
|
| - if(((!pfx->old) && pfx->swapUnicode) || (pfx->old)){
|
| - PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
|
| - ret = PR_FALSE;
|
| - } else {
|
| - SECITEM_ZfreeItem(mac, PR_TRUE);
|
| - pfx->swapUnicode = PR_TRUE;
|
| - goto recheckUnicodePassword;
|
| - }
|
| - }
|
| - SECITEM_ZfreeItem(mac, PR_TRUE);
|
| - } else {
|
| - ret = PR_FALSE;
|
| - }
|
| - break;
|
| - default:
|
| - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM);
|
| - ret = PR_FALSE;
|
| - break;
|
| - }
|
| -
|
| - /* let success fall through */
|
| - if(key != NULL)
|
| - SECITEM_ZfreeItem(key, PR_TRUE);
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -/* check the validity of the pfx structure. we currently only support
|
| - * password integrity mode, so we check the MAC.
|
| - */
|
| -static PRBool
|
| -sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx,
|
| - SECItem *pwitem)
|
| -{
|
| - SECOidTag contentType;
|
| -
|
| - contentType = SEC_PKCS7ContentType(&pfx->authSafe);
|
| - switch(contentType)
|
| - {
|
| - case SEC_OID_PKCS7_DATA:
|
| - return sec_pkcs12_check_pfx_mac(pfx, pwitem);
|
| - break;
|
| - case SEC_OID_PKCS7_SIGNED_DATA:
|
| - default:
|
| - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
|
| - break;
|
| - }
|
| -
|
| - return PR_FALSE;
|
| -}
|
| -
|
| -/* decode and return the valid PFX. if the PFX item is not valid,
|
| - * NULL is returned.
|
| - */
|
| -static SEC_PKCS12PFXItem *
|
| -sec_pkcs12_get_pfx(SECItem *pfx_data,
|
| - SECItem *pwitem)
|
| -{
|
| - SEC_PKCS12PFXItem *pfx;
|
| - PRBool valid_pfx;
|
| -
|
| - if((pfx_data == NULL) || (pwitem == NULL)) {
|
| - return NULL;
|
| - }
|
| -
|
| - pfx = sec_pkcs12_decode_pfx(pfx_data);
|
| - if(pfx == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem);
|
| - if(valid_pfx != PR_TRUE) {
|
| - SEC_PKCS12DestroyPFX(pfx);
|
| - pfx = NULL;
|
| - }
|
| -
|
| - return pfx;
|
| -}
|
| -
|
| -/* authenticated safe decoding, validation, and access routines
|
| - */
|
| -
|
| -/* convert dogbert beta 3 authenticated safe structure to a post
|
| - * beta three structure, so that we don't have to change more routines.
|
| - */
|
| -static SECStatus
|
| -sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
|
| -{
|
| - SEC_PKCS12Baggage *baggage;
|
| - SEC_PKCS12BaggageItem *bag;
|
| - SECStatus rv = SECSuccess;
|
| -
|
| - if(asafe->old_baggage.espvks == NULL) {
|
| - /* XXX should the ASN1 engine produce a single NULL element list
|
| - * rather than setting the pointer to NULL?
|
| - * There is no need to return an error -- assume that the list
|
| - * was empty.
|
| - */
|
| - return SECSuccess;
|
| - }
|
| -
|
| - baggage = sec_pkcs12_create_baggage(asafe->poolp);
|
| - if(!baggage) {
|
| - return SECFailure;
|
| - }
|
| - bag = sec_pkcs12_create_external_bag(baggage);
|
| - if(!bag) {
|
| - return SECFailure;
|
| - }
|
| -
|
| - PORT_Memcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage));
|
| -
|
| - /* if there are shrouded keys, append them to the bag */
|
| - rv = SECSuccess;
|
| - if(asafe->old_baggage.espvks[0] != NULL) {
|
| - int nEspvk = 0;
|
| - rv = SECSuccess;
|
| - while((asafe->old_baggage.espvks[nEspvk] != NULL) &&
|
| - (rv == SECSuccess)) {
|
| - rv = sec_pkcs12_append_shrouded_key(bag,
|
| - asafe->old_baggage.espvks[nEspvk]);
|
| - nEspvk++;
|
| - }
|
| - }
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -/* decodes the authenticated safe item. a return of NULL indicates
|
| - * an error. however, the error will have occurred either in memory
|
| - * allocation or in decoding the authenticated safe.
|
| - *
|
| - * if an old PFX item has been found, we want to convert the
|
| - * old authenticated safe to the new one.
|
| - */
|
| -static SEC_PKCS12AuthenticatedSafe *
|
| -sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx)
|
| -{
|
| - SECItem *der_asafe = NULL;
|
| - SEC_PKCS12AuthenticatedSafe *asafe = NULL;
|
| - SECStatus rv;
|
| -
|
| - if(pfx == NULL) {
|
| - return NULL;
|
| - }
|
| -
|
| - der_asafe = SEC_PKCS7GetContent(&pfx->authSafe);
|
| - if(der_asafe == NULL) {
|
| - /* XXX set error ? */
|
| - goto loser;
|
| - }
|
| -
|
| - asafe = sec_pkcs12_new_asafe(pfx->poolp);
|
| - if(asafe == NULL) {
|
| - goto loser;
|
| - }
|
| -
|
| - if(pfx->old == PR_FALSE) {
|
| - rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
|
| - SEC_PKCS12AuthenticatedSafeTemplate,
|
| - der_asafe);
|
| - asafe->old = PR_FALSE;
|
| - asafe->swapUnicode = pfx->swapUnicode;
|
| - } else {
|
| - /* handle beta exported files */
|
| - rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
|
| - SEC_PKCS12AuthenticatedSafeTemplate_OLD,
|
| - der_asafe);
|
| - asafe->safe = &(asafe->old_safe);
|
| - rv = sec_pkcs12_convert_old_auth_safe(asafe);
|
| - asafe->old = PR_TRUE;
|
| - }
|
| -
|
| - if(rv != SECSuccess) {
|
| - goto loser;
|
| - }
|
| -
|
| - asafe->poolp = pfx->poolp;
|
| -
|
| - return asafe;
|
| -
|
| -loser:
|
| - 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 occurred.
|
| - */
|
| -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 SECStatus
|
| -sec_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
|
| - */
|
| -SECStatus
|
| -SEC_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);
|
| - if(safe_contents == NULL) {
|
| - rv = SECFailure;
|
| - } else {
|
| - safe_contents->swapUnicode = pfx->swapUnicode;
|
| - 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;
|
| -}
|
|
|