p12d.c

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

C
2,435
字号
    SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsDcx);    return;}/* initialize the safeContents for decoding.  this routine * is used for authenticatedSafes as well as nested safeContents. */static sec_PKCS12SafeContentsContext *sec_pkcs12_decoder_safe_contents_init_decode(SEC_PKCS12DecoderContext *p12dcx,					     PRBool nestedSafe){    sec_PKCS12SafeContentsContext *safeContentsCtx = NULL;    const SEC_ASN1Template *theTemplate;    if(!p12dcx || p12dcx->error) {	return NULL;    }    /* allocate a new safeContents list or grow the existing list and     * append the new safeContents onto the end.     */    if(!p12dcx->safeContentsCnt) {	p12dcx->safeContentsList = 	    (sec_PKCS12SafeContentsContext**)PORT_ArenaZAlloc(p12dcx->arena, 	       			 sizeof(sec_PKCS12SafeContentsContext *));    } else {	p12dcx->safeContentsList = 	   (sec_PKCS12SafeContentsContext **) PORT_ArenaGrow(p12dcx->arena,			p12dcx->safeContentsList,			(p12dcx->safeContentsCnt * 				sizeof(sec_PKCS12SafeContentsContext *)),			(1 + p12dcx->safeContentsCnt * 				sizeof(sec_PKCS12SafeContentsContext *)));    }    if(!p12dcx->safeContentsList) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	goto loser;    }    p12dcx->safeContentsList[p12dcx->safeContentsCnt] =         (sec_PKCS12SafeContentsContext*)PORT_ArenaZAlloc(					p12dcx->arena,					sizeof(sec_PKCS12SafeContentsContext));    p12dcx->safeContentsList[p12dcx->safeContentsCnt+1] = NULL;    if(!p12dcx->safeContentsList[p12dcx->safeContentsCnt]) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	goto loser;    }    /* set up the state variables */    safeContentsCtx = p12dcx->safeContentsList[p12dcx->safeContentsCnt];    p12dcx->safeContentsCnt++;    safeContentsCtx->p12dcx = p12dcx;    safeContentsCtx->arena = p12dcx->arena;    /* begin the decoding -- the template is based on whether we are     * decoding a nested safeContents or not.     */    if(nestedSafe == PR_TRUE) {	theTemplate = sec_PKCS12NestedSafeContentsDecodeTemplate;    } else {	theTemplate = sec_PKCS12SafeContentsDecodeTemplate;    }    /* start the decoder context */    safeContentsCtx->safeContentsDcx = SEC_ASN1DecoderStart(p12dcx->arena, 					&safeContentsCtx->safeContents,					theTemplate);	    if(!safeContentsCtx->safeContentsDcx) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	goto loser;    }    /* set the safeContents notify procedure to look for     * and start the decode of safeBags.     */    SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->safeContentsDcx, 				sec_pkcs12_decoder_safe_contents_notify,				safeContentsCtx);    return safeContentsCtx;loser:    /* in the case of an error, we want to finish the decoder     * context and set the error flag.     */    if(safeContentsCtx && safeContentsCtx->safeContentsDcx) {	SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);	safeContentsCtx->safeContentsDcx = NULL;    }    p12dcx->error = PR_TRUE;    return NULL;}/* wrapper for updating safeContents.  this is set as the filter of * safeBag when there is a nested safeContents. */static voidsec_pkcs12_decoder_nested_safe_contents_update(void *arg, const char *buf,					  unsigned long len, int depth,					  SEC_ASN1EncodingPart data_kind){    sec_PKCS12SafeContentsContext *safeContentsCtx =         (sec_PKCS12SafeContentsContext *)arg;    SEC_PKCS12DecoderContext *p12dcx;    SECStatus rv;    /* check for an error */    if(!safeContentsCtx || !safeContentsCtx->p12dcx 			|| safeContentsCtx->p12dcx->error) {	return;    }    /* no need to update if no data sent in */    if(!len || !buf) {	return;    }    /* update the decoding context */    p12dcx = safeContentsCtx->p12dcx;    rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len);    if(rv != SECSuccess) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	goto loser;    }    return;loser:    /* handle any errors.  If a decoding context is open, close it. */    p12dcx->error = PR_TRUE;    if(safeContentsCtx->safeContentsDcx) {	SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);	safeContentsCtx->safeContentsDcx = NULL;    }}/* whenever a new safeContentsSafeBag is encountered, we need * to init a safeContentsContext.   */static SECStatus  sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext 							*safeContentsCtx){    /* check for an error */    if(!safeContentsCtx || !safeContentsCtx->p12dcx || 		safeContentsCtx->p12dcx->error) {	return SECFailure;    }    safeContentsCtx->nestedCtx = sec_pkcs12_decoder_safe_contents_init_decode(						safeContentsCtx->p12dcx,						PR_TRUE);    if(!safeContentsCtx->nestedCtx) {	return SECFailure;    }    /* set up new filter proc */    SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx,				 sec_pkcs12_decoder_safe_contents_notify,				 safeContentsCtx->nestedCtx);    SEC_ASN1DecoderSetFilterProc(safeContentsCtx->currentSafeBagDcx,				 sec_pkcs12_decoder_nested_safe_contents_update,				 safeContentsCtx->nestedCtx, PR_TRUE);    return SECSuccess;}/* when the safeContents is done decoding, we need to reset the * proper filter and notify procs and close the decoding context  */static SECStatussec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext							*safeContentsCtx){    /* check for error */    if(!safeContentsCtx || !safeContentsCtx->p12dcx || 		safeContentsCtx->p12dcx->error) {	return SECFailure;    }    /* clean up */	    SEC_ASN1DecoderClearFilterProc(safeContentsCtx->currentSafeBagDcx);    SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx);    SEC_ASN1DecoderFinish(safeContentsCtx->nestedCtx->safeContentsDcx);    safeContentsCtx->nestedCtx->safeContentsDcx = NULL;    safeContentsCtx->nestedCtx = NULL;    return SECSuccess;}/* wrapper for updating safeContents.  This is used when decoding * the nested safeContents and any authenticatedSafes. */static voidsec_pkcs12_decoder_safe_contents_callback(void *arg, const char *buf,					  unsigned long len){    SECStatus rv;    sec_PKCS12SafeContentsContext *safeContentsCtx =         (sec_PKCS12SafeContentsContext *)arg;    SEC_PKCS12DecoderContext *p12dcx;    /* check for error */      if(!safeContentsCtx || !safeContentsCtx->p12dcx 		|| safeContentsCtx->p12dcx->error) {	return;    }    p12dcx = safeContentsCtx->p12dcx;    /* update the decoder */    rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len);    if(rv != SECSuccess) {	p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;	goto loser;    }    return;loser:    /* set the error and finish the context */    p12dcx->error = PR_TRUE;    if(safeContentsCtx->safeContentsDcx) {	SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);	safeContentsCtx->safeContentsDcx = NULL;    }    return;}/* this is a wrapper for the ASN1 decoder to call SEC_PKCS7DecoderUpdate */static voidsec_pkcs12_decoder_wrap_p7_update(void *arg, const char *data,				  unsigned long len, int depth,				  SEC_ASN1EncodingPart data_kind){    SEC_PKCS7DecoderContext *p7dcx = (SEC_PKCS7DecoderContext *)arg;    SEC_PKCS7DecoderUpdate(p7dcx, data, len);}/* notify function for decoding aSafes.  at the beginning, * of an authenticatedSafe, we start a decode of a safeContents. * at the end, we clean up the safeContents decoder context and * reset state variables  */static voidsec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, 			       int real_depth){    SEC_PKCS12DecoderContext *p12dcx;    sec_PKCS12SafeContentsContext *safeContentsCtx;    /* make sure no error occurred. */    p12dcx = (SEC_PKCS12DecoderContext *)arg;    if(!p12dcx || p12dcx->error) {	return;    }    if(before) {	/* init a new safeContentsContext */	safeContentsCtx = sec_pkcs12_decoder_safe_contents_init_decode(p12dcx, 								PR_FALSE);	if(!safeContentsCtx) {	    goto loser;	}	/* set up password and encryption key information */	p12dcx->currentASafeKeyPwd = 	    (SEC_PKCS5KeyAndPassword*)PORT_ArenaZAlloc(p12dcx->arena, 					      sizeof(SEC_PKCS5KeyAndPassword));	if(!p12dcx->currentASafeKeyPwd) {	    p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	    goto loser;	}	p12dcx->currentASafeKeyPwd->pwitem = p12dcx->pwitem;	p12dcx->currentASafeKeyPwd->slot = p12dcx->slot;	p12dcx->currentASafeKeyPwd->wincx = p12dcx->wincx;	/* initiate the PKCS7ContentInfo decode */	p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart(				sec_pkcs12_decoder_safe_contents_callback,				safeContentsCtx, 				p12dcx->pwfn, p12dcx->pwfnarg,				sec_pkcs12_decoder_get_decrypt_key, 				p12dcx->currentASafeKeyPwd, 				sec_pkcs12_decoder_decryption_allowed);	if(!p12dcx->currentASafeP7Dcx) {	    p12dcx->errorValue = PORT_GetError();	    goto loser;	}	SEC_ASN1DecoderSetFilterProc(p12dcx->aSafeDcx, 				     sec_pkcs12_decoder_wrap_p7_update,				     p12dcx->currentASafeP7Dcx, PR_TRUE);    }    if(!before) {	/* if one is being decoded, finish the decode */	if(p12dcx->currentASafeP7Dcx != NULL) {	    if(!SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx)) {		p12dcx->currentASafeP7Dcx = NULL;		p12dcx->errorValue = PORT_GetError();		goto loser;	    }	    p12dcx->currentASafeP7Dcx = NULL;	}	p12dcx->currentASafeP7Dcx = NULL;	if(p12dcx->currentASafeKeyPwd->key != NULL) {	    p12dcx->currentASafeKeyPwd->key = NULL;	}    }    return;loser:    /* set the error flag */    p12dcx->error = PR_TRUE;    return;}/* wrapper for updating asafes decoding context.  this function * writes data being decoded to disk, so that a mac can be computed * later.   */static voidsec_pkcs12_decoder_asafes_callback(void *arg, const char *buf, 				  unsigned long len){    SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;    SECStatus rv;    if(!p12dcx || p12dcx->error) {	return;    }    /* update the context */    rv = SEC_ASN1DecoderUpdate(p12dcx->aSafeDcx, buf, len);    if(rv != SECSuccess) {	p12dcx->error = (PRBool)SEC_ERROR_NO_MEMORY;	goto loser;    }    /* if we are writing to a file, write out the new information */    if(p12dcx->dWrite) {	unsigned long writeLen = (*p12dcx->dWrite)(p12dcx->dArg, 							   (unsigned char *)buf, len);	if(writeLen != len) {	    p12dcx->errorValue = PORT_GetError();	    goto loser;	}    }    return;loser:    /* set the error flag */    p12dcx->error = PR_TRUE;    SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);    p12dcx->aSafeDcx = NULL;    return;}   /* start the decode of an authenticatedSafe contentInfo. */ static SECStatussec_pkcs12_decode_start_asafes_cinfo(SEC_PKCS12DecoderContext *p12dcx){    if(!p12dcx || p12dcx->error) {	return SECFailure;    }    /* start the decode context */    p12dcx->aSafeDcx = SEC_ASN1DecoderStart(p12dcx->arena,     					&p12dcx->authSafe,    					sec_PKCS12AuthenticatedSafeTemplate);    if(!p12dcx->aSafeDcx) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;   	goto loser;    }    /* set the notify function */    SEC_ASN1DecoderSetNotifyProc(p12dcx->aSafeDcx,    				 sec_pkcs12_decoder_asafes_notify, p12dcx);    /* begin the authSafe decoder context */    p12dcx->aSafeP7Dcx = SEC_PKCS7DecoderStart(    				sec_pkcs12_decoder_asafes_callback, p12dcx,    				p12dcx->pwfn, p12dcx->pwfnarg, NULL, NULL, NULL);    if(!p12dcx->aSafeP7Dcx) {	p12dcx->errorValue = SEC_ERROR_NO_MEMORY;	goto loser;    }      /* open the temp file for writing, if the filter functions were set */     if(p12dcx->dOpen && (*p12dcx->dOpen)(p12dcx->dArg, PR_FALSE) 				!= SECSuccess) {	p12dcx->errorValue = PORT_GetError();	goto loser;    }    return SECSuccess;loser:    p12dcx->error = PR_TRUE;    if(p12dcx->aSafeDcx) {	SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);	p12dcx->aSafeDcx = NULL;    }     if(p12dcx->aSafeP7Dcx) {	SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);	p12dcx->aSafeP7Dcx = NULL;    }    return SECFailure;}/* wrapper for updating the safeContents.  this function is used as * a filter for the pfx when decoding the authenticated safes  */static void sec_pkcs12_decode_asafes_cinfo_update(void *arg, const char *buf,				      unsigned long len, int depth,				      SEC_ASN1EncodingPart data_kind){    SEC_PKCS12DecoderContext *p12dcx;    SECStatus rv;    p12dcx = (SEC_PKCS12DecoderContext*)arg;    if(!p12dcx || p12dcx->error) {	return;    }    /* update the safeContents decoder */    rv = SEC_PKCS7DecoderUpdate(p12dcx->aSafeP7Dcx, buf, len);    if(rv != SECSuccess) {	p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;	goto loser;    }    return;loser:    /* did we find an error?  if so, close the context and set the      * error flag.     */    SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);    p12dcx->aSafeP7Dcx = NULL;    p12dcx->error = PR_TRUE;}/* notify procedure used while decoding the pfx.  When we encounter * the authSafes, we want to trigger the decoding of authSafes as well * as when we encounter the macData, trigger the decoding of it.  we do * this because we we are streaming the decoder and not decoding in place. * the pfx which is the destination, only has the version decoded into it. */static void sec_pkcs12_decoder_pfx_notify_proc(void *arg, PRBool before, void *dest,				   int real_depth){    SECStatus rv;    SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext*)arg;    /* if an error occurrs, clear the notifyProc and the filterProc      * and continue.      */    if(p12dcx->error) {	SEC_ASN1DecoderClearNotifyProc(p12dcx->pfxDcx);	SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx);	return;    }    if(before && (dest == &p12dcx->pfx.encodedAuthSafe)) {	/* we want to make sure this is a version we support */	if(!sec_pkcs12_proper_version(&p12dcx->pfx)) {

⌨️ 快捷键说明

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