The branch master has been updated via 67ecd65cc4fdaa03fbae5fcccf53ebca7d785554 (commit) via cccf532fef10aaa2d682227061b8828a1eb2c031 (commit) via fe2f8aecfe4a0de483334bf671a8eb4f14444c00 (commit) from bde4aa8dc1946dff189c89396814a98d1052262d (commit)
- Log ----------------------------------------------------------------- commit 67ecd65cc4fdaa03fbae5fcccf53ebca7d785554 Author: Tomas Mraz <tm...@fedoraproject.org> Date: Fri Sep 11 15:27:23 2020 +0200 Rename check_chain_extensions to check_chain The function does much more than just checking extensions. Reviewed-by: David von Oheimb <david.von.ohe...@siemens.com> Reviewed-by: Nicola Tuveri <nic....@gmail.com> (Merged from https://github.com/openssl/openssl/pull/12683) commit cccf532fef10aaa2d682227061b8828a1eb2c031 Author: Tomas Mraz <tm...@fedoraproject.org> Date: Fri Sep 11 09:09:29 2020 +0200 Disallow certs with explicit curve in verification chain The check is applied only with X509_V_FLAG_X509_STRICT. Fixes #12139 Reviewed-by: David von Oheimb <david.von.ohe...@siemens.com> Reviewed-by: Nicola Tuveri <nic....@gmail.com> (Merged from https://github.com/openssl/openssl/pull/12683) commit fe2f8aecfe4a0de483334bf671a8eb4f14444c00 Author: Tomas Mraz <tm...@fedoraproject.org> Date: Fri Aug 21 14:50:52 2020 +0200 EC_KEY: add EC_KEY_decoded_from_explicit_params() The function returns 1 when the encoding of a decoded EC key used explicit encoding of the curve parameters. Reviewed-by: David von Oheimb <david.von.ohe...@siemens.com> Reviewed-by: Nicola Tuveri <nic....@gmail.com> (Merged from https://github.com/openssl/openssl/pull/12683) ----------------------------------------------------------------------- Summary of changes: crypto/ec/ec_asn1.c | 31 +++++++--- crypto/ec/ec_key.c | 7 +++ crypto/ec/ec_lib.c | 1 + crypto/ec/ec_local.h | 2 + crypto/x509/v3_purp.c | 2 +- crypto/x509/x509_txt.c | 2 + crypto/x509/x509_vfy.c | 41 ++++++++++++- doc/man3/EC_KEY_new.pod | 8 ++- include/openssl/ec.h | 2 + include/openssl/x509_vfy.h.in | 1 + ssl/statem/statem_lib.c | 1 + test/certs/ca-cert-ec-explicit.pem | 19 ++++++ test/certs/ca-cert-ec-named.pem | 14 +++++ test/certs/ca-key-ec-explicit.pem | 10 +++ test/certs/ca-key-ec-named.pem | 5 ++ test/certs/ee-cert-ec-explicit.pem | 16 +++++ test/certs/ee-cert-ec-named-explicit.pem | 11 ++++ test/certs/ee-cert-ec-named-named.pem | 11 ++++ test/certs/ee-key-ec-explicit.pem | 10 +++ test/certs/ee-key-ec-named-explicit.pem | 5 ++ test/certs/ee-key-ec-named-named.pem | 5 ++ test/certs/setup.sh | 10 +++ test/ec_internal_test.c | 101 +++++++++++++++++++++++++++++++ test/recipes/25-test_verify.t | 17 +++++- util/libcrypto.num | 1 + 25 files changed, 319 insertions(+), 14 deletions(-) create mode 100644 test/certs/ca-cert-ec-explicit.pem create mode 100644 test/certs/ca-cert-ec-named.pem create mode 100644 test/certs/ca-key-ec-explicit.pem create mode 100644 test/certs/ca-key-ec-named.pem create mode 100644 test/certs/ee-cert-ec-explicit.pem create mode 100644 test/certs/ee-cert-ec-named-explicit.pem create mode 100644 test/certs/ee-cert-ec-named-named.pem create mode 100644 test/certs/ee-key-ec-explicit.pem create mode 100644 test/certs/ee-key-ec-named-explicit.pem create mode 100644 test/certs/ee-key-ec-named-named.pem diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 879ff9faa2..9454f580d5 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -74,6 +74,12 @@ struct ec_parameters_st { ASN1_INTEGER *cofactor; } /* ECPARAMETERS */ ; +typedef enum { + ECPKPARAMETERS_TYPE_NAMED = 0, + ECPKPARAMETERS_TYPE_EXPLICIT, + ECPKPARAMETERS_TYPE_IMPLICIT +} ecpk_parameters_type_t; + struct ecpk_parameters_st { int type; union { @@ -472,9 +478,10 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, return NULL; } } else { - if (ret->type == 0) + if (ret->type == ECPKPARAMETERS_TYPE_NAMED) ASN1_OBJECT_free(ret->value.named_curve); - else if (ret->type == 1 && ret->value.parameters) + else if (ret->type == ECPKPARAMETERS_TYPE_EXPLICIT + && ret->value.parameters != NULL) ECPARAMETERS_free(ret->value.parameters); } @@ -491,7 +498,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, EC_R_MISSING_OID); ok = 0; } else { - ret->type = 0; + ret->type = ECPKPARAMETERS_TYPE_NAMED; ret->value.named_curve = asn1obj; } } else @@ -499,7 +506,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, ok = 0; } else { /* use the ECPARAMETERS structure */ - ret->type = 1; + ret->type = ECPKPARAMETERS_TYPE_EXPLICIT; if ((ret->value.parameters = EC_GROUP_get_ecparameters(group, NULL)) == NULL) ok = 0; @@ -841,7 +848,8 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) return NULL; } - if (params->type == 0) { /* the curve is given by an OID */ + if (params->type == ECPKPARAMETERS_TYPE_NAMED) { + /* the curve is given by an OID */ tmp = OBJ_obj2nid(params->value.named_curve); if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, @@ -849,15 +857,16 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) return NULL; } EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); - } else if (params->type == 1) { /* the parameters are given by a - * ECPARAMETERS structure */ + } else if (params->type == ECPKPARAMETERS_TYPE_EXPLICIT) { + /* the parameters are given by an ECPARAMETERS structure */ ret = EC_GROUP_new_from_ecparameters(params->value.parameters); if (!ret) { ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB); return NULL; } EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE); - } else if (params->type == 2) { /* implicitlyCA */ + } else if (params->type == ECPKPARAMETERS_TYPE_IMPLICIT) { + /* implicit parameters inherited from CA - unsupported */ return NULL; } else { ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_ASN1_ERROR); @@ -887,6 +896,9 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) return NULL; } + if (params->type == ECPKPARAMETERS_TYPE_EXPLICIT) + group->decoded_from_explicit_params = 1; + if (a) { EC_GROUP_free(*a); *a = group; @@ -938,6 +950,9 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) if (priv_key->parameters) { EC_GROUP_free(ret->group); ret->group = EC_GROUP_new_from_ecpkparameters(priv_key->parameters); + if (ret->group != NULL + && priv_key->parameters->type == ECPKPARAMETERS_TYPE_EXPLICIT) + ret->group->decoded_from_explicit_params = 1; } if (ret->group == NULL) { diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 84e1b96c48..f1f325237e 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -822,6 +822,13 @@ void EC_KEY_clear_flags(EC_KEY *key, int flags) key->dirty_cnt++; } +int EC_KEY_decoded_from_explicit_params(const EC_KEY *key) +{ + if (key == NULL || key->group == NULL) + return -1; + return key->group->decoded_from_explicit_params; +} + size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, unsigned char **pbuf, BN_CTX *ctx) { diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index d7752e953f..222df55632 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -243,6 +243,7 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) dest->asn1_flag = src->asn1_flag; dest->asn1_form = src->asn1_form; + dest->decoded_from_explicit_params = src->decoded_from_explicit_params; if (src->seed) { OPENSSL_free(dest->seed); diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index aa040b54d1..11fab6b985 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -213,6 +213,8 @@ struct ec_group_st { BIGNUM *order, *cofactor; int curve_name; /* optional NID for named curve */ int asn1_flag; /* flag to control the asn1 encoding */ + int decoded_from_explicit_params; /* set if decoded from explicit + * curve parameters encoding */ point_conversion_form_t asn1_form; unsigned char *seed; /* optional seed for parameters (appears in * ASN1) */ diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c index 92f3bbe3b0..8b0dfd9759 100644 --- a/crypto/x509/v3_purp.c +++ b/crypto/x509/v3_purp.c @@ -431,7 +431,7 @@ int x509v3_cache_extensions(X509 *x) x->ex_flags |= EXFLAG_CA; if (bs->pathlen != NULL) { /* - * the error case !bs->ca is checked by check_chain_extensions() + * the error case !bs->ca is checked by check_chain() * in case ctx->param->flags & X509_V_FLAG_X509_STRICT */ if (bs->pathlen->type == V_ASN1_NEG_INTEGER) { diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 53b19e46df..0c7ae1ed79 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -210,6 +210,8 @@ const char *X509_verify_cert_error_string(long n) return "CA cert does not include key usage extension"; case X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3: return "Using cert extension requires at least X509v3"; + case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS: + return "Certificate public key has explicit ECC parameters"; default: /* Printing an error number into a static buffer is not thread-safe */ diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index f234ec0df6..3d6c665aed 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -69,7 +69,7 @@ static int dane_verify(X509_STORE_CTX *ctx); static int null_callback(int ok, X509_STORE_CTX *e); static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); -static int check_chain_extensions(X509_STORE_CTX *ctx); +static int check_chain(X509_STORE_CTX *ctx); static int check_name_constraints(X509_STORE_CTX *ctx); static int check_id(X509_STORE_CTX *ctx); static int check_trust(X509_STORE_CTX *ctx, int num_untrusted); @@ -80,6 +80,7 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); static int check_dane_issuer(X509_STORE_CTX *ctx, int depth); static int check_key_level(X509_STORE_CTX *ctx, X509 *cert); static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert); +static int check_curve(X509 *cert); static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, unsigned int *preasons, X509_CRL *crl, X509 *x); @@ -221,7 +222,7 @@ static int verify_chain(X509_STORE_CTX *ctx) * instantiate chain public key parameters. */ if ((ok = build_chain(ctx)) == 0 || - (ok = check_chain_extensions(ctx)) == 0 || + (ok = check_chain(ctx)) == 0 || (ok = check_auth_level(ctx)) == 0 || (ok = check_id(ctx)) == 0 || 1) X509_get_pubkey_parameters(NULL, ctx->chain); @@ -440,7 +441,7 @@ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, * purpose */ -static int check_chain_extensions(X509_STORE_CTX *ctx) +static int check_chain(X509_STORE_CTX *ctx) { int i, must_be_ca, plen = 0; X509 *x; @@ -513,6 +514,14 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ret = 1; break; } + if (num > 1) { + /* Check for presence of explicit elliptic curve parameters */ + ret = check_curve(x); + if (ret < 0) + ctx->error = X509_V_ERR_UNSPECIFIED; + else if (ret == 0) + ctx->error = X509_V_ERR_EC_KEY_EXPLICIT_PARAMS; + } /* * Do the following set of checks only if strict checking is requrested * and not for self-issued (including self-signed) EE (non-CA) certs @@ -3433,6 +3442,32 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1]; } +/* + * Check whether the public key of ``cert`` does not use explicit params + * for an elliptic curve. + * + * Returns 1 on success, 0 if check fails, -1 for other errors. + */ +static int check_curve(X509 *cert) +{ +#ifndef OPENSSL_NO_EC + EVP_PKEY *pkey = X509_get0_pubkey(cert); + + /* Unsupported or malformed key */ + if (pkey == NULL) + return -1; + + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { + int ret; + + ret = EC_KEY_decoded_from_explicit_params(EVP_PKEY_get0_EC_KEY(pkey)); + return ret < 0 ? ret : !ret; + } +#endif + + return 1; +} + /* * Check whether the signature digest algorithm of ``cert`` meets the security * level of ``ctx``. Should not be checked for trust anchors (whether diff --git a/doc/man3/EC_KEY_new.pod b/doc/man3/EC_KEY_new.pod index a907435153..c3e90a2474 100644 --- a/doc/man3/EC_KEY_new.pod +++ b/doc/man3/EC_KEY_new.pod @@ -9,7 +9,8 @@ EC_KEY_copy, EC_KEY_dup, EC_KEY_up_ref, EC_KEY_get0_engine, EC_KEY_get0_group, EC_KEY_set_group, EC_KEY_get0_private_key, EC_KEY_set_private_key, EC_KEY_get0_public_key, EC_KEY_set_public_key, EC_KEY_get_conv_form, -EC_KEY_set_conv_form, EC_KEY_set_asn1_flag, EC_KEY_precompute_mult, +EC_KEY_set_conv_form, EC_KEY_set_asn1_flag, +EC_KEY_decoded_from_explicit_params, EC_KEY_precompute_mult, EC_KEY_generate_key, EC_KEY_check_key, EC_KEY_set_public_key_affine_coordinates, EC_KEY_oct2key, EC_KEY_key2buf, EC_KEY_oct2priv, EC_KEY_priv2oct, EC_KEY_priv2buf - Functions for creating, destroying and manipulating @@ -41,6 +42,7 @@ EC_KEY objects point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); + int EC_KEY_decoded_from_explicit_params(const EC_KEY *key); int EC_KEY_generate_key(EC_KEY *key); int EC_KEY_check_key(const EC_KEY *key); int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y); @@ -142,6 +144,10 @@ EC_KEY_set_asn1_flag() sets the asn1_flag on the underlying EC_GROUP object (if set). Refer to L<EC_GROUP_copy(3)> for further information on the asn1_flag. +EC_KEY_decoded_from_explicit_params() returns 1 if the group of the I<key> was +decoded from data with explicitly encoded group parameters, -1 if the I<key> +is NULL or the group parameters are missing, and 0 otherwise. + Although deprecated in OpenSSL 3.0 and should no longer be used, EC_KEY_precompute_mult() stores multiples of the underlying EC_GROUP generator for faster point multiplication. See also L<EC_POINT_add(3)>. diff --git a/include/openssl/ec.h b/include/openssl/ec.h index aca52e6923..ed83e3bcb0 100644 --- a/include/openssl/ec.h +++ b/include/openssl/ec.h @@ -896,6 +896,8 @@ void EC_KEY_set_flags(EC_KEY *key, int flags); void EC_KEY_clear_flags(EC_KEY *key, int flags); +int EC_KEY_decoded_from_explicit_params(const EC_KEY *key); + /** * Creates a new EC_KEY object using a named curve as underlying * EC_GROUP object. diff --git a/include/openssl/x509_vfy.h.in b/include/openssl/x509_vfy.h.in index 8a565f71a3..6266e6007d 100644 --- a/include/openssl/x509_vfy.h.in +++ b/include/openssl/x509_vfy.h.in @@ -242,6 +242,7 @@ X509_LOOKUP_ctrl_with_libctx((x), X509_L_ADD_STORE, (name), 0, NULL, \ # define X509_V_ERR_SUBJECT_KEY_IDENTIFIER_CRITICAL 91 # define X509_V_ERR_CA_CERT_MISSING_KEY_USAGE 92 # define X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 93 +# define X509_V_ERR_EC_KEY_EXPLICIT_PARAMS 94 /* Certificate verify flags */ # ifndef OPENSSL_NO_DEPRECATED_1_1_0 diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 6d0efb3239..618a58d659 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1408,6 +1408,7 @@ int tls_get_message_body(SSL *s, size_t *len) static const X509ERR2ALERT x509table[] = { {X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE}, {X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE}, + {X509_V_ERR_EC_KEY_EXPLICIT_PARAMS, SSL_AD_BAD_CERTIFICATE}, {X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE}, {X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA}, {X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED}, diff --git a/test/certs/ca-cert-ec-explicit.pem b/test/certs/ca-cert-ec-explicit.pem new file mode 100644 index 0000000000..d741ecdb65 --- /dev/null +++ b/test/certs/ca-cert-ec-explicit.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGDCCAgCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 +IENBMCAXDTIwMDkxNTEzMDY0MVoYDzIxMjAwOTE2MTMwNjQxWjANMQswCQYDVQQD +DAJDQTCCAUswggEDBgcqhkjOPQIBMIH3AgEBMCwGByqGSM49AQECIQD/////AAAA +AQAAAAAAAAAAAAAAAP///////////////zBbBCD/////AAAAAQAAAAAAAAAAAAAA +AP///////////////AQgWsY12Ko6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsD +FQDEnTYIhucEk2pmeOETnSa3gZ9+kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLesz +oPShOUXYmMKWT+NC4v4af5uO5+tKfA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD///// +AAAAAP//////////vOb6racXnoTzucrC/GMlUQIBAQNCAASlXna3kSD/Yol3RA5I +icjIxYb9UJoCTzb/LsxjlOvIS5OqCTzpqP0p3JrnvLPsbzq7Cf/g0bNlxAGs1iVM +5NDco1MwUTAdBgNVHQ4EFgQUFk6ucH6gMXeadmuV7a1iWEnU/CIwHwYDVR0jBBgw +FoAUjvUlrx6ba4Q9fICayVOcTXL3o1IwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQsFAAOCAQEAdyUgfT0eAsZzoHFXoWN5uqi0MHuhLI37TEzkH5h7iTpDQJTQ +F0SjbawfM/nxxUekRW3mjFu3lft+VA7yC0OTNBLffan/vTh+HGOvvYZSMJYgKrMG +PRWgDId+n9RTcQCf+91cISvOazHixRiJG7JfRLdNZsAE+miw4HgPLFboTwpxtTDJ +zJ4ssBC6P+5IHwBCtNMiilJMMMzuSaZa5iSo6M9AdXWfcQN3uhW1lgQOLOlKLcbo +3UhW1GMMhTTeytM5aylbKhRsnL7ozmS44zsKZ25YaQxgjdKitFjVN6j7eyQ7C9J2 +bLXgl3APweLQbGGs0zv08Ad0SCCKYLHK6mMJqg== +-----END CERTIFICATE----- diff --git a/test/certs/ca-cert-ec-named.pem b/test/certs/ca-cert-ec-named.pem new file mode 100644 index 0000000000..5fbe251afb --- /dev/null +++ b/test/certs/ca-cert-ec-named.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICJDCCAQygAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290 +IENBMCAXDTIwMDkxNTEzMDY1MFoYDzIxMjAwOTE2MTMwNjUwWjANMQswCQYDVQQD +DAJDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPt+MXCi9+wztEvmdG2EVSk7 +bAiJMXJXW/u0NbcGCrrbhO1NJSHHV3Lks888sqeSPh/bif/ASJ0HX+VarMUoFIKj +UzBRMB0GA1UdDgQWBBRjigU5REz8Lwf1iD6mALVhsHIanjAfBgNVHSMEGDAWgBSO +9SWvHptrhD18gJrJU5xNcvejUjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQCQs9wpblefb2C9a7usGL1DJjWJQIFHtUf+6p/KPgEV7LF138ECjL5s +0AWRd8Q8SbsBH49j2r3LLLMkvFglyRaN+FF+TCC/UQtclTb4+HgLsUT2xSU8U2cY +SOnzNB5AX/qAAsdOGqOjivPtGXcXFexDKPsw3n+3rJgymBP6hbLagb47IabNhot5 +bMM6S+bmfpMwfsm885zr5vG2Gg9FjjH94Vx4I7eRLkjCS88gkIR1J35ecHFteOdo +idOaCHQddYiKukBzgdjtTxSDXKffkaybylrwOZ8VBlQd3zC7s02d+riHCnroLnnE +cwYLlJ5z6jN7zoPZ55yX/EmA0RVny2le +-----END CERTIFICATE----- diff --git a/test/certs/ca-key-ec-explicit.pem b/test/certs/ca-key-ec-explicit.pem new file mode 100644 index 0000000000..08add31ca5 --- /dev/null +++ b/test/certs/ca-key-ec-explicit.pem @@ -0,0 +1,10 @@ +-----BEGIN PRIVATE KEY----- +MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB +AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA +///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV +AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg +9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A +AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgdEf20fpuqEZU +tZ4ORoq4vb5ETV4a6QOl/iGnDQt++/ihRANCAASlXna3kSD/Yol3RA5IicjIxYb9 +UJoCTzb/LsxjlOvIS5OqCTzpqP0p3JrnvLPsbzq7Cf/g0bNlxAGs1iVM5NDc +-----END PRIVATE KEY----- diff --git a/test/certs/ca-key-ec-named.pem b/test/certs/ca-key-ec-named.pem new file mode 100644 index 0000000000..cff7a64e84 --- /dev/null +++ b/test/certs/ca-key-ec-named.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgCTrYrMKcyV49+w4B +TWr2WTZsMM4aFpaYulKAuhiuQ7mhRANCAAT7fjFwovfsM7RL5nRthFUpO2wIiTFy +V1v7tDW3Bgq624TtTSUhx1dy5LPPPLKnkj4f24n/wEidB1/lWqzFKBSC +-----END PRIVATE KEY----- diff --git a/test/certs/ee-cert-ec-explicit.pem b/test/certs/ee-cert-ec-explicit.pem new file mode 100644 index 0000000000..eccb3342ca --- /dev/null +++ b/test/certs/ee-cert-ec-explicit.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAi6gAwIBAgIBAjAKBggqhkjOPQQDAjANMQswCQYDVQQDDAJDQTAgFw0y +MDA5MTUxMzE0MzlaGA8yMTIwMDkxNjEzMTQzOVowGTEXMBUGA1UEAwwOc2VydmVy +LmV4YW1wbGUwggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA//// +/wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAA +AAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n +0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9 +gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA +/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAE+7TDP7C9VqQP +TnqoJc/Fvf/N45BX+lBfmfiGBeRKtSsvrERUlymzQ4/nxVtymozAgFxQ0my998HH +TSVCj7Sq56N9MHswHQYDVR0OBBYEFKKwEfKYhNv6fbQf0Xd0te7J3GZdMB8GA1Ud +IwQYMBaAFGOKBTlETPwvB/WIPqYAtWGwchqeMAkGA1UdEwQCMAAwEwYDVR0lBAww +CgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4YW1wbGUwCgYIKoZIzj0E +AwIDRwAwRAIgb4UITAOFlATeaayWQX9r5gf61qcnzT7TjXCekf7ww9oCIBDltg/u +ZvS9gqviMFuPjTuk/FhsCTAUzTT7WmgcWeH7 +-----END CERTIFICATE----- diff --git a/test/certs/ee-cert-ec-named-explicit.pem b/test/certs/ee-cert-ec-named-explicit.pem new file mode 100644 index 0000000000..db13c0e5ef --- /dev/null +++ b/test/certs/ee-cert-ec-named-explicit.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlDCCATqgAwIBAgIBAjAKBggqhkjOPQQDAjANMQswCQYDVQQDDAJDQTAgFw0y +MDA5MTUxMzE0NDVaGA8yMTIwMDkxNjEzMTQ0NVowGTEXMBUGA1UEAwwOc2VydmVy +LmV4YW1wbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQv5PnMStW/Wx9lpvjl +JTsFIjc2wBv14sNuMh1hfNX8ZJcoCfAAKYu6ujxXt328GWBMaubRbBjOd/eqpEst +tYKzo30wezAdBgNVHQ4EFgQUmb/qcE413hkpmtjEMyRZZFcN1TYwHwYDVR0jBBgw +FoAUFk6ucH6gMXeadmuV7a1iWEnU/CIwCQYDVR0TBAIwADATBgNVHSUEDDAKBggr +BgEFBQcDATAZBgNVHREEEjAQgg5zZXJ2ZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNI +ADBFAiEA9y6J8rdAbO0mDZscIb8rIn6HgxBW4WAqTlFeZeHjjOYCIAmt2ldyObOL +tXaiaxYX3WAOR1vmfzsdrkCAOCfAkpbo +-----END CERTIFICATE----- diff --git a/test/certs/ee-cert-ec-named-named.pem b/test/certs/ee-cert-ec-named-named.pem new file mode 100644 index 0000000000..0730febf46 --- /dev/null +++ b/test/certs/ee-cert-ec-named-named.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBkzCCATqgAwIBAgIBAjAKBggqhkjOPQQDAjANMQswCQYDVQQDDAJDQTAgFw0y +MDA5MTUxNDEwNDhaGA8yMTIwMDkxNjE0MTA0OFowGTEXMBUGA1UEAwwOc2VydmVy +LmV4YW1wbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS0YU57+RFRWxr/frnL ++vOYkY3h9roKnvxCG07wK5tevEYtSdKz0KsHvDBDatw1r3JNv+m2p54/3AqFPAZ3 +5b0Po30wezAdBgNVHQ4EFgQUypypuZrUl0BEmbuhfJpo3QFNIvUwHwYDVR0jBBgw +FoAUY4oFOURM/C8H9Yg+pgC1YbByGp4wCQYDVR0TBAIwADATBgNVHSUEDDAKBggr +BgEFBQcDATAZBgNVHREEEjAQgg5zZXJ2ZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNH +ADBEAiAEkKD7H5uxQ4YbQOiN4evbu5RCV5W7TVE80iBfcY5u4wIgGcwr++lVNX0Q +CTT+M3ukDjOA8OEvKUz1TiDuRAQ29qU= +-----END CERTIFICATE----- diff --git a/test/certs/ee-key-ec-explicit.pem b/test/certs/ee-key-ec-explicit.pem new file mode 100644 index 0000000000..d847d85dbe --- /dev/null +++ b/test/certs/ee-key-ec-explicit.pem @@ -0,0 +1,10 @@ +-----BEGIN PRIVATE KEY----- +MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB +AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA +///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV +AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg +9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A +AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQg0cmpcTcEYG5G +ZaVkGjtsBc3sLZn1EuV9qNK2qx6iNzmhRANCAAT7tMM/sL1WpA9Oeqglz8W9/83j +kFf6UF+Z+IYF5Eq1Ky+sRFSXKbNDj+fFW3KajMCAXFDSbL33wcdNJUKPtKrn +-----END PRIVATE KEY----- diff --git a/test/certs/ee-key-ec-named-explicit.pem b/test/certs/ee-key-ec-named-explicit.pem new file mode 100644 index 0000000000..28f81e9569 --- /dev/null +++ b/test/certs/ee-key-ec-named-explicit.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg2ue+X5ZFJPJPQG2E +WQY4ALv2PkPp2Gy6KrMiokgmjkehRANCAAQv5PnMStW/Wx9lpvjlJTsFIjc2wBv1 +4sNuMh1hfNX8ZJcoCfAAKYu6ujxXt328GWBMaubRbBjOd/eqpEsttYKz +-----END PRIVATE KEY----- diff --git a/test/certs/ee-key-ec-named-named.pem b/test/certs/ee-key-ec-named-named.pem new file mode 100644 index 0000000000..d627bcf0dd --- /dev/null +++ b/test/certs/ee-key-ec-named-named.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGSoneIKG3//ujXGu +/EoJdNhpKZj026EF/YQ5FblUBWahRANCAAS0YU57+RFRWxr/frnL+vOYkY3h9roK +nvxCG07wK5tevEYtSdKz0KsHvDBDatw1r3JNv+m2p54/3AqFPAZ35b0P +-----END PRIVATE KEY----- diff --git a/test/certs/setup.sh b/test/certs/setup.sh index 369fef4f43..6839e60674 100755 --- a/test/certs/setup.sh +++ b/test/certs/setup.sh @@ -116,6 +116,10 @@ openssl x509 -in ca-cert-md5.pem -trustout \ # CA has 768-bit key OPENSSL_KEYBITS=768 \ ./mkcert.sh genca "CA" ca-key-768 ca-cert-768 root-key root-cert +# EC cert with explicit curve +./mkcert.sh genca "CA" ca-key-ec-explicit ca-cert-ec-explicit root-key root-cert +# EC cert with named curve +./mkcert.sh genca "CA" ca-key-ec-named ca-cert-ec-named root-key root-cert # client intermediate ca: cca-cert # trust variants: +serverAuth, -serverAuth, +clientAuth, -clientAuth @@ -184,6 +188,12 @@ OPENSSL_SIGALG=md5 \ # 768-bit leaf key OPENSSL_KEYBITS=768 \ ./mkcert.sh genee server.example ee-key-768 ee-cert-768 ca-key ca-cert +# EC cert with explicit curve signed by named curve ca +./mkcert.sh genee server.example ee-key-ec-explicit ee-cert-ec-explicit ca-key-ec-named ca-cert-ec-named +# EC cert with named curve signed by explicit curve ca +./mkcert.sh genee server.example ee-key-ec-named ee-cert-ec-named ca-key-ec-explicit ca-cert-ec-explicit +# EC cert with named curve signed by named curve ca +./mkcert.sh genee server.example ee-key-ec-namnam ee-cert-ec-namnam ca-key-ec-named ca-cert-ec-named # self-signed end-entity cert with explicit keyUsage not including KeyCertSign openssl req -new -x509 -key ee-key.pem -subj /CN=ee-self-signed -out ee-self-signed.pem -addext keyUsage=digitalSignature -days 36500 diff --git a/test/ec_internal_test.c b/test/ec_internal_test.c index 38a6ab5b4a..d3db698467 100644 --- a/test/ec_internal_test.c +++ b/test/ec_internal_test.c @@ -259,6 +259,106 @@ static int underflow_test(void) } #endif +/* + * Tests behavior of the decoded_from_explicit_params flag and API + */ +static int decoded_flag_test(void) +{ + EC_GROUP *grp; + EC_GROUP *grp_copy = NULL; + ECPARAMETERS *ecparams = NULL; + ECPKPARAMETERS *ecpkparams = NULL; + EC_KEY *key = NULL; + unsigned char *encodedparams = NULL; + const unsigned char *encp; + int encodedlen; + int testresult = 0; + + /* Test EC_GROUP_new not setting the flag */ + grp = EC_GROUP_new(EC_GFp_simple_method()); + if (!TEST_ptr(grp) + || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) + goto err; + EC_GROUP_free(grp); + + /* Test EC_GROUP_new_by_curve_name not setting the flag */ + grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (!TEST_ptr(grp) + || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) + goto err; + + /* Test EC_GROUP_new_from_ecparameters not setting the flag */ + if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL)) + || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams)) + || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) + goto err; + EC_GROUP_free(grp_copy); + grp_copy = NULL; + ECPARAMETERS_free(ecparams); + ecparams = NULL; + + /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */ + if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE) + || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) + || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) + || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0) + || !TEST_ptr(key = EC_KEY_new()) + /* Test EC_KEY_decoded_from_explicit_params on key without a group */ + || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1) + || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) + /* Test EC_KEY_decoded_from_explicit_params negative case */ + || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0)) + goto err; + EC_GROUP_free(grp_copy); + grp_copy = NULL; + ECPKPARAMETERS_free(ecpkparams); + ecpkparams = NULL; + + /* Test d2i_ECPKParameters with named params not setting the flag */ + if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) + || !TEST_ptr(encp = encodedparams) + || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) + || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) + goto err; + EC_GROUP_free(grp_copy); + grp_copy = NULL; + OPENSSL_free(encodedparams); + encodedparams = NULL; + + /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */ + EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE); + if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) + || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) + || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) + || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) + goto err; + EC_GROUP_free(grp_copy); + grp_copy = NULL; + + /* Test d2i_ECPKParameters with explicit params setting the flag */ + if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) + || !TEST_ptr(encp = encodedparams) + || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) + || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) + || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1) + || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) + /* Test EC_KEY_decoded_from_explicit_params positive case */ + || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1)) + goto err; + + testresult = 1; + + err: + EC_KEY_free(key); + EC_GROUP_free(grp); + EC_GROUP_free(grp_copy); + ECPARAMETERS_free(ecparams); + ECPKPARAMETERS_free(ecpkparams); + OPENSSL_free(encodedparams); + + return testresult; +} + int setup_tests(void) { crv_len = EC_get_builtin_curves(NULL, 0); @@ -275,6 +375,7 @@ int setup_tests(void) #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 ADD_TEST(underflow_test); #endif + ADD_TEST(decoded_flag_test); return 1; } diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t index aaa7fa3d90..6d8f78c978 100644 --- a/test/recipes/25-test_verify.t +++ b/test/recipes/25-test_verify.t @@ -27,7 +27,7 @@ sub verify { run(app([@args])); } -plan tests => 145; +plan tests => 148; # Canonical success ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), @@ -280,6 +280,21 @@ ok(verify("ee-cert-md5", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", ok(!verify("ee-cert-md5", "sslserver", ["root-cert"], ["ca-cert"]), "reject md5 leaf at auth level 1"); +# Explicit vs named curve tests +SKIP: { + skip "EC is not supported by this OpenSSL build", 3 + if disabled("ec"); + ok(!verify("ee-cert-ec-explicit", "sslserver", ["root-cert"], + ["ca-cert-ec-named"]), + "reject explicit curve leaf with named curve intermediate"); + ok(!verify("ee-cert-ec-named-explicit", "sslserver", ["root-cert"], + ["ca-cert-ec-explicit"]), + "reject named curve leaf with explicit curve intermediate"); + ok(verify("ee-cert-ec-named-named", "sslserver", ["root-cert"], + ["ca-cert-ec-named"]), + "accept named curve leaf with named curve intermediate"); +} + # Depth tests, note the depth limit bounds the number of CA certificates # between the trust-anchor and the leaf, so, for example, with a root->ca->leaf # chain, depth = 1 is sufficient, but depth == 0 is not. diff --git a/util/libcrypto.num b/util/libcrypto.num index a1b8ce0be1..e9f6e56690 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5282,3 +5282,4 @@ CMS_AuthEnvelopedData_create_with_libctx ? 3_0_0 EXIST::FUNCTION:CMS EVP_PKEY_CTX_set_ec_param_enc ? 3_0_0 EXIST::FUNCTION:EC EVP_PKEY_get0_first_alg_name ? 3_0_0 EXIST::FUNCTION: EVP_KEYMGMT_get0_first_name ? 3_0_0 EXIST::FUNCTION: +EC_KEY_decoded_from_explicit_params ? 3_0_0 EXIST::FUNCTION:EC