From ec1cc732eea452b2c8e9f1282111d9cc0104e4b6 Mon Sep 17 00:00:00 2001 From: job Date: Thu, 19 Oct 2023 17:05:54 +0000 Subject: [PATCH] Add experimental support for secp256r1 aka P-256 aka prime256v1 ECDSA signatures are much smaller than RSA signatures while offering similar security. Adding support for P-256 now allows CA developers to test their implementations, and paving the way for signers in the production environment in the future to take advantage of ECDSA. OK tb@ --- usr.sbin/rpki-client/cert.c | 8 +++- usr.sbin/rpki-client/cms.c | 8 +++- usr.sbin/rpki-client/crl.c | 8 +++- usr.sbin/rpki-client/validate.c | 69 ++++++++++++++++++++++++++------- 4 files changed, 73 insertions(+), 20 deletions(-) diff --git a/usr.sbin/rpki-client/cert.c b/usr.sbin/rpki-client/cert.c index 6e370bf1709..0f98100b3d3 100644 --- a/usr.sbin/rpki-client/cert.c +++ b/usr.sbin/rpki-client/cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cert.c,v 1.118 2023/10/13 12:06:49 job Exp $ */ +/* $OpenBSD: cert.c,v 1.119 2023/10/19 17:05:54 job Exp $ */ /* * Copyright (c) 2022 Theo Buehler * Copyright (c) 2021 Job Snijders @@ -762,7 +762,11 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len) goto out; } X509_ALGOR_get0(&cobj, NULL, NULL, palg); - if ((nid = OBJ_obj2nid(cobj)) != NID_sha256WithRSAEncryption) { + nid = OBJ_obj2nid(cobj); + if (nid == NID_ecdsa_with_SHA256) { + if (verbose) + warn("%s: P-256 support is experimental", fn); + } else if (nid != NID_sha256WithRSAEncryption) { warnx("%s: RFC 7935: wrong signature algorithm %s, want %s", fn, OBJ_nid2ln(nid), OBJ_nid2ln(NID_sha256WithRSAEncryption)); diff --git a/usr.sbin/rpki-client/cms.c b/usr.sbin/rpki-client/cms.c index 2cc93bc0da4..5fe0607bb90 100644 --- a/usr.sbin/rpki-client/cms.c +++ b/usr.sbin/rpki-client/cms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms.c,v 1.39 2023/08/14 08:25:26 tb Exp $ */ +/* $OpenBSD: cms.c,v 1.40 2023/10/19 17:05:54 job Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -265,7 +265,11 @@ cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der, X509_ALGOR_get0(&obj, NULL, NULL, psig); nid = OBJ_obj2nid(obj); /* RFC7935 last paragraph of section 2 specifies the allowed psig */ - if (nid != NID_rsaEncryption && nid != NID_sha256WithRSAEncryption) { + if (nid == NID_ecdsa_with_SHA256) { + if (verbose) + warn("%s: P-256 support is experimental", fn); + } else 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; diff --git a/usr.sbin/rpki-client/crl.c b/usr.sbin/rpki-client/crl.c index ac20c055c05..d4d3fe4c40a 100644 --- a/usr.sbin/rpki-client/crl.c +++ b/usr.sbin/rpki-client/crl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crl.c,v 1.27 2023/06/29 10:28:25 tb Exp $ */ +/* $OpenBSD: crl.c,v 1.28 2023/10/19 17:05:54 job Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -62,7 +62,11 @@ crl_parse(const char *fn, const unsigned char *der, size_t len) goto out; } X509_ALGOR_get0(&cobj, NULL, NULL, palg); - if ((nid = OBJ_obj2nid(cobj)) != NID_sha256WithRSAEncryption) { + nid = OBJ_obj2nid(cobj); + if (nid == NID_ecdsa_with_SHA256) { + if (verbose) + warn("%s: P-256 support is experimental", fn); + } else if (nid != NID_sha256WithRSAEncryption) { warnx("%s: RFC 7935: wrong signature algorithm %s, want %s", fn, OBJ_nid2ln(nid), OBJ_nid2ln(NID_sha256WithRSAEncryption)); diff --git a/usr.sbin/rpki-client/validate.c b/usr.sbin/rpki-client/validate.c index 1638c2846fe..8e3a08793a0 100644 --- a/usr.sbin/rpki-client/validate.c +++ b/usr.sbin/rpki-client/validate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: validate.c,v 1.67 2023/09/25 08:48:14 job Exp $ */ +/* $OpenBSD: validate.c,v 1.68 2023/10/19 17:05:55 job Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -643,24 +643,13 @@ valid_uuid(const char *s) } } -int -valid_ca_pkey(const char *fn, EVP_PKEY *pkey) +static int +valid_ca_pkey_rsa(const char *fn, EVP_PKEY *pkey) { RSA *rsa; const BIGNUM *rsa_e; int key_bits; - if (pkey == NULL) { - warnx("%s: failure, pkey is NULL", fn); - return 0; - } - - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { - warnx("%s: Expected EVP_PKEY_RSA, got %d", fn, - EVP_PKEY_base_id(pkey)); - return 0; - } - if ((key_bits = EVP_PKEY_bits(pkey)) != 2048) { warnx("%s: RFC 7935: expected 2048-bit modulus, got %d bits", fn, key_bits); @@ -684,3 +673,55 @@ valid_ca_pkey(const char *fn, EVP_PKEY *pkey) return 1; } + +static int +valid_ca_pkey_ec(const char *fn, EVP_PKEY *pkey) +{ + EC_KEY *ec; + const EC_GROUP *group; + int nid; + const char *cname; + + if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { + warnx("%s: failed to extract ECDSA public key", fn); + return 0; + } + + if ((group = EC_KEY_get0_group(ec)) == NULL) { + warnx("%s: EC_KEY_get0_group failed", fn); + return 0; + } + + nid = EC_GROUP_get_curve_name(group); + if (nid != NID_X9_62_prime256v1) { + if ((cname = EC_curve_nid2nist(nid)) == NULL) + cname = OBJ_nid2sn(nid); + warnx("%s: Expected P-256, got %s", fn, cname); + return 0; + } + + if (!EC_KEY_check_key(ec)) { + warnx("%s: EC_KEY_check_key failed", fn); + return 0; + } + + return 1; +} + +int +valid_ca_pkey(const char *fn, EVP_PKEY *pkey) +{ + if (pkey == NULL) { + warnx("%s: failure, pkey is NULL", fn); + return 0; + } + + if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) + return valid_ca_pkey_rsa(fn, pkey); + + if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) + return valid_ca_pkey_ec(fn, pkey); + + warnx("%s: unsupported public key algorithm", fn); + return 0; +} -- 2.20.1