Ensure .cer and .crl outside-TBS signatures are sha256WithRSAEncryption
authorjob <job@openbsd.org>
Mon, 6 Mar 2023 16:58:41 +0000 (16:58 +0000)
committerjob <job@openbsd.org>
Mon, 6 Mar 2023 16:58:41 +0000 (16:58 +0000)
Note: there is a potential for confusion in RFC 7935, the specification
differentiates between 2 contexts: "in the certificate" and "CMS SignedData".

In the CMS context, either rsaEncryption or sha256WithRSAEncryption can
appear (and both *do* appear in the wild).

However, RFC 7935 section 2 fourth paragraph starting with "In certificates,
CRLs, ..." mandates that sha256WithRSAEncryption is used to sign .cer and
.crl files:

    "The Object Identifier (OID) sha256WithRSAEncryption from RFC4055 MUST
    be used in these products."

The above requirement matches observations on existing RPKI deployments.

OK tb@

usr.sbin/rpki-client/cert.c
usr.sbin/rpki-client/crl.c

index 7185fab..540e2b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cert.c,v 1.103 2023/03/06 16:04:52 job Exp $ */
+/*     $OpenBSD: cert.c,v 1.104 2023/03/06 16:58:41 job Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  * Copyright (c) 2021 Job Snijders <job@openbsd.org>
@@ -647,9 +647,12 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
        size_t                   i;
        X509                    *x = NULL;
        X509_EXTENSION          *ext = NULL;
+       const X509_ALGOR        *palg;
+       const ASN1_OBJECT       *cobj;
        ASN1_OBJECT             *obj;
        EVP_PKEY                *pkey;
        struct parse             p;
+       int                      nid;
 
        /* just fail for empty buffers, the warning was printed elsewhere */
        if (der == NULL)
@@ -676,6 +679,19 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
                goto out;
        }
 
+       X509_get0_signature(NULL, &palg, x);
+       if (palg == NULL) {
+               cryptowarnx("%s: X509_get0_signature", p.fn);
+               goto out;
+       }
+       X509_ALGOR_get0(&cobj, NULL, NULL, palg);
+       if ((nid = OBJ_obj2nid(cobj)) != NID_sha256WithRSAEncryption) {
+               warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
+                   fn, OBJ_nid2ln(nid),
+                   OBJ_nid2ln(NID_sha256WithRSAEncryption));
+               goto out;
+       }
+
        /* Look for X509v3 extensions. */
 
        if ((extsz = X509_get_ext_count(x)) < 0)
index da4eebf..98a2059 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: crl.c,v 1.22 2023/02/21 10:18:47 tb Exp $ */
+/*     $OpenBSD: crl.c,v 1.23 2023/03/06 16:58:41 job Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -20,6 +20,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <openssl/x509.h>
+
 #include "extern.h"
 
 struct crl *
@@ -27,8 +29,10 @@ crl_parse(const char *fn, const unsigned char *der, size_t len)
 {
        const unsigned char     *oder;
        struct crl              *crl;
+       const X509_ALGOR        *palg;
+       const ASN1_OBJECT       *cobj;
        const ASN1_TIME         *at;
-       int                      rc = 0;
+       int                      nid, rc = 0;
 
        /* just fail for empty buffers, the warning was printed elsewhere */
        if (der == NULL)
@@ -47,6 +51,19 @@ crl_parse(const char *fn, const unsigned char *der, size_t len)
                goto out;
        }
 
+       X509_CRL_get0_signature(crl->x509_crl, NULL, &palg);
+       if (palg == NULL) {
+               cryptowarnx("%s: X509_CRL_get0_signature", fn);
+               goto out;
+       }
+       X509_ALGOR_get0(&cobj, NULL, NULL, palg);
+       if ((nid = OBJ_obj2nid(cobj)) != NID_sha256WithRSAEncryption) {
+               warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
+                   fn, OBJ_nid2ln(nid),
+                   OBJ_nid2ln(NID_sha256WithRSAEncryption));
+               goto out;
+       }
+
        if ((crl->aki = x509_crl_get_aki(crl->x509_crl, fn)) == NULL) {
                warnx("x509_crl_get_aki failed");
                goto out;