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