p12d.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,435 行 · 第 1/5 页

C
2,435
字号
	    p12dcx->errorValue = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;	    goto loser;	}	/* start the decode of the aSafes cinfo... */	rv = sec_pkcs12_decode_start_asafes_cinfo(p12dcx);	if(rv != SECSuccess) {	    goto loser;	}	/* set the filter proc to update the authenticated safes. */	SEC_ASN1DecoderSetFilterProc(p12dcx->pfxDcx,				     sec_pkcs12_decode_asafes_cinfo_update,				     p12dcx, PR_TRUE);    }    if(!before && (dest == &p12dcx->pfx.encodedAuthSafe)) {	/* we are done decoding the authenticatedSafes, so we need to 	 * finish the decoderContext and clear the filter proc	 * and close the hmac callback, if present	 */	p12dcx->aSafeCinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);	p12dcx->aSafeP7Dcx = NULL;	if(!p12dcx->aSafeCinfo) {	    p12dcx->errorValue = PORT_GetError();	    goto loser;	}	SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx);	if(p12dcx->dClose && ((*p12dcx->dClose)(p12dcx->dArg, PR_FALSE) 				!= SECSuccess)) {	    p12dcx->errorValue = PORT_GetError();	    goto loser;	}    }    return;loser:    p12dcx->error = PR_TRUE;}/* SEC_PKCS12DecoderStart *	Creates a decoder context for decoding a PKCS 12 PDU objct. *	This function sets up the initial decoding context for the *	PFX and sets the needed state variables. * *	pwitem - the password for the hMac and any encoded safes. *		 this should be changed to take a callback which retrieves *		 the password.  it may be possible for different safes to *		 have different passwords.  also, the password is already *		 in unicode.  it should probably be converted down below via *		 a unicode conversion callback. *	slot - the slot to import the dataa into should multiple slots  *		 be supported based on key type and cert type? *	dOpen, dClose, dRead, dWrite - digest routines for writing data *		 to a file so it could be read back and the hmack recomputed *		 and verified.  doesn't seem to be away for both encoding *		 and decoding to be single pass, thus the need for these *		 routines. *	dArg - the argument for dOpen, etc. * *	This function returns the decoder context, if it was successful. *	Otherwise, null is returned. */SEC_PKCS12DecoderContext *SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,		       digestOpenFn dOpen, digestCloseFn dClose, 		       digestIOFn dRead, digestIOFn dWrite, void *dArg){    SEC_PKCS12DecoderContext *p12dcx;    PRArenaPool *arena;    arena = PORT_NewArena(2048); /* different size? */    if(!arena) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return NULL;    }    /* allocate the decoder context and set the state variables */    p12dcx = (SEC_PKCS12DecoderContext*)PORT_ArenaZAlloc(arena, sizeof(SEC_PKCS12DecoderContext));    if(!p12dcx) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    p12dcx->arena = arena;    p12dcx->pwitem = pwitem;    p12dcx->slot = (slot ? slot : PK11_GetInternalKeySlot());    p12dcx->wincx = wincx;#ifdef IS_LITTLE_ENDIAN    p12dcx->swapUnicodeBytes = PR_TRUE;#else    p12dcx->swapUnicodeBytes = PR_FALSE;#endif    p12dcx->errorValue = 0;    p12dcx->error = PR_FALSE;    /* a slot is *required */    if(!slot) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* start the decoding of the PFX and set the notify proc     * for the PFX item.     */    p12dcx->pfxDcx = SEC_ASN1DecoderStart(p12dcx->arena, &p12dcx->pfx,    					  sec_PKCS12PFXItemTemplate);    if(!p12dcx->pfxDcx) {	PORT_SetError(SEC_ERROR_NO_MEMORY); 	goto loser;    }    SEC_ASN1DecoderSetNotifyProc(p12dcx->pfxDcx, 				 sec_pkcs12_decoder_pfx_notify_proc,    				 p12dcx);         /* set up digest functions */    p12dcx->dOpen = dOpen;    p12dcx->dWrite = dWrite;    p12dcx->dClose = dClose;    p12dcx->dRead = dRead;    p12dcx->dArg = dArg;    return p12dcx;loser:    PORT_FreeArena(arena, PR_TRUE);    return NULL;}/* SEC_PKCS12DecoderUpdate  *	Streaming update sending more data to the decoder.  If  *	an error occurs, SECFailure is returned. * *	p12dcx - the decoder context  *	data, len - the data buffer and length of data to send to  *		the update functions. */SECStatusSEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx,			unsigned char *data, unsigned long len){    SECStatus rv;    if(!p12dcx || p12dcx->error) {	return SECFailure;    }    /* update the PFX decoder context */    rv = SEC_ASN1DecoderUpdate(p12dcx->pfxDcx, (const char *)data, len);    if(rv != SECSuccess) {	p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;	goto loser;    }    return SECSuccess;loser:    p12dcx->error = PR_TRUE;    return SECFailure;}/* IN_BUF_LEN should be larger than SHA1_LENGTH */#define IN_BUF_LEN		80/* verify the hmac by reading the data from the temporary file * using the routines specified when the decodingContext was  * created and return SECSuccess if the hmac matches. */static SECStatussec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx){    SECStatus rv = SECFailure;    PBEBitGenContext *pbeCtxt = NULL;    SECItem *hmacKey = NULL, hmacRes;    unsigned char buf[IN_BUF_LEN];    void *hmacCx;    unsigned int bufLen;    int iteration;        if(!p12dcx || p12dcx->error) {	return SECFailure;    }    /* generate hmac key */    if(p12dcx->macData.iter.data) {	iteration = (int)DER_GetInteger(&p12dcx->macData.iter);    } else {	iteration = 1;    }    pbeCtxt = PBE_CreateContext(SECOID_GetAlgorithmTag(				&p12dcx->macData.safeMac.digestAlgorithm),				pbeBitGenIntegrityKey, p12dcx->pwitem,				&p12dcx->macData.macSalt, 160, iteration);    if(!pbeCtxt) {	return SECFailure;    }    hmacKey = PBE_GenerateBits(pbeCtxt);    PBE_DestroyContext(pbeCtxt);    pbeCtxt = NULL;    if(!hmacKey) {	return SECFailure;    }    /* init hmac */    hmacCx = HMAC_Create(SECOID_GetAlgorithmTag(				&p12dcx->macData.safeMac.digestAlgorithm),			 hmacKey->data, hmacKey->len);    SECITEM_ZfreeItem(hmacKey, PR_TRUE);    hmacKey = NULL;    if(!hmacCx) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    HMAC_Begin((HMACContext*)hmacCx);    /* try to open the data for readback */    if(p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE) 			!= SECSuccess)) {	goto loser;    }    /* read the data back IN_BUF_LEN bytes at a time and recompute     * the hmac.  if fewer bytes are read than are requested, it is     * assumed that the end of file has been reached. if bytesRead     * is returned as -1, then an error occured reading from the      * file.     */    while(1) {	int bytesRead = (*p12dcx->dRead)(p12dcx->dArg, buf, IN_BUF_LEN);	if(bytesRead == -1) {	    goto loser;	}	HMAC_Update((HMACContext*)hmacCx, buf, bytesRead);	if(bytesRead < IN_BUF_LEN) {	    break;	}    }    /* finish the hmac context */    HMAC_Finish((HMACContext*)hmacCx, buf, &bufLen, IN_BUF_LEN);    HMAC_Destroy((HMACContext*)hmacCx);    hmacCx = NULL;    hmacRes.data = buf;    hmacRes.len = bufLen;    /* is the hmac computed the same as the hmac which was decoded? */    rv = SECSuccess;    if(SECITEM_CompareItem(&hmacRes, &p12dcx->macData.safeMac.digest) 			!= SECEqual) {	PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);	rv = SECFailure;    }loser:    /* close the file and remove it */    if(p12dcx->dClose) {	(*p12dcx->dClose)(p12dcx->dArg, PR_TRUE);    }    if(hmacCx) {	HMAC_Destroy((HMACContext*)hmacCx);    }    if(hmacKey) {	SECITEM_ZfreeItem(hmacKey, PR_TRUE);    }    return rv;}/* SEC_PKCS12DecoderVerify * 	Verify the macData or the signature of the decoded PKCS 12 PDU. *	If the signature or the macData do not match, SECFailure is *	returned. * * 	p12dcx - the decoder context  */SECStatusSEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx){    SECStatus rv = SECSuccess;    /* make sure that no errors have occured... */    if(!p12dcx || p12dcx->error) {	return SECFailure;    }    /* check the signature or the mac depending on the type of     * integrity used.     */    if(p12dcx->pfx.encodedMacData.len) {	rv = SEC_ASN1DecodeItem(p12dcx->arena, &p12dcx->macData,				sec_PKCS12MacDataTemplate,				&p12dcx->pfx.encodedMacData);	if(rv == SECSuccess) {	    return sec_pkcs12_decoder_verify_mac(p12dcx);	} else {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	}    } else {	if(SEC_PKCS7VerifySignature(p12dcx->aSafeCinfo, certUsageEmailSigner,				    PR_FALSE)) {	    return SECSuccess;	} else {	    PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);	}    }    return SECFailure;}/* SEC_PKCS12DecoderFinish *	Free any open ASN1 or PKCS7 decoder contexts and then *	free the arena pool which everything should be allocated *	from.  This function should be called upon completion of *	decoding and installing of a pfx pdu.  This should be *	called even if an error occurs. * *	p12dcx - the decoder context */voidSEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx){    void *freedCtxt = NULL;    if(!p12dcx) {	return;    }    if(p12dcx->pfxDcx) {	SEC_ASN1DecoderFinish(p12dcx->pfxDcx);	p12dcx->pfxDcx = NULL;    }    if(p12dcx->aSafeDcx) {	SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);	p12dcx->aSafeDcx = NULL;    }    if(p12dcx->currentASafeP7Dcx) {	SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx);	p12dcx->currentASafeP7Dcx = NULL;    }    if(p12dcx->aSafeP7Dcx) {	SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);    }    if(p12dcx->hmacDcx) {	SEC_ASN1DecoderFinish(p12dcx->hmacDcx);	p12dcx->hmacDcx = NULL;    }    if(p12dcx->arena) {	PORT_FreeArena(p12dcx->arena, PR_TRUE);    }}static SECStatussec_pkcs12_decoder_set_attribute_value(sec_PKCS12SafeBag *bag,			       SECOidTag attributeType,			       SECItem *attrValue){    int i = 0;    SECOidData *oid;    if(!bag || !attrValue) {	return SECFailure;    }    oid = SECOID_FindOIDByTag(attributeType);    if(!oid) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    if(!bag->attribs) {	bag->attribs = (sec_PKCS12Attribute**)PORT_ArenaZAlloc(bag->arena, 					sizeof(sec_PKCS12Attribute *) * 2);    } else {	while(bag->attribs[i]) i++;	bag->attribs = (sec_PKCS12Attribute **)PORT_ArenaGrow(bag->arena, 				      bag->attribs, 				      (i + 1) * sizeof(sec_PKCS12Attribute *),				      (i + 2) * sizeof(sec_PKCS12Attribute *));    }    if(!bag->attribs) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    bag->attribs[i] = (sec_PKCS12Attribute*)PORT_ArenaZAlloc(bag->arena, 						  sizeof(sec_PKCS12Attribute));    if(!bag->attribs) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    bag->attribs[i]->attrValue = (SECItem**)PORT_ArenaZAlloc(bag->arena, 						  sizeof(SECItem *) * 2);    if(!bag->attribs[i]->attrValue) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    bag->attribs[i+1] = NULL;    bag->attribs[i]->attrValue[0] = attrValue;    bag->attribs[i]->attrValue[1] = NULL;    if(SECITEM_CopyItem(bag->arena, &bag->attribs[i]->attrType, &oid->oid)			!= SECSuccess) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return SECFailure;    }    return SECSuccess;}static SECItem *sec_pkcs12_get_attribute_value(sec_PKCS12SafeBag *bag,			       SECOidTag attributeType){    int i = 0;    if(!bag->attribs) {	return NULL;    }    while(bag->attribs[i] != NULL) {	if(SECOID_FindOIDTag(&bag->attribs[i]->attrType) 			== attributeType) {	    return bag->attribs[i]->attrValue[0];	}	i++;    }    return NULL;}/* For now, this function will merely remove any ":" * in the nickname which the PK11 functions may have * placed there.  This will keep dual certs from appearing * twice under "Your" certificates when imported onto smart * cards.  Once with the name "Slot:Cert" and another with * the nickname "Slot:Slot:Cert" */static voidsec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick){    char *nickname;    char *delimit;    int delimitlen;     nickname = (char*)nick->data; /*Mac breaks without this type cast*/    if ((delimit = PORT_Strchr(nickname, ':')) != NULL) {        char *slotName;	int slotNameLen;	slotNameLen = delimit-nickname;	slotName = PORT_NewArray(char, (slotNameLen+1));	PORT_Assert(slotName);	if (slotName == NULL) {	  /* What else can we do?*/	  return;	}	PORT_Memcpy(slotName, nickname, slotNameLen);	slotName[slotNameLen] = '\0';	if (PORT_Strcmp(PK11_GetTokenName(slot), slotName) == 0) {	  delimitlen = PORT_Strlen(delimit+1);	  PORT_Memmove(nickname, delimit+1, delimitlen+1);	  nick->len = delimitlen;	}	PORT_Free(slotName);    } }static SECItem *sec_pkcs12_get_nickname(sec_PKCS12SafeBag *bag){

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?