int main(int argc, char const *argv[]) { PKCS7 *p7; FILE *fp = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(PKCS7_SIGNER_INFO) *sk; X509_STORE_CTX cert_ctx; X509_STORE *cert_store; BIO *mybio; int ret, len, i; unsigned char *errordesc; unsigned long errorno; unsigned char data[2028], *p, *buf; OpenSSL_add_all_algorithms(); fp = fopen("p7signed.cer", "rb"); if(fp == NULL) return 0; len = fread(data, 1, 2048, fp); fclose(fp); p = data; p7 = d2i_PKCS7(NULL, (const unsigned char **)&p, len); mybio = PKCS7_dataInit(p7, NULL); sk = PKCS7_get_signer_info(p7); if(sk == NULL) { printf("no signer in p7\n"); return 0; } cert_store=X509_STORE_new(); X509_STORE_set_verify_cb_func(cert_store,verify_callback);//必须要有回调设置 for(i = 0; i < sk_PKCS7_SIGNER_INFO_num(sk); i++) { si = sk_PKCS7_SIGNER_INFO_value(sk, i); ret = PKCS7_dataVerify(cert_store, &cert_ctx, mybio, p7, si); if(ret == 1) printf("succ in pkcs7 signed data verify\n"); else printf("fail in pkcs7 signed data verify\n"); } X509_STORE_free(cert_store); PKCS7_free(p7); return 1; }
void openssl_pkcs7_sign() { int len; BIO *in; X509 *x; FILE *fp; PKCS7 *p7; X509_ALGOR *md; PKCS7_SIGNER_INFO *si; char name[MAX1_LEN], tmp[MAX1_LEN]; unsigned char *der, *p, buf[SHA_DIGEST_LENGTH] = "pkcs7 sign"; p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_data); ASN1_OCTET_STRING_set(p7->d.data, buf, SHA_DIGEST_LENGTH); len = i2d_PKCS7(p7, NULL); der = (unsigned char *)malloc(len); p = der; len = i2d_PKCS7(p7, &p); fp = fopen("/tmp/test.cer", "wb"); fwrite(der, 1, len, fp); fclose(fp); free(der); PKCS7_free(p7); p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_signed); p7->d.sign->cert = sk_X509_new_null(); in = BIO_new_file("/tmp/test.cer", "r"); x = PEM_read_bio_X509(in, NULL, NULL, NULL); sk_X509_push(p7->d.sign->cert, x); BIO_free(in); md = X509_ALGOR_new(); md->algorithm = OBJ_nid2obj(NID_md5); sk_X509_ALGOR_push(p7->d.sign->md_algs, md); si = PKCS7_SIGNER_INFO_new(); ASN1_INTEGER_set(si->version, 2); ASN1_INTEGER_set(si->issuer_and_serial->serial, 333); sk_PKCS7_SIGNER_INFO_push(p7->d.sign->signer_info, si); len = i2d_PKCS7(p7, NULL); der = (unsigned char *)malloc(len); p = der; len = i2d_PKCS7(p7, &p); fp = fopen("/tmp/test.cer", "wb"); fwrite(der, 1, len, fp); fclose(fp); free(der); fp = fopen("/tmp/test.cer", "rb"); len = fread(tmp, 1, MAX1_LEN, fp); fclose(fp); p = (unsigned char *)&tmp; d2i_PKCS7(&p7, (const unsigned char **)&p, len); OBJ_obj2txt(name, MAX1_LEN, p7->type, 0); PKCS7_free(p7); }
// Verify the signed block, the first 32 bytes of the data must be the certificate hash to work. int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert, char** data) { unsigned int size, r; BIO *out = NULL; PKCS7 *message = NULL; char* data2 = NULL; char hash[UTIL_HASHSIZE]; STACK_OF(X509) *st = NULL; cert->x509 = NULL; cert->pkey = NULL; *data = NULL; message = d2i_PKCS7(NULL, (const unsigned char**)&signature, signlen); if (message == NULL) goto error; out = BIO_new(BIO_s_mem()); // Lets rebuild the original message and check the size size = i2d_PKCS7(message, NULL); if (size < (unsigned int)signlen) goto error; // Check the PKCS7 signature, but not the certificate chain. r = PKCS7_verify(message, NULL, NULL, NULL, out, PKCS7_NOVERIFY); if (r == 0) goto error; // If data block contains less than 32 bytes, fail. size = BIO_get_mem_data(out, &data2); if (size <= UTIL_HASHSIZE) goto error; // Copy the data block *data = (char*)malloc(size + 1); if (*data == NULL) goto error; memcpy(*data, data2, size); (*data)[size] = 0; // Get the certificate signer st = PKCS7_get0_signers(message, NULL, PKCS7_NOVERIFY); cert->x509 = X509_dup(sk_X509_value(st, 0)); sk_X509_free(st); // Get a full certificate hash of the signer r = UTIL_HASHSIZE; X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r); // Check certificate hash with first 32 bytes of data. if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error; // Approved, cleanup and return. BIO_free(out); PKCS7_free(message); return size; error: if (out != NULL) BIO_free(out); if (message != NULL) PKCS7_free(message); if (*data != NULL) free(*data); if (cert->x509 != NULL) { X509_free(cert->x509); cert->x509 = NULL; } return 0; }
PKCS7* CryptoNative_DecodePkcs7(const uint8_t* buf, int32_t len) { if (!buf || !len) { return NULL; } return d2i_PKCS7(NULL, &buf, len); }
extern "C" PKCS7* CryptoNative_DecodePkcs7(const uint8_t* buf, int32_t len) { if (!buf || !len) { return nullptr; } return d2i_PKCS7(nullptr, &buf, len); }
extern "C" PKCS7* DecodePkcs7(const unsigned char* buf, int32_t len) { if (!buf || !len) { return nullptr; } return d2i_PKCS7(nullptr, &buf, len); }
/* * Internal static function for decoding of the signature of the published * file. */ static int decodeSignature(GTPublicationsFile *pubfile) { const unsigned char *p; assert(pubfile->signature == NULL); p = pubfile->data + pubfile->signature_block_begin; ERR_clear_error(); pubfile->signature = d2i_PKCS7( NULL, &p, pubfile->data_length - pubfile->signature_block_begin); if (pubfile->signature == NULL) { return GT_isMallocFailure() ? GT_OUT_OF_MEMORY : GT_INVALID_FORMAT; } return GT_OK; }
static int attach_sig(struct image *image, const char *image_filename, const char *sig_filename) { const uint8_t *tmp_buf; uint8_t *sigbuf; size_t size; PKCS7 *p7; int rc; rc = fileio_read_file(image, sig_filename, &sigbuf, &size); if (rc) goto out; image_add_signature(image, sigbuf, size); rc = -1; tmp_buf = sigbuf; p7 = d2i_PKCS7(NULL, &tmp_buf, size); if (!p7) { fprintf(stderr, "Unable to parse signature data in file: %s\n", sig_filename); ERR_print_errors_fp(stderr); goto out; } rc = PKCS7_verify(p7, NULL, NULL, NULL, NULL, PKCS7_BINARY | PKCS7_NOVERIFY | PKCS7_NOSIGS); if (!rc) { fprintf(stderr, "PKCS7 verification failed for file %s\n", sig_filename); ERR_print_errors_fp(stderr); goto out; } rc = image_write(image, image_filename); if (rc) fprintf(stderr, "Error writing %s: %s\n", image_filename, strerror(errno)); out: talloc_free(sigbuf); return rc; }
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; }
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7, size_t len, char *pem_file, char *der_file) { #ifdef OPENSSL_IS_BORINGSSL CBS pkcs7_cbs; #else /* OPENSSL_IS_BORINGSSL */ PKCS7 *p7 = NULL; const unsigned char *p = pkcs7; #endif /* OPENSSL_IS_BORINGSSL */ STACK_OF(X509) *certs; int i, num, ret = -1; BIO *out = NULL; #ifdef OPENSSL_IS_BORINGSSL certs = sk_X509_new_null(); if (!certs) goto fail; CBS_init(&pkcs7_cbs, pkcs7, len); if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s", ERR_error_string(ERR_get_error(), NULL)); write_result(ctx, "Could not parse PKCS#7 object from EST"); goto fail; } #else /* OPENSSL_IS_BORINGSSL */ p7 = d2i_PKCS7(NULL, &p, len); if (p7 == NULL) { wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s", ERR_error_string(ERR_get_error(), NULL)); write_result(ctx, "Could not parse PKCS#7 object from EST"); goto fail; } switch (OBJ_obj2nid(p7->type)) { case NID_pkcs7_signed: certs = p7->d.sign->cert; break; case NID_pkcs7_signedAndEnveloped: certs = p7->d.signed_and_enveloped->cert; break; default: certs = NULL; break; } #endif /* OPENSSL_IS_BORINGSSL */ if (!certs || ((num = sk_X509_num(certs)) == 0)) { wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object"); write_result(ctx, "No certificates found in PKCS#7 object"); goto fail; } if (der_file) { FILE *f = fopen(der_file, "wb"); if (f == NULL) goto fail; i2d_X509_fp(f, sk_X509_value(certs, 0)); fclose(f); } if (pem_file) { out = BIO_new(BIO_s_file()); if (out == NULL || BIO_write_filename(out, pem_file) <= 0) goto fail; for (i = 0; i < num; i++) { X509 *cert = sk_X509_value(certs, i); X509_print(out, cert); PEM_write_bio_X509(out, cert); BIO_puts(out, "\n"); } } ret = 0; fail: #ifdef OPENSSL_IS_BORINGSSL if (certs) sk_X509_pop_free(certs, X509_free); #else /* OPENSSL_IS_BORINGSSL */ PKCS7_free(p7); #endif /* OPENSSL_IS_BORINGSSL */ if (out) BIO_free_all(out); return ret; }
/** 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; }
static int rtCrPkcs7VerifySignedDataUsingOpenSsl(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags, RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts, void const *pvContent, uint32_t cbContent, PRTERRINFO pErrInfo) { /* * Verify using OpenSSL. */ int rcOssl; unsigned char const *pbRawContent = RTASN1CORE_GET_RAW_ASN1_PTR(&pContentInfo->SeqCore.Asn1Core); PKCS7 *pOsslPkcs7 = NULL; if (d2i_PKCS7(&pOsslPkcs7, &pbRawContent, RTASN1CORE_GET_RAW_ASN1_SIZE(&pContentInfo->SeqCore.Asn1Core)) == pOsslPkcs7) { STACK_OF(X509) *pAddCerts = NULL; if (hAdditionalCerts != NIL_RTCRSTORE) rcOssl = RTCrStoreConvertToOpenSslCertStack(hAdditionalCerts, 0, (void **)&pAddCerts); else { pAddCerts = sk_X509_new_null(); rcOssl = RT_LIKELY(pAddCerts != NULL) ? VINF_SUCCESS : VERR_NO_MEMORY; } if (RT_SUCCESS(rcOssl)) { PCRTCRPKCS7SETOFCERTS pCerts = &pContentInfo->u.pSignedData->Certificates; for (uint32_t i = 0; i < pCerts->cItems; i++) if (pCerts->paItems[i].enmChoice == RTCRPKCS7CERTCHOICE_X509) rtCrOpenSslAddX509CertToStack(pAddCerts, pCerts->paItems[i].u.pX509Cert); X509_STORE *pTrustedCerts = NULL; if (hTrustedCerts != NIL_RTCRSTORE) rcOssl = RTCrStoreConvertToOpenSslCertStore(hTrustedCerts, 0, (void **)&pTrustedCerts); if (RT_SUCCESS(rcOssl)) { rtCrOpenSslInit(); BIO *pBioContent = BIO_new_mem_buf((void *)pvContent, cbContent); if (pBioContent) { uint32_t fOsslFlags = PKCS7_NOCHAIN; fOsslFlags |= PKCS7_NOVERIFY; // temporary hack. if (PKCS7_verify(pOsslPkcs7, pAddCerts, pTrustedCerts, pBioContent, NULL /*out*/, fOsslFlags)) rcOssl = VINF_SUCCESS; else { rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_VERIFY_FAILED, "PKCS7_verify failed: "); if (pErrInfo) ERR_print_errors_cb(rtCrOpenSslErrInfoCallback, pErrInfo); } BIO_free(pBioContent); } if (pTrustedCerts) X509_STORE_free(pTrustedCerts); } else rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed"); if (pAddCerts) sk_X509_pop_free(pAddCerts, X509_free); } else rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed"); PKCS7_free(pOsslPkcs7); } else rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_D2I_FAILED, "d2i_PKCS7 failed"); return rcOssl; }
/** This function receives a PKCS#7 formatted signature blob, looks for the EKU SEQUENCE blob, and if found then looks for all the required EKUs. This function was created so that the Surface team can cut down on the number of Certificate Authorities (CA's) by checking EKU's on leaf signers for a specific product. This prevents one product's certificate from signing another product's firmware or unlock blobs. Note that this function does not validate the certificate chain. That needs to be done before using this function. @param[in] Pkcs7Signature The PKCS#7 signed information content block. An array containing the content block with both the signature, the signer's certificate, and any necessary intermediate certificates. @param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature. @param[in] RequiredEKUs Array of null-terminated strings listing OIDs of required EKUs that must be present in the signature. @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array. @param[in] RequireAllPresent If this is TRUE, then all of the specified EKU's must be present in the leaf signer. If it is FALSE, then we will succeed if we find any of the specified EKU's. @retval EFI_SUCCESS The required EKUs were found in the signature. @retval EFI_INVALID_PARAMETER A parameter was invalid. @retval EFI_NOT_FOUND One or more EKU's were not found in the signature. **/ EFI_STATUS EFIAPI VerifyEKUsInPkcs7Signature ( IN CONST UINT8 *Pkcs7Signature, IN CONST UINT32 SignatureSize, IN CONST CHAR8 *RequiredEKUs[], IN CONST UINT32 RequiredEKUsSize, IN BOOLEAN RequireAllPresent ) { EFI_STATUS Status; PKCS7 *Pkcs7; STACK_OF(X509) *CertChain; INT32 SignatureType; INT32 NumberCertsInSignature; X509 *SignerCert; UINT8 *SignedData; UINT8 *Temp; UINTN SignedDataSize; BOOLEAN IsWrapped; BOOLEAN Ok; Status = EFI_SUCCESS; Pkcs7 = NULL; CertChain = NULL; SignatureType = 0; NumberCertsInSignature = 0; SignerCert = NULL; SignedData = NULL; SignedDataSize = 0; IsWrapped = FALSE; Ok = FALSE; // //Validate the input parameters. // if (Pkcs7Signature == NULL || SignatureSize == 0 || RequiredEKUs == NULL || RequiredEKUsSize == 0) { Status = EFI_INVALID_PARAMETER; goto Exit; } if (RequiredEKUsSize == 1) { RequireAllPresent = TRUE; } // // Wrap the PKCS7 data if needed. // Ok = WrapPkcs7Data (Pkcs7Signature, SignatureSize, &IsWrapped, &SignedData, &SignedDataSize); if (!Ok) { // // Fail to Wrap the PKCS7 data. // Status = EFI_INVALID_PARAMETER; goto Exit; } Temp = SignedData; // // Create the PKCS7 object. // Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (INT32)SignedDataSize); if (Pkcs7 == NULL) { // // Fail to read PKCS7 data. // Status = EFI_INVALID_PARAMETER; goto Exit; } // // Get the certificate chain. // SignatureType = OBJ_obj2nid (Pkcs7->type); switch (SignatureType) { case NID_pkcs7_signed: if (Pkcs7->d.sign != NULL) { CertChain = Pkcs7->d.sign->cert; } break; case NID_pkcs7_signedAndEnveloped: if (Pkcs7->d.signed_and_enveloped != NULL) { CertChain = Pkcs7->d.signed_and_enveloped->cert; } break; default: break; } // // Ensure we have a certificate stack // if (CertChain == NULL) { // // Fail to get the certificate stack from signature. // Status = EFI_INVALID_PARAMETER; goto Exit; } // // Find out how many certificates were in the PKCS7 signature. // NumberCertsInSignature = sk_X509_num (CertChain); if (NumberCertsInSignature == 0) { // // Fail to find any certificates in signature. // Status = EFI_INVALID_PARAMETER; goto Exit; } // // Get the leaf signer. // Status = GetSignerCertificate (Pkcs7, &SignerCert); if (Status != EFI_SUCCESS || SignerCert == NULL) { // // Fail to get the end-entity leaf signer certificate. // Status = EFI_INVALID_PARAMETER; goto Exit; } Status = CheckEKUs (SignerCert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent); if (Status != EFI_SUCCESS) { goto Exit; } Exit: // // Release Resources // // If the signature was not wrapped, then the call to WrapData() will allocate // the data and add a header to it // if (!IsWrapped && SignedData) { free (SignedData); } if (SignerCert) { X509_free (SignerCert); } if (Pkcs7) { PKCS7_free (Pkcs7); } return Status; }