/* Getting encapsulated TS_TST_INFO object from PKCS7. */ TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token) { PKCS7_SIGNED *pkcs7_signed; PKCS7 *enveloped; ASN1_TYPE *tst_info_wrapper; ASN1_OCTET_STRING *tst_info_der; const unsigned char *p; if (!PKCS7_type_is_signed(token)) { TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE); return NULL; } /* Content must be present. */ if (PKCS7_get_detached(token)) { TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_DETACHED_CONTENT); return NULL; } /* We have a signed data with content. */ pkcs7_signed = token->d.sign; enveloped = pkcs7_signed->contents; if (OBJ_obj2nid(enveloped->type) != NID_id_smime_ct_TSTInfo) { TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_PKCS7_TYPE); return NULL; } /* We have a DER encoded TST_INFO as the signed data. */ tst_info_wrapper = enveloped->d.other; if (tst_info_wrapper->type != V_ASN1_OCTET_STRING) { TSerr(TS_F_PKCS7_TO_TS_TST_INFO, TS_R_BAD_TYPE); return NULL; } /* We have the correct ASN1_OCTET_STRING type. */ tst_info_der = tst_info_wrapper->value.octet_string; /* At last, decode the TST_INFO. */ p = tst_info_der->data; return d2i_TS_TST_INFO(NULL, &p, tst_info_der->length); }
int EAC_CTX_init_ef_cardsecurity(const unsigned char *ef_cardsecurity, size_t ef_cardsecurity_len, EAC_CTX *ctx) { PKCS7 *p7 = NULL, *signed_data; ASN1_OCTET_STRING *os; int r = 0; check(ef_cardsecurity, "Invalid arguments"); if (!d2i_PKCS7(&p7, &ef_cardsecurity, ef_cardsecurity_len) || !PKCS7_type_is_signed(p7)) goto err; if (ctx && ctx->ca_ctx && !(ctx->ca_ctx->flags & CA_FLAG_DISABLE_PASSIVE_AUTH)) check((CA_passive_authentication(ctx, p7) == 1), "Failed to perform passive authentication"); signed_data = p7->d.sign->contents; if (OBJ_obj2nid(signed_data->type) != NID_id_SecurityObject || ASN1_TYPE_get(signed_data->d.other) != V_ASN1_OCTET_STRING) goto err; os = signed_data->d.other->value.octet_string; if (!EAC_CTX_init_ef_cardaccess(os->data, os->length, ctx) || !ctx || !ctx->ca_ctx || !ctx->ca_ctx->ka_ctx) goto err; r = 1; err: if (p7) PKCS7_free(p7); return r; }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp, *mdc; int ret = 0, i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; EVP_MD_CTX_init(&mdc_tmp); if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type = OBJ_obj2nid(si->digest_alg->algorithm); btmp = bio; for (;;) { if ((btmp == NULL) || ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp, &mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; /* * Workaround for some broken clients that put the signature OID * instead of the digest OID in digest_alg->algorithm */ if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) break; btmp = BIO_next(btmp); } /* * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes */ if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) goto err; sk = si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len; int alen; ASN1_OCTET_STRING *message_digest; if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) goto err; message_digest = PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data, md_dat, md_len))) { #if 0 { int ii; for (ii = 0; ii < message_digest->length; ii++) printf("%02X", message_digest->data[ii]); printf(" sent\n"); for (ii = 0; ii < md_len; ii++) printf("%02X", md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret = -1; goto err; } if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); if (alen <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); ret = -1; goto err; } if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) goto err; OPENSSL_free(abuf); } os = si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; goto err; } else ret = 1; err: EVP_MD_CTX_cleanup(&mdc_tmp); return (ret); }
/******************************************************************************* 函数名称: cert_pkcs7_unwrap 功能描述: 解析从服务器收到的信息,包括验证签名以及解密。 输入参数: struct scep *s, SCEP操作的结构体指针。 输出参数: 无 返 回 值: 1,成功;-1,失败 -------------------------------------------------------------------------------- 最近一次修改记录: 修改作者:王朝 修改目的:添加新函数 修改日期:2009年12月28日 *********************************************************************************/ s32 cert_pkcs7_unwrap(struct scep *s) { BIO *memorybio = NULL; BIO *outbio = NULL; BIO *pkcs7bio = NULL; s32 bytes, used, retval = -1; STACK_OF(PKCS7_SIGNER_INFO) *sk = NULL; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si = NULL; STACK_OF(X509_ATTRIBUTE) *attribs = NULL; s8 *p = NULL; u8 buffer[1024]; X509 *recipientcert = NULL; EVP_PKEY *recipientkey = NULL; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if ((BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) { goto end; } BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL); BIO_free(memorybio); memorybio = NULL; /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { goto end; } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL); if (pkcs7bio == NULL) { goto end; } /* */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } (void)BIO_flush(outbio); /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL) { goto end; } /* Verify signature */ si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cert_cacert) <= 0) { goto end; } /* Get signed attributes */ attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL) { goto end; } /* Transaction id */ if (1 != cert_get_signed_attribute(attribs, nid_transId, V_ASN1_PRINTABLESTRING, &p)) { goto end; } if (strncmp(s->transaction_id, p, strlen(p))) { goto end; } /* Message type, should be of type CertRep */ if (1 != cert_get_signed_attribute(attribs, nid_messageType, V_ASN1_PRINTABLESTRING, &p)) { goto end; } if (atoi(p) != 3) { goto end; } /* Sender and recipient nonces: */ if (1 == cert_get_signed_attribute(attribs, nid_senderNonce, V_ASN1_OCTET_STRING, &p)) { s->reply_sender_nonce = (u8 *)p; } else { s->reply_sender_nonce = NULL; } if ( 1 != cert_get_signed_attribute(attribs, nid_recipientNonce,V_ASN1_OCTET_STRING, &p)) { goto end; } s->reply_recipient_nonce = (u8 *)p; /* Get pkiStatus */ if (1 != cert_get_signed_attribute(attribs, nid_pkiStatus,V_ASN1_PRINTABLESTRING, &p)) { goto end; } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: s->pki_status = SCEP_PKISTATUS_PENDING; break; default: goto end; } /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if (1 != cert_get_signed_attribute(attribs, nid_failInfo,V_ASN1_PRINTABLESTRING, &p)) { goto end; } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; break; default: goto end; } } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ retval = 1; goto end; } /* We got success and expect data */ if (used == 0) { goto end; } /* Decrypt the inner PKCS#7 */ if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT)) { recipientcert = s->signercert; recipientkey = s->signerkey; } else { recipientcert = cert_localcert; recipientkey = cert_rsa; } p7enc = d2i_PKCS7_bio(outbio, NULL); if (p7enc == NULL) { goto end; } BIO_free(outbio); outbio = NULL; /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { goto end; } (void)BIO_flush(outbio); /* Write decrypted data */ s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload); BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL); retval = 1; end: if(NULL != outbio) { BIO_free(outbio); } if(NULL != memorybio) { BIO_free(memorybio); } if(NULL != pkcs7bio) { BIO_free(pkcs7bio); } if(NULL != p7enc) { PKCS7_free(p7enc); } return retval; }
/** Verifies the validility of a PE/COFF Authenticode Signature as described in "Windows Authenticode Portable Executable Signature Format". If AuthData is NULL, then return FALSE. If ImageHash is NULL, then return FALSE. Caution: This function may receive untrusted input. PE/COFF Authenticode is external input, so this function will do basic check for Authenticode data structure. @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed PE/COFF image to be verified. @param[in] DataSize Size of the Authenticode Signature in bytes. @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which is used for certificate chain verification. @param[in] CertSize Size of the trusted certificate in bytes. @param[in] ImageHash Pointer to the original image file hash value. The procudure for calculating the image hash value is described in Authenticode specification. @param[in] HashSize Size of Image hash value in bytes. @retval TRUE The specified Authenticode Signature is valid. @retval FALSE Invalid Authenticode Signature. **/ BOOLEAN EFIAPI AuthenticodeVerify ( IN CONST UINT8 *AuthData, IN UINTN DataSize, IN CONST UINT8 *TrustedCert, IN UINTN CertSize, IN CONST UINT8 *ImageHash, IN UINTN HashSize ) { BOOLEAN Status; PKCS7 *Pkcs7; CONST UINT8 *OrigAuthData; UINT8 *SpcIndirectDataContent; UINT8 Asn1Byte; UINTN ContentSize; UINT8 *SpcIndirectDataOid; // // Check input parameters. // if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) { return FALSE; } if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) { return FALSE; } Status = FALSE; Pkcs7 = NULL; OrigAuthData = AuthData; // // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature // Pkcs7 = d2i_PKCS7 (NULL, &AuthData, (int)DataSize); if (Pkcs7 == NULL) { goto _Exit; } // // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) // if (!PKCS7_type_is_signed (Pkcs7)) { goto _Exit; } // // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to // some authenticode-specific structure. Use opaque ASN.1 string to retrieve // PKCS#7 ContentInfo here. // SpcIndirectDataOid = (UINT8 *)(Pkcs7->d.sign->contents->type->data); if (CompareMem ( SpcIndirectDataOid, mSpcIndirectOidValue, sizeof (mSpcIndirectOidValue) ) != 0) { // // Un-matched SPC_INDIRECT_DATA_OBJID. // goto _Exit; } SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data); // // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent. // Asn1Byte = *(SpcIndirectDataContent + 1); if ((Asn1Byte & 0x80) == 0) { // // Short Form of Length Encoding // ContentSize = (UINTN) (Asn1Byte & 0x7F); // // Skip the SEQUENCE Tag; // SpcIndirectDataContent += 2; } else if ((Asn1Byte & 0x82) == 0x82) { // // Long Form of Length Encoding, only support two bytes. // ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3)); // // Skip the SEQUENCE Tag; // SpcIndirectDataContent += 4; } else { goto _Exit; } // // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent // defined in Authenticode // NOTE: Need to double-check HashLength here! // if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) { // // Un-matched PE/COFF Hash Value // goto _Exit; } // // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature // Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize); _Exit: // // Release Resources // PKCS7_free (Pkcs7); return Status; }
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i,j; BIO *out=NULL,*btmp=NULL; X509_ALGOR *xa; const EVP_MD *evp_md; const EVP_CIPHER *evp_cipher=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; EVP_PKEY *pkey; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: md_sk=p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; xalg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; xalg=p7->d.enveloped->enc_data->algorithm; evp_cipher=p7->d.enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } if (md_sk != NULL) { for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) { xa=sk_X509_ALGOR_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } j=OBJ_obj2nid(xa->algorithm); evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } BIO_set_md(btmp,evp_md); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } } if (evp_cipher != NULL) { unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; int keylen,ivlen; int jj,max; unsigned char *tmp; EVP_CIPHER_CTX *ctx; if ((btmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); if (RAND_bytes(key,keylen) <= 0) goto err; xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1); if (ivlen > 0) { if (xalg->parameter == NULL) xalg->parameter=ASN1_TYPE_new(); if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) goto err; } /* Lets do the pub key stuff :-) */ max=0; for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if (ri->cert == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); goto err; } pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_size(pkey); EVP_PKEY_free(pkey); if (max < jj) max=jj; } if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE); goto err; } for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); EVP_PKEY_free(pkey); if (jj <= 0) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB); OPENSSL_free(tmp); goto err; } M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj); } OPENSSL_free(tmp); OPENSSL_cleanse(key, keylen); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } if (bio == NULL) { if (PKCS7_is_detached(p7)) bio=BIO_new(BIO_s_null()); else { if (PKCS7_type_is_signed(p7) ) { if ( PKCS7_type_is_data(p7->d.sign->contents)) { ASN1_OCTET_STRING *os; os=p7->d.sign->contents->d.data; if (os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); } else if ( PKCS7_type_is_octet_string(p7->d.sign->contents) ) { ASN1_OCTET_STRING *os; os=p7->d.sign->contents->d.other->value.octet_string; if (os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); } } if(bio == NULL) { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } } } BIO_push(out,bio); bio=NULL; if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); out=NULL; } return(out); }
/* * Unwrap PKCS#7 data and decrypt if necessary */ int pkcs7_unwrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info, char* data, int datalen) { BIO *memorybio = NULL; BIO *outbio = NULL; BIO *pkcs7bio = NULL; int i, bytes, used; STACK_OF(PKCS7_SIGNER_INFO) *sk; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attribs; char *p = NULL; unsigned char buffer[1024]; X509 *recipientcert; EVP_PKEY *recipientkey; int ret = SCEP_PKISTATUS_P7; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if (ctx->verbose){ qeo_log_i("reading outer PKCS#7"); } if (BIO_write(memorybio, data, datalen) <= 0) { qeo_log_e("error reading PKCS#7 data"); goto error; } if (ctx->verbose){ qeo_log_i("PKCS#7 payload size: %d bytes", datalen); } s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL ); if (s->reply_p7 == NULL ) { qeo_log_e("error retrieving PKCS#7 data"); goto error; } if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, s->reply_p7); } /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { qeo_log_e("PKCS#7 is not signed!"); goto error; } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL ); if (pkcs7bio == NULL ) { qeo_log_e("cannot get PKCS#7 data"); goto error; } /* Copy enveloped data from PKCS#7 */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } (void)BIO_flush(outbio); if (ctx->verbose){ qeo_log_i("PKCS#7 contains %d bytes of enveloped data", used); } /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL ) { qeo_log_e("cannot get signer info!"); goto error; } /* Verify signature */ if (ctx->verbose){ qeo_log_i("verifying signature"); } si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, op_info->racert) <= 0) { qeo_log_e("error verifying signature"); goto error; } if (ctx->verbose){ qeo_log_i("signature ok"); } /* Get signed attributes */ if (ctx->verbose){ qeo_log_i("finding signed attributes"); } attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL ) { qeo_log_e("no attributes found"); goto error; } /* Transaction id */ if ((get_signed_attribute(attribs, ctx->nid_transId, V_ASN1_PRINTABLESTRING, &p, ctx)) == 1) { qeo_log_e("cannot find transId"); goto error; } if (ctx->verbose){ qeo_log_i("reply transaction id: %s", p); } if (strncmp(s->transaction_id, p, strlen(p))) { qeo_log_e("transaction id mismatch"); goto error; } free(p); p=NULL; /* Message type, should be of type CertRep */ if (get_signed_attribute(attribs, ctx->nid_messageType, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find messageType"); goto error; } if (atoi(p) != 3) { qeo_log_e("wrong message type in reply"); goto error; } if (ctx->verbose){ qeo_log_i("reply message type is good"); } free(p); p=NULL; /* Recipient nonces: */ if (get_signed_attribute(attribs, ctx->nid_recipientNonce, V_ASN1_OCTET_STRING, &p, ctx) == 1) { qeo_log_e("cannot find recipientNonce"); goto error; } s->reply_recipient_nonce = p; p = NULL; if (ctx->verbose) { qeo_log_i("recipientNonce in reply"); } /* * Compare recipient nonce to original sender nonce * The draft says nothing about this, but it makes sense to me.. * XXXXXXXXXXXXXX check */ for (i = 0; i < 16; i++) { if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) { if (ctx->verbose) qeo_log_e("corrupted nonce received"); /* Instead of exit, break out */ break; } } /* Get pkiStatus */ if (get_signed_attribute(attribs, ctx->nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find pkiStatus"); /* This is a mandatory attribute.. */ goto error; } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: qeo_log_i("pkistatus: SUCCESS"); s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: qeo_log_i("pkistatus: FAILURE"); s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: qeo_log_i("pkistatus: PENDING"); s->pki_status = SCEP_PKISTATUS_PENDING; break; default: qeo_log_e("wrong pkistatus in reply"); goto error; } free(p); p=NULL; /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if (get_signed_attribute(attribs, ctx->nid_failInfo, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find failInfo"); goto error; } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; qeo_log_i("reason: %s", SCEP_FAILINFO_BADALG_STR); break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; qeo_log_i("reason: %s", SCEP_FAILINFO_BADMSGCHK_STR); break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; qeo_log_i("reason: %s", SCEP_FAILINFO_BADREQ_STR); break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; qeo_log_i("reason: %s", SCEP_FAILINFO_BADTIME_STR); break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; qeo_log_i("reason: %s", SCEP_FAILINFO_BADCERTID_STR); break; default: qeo_log_e("wrong failInfo in " "reply"); goto error; } free(p); p=NULL; } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ if (ctx->verbose && (used != 0)) { qeo_log_e("illegal size of payload"); } return (0); } /* We got success and expect data */ if (used == 0) { qeo_log_e("illegal size of payload"); goto error; } /* Decrypt the inner PKCS#7 */ recipientcert = s->signercert; recipientkey = s->signerkey; if (ctx->verbose){ qeo_log_i("reading inner PKCS#7"); } p7enc = d2i_PKCS7_bio(outbio, NULL ); if (p7enc == NULL ) { qeo_log_e("cannot read inner PKCS#7"); goto error; } BIO_free(outbio);/* No longer need it */ outbio = NULL; if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, p7enc); } /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (ctx->verbose){ qeo_log_i("decrypting inner PKCS#7"); } if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { qeo_log_e("error decrypting inner PKCS#7"); goto error; } (void)BIO_flush(outbio); /* Write decrypted data */ PKCS7_free(s->reply_p7); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL ); ret = 0; error: free(p); BIO_free(outbio); BIO_free_all(pkcs7bio); BIO_free(memorybio); PKCS7_free(p7enc); return ret; }
static LUA_FUNCTION(openssl_pkcs7_verify_digest) { PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7"); STACK_OF(X509) *certs = lua_isnoneornil(L, 2) ? NULL : openssl_sk_x509_fromtable(L, 2); X509_STORE *store = lua_isnoneornil(L, 3) ? NULL : CHECK_OBJECT(3, X509_STORE, "openssl.x509_store"); size_t len; const char* data = luaL_checklstring(L, 4, &len); long flags = luaL_optint(L, 5, 0); int hash = lua_isnoneornil(L, 6) ? 0 : lua_toboolean(L, 6); STACK_OF(X509) *signers; X509 *signer; STACK_OF(PKCS7_SIGNER_INFO) *sinfos; PKCS7_SIGNER_INFO *si; X509_STORE_CTX cert_ctx; int i, j = 0, k, ret = 0; if (!PKCS7_type_is_signed(p7)) { luaL_error(L, "pkcs7 must be signedData"); } /* Check for no data and no content: no data to verify signature */ if (!PKCS7_get_detached(p7)) { luaL_error(L, "pkcs7 must be detached signedData"); } sinfos = PKCS7_get_signer_info(p7); if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) { luaL_error(L, "pkcs7 signedData without signature"); } signers = PKCS7_get0_signers(p7, certs, flags); if (!signers) { luaL_error(L, "pkcs7 signedData without signers"); } if (!store) flags |= PKCS7_NOVERIFY; /* Now verify the certificates */ if (!(flags & PKCS7_NOVERIFY)) for (k = 0; k < sk_X509_num(signers); k++) { signer = sk_X509_value(signers, k); if (!(flags & PKCS7_NOCHAIN)) { if (!X509_STORE_CTX_init(&cert_ctx, store, signer, p7->d.sign->cert)) { PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); goto err; } X509_STORE_CTX_set_default(&cert_ctx, "smime_sign"); } else if (!X509_STORE_CTX_init(&cert_ctx, store, signer, NULL)) { PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); goto err; } if (!(flags & PKCS7_NOCRL)) X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl); i = X509_verify_cert(&cert_ctx); if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx); X509_STORE_CTX_cleanup(&cert_ctx); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CERTIFICATE_VERIFY_ERROR); ERR_add_error_data(2, "Verify error:", X509_verify_cert_error_string(j)); goto err; } /* Check for revocation status here */ } /* Now Verify All Signatures */ if (!(flags & PKCS7_NOSIGS)) for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); signer = sk_X509_value(signers, i); j = PKCS7_signatureVerify_digest(p7, si, signer, (const unsigned char*) data, len, hash); if (j <= 0) { PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE); goto err; } } ret = 1; err: if (certs) sk_X509_pop_free(certs, X509_free); sk_X509_free(signers); return openssl_pushresult(L, ret); }
int PKCS7_signatureVerify_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509, const unsigned char* data, size_t len, int hash) { ASN1_OCTET_STRING *os; const EVP_MD* md; EVP_MD_CTX mdc, mdc_tmp; int ret = 0, i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; EVP_PKEY *pkey = NULL; EVP_MD_CTX_init(&mdc); EVP_MD_CTX_init(&mdc_tmp); if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type = OBJ_obj2nid(si->digest_alg->algorithm); md = EVP_get_digestbynid(md_type); if (!md || !data || (hash && len != (size_t) md->ctx_size) ) goto err; if (!EVP_DigestInit_ex(&mdc, md, NULL)) goto err; if (hash) memcpy(mdc.md_data, data, len); else EVP_DigestUpdate(&mdc, data, len); pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } /* * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes */ if (!EVP_MD_CTX_copy_ex(&mdc_tmp, &mdc)) goto err; sk = si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len; int alen; ASN1_OCTET_STRING *message_digest; if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) goto err; message_digest = PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int) md_len) || (memcmp(message_digest->data, md_dat, md_len))) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret = -1; goto err; } if (!EVP_DigestVerifyInit(&mdc_tmp, NULL, EVP_get_digestbynid(md_type), NULL, pkey)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); if (alen <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); ret = -1; goto err; } if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) goto err; OPENSSL_free(abuf); } os = si->enc_digest; i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; goto err; } else ret = 1; err: EVP_PKEY_free(pkey); EVP_MD_CTX_cleanup(&mdc); EVP_MD_CTX_cleanup(&mdc_tmp); return (ret); }
/* * Unwrap PKCS#7 data and decrypt if necessary */ int pkcs7_unwrap(struct scep *s) { BIO *memorybio; BIO *outbio; BIO *pkcs7bio; int i, len, bytes, used; STACK_OF(PKCS7_SIGNER_INFO) *sk; PKCS7 *p7enc; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attribs; char *p; unsigned char buffer[1024]; X509 *recipientcert; EVP_PKEY *recipientkey; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if (v_flag) printf("%s: reading outer PKCS#7\n",pname); if ((len = BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) { fprintf(stderr, "%s: error reading PKCS#7 data\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: PKCS#7 payload size: %d bytes\n", pname, len); BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL); if (d_flag) { printf("%s: printing PEM fomatted PKCS#7\n", pname); PEM_write_PKCS7(stdout, s->reply_p7); } /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { fprintf(stderr, "%s: PKCS#7 is not signed!\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL); if (pkcs7bio == NULL) { fprintf(stderr, "%s: cannot get PKCS#7 data\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Copy enveloped data from PKCS#7 */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } BIO_flush(outbio); if (v_flag) printf("%s: PKCS#7 contains %d bytes of enveloped data\n", pname, used); /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL) { fprintf(stderr, "%s: cannot get signer info!\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Verify signature */ if (v_flag) printf("%s: verifying signature\n", pname); si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cacert) <= 0) { fprintf(stderr, "%s: error verifying signature\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: signature ok\n", pname); /* Get signed attributes */ if (v_flag) printf("%s: finding signed attributes\n", pname); attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL) { fprintf(stderr, "%s: no attributes found\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } /* Transaction id */ if ((get_signed_attribute(attribs, nid_transId, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find transId\n", pname); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: reply transaction id: %s\n", pname, p); if (strncmp(s->transaction_id, p, strlen(p))) { fprintf(stderr, "%s: transaction id mismatch\n", pname); exit (SCEP_PKISTATUS_P7); } /* Message type, should be of type CertRep */ if ((i = get_signed_attribute(attribs, nid_messageType, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find messageType\n", pname); exit (SCEP_PKISTATUS_P7); } if (atoi(p) != 3) { fprintf(stderr, "%s: wrong message type in reply\n", pname); exit (SCEP_PKISTATUS_P7); } if (v_flag) printf("%s: reply message type is good\n", pname); /* Sender and recipient nonces: */ if ((i = get_signed_attribute(attribs, nid_senderNonce, V_ASN1_OCTET_STRING, &p)) == 1) { if (v_flag) fprintf(stderr, "%s: cannot find senderNonce\n", pname); /* Some implementations don't put in on reply */ /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX exit (SCEP_PKISTATUS_P7); */ } s->reply_sender_nonce = p; if (v_flag) { printf("%s: senderNonce in reply: ", pname); for (i = 0; i < 16; i++) { printf("%02X", s->reply_sender_nonce[i]); } printf("\n"); } if (( i = get_signed_attribute(attribs, nid_recipientNonce, V_ASN1_OCTET_STRING, &p)) == 1) { fprintf(stderr, "%s: cannot find recipientNonce\n", pname); exit (SCEP_PKISTATUS_P7); } s->reply_recipient_nonce = p; if (v_flag) { printf("%s: recipientNonce in reply: ", pname); for (i = 0; i < 16; i++) { printf("%02X", s->reply_recipient_nonce[i]); } printf("\n"); } /* * Compare recipient nonce to original sender nonce * The draft says nothing about this, but it makes sense to me.. * XXXXXXXXXXXXXX check */ for (i = 0; i < 16; i++) { if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) { if (v_flag) fprintf(stderr, "%s: corrupted nonce " "received\n", pname); /* Instead of exit, break out */ break; } } /* Get pkiStatus */ if ((i = get_signed_attribute(attribs, nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find pkiStatus\n", pname); /* This is a mandatory attribute.. */ exit (SCEP_PKISTATUS_P7); } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: printf("%s: pkistatus: SUCCESS\n",pname); s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: printf("%s: pkistatus: FAILURE\n",pname); s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: printf("%s: pkistatus: PENDING\n",pname); s->pki_status = SCEP_PKISTATUS_PENDING; break; default: fprintf(stderr, "%s: wrong pkistatus in reply\n",pname); exit (SCEP_PKISTATUS_P7); } /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if ((i = get_signed_attribute(attribs, nid_failInfo, V_ASN1_PRINTABLESTRING, &p)) == 1) { fprintf(stderr, "%s: cannot find failInfo\n", pname); exit (SCEP_PKISTATUS_P7); } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADALG_STR); break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADMSGCHK_STR); break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADREQ_STR); break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADTIME_STR); break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; printf("%s: reason: %s\n", pname, SCEP_FAILINFO_BADCERTID_STR); break; default: fprintf(stderr, "%s: wrong failInfo in " "reply\n",pname); exit (SCEP_PKISTATUS_P7); } } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ if (v_flag && (used != 0)) { fprintf(stderr, "%s: illegal size of payload\n", pname); } return (0); } /* We got success and expect data */ if (used == 0) { fprintf(stderr, "%s: illegal size of payload\n", pname); exit (SCEP_PKISTATUS_P7); } /* Decrypt the inner PKCS#7 */ if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT)) { recipientcert = s->signercert; recipientkey = s->signerkey; } else { recipientcert = localcert; recipientkey = rsa; } if (v_flag) printf("%s: reading inner PKCS#7\n",pname); p7enc = d2i_PKCS7_bio(outbio, NULL); if (p7enc == NULL) { fprintf(stderr, "%s: cannot read inner PKCS#7\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } if (d_flag) { printf("%s: printing PEM fomatted PKCS#7\n", pname); PEM_write_PKCS7(stdout, p7enc); } /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (v_flag) printf("%s: decrypting inner PKCS#7\n",pname); if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { fprintf(stderr, "%s: error decrypting inner PKCS#7\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_P7); } BIO_flush(outbio); /* Write decrypted data */ s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload); if (v_flag) printf("%s: PKCS#7 payload size: %d bytes\n", pname, s->reply_len); BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL); return (0); }
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si) { PKCS7_ISSUER_AND_SERIAL *ias; int ret=0,i; STACK_OF(X509) *cert; X509 *x509; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); return 0; } if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); return 0; } if (PKCS7_type_is_signed(p7)) { cert=p7->d.sign->cert; } else if (PKCS7_type_is_signedAndEnveloped(p7)) { cert=p7->d.signed_and_enveloped->cert; } else { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE); goto err; } /* XXXXXXXXXXXXXXXXXXXXXXX */ ias=si->issuer_and_serial; x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial); /* were we able to find the cert in passed to us */ if (x509 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); goto err; } /* Lets verify */ if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert)) { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); goto err; } X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); i=X509_verify_cert(ctx); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); X509_STORE_CTX_cleanup(ctx); goto err; } X509_STORE_CTX_cleanup(ctx); return PKCS7_signatureVerify(bio, p7, si, x509); err: return ret; }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; unsigned char *pp,*p; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp == NULL) || ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; btmp=BIO_next(btmp); } /* mdc is the digest ctx that we want, unless there are attributes, * in which case the digest is the signed attributes */ memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp)); sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE]; unsigned int md_len; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal(&mdc_tmp,md_dat,&md_len); message_digest=PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data,md_dat,md_len))) { #if 0 { int ii; for (ii=0; ii<message_digest->length; ii++) printf("%02X",message_digest->data[ii]); printf(" sent\n"); for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret= -1; goto err; } EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type)); /* Note: when forming the encoding of the attributes we * shouldn't reorder them or this will break the signature. * This is done by using the IS_SEQUENCE flag. */ i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); pp=OPENSSL_malloc(i); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); EVP_VerifyUpdate(&mdc_tmp,pp,i); OPENSSL_free(pp); } os=si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } #ifndef NO_DSA if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); #endif i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret= -1; goto err; } else ret=1; err: return(ret); }
void format_smime_info(int pass, BODY *body, long msgno, gf_io_t pc) { PKCS7 *p7; int i; if(body->type == TYPEMULTIPART){ PART *p; for(p=body->nested.part; p; p=p->next) format_smime_info(pass, &p->body, msgno, pc); } p7 = body->sparep; if(p7){ if(PKCS7_type_is_signed(p7)){ STACK_OF(X509) *signers; switch(pass){ case 1: gf_puts(_("This message was cryptographically signed."), pc); gf_puts(NEWLINE, pc); break; case 2: signers = PKCS7_get0_signers(p7, NULL, 0); if(signers){ snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Certificate%s used for signing"), plural(sk_X509_num(signers))); gf_puts_uline(tmp_20k_buf, pc); gf_puts(NEWLINE, pc); print_separator_line(100, '-', pc); for(i=0; i<sk_X509_num(signers); i++){ X509 *x = sk_X509_value(signers, i); if(x){ output_cert_info(x, pc); gf_puts(NEWLINE, pc); } } } sk_X509_free(signers); break; } } else if(PKCS7_type_is_enveloped(p7)){ switch(pass){ case 1: gf_puts(_("This message was encrypted."), pc); gf_puts(NEWLINE, pc); break; case 2: if(p7->d.enveloped && p7->d.enveloped->enc_data){ X509_ALGOR *alg = p7->d.enveloped->enc_data->algorithm; STACK_OF(PKCS7_RECIP_INFO) *ris = p7->d.enveloped->recipientinfo; int found = 0; gf_puts(_("The algorithm used to encrypt was "), pc); if(alg){ char *n = (char *) OBJ_nid2sn( OBJ_obj2nid(alg->algorithm)); gf_puts(n ? n : "<unknown>", pc); } else gf_puts("<unknown>", pc); gf_puts("." NEWLINE NEWLINE, pc); snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Certificate%s for decrypting"), plural(sk_PKCS7_RECIP_INFO_num(ris))); gf_puts_uline(tmp_20k_buf, pc); gf_puts(NEWLINE, pc); print_separator_line(100, '-', pc); for(i=0; i<sk_PKCS7_RECIP_INFO_num(ris); i++){ PKCS7_RECIP_INFO *ri; PERSONAL_CERT *pcert; ri = sk_PKCS7_RECIP_INFO_value(ris, i); if(!ri) continue; pcert = find_certificate_matching_recip_info(ri); if(pcert){ if(found){ print_separator_line(25, '*', pc); gf_puts(NEWLINE, pc); } found = 1; output_cert_info(pcert->cert, pc); gf_puts(NEWLINE, pc); } } if(!found){ gf_puts(_("No certificate capable of decrypting could be found."), pc); gf_puts(NEWLINE, pc); gf_puts(NEWLINE, pc); } } break; } } } }