mtrojnar / osslsigncode

OpenSSL based Authenticode signing for PE/MSI/Java CAB files
Other
729 stars 124 forks source link

[Feature Request] Ignore CRL #385

Closed adb014 closed 1 month ago

adb014 commented 2 months ago

I'm using osslsigncode in an airgapped environment where all files entering the zone are scanned before permitiing them to enter. Recent changes (since version 2.6) in osslsigncode have added the feature to always check the CRL and fail the verification if the CRL is not available. In an airgapped environment I certainly don't have access to the CRL.

The patch below adds the "-ignore-crl" option to the verify commands, allowing the verification to suceed even if the CRL is not available.

--- ./osslsigncode.h.orig   2024-04-22 19:31:17.644374781 +0200
+++ ./osslsigncode.h    2024-04-22 19:34:38.907692755 +0200
@@ -272,6 +272,7 @@
     int index;
     int ignore_timestamp;
     int ignore_cdp;
+    int ignore_crl;
     int verbose;
     int add_msi_dse;
     char *catalog;
--- ./osslsigncode.c.orig   2024-04-22 19:31:23.733328776 +0200
+++ ./osslsigncode.c    2024-04-22 19:39:28.494826698 +0200
@@ -1822,39 +1822,41 @@
     cmssi = sk_CMS_SignerInfo_value(sinfos, 0);
     CMS_SignerInfo_get0_algs(cmssi, NULL, &signer, NULL, NULL);

-    /* verify a Certificate Revocation List */
-    url = clrdp_url_get_x509(signer);
-    if (url) {
-        if (ctx->options->ignore_cdp) {
-            printf("Ignored TSA's CRL distribution point: %s\n", url);
-        } else {
-            printf("TSA's CRL distribution point: %s\n", url);
-            crl = x509_crl_get(ctx->options->proxy, url);
-        }
-        OPENSSL_free(url);
-        if (!crl && !ctx->options->tsa_crlfile) {
-            printf("Use the \"-TSA-CRLfile\" option to add one or more Time-Stamp Authority CRLs in PEM format.\n");
-            goto out;
-        }
-    }
-    if (p7->d.sign->crl || crl) {
-        crls = x509_crl_list_get(p7, crl);
-        if (!crls) {
-            printf("Failed to use CRL distribution point\n");
-            goto out;
-        }
-    }
-    if (ctx->options->tsa_crlfile || crls) {
-        STACK_OF(X509) *chain = CMS_get1_certs(timestamp);
-        int crlok = verify_crl(ctx->options->tsa_cafile, ctx->options->tsa_crlfile,
-            crls, signer, chain);
-        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");
-        if (!crlok)
-            goto out;
-    } else {
-        printf("\n");
+    if (! ctx->options->ignore_crl) {
+      /* verify a Certificate Revocation List */
+      url = clrdp_url_get_x509(signer);
+      if (url) {
+          if (ctx->options->ignore_cdp) {
+              printf("Ignored TSA's CRL distribution point: %s\n", url);
+          } else {
+              printf("TSA's CRL distribution point: %s\n", url);
+              crl = x509_crl_get(ctx->options->proxy, url);
+          }
+          OPENSSL_free(url);
+          if (!crl && !ctx->options->tsa_crlfile) {
+              printf("Use the \"-TSA-CRLfile\" option to add one or more Time-Stamp Authority CRLs in PEM format.\n");
+              goto out;
+          }
+      }
+      if (p7->d.sign->crl || crl) {
+          crls = x509_crl_list_get(p7, crl);
+          if (!crls) {
+              printf("Failed to use CRL distribution point\n");
+              goto out;
+          }
+      }
+      if (ctx->options->tsa_crlfile || crls) {
+          STACK_OF(X509) *chain = CMS_get1_certs(timestamp);
+          int crlok = verify_crl(ctx->options->tsa_cafile, ctx->options->tsa_crlfile,
+              crls, signer, chain);
+          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");
+          if (!crlok)
+              goto out;
+      } else {
+          printf("\n");
+      }
     }
     /* check extended key usage flag XKU_TIMESTAMP */
     if (!(X509_get_extended_key_usage(signer) & XKU_TIMESTAMP)) {
@@ -1985,36 +1987,39 @@
     BIO_free(bio);

     /* verify a Certificate Revocation List */
-    url = clrdp_url_get_x509(signer);
-    if (url) {
-        if (ctx->options->ignore_cdp) {
-            printf("Ignored CRL distribution point: %s\n", url);
-        } else {
-            printf("CRL distribution point: %s\n", url);
-            crl = x509_crl_get(ctx->options->proxy, url);
-        }
-        OPENSSL_free(url);
-        if (!crl && !ctx->options->crlfile) {
-            printf("Use the \"-CRLfile\" option to add one or more CRLs in PEM format.\n");
-            goto out;
-        }
-    }
-    if (p7->d.sign->crl || crl) {
-        crls = x509_crl_list_get(p7, crl);
-        if (!crls) {
-            printf("Failed to use CRL distribution point\n");
-            goto out;
-        }
-    }
-    if (ctx->options->crlfile || crls) {
-        STACK_OF(X509) *chain = p7->d.sign->cert;
-        int crlok = verify_crl(ctx->options->cafile, ctx->options->crlfile,
-            crls, signer, chain);
-        sk_X509_CRL_pop_free(crls, X509_CRL_free);
-        printf("Signature CRL verification: %s\n", crlok ? "ok" : "failed");
-        if (!crlok)
-            goto out;
+    if (! ctx->options->ignore_crl) {
+      url = clrdp_url_get_x509(signer);
+      if (url) {
+          if (ctx->options->ignore_cdp) {
+              printf("Ignored CRL distribution point: %s\n", url);
+          } else {
+              printf("CRL distribution point: %s\n", url);
+              crl = x509_crl_get(ctx->options->proxy, url);
+          }
+          OPENSSL_free(url);
+          if (!crl && !ctx->options->crlfile) {
+              printf("Use the \"-CRLfile\" option to add one or more CRLs in PEM format.\n");
+              goto out;
+          }
+      }
+      if (p7->d.sign->crl || crl) {
+          crls = x509_crl_list_get(p7, crl);
+          if (!crls) {
+              printf("Failed to use CRL distribution point\n");
+              goto out;
+          }
+      }
+      if (ctx->options->crlfile || crls) {
+          STACK_OF(X509) *chain = p7->d.sign->cert;
+          int crlok = verify_crl(ctx->options->cafile, ctx->options->crlfile,
+              crls, signer, chain);
+          sk_X509_CRL_pop_free(crls, X509_CRL_free);
+          printf("Signature CRL verification: %s\n", crlok ? "ok" : "failed");
+          if (!crlok)
+              goto out;
+      }
     }
+    
     /* check extended key usage flag XKU_CODE_SIGN */
     if (!(X509_get_extended_key_usage(signer) & XKU_CODE_SIGN)) {
         printf("Unsupported Signer's certificate purpose XKU_CODE_SIGN\n");
@@ -3163,6 +3168,7 @@
     const char *cmds_time[] = {"attach-signature", "sign", "verify", NULL};
     const char *cmds_ignore_timestamp[] = {"verify", NULL};
     const char *cmds_ignore_cdp[] = {"verify", NULL};
+    const char *cmds_ignore_crl[] = {"verify", NULL};
     const char *cmds_t[] = {"add", "sign", NULL};
     const char *cmds_ts[] = {"add", "sign", NULL};
     const char *cmds_CAfileTSA[] = {"attach-signature", "verify", NULL};
@@ -3305,6 +3311,8 @@
         printf("%-24s= disable verification of the Timestamp Server signature\n", "-ignore-timestamp");
     if (on_list(cmd, cmds_ignore_cdp))
         printf("%-24s= disable CRL Distribution Points online verification\n", "-ignore-cdp");
+    if (on_list(cmd, cmds_ignore_crl))
+        printf("%-24s= disable CRL online verification\n", "-ignore-crl");
     if (on_list(cmd, cmds_t)) {
         printf("%-24s= specifies that the digital signature will be timestamped\n", "-t");
         printf("%26sby the Time-Stamp Authority (TSA) indicated by the URL\n", "");
@@ -4205,6 +4213,8 @@
             options->ignore_timestamp = 1;
         } else if ((cmd == CMD_VERIFY) && !strcmp(*argv, "-ignore-cdp")) {
             options->ignore_cdp = 1;
+        } else if ((cmd == CMD_VERIFY) && !strcmp(*argv, "-ignore-crl")) {
+            options->ignore_crl = 1;
         } else if ((cmd == CMD_SIGN || cmd == CMD_ADD || cmd == CMD_VERIFY) && !strcmp(*argv, "-verbose")) {
             options->verbose = 1;
         } else if ((cmd == CMD_SIGN || cmd == CMD_EXTRACT_DATA || cmd == CMD_ADD || cmd == CMD_ATTACH)

Sorry there are quite a few whitespace changes in the above as the CRL verification is in an if block. But hopefully these whitespace changes should be relatively obvious. Could this feature be addded in a future version of osslsigncode ?

mtrojnar commented 2 months ago

Duplicate of #373. The "-ignore-cdp" option already does what you need.

adb014 commented 2 months ago

Sorry to contradict you but -ignore-cdp will ignore the crl specified in the certificate and then the verification will fail asking for “-CRLfile” to be specified. I wouldn’t have implemented this otherwise. Try disconnecting from the network and trying to verify a Microsoft kb with

osslsigncode verify -CAfile cert.crt -TSA-CAfile cert.crt -time $time <kb>

where cert.crt is the Microsoft root certificate and time is the signature time. Before you tell me this doesn’t fully verify the chain of trust, I know it’s only a simple example to show to problem. In real life I check all intermediate and leaf certificates as well

mtrojnar commented 2 months ago

I discussed it with @olszomal, who wrote the "-ignore-cdp" code, and you're right: it only disables fetching CRLs, and not verifying them. Please submit a PR.

Don't forget to also update the usage() and help_for() functions. Apparently, the current help for "-ignore-cdp" is somewhat confusing, so please use the opportunity to also clarify it.