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