On Mon, Mar 06, 2023 at 10:52:31AM +0000, Job Snijders wrote:
> Hi,
> 
> RFC 7935 states in section 3: "The RSA key pairs used to compute the
> signatures MUST have a 2048-bit modulus and a public exponent (e) of
> 65,537."
> 
> The below adds a check for that.

That's a good first step. See comments below.

> OK?
> 
> Kind regards,
> 
> Job
> 
> Index: cms.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
> retrieving revision 1.28
> diff -u -p -r1.28 cms.c
> --- cms.c     6 Mar 2023 09:14:29 -0000       1.28
> +++ cms.c     6 Mar 2023 10:50:33 -0000
> @@ -23,6 +23,7 @@
>  #include <unistd.h>
>  
>  #include <openssl/bio.h>
> +#include <openssl/bn.h>
>  #include <openssl/cms.h>
>  
>  #include "extern.h"
> @@ -76,10 +77,15 @@ cms_parse_validate_internal(X509 **xp, c
>       STACK_OF(X509_CRL)              *crls;
>       STACK_OF(CMS_SignerInfo)        *sinfos;
>       CMS_SignerInfo                  *si;
> +     EVP_PKEY                        *pkey;
>       X509_ALGOR                      *pdig, *psig;
> +     RSA                             *rsa;
> +     const BIGNUM                    *rsa_e;
> +     BN_ULONG                         e_value;
>       int                              i, nattrs, nid;
>       int                              has_ct = 0, has_md = 0, has_st = 0,
>                                        has_bst = 0;
> +     int                              key_bits;
>       int                              rc = 0;
>  
>       *xp = NULL;
> @@ -184,7 +190,7 @@ cms_parse_validate_internal(X509 **xp, c
>       }
>  
>       /* Check digest and signature algorithms */
> -     CMS_SignerInfo_get0_algs(si, NULL, NULL, &pdig, &psig);
> +     CMS_SignerInfo_get0_algs(si, &pkey, NULL, &pdig, &psig);
>       X509_ALGOR_get0(&obj, NULL, NULL, pdig);
>       nid = OBJ_obj2nid(obj);
>       if (nid != NID_sha256) {
> @@ -198,6 +204,29 @@ cms_parse_validate_internal(X509 **xp, c
>       if (nid != NID_rsaEncryption && nid != NID_sha256WithRSAEncryption) {
>               warnx("%s: RFC 6488: wrong signature algorithm %s, want %s",
>                   fn, OBJ_nid2ln(nid), OBJ_nid2ln(NID_rsaEncryption));
> +             goto out;
> +     }

I think we should avoid making cms_parse_validate_internal() longer than
it already is. Since we anticipate that we need this check elsewhere,
perhaps it's better to split it into a helper from the start. How about
adding this to cms.c for now:

static int
validate_pkey(const EVP_PKEY *pkey)
{
}

so cms_parse_validate_internal() only gets a pkey variable and can do

        if (!validate_pkey(pkey))
                goto err;

This could be moved to validate.c later when we identify the other
places that need this check.

> +     if ((key_bits = EVP_PKEY_bits(pkey)) <= 0) {
> +             cryptowarnx("%s: failed to get cryptographic key length", fn);
> +             goto out;
> +     }
> +     if (key_bits != 2048) {
> +             warnx("%s: RFC 7935: expected 2048-bit modulus", fn);
> +             goto out;
> +     }

Merge the previous two checks for simplicity:

        if ((key_bits = EVP_PKEY_bits(pkey)) != 2048) {
                warnx("%s: RFC 7935: expected 2048-bit modulus, got %d bits",
                    fn, key_bits);
                goto out;
        }

> +     if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) {
> +             warnx("%s: failed to extract RSA public key", fn);
> +             goto out;
> +     }
> +
> +     RSA_get0_key(rsa, NULL, &rsa_e, NULL);

I would prefer using the more explicit RSA_get0_e() (available since
LibreSSL 3.5, which is the minimum supported version in portable):

        if ((rsa_e = RSA_get0_e(rsa)) == NULL) {

> +     if (rsa_e == NULL) {
> +             warnx("%s: failed to get RSA exponent", fn);
> +             goto out;
> +     }
> +     e_value = BN_get_word(rsa_e);
> +     if (e_value != 65537) {

No need for e_value:

        if (!BN_is_word(rsa_e, 65537)) {

> +             warnx("%s: incorrect exponent (e) in RSA public key", fn);

Should this error mention RFC 7935?

>               goto out;
>       }
>  
> 

Reply via email to