From 7b00d13e09bfe3d09b9f48142974e8cc936d1984 Mon Sep 17 00:00:00 2001 From: Paul Gardiner Date: Wed, 20 Dec 2017 13:37:41 +0000 Subject: Further changes to signature support related to changes in openssl Reinstate the separate consideration of errors relating to the certificate trust checking phase. Remove the key-usage records from the certificate before signature verification. This is done so that openssl will recognise self signed cerificates. openssl doesn't consider them as such when the key usage doesn't include certificate signing. --- source/pdf/pdf-pkcs7.c | 89 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/source/pdf/pdf-pkcs7.c b/source/pdf/pdf-pkcs7.c index 2f3382bd..4526d5e9 100644 --- a/source/pdf/pdf-pkcs7.c +++ b/source/pdf/pdf-pkcs7.c @@ -247,9 +247,33 @@ static int verify_callback(int ok, X509_STORE_CTX *ctx) return ok; } +/* Get the certificates from a PKCS7 object */ +static STACK_OF(X509) *pk7_certs(PKCS7 *pk7) +{ + if (pk7 == NULL) + return NULL; + + if (PKCS7_type_is_signed(pk7)) + return pk7->d.sign->cert; + else if (PKCS7_type_is_signedAndEnveloped(pk7)) + return pk7->d.signed_and_enveloped->cert; + else + return NULL; +} + +/* Get the signing certificate from a PKCS7 object */ +static X509 *pk7_signer(PKCS7 *pk7, PKCS7_SIGNER_INFO *si) +{ + PKCS7_ISSUER_AND_SERIAL *ias = si->issuer_and_serial; + STACK_OF(X509) *certs = pk7_certs(pk7); + if (certs == NULL) + return NULL; + + return X509_find_by_issuer_and_serial(certs, ias->issuer, ias->serial); +} + static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *ebuf, int ebufsize) { - PKCS7_SIGNER_INFO *si; BIO *p7bio=NULL; char readbuf[1024*4]; int res = 1; @@ -297,15 +321,51 @@ static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *eb for (i=0; i= 0) + { + X509_EXTENSION *ext = X509_get_ext(cert, i); + X509_delete_ext(cert, i); + X509_EXTENSION_free(ext); + } + } + rc = PKCS7_dataVerify(cert_store, ctx, p7bio, p7, si); - if (rc == 0) + ctx_err = X509_STORE_CTX_get_error(ctx); + + if (rc <= 0 || ctx_err != X509_V_OK) { - unsigned long err = ERR_get_error(); - ERR_error_string_n(err, ebuf, ebufsize); - strncat(ebuf, ":", ebufsize); - err = X509_STORE_CTX_get_error(ctx); - strncat(ebuf, X509_verify_cert_error_string(err), ebufsize); + if (rc <= 0) + { + /* dataVerify failed */ + ERR_error_string_n(ERR_get_error(), ebuf, ebufsize); + } + else + { + int used; + /* dataVerify passed, but only because our verify callback + skipped over some problems during the certificate trust + checking stage. */ + fz_snprintf(ebuf, ebufsize, "%s(%d): ", X509_verify_cert_error_string(ctx_err), ctx_err); + used = strlen(ebuf); + X509_NAME_oneline(X509_get_subject_name(cert), ebuf + used, ebufsize - used); + } + res = 0; goto exit; } @@ -328,7 +388,6 @@ static int verify_sig(char *sig, int sig_len, char *file, int (*byte_range)[2], BIO *bdata = NULL; BIO *bsegs = NULL; STACK_OF(X509) *certs = NULL; - int t; int res = 0; bsig = BIO_new_mem_buf(sig, sig_len); @@ -354,17 +413,7 @@ static int verify_sig(char *sig, int sig_len, char *file, int (*byte_range)[2], if (pk7cert == NULL) goto exit; - t = OBJ_obj2nid(pk7cert->type); - switch (t) - { - case NID_pkcs7_signed: - case NID_pkcs7_signedAndEnveloped: - certs = pk7cert->d.sign->cert; - break; - - default: - break; - } + certs = pk7_certs(pk7cert); st = X509_STORE_new(); if (st == NULL) -- cgit v1.2.3