mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-05-05 04:12:10 -05:00
Improve PKCS#7 verification with OpenSSL 3.5
Enhanced verification logic for PKCS#7 signedData structures by introducing a dedicated `verify_pkcs7_data()` function. This update addresses compatibility with older OpenSSL versions (< 3.0.5) and ensures correct handling of detached signed content using a BIO buffer. The change enables support for PKCS#7 inner content (RFC 2315, section 7), as per OpenSSL PR#22575. Refactored timestamp and authenticode verification functions to reduce duplication and properly manage X509_STORE and X509_CRL structures.
This commit is contained in:
parent
475ea95ba3
commit
68e8845ef1
122
osslsigncode.c
122
osslsigncode.c
@ -2216,7 +2216,6 @@ static int verify_timestamp_token(PKCS7 *p7, CMS_ContentInfo *timestamp)
|
|||||||
*/
|
*/
|
||||||
static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *timestamp, time_t time)
|
static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *timestamp, time_t time)
|
||||||
{
|
{
|
||||||
X509_STORE *store;
|
|
||||||
STACK_OF(CMS_SignerInfo) *sinfos;
|
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||||
CMS_SignerInfo *cmssi;
|
CMS_SignerInfo *cmssi;
|
||||||
X509 *signer;
|
X509 *signer;
|
||||||
@ -2224,8 +2223,8 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|||||||
STACK_OF(X509_CRL) *crls = NULL;
|
STACK_OF(X509_CRL) *crls = NULL;
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
int verok = 0;
|
int verok = 0;
|
||||||
|
X509_STORE *store = X509_STORE_new();
|
||||||
|
|
||||||
store = X509_STORE_new();
|
|
||||||
if (!store)
|
if (!store)
|
||||||
goto out;
|
goto out;
|
||||||
if (x509_store_load_file(store, ctx->options->tsa_cafile)) {
|
if (x509_store_load_file(store, ctx->options->tsa_cafile)) {
|
||||||
@ -2240,12 +2239,10 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|||||||
*/
|
*/
|
||||||
if (!x509_store_set_time(store, time)) {
|
if (!x509_store_set_time(store, time)) {
|
||||||
fprintf(stderr, "Failed to set store time\n");
|
fprintf(stderr, "Failed to set store time\n");
|
||||||
X509_STORE_free(store);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Use the \"-TSA-CAfile\" option to add the Time-Stamp Authority certificates bundle to verify the Timestamp Server.\n");
|
printf("Use the \"-TSA-CAfile\" option to add the Time-Stamp Authority certificates bundle to verify the Timestamp Server.\n");
|
||||||
X509_STORE_free(store);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2255,14 +2252,12 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|||||||
STACK_OF(X509) *cms_certs;
|
STACK_OF(X509) *cms_certs;
|
||||||
|
|
||||||
printf("CMS_verify error\n");
|
printf("CMS_verify error\n");
|
||||||
X509_STORE_free(store);
|
|
||||||
printf("\nFailed timestamp certificate chain retrieved from the signature:\n");
|
printf("\nFailed timestamp certificate chain retrieved from the signature:\n");
|
||||||
cms_certs = CMS_get1_certs(timestamp);
|
cms_certs = CMS_get1_certs(timestamp);
|
||||||
print_certs_chain(cms_certs);
|
print_certs_chain(cms_certs);
|
||||||
sk_X509_pop_free(cms_certs, X509_free);
|
sk_X509_pop_free(cms_certs, X509_free);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
X509_STORE_free(store);
|
|
||||||
|
|
||||||
sinfos = CMS_get0_SignerInfos(timestamp);
|
sinfos = CMS_get0_SignerInfos(timestamp);
|
||||||
cmssi = sk_CMS_SignerInfo_value(sinfos, 0);
|
cmssi = sk_CMS_SignerInfo_value(sinfos, 0);
|
||||||
@ -2299,7 +2294,6 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|||||||
int crlok = verify_crl(ctx->options->tsa_cafile, ctx->options->tsa_crlfile,
|
int crlok = verify_crl(ctx->options->tsa_cafile, ctx->options->tsa_crlfile,
|
||||||
crls, signer, chain);
|
crls, signer, chain);
|
||||||
sk_X509_pop_free(chain, X509_free);
|
sk_X509_pop_free(chain, X509_free);
|
||||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
|
||||||
printf("Timestamp Server Signature CRL verification: %s\n", crlok ? "ok" : "failed");
|
printf("Timestamp Server Signature CRL verification: %s\n", crlok ? "ok" : "failed");
|
||||||
if (!crlok)
|
if (!crlok)
|
||||||
goto out;
|
goto out;
|
||||||
@ -2317,6 +2311,8 @@ static int verify_timestamp(FILE_FORMAT_CTX *ctx, PKCS7 *p7, CMS_ContentInfo *ti
|
|||||||
}
|
}
|
||||||
verok = 1; /* OK */
|
verok = 1; /* OK */
|
||||||
out:
|
out:
|
||||||
|
X509_STORE_free(store);
|
||||||
|
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||||
if (!verok)
|
if (!verok)
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
return verok;
|
return verok;
|
||||||
@ -2345,49 +2341,24 @@ static int PKCS7_type_is_other(PKCS7 *p7)
|
|||||||
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in] ctx: structure holds input and output data
|
|
||||||
* [in] p7: PKCS#7 signature
|
* [in] p7: PKCS#7 signature
|
||||||
* [in] time: signature verification time
|
* [in] store: X509_STORE
|
||||||
* [in] signer: signer's X509 certificate
|
|
||||||
* [returns] 1 on error or 0 on success
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X509 *signer)
|
static int verify_pkcs7_data(PKCS7 *p7, X509_STORE *store)
|
||||||
{
|
{
|
||||||
X509_STORE *store;
|
|
||||||
X509_CRL *crl = NULL;
|
|
||||||
STACK_OF(X509_CRL) *crls = NULL;
|
|
||||||
BIO *bio = NULL;
|
|
||||||
int verok = 0;
|
int verok = 0;
|
||||||
char *url = NULL;
|
#if OPENSSL_VERSION_NUMBER<0x30500000L
|
||||||
|
BIO *bio = NULL;
|
||||||
PKCS7 *contents = p7->d.sign->contents;
|
PKCS7 *contents = p7->d.sign->contents;
|
||||||
|
|
||||||
store = X509_STORE_new();
|
/*
|
||||||
if (!store)
|
* In the PKCS7_verify() function, the BIO *indata parameter refers to
|
||||||
goto out;
|
* the signed data if the content is detached from p7.
|
||||||
|
* Otherwise, indata should be NULL, and then the signed data must be in p7.
|
||||||
if (!x509_store_load_file(store, ctx->options->cafile)) {
|
* The OpenSSL error workaround is to put the inner content into BIO *indata parameter
|
||||||
fprintf(stderr, "Failed to add store lookup file\n");
|
* https://github.com/openssl/openssl/pull/22575
|
||||||
X509_STORE_free(store);
|
*/
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (time != INVALID_TIME) {
|
|
||||||
printf("Signature verification time: ");
|
|
||||||
print_time_t(time);
|
|
||||||
if (!x509_store_set_time(store, time)) {
|
|
||||||
fprintf(stderr, "Failed to set signature time\n");
|
|
||||||
X509_STORE_free(store);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else if (ctx->options->time != INVALID_TIME) {
|
|
||||||
printf("Signature verification time: ");
|
|
||||||
print_time_t(ctx->options->time);
|
|
||||||
if (!x509_store_set_time(store, ctx->options->time)) {
|
|
||||||
fprintf(stderr, "Failed to set verifying time\n");
|
|
||||||
X509_STORE_free(store);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* verify a PKCS#7 signedData structure */
|
|
||||||
if (PKCS7_type_is_other(contents) && (contents->d.other != NULL)
|
if (PKCS7_type_is_other(contents) && (contents->d.other != NULL)
|
||||||
&& (contents->d.other->value.sequence != NULL)
|
&& (contents->d.other->value.sequence != NULL)
|
||||||
&& (contents->d.other->value.sequence->length > 0)) {
|
&& (contents->d.other->value.sequence->length > 0)) {
|
||||||
@ -2402,7 +2373,7 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
|||||||
if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE) {
|
if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE) {
|
||||||
fprintf(stderr, "Corrupted data content\n");
|
fprintf(stderr, "Corrupted data content\n");
|
||||||
X509_STORE_free(store);
|
X509_STORE_free(store);
|
||||||
goto out;
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
bio = BIO_new_mem_buf(data, (int)len);
|
bio = BIO_new_mem_buf(data, (int)len);
|
||||||
} else {
|
} else {
|
||||||
@ -2413,26 +2384,61 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
|||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Corrupted data content\n");
|
fprintf(stderr, "Corrupted data content\n");
|
||||||
X509_STORE_free(store);
|
X509_STORE_free(store);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
verok = PKCS7_verify(p7, NULL, store, bio, NULL, 0);
|
||||||
|
BIO_free(bio);
|
||||||
|
#else /* OPENSSL_VERSION_NUMBER<0x30500000L */
|
||||||
|
verok = PKCS7_verify(p7, NULL, store, NULL, NULL, 0);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER<0x30500000L */
|
||||||
|
return verok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [in] time: signature verification time
|
||||||
|
* [in] signer: signer's X509 certificate
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X509 *signer)
|
||||||
|
{
|
||||||
|
X509_CRL *crl = NULL;
|
||||||
|
STACK_OF(X509_CRL) *crls = NULL;
|
||||||
|
int verok = 0;
|
||||||
|
char *url = NULL;
|
||||||
|
X509_STORE *store = X509_STORE_new();
|
||||||
|
|
||||||
|
if (!store)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!x509_store_load_file(store, ctx->options->cafile)) {
|
||||||
|
fprintf(stderr, "Failed to add store lookup file\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (time != INVALID_TIME) {
|
||||||
|
printf("Signature verification time: ");
|
||||||
|
print_time_t(time);
|
||||||
|
if (!x509_store_set_time(store, time)) {
|
||||||
|
fprintf(stderr, "Failed to set signature time\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else if (ctx->options->time != INVALID_TIME) {
|
||||||
|
printf("Signature verification time: ");
|
||||||
|
print_time_t(ctx->options->time);
|
||||||
|
if (!x509_store_set_time(store, ctx->options->time)) {
|
||||||
|
fprintf(stderr, "Failed to set verifying time\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* verify a PKCS#7 signedData structure */
|
||||||
printf("Signing certificate chain verified using:\n");
|
printf("Signing certificate chain verified using:\n");
|
||||||
/*
|
if (!verify_pkcs7_data(p7, store)) {
|
||||||
* In the PKCS7_verify() function, the BIO *indata parameter refers to
|
|
||||||
* the signed data if the content is detached from p7.
|
|
||||||
* Otherwise, indata should be NULL, and then the signed data must be in p7.
|
|
||||||
* The OpenSSL error workaround is to put the inner content into BIO *indata parameter
|
|
||||||
* https://github.com/openssl/openssl/pull/22575
|
|
||||||
*/
|
|
||||||
if (!PKCS7_verify(p7, NULL, store, bio, NULL, 0)) {
|
|
||||||
printf("PKCS7_verify error\n");
|
printf("PKCS7_verify error\n");
|
||||||
X509_STORE_free(store);
|
|
||||||
BIO_free(bio);
|
|
||||||
printf("Failed signing certificate chain retrieved from the signature:\n");
|
printf("Failed signing certificate chain retrieved from the signature:\n");
|
||||||
print_certs_chain(p7->d.sign->cert);
|
print_certs_chain(p7->d.sign->cert);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
X509_STORE_free(store);
|
|
||||||
BIO_free(bio);
|
|
||||||
|
|
||||||
/* verify a Certificate Revocation List */
|
/* verify a Certificate Revocation List */
|
||||||
if (!ctx->options->ignore_crl) {
|
if (!ctx->options->ignore_crl) {
|
||||||
@ -2464,7 +2470,7 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
|||||||
STACK_OF(X509) *chain = p7->d.sign->cert;
|
STACK_OF(X509) *chain = p7->d.sign->cert;
|
||||||
int crlok = verify_crl(ctx->options->cafile, ctx->options->crlfile,
|
int crlok = verify_crl(ctx->options->cafile, ctx->options->crlfile,
|
||||||
crls, signer, chain);
|
crls, signer, chain);
|
||||||
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
|
||||||
printf("Signature CRL verification: %s\n", crlok ? "ok" : "failed");
|
printf("Signature CRL verification: %s\n", crlok ? "ok" : "failed");
|
||||||
if (!crlok)
|
if (!crlok)
|
||||||
goto out;
|
goto out;
|
||||||
@ -2477,6 +2483,8 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
|
|||||||
|
|
||||||
verok = 1; /* OK */
|
verok = 1; /* OK */
|
||||||
out:
|
out:
|
||||||
|
X509_STORE_free(store);
|
||||||
|
sk_X509_CRL_pop_free(crls, X509_CRL_free);
|
||||||
if (!verok)
|
if (!verok)
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
return verok;
|
return verok;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user