[openssl] master update

tmraz at fedoraproject.org tmraz at fedoraproject.org
Thu Sep 17 15:15:58 UTC 2020


The branch master has been updated
       via  67ecd65cc4fdaa03fbae5fcccf53ebca7d785554 (commit)
       via  cccf532fef10aaa2d682227061b8828a1eb2c031 (commit)
       via  fe2f8aecfe4a0de483334bf671a8eb4f14444c00 (commit)
      from  bde4aa8dc1946dff189c89396814a98d1052262d (commit)


- Log -----------------------------------------------------------------
commit 67ecd65cc4fdaa03fbae5fcccf53ebca7d785554
Author: Tomas Mraz <tmraz at 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.oheimb at siemens.com>
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/12683)

commit cccf532fef10aaa2d682227061b8828a1eb2c031
Author: Tomas Mraz <tmraz at 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.oheimb at siemens.com>
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/12683)

commit fe2f8aecfe4a0de483334bf671a8eb4f14444c00
Author: Tomas Mraz <tmraz at 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.oheimb at siemens.com>
    Reviewed-by: Nicola Tuveri <nic.tuv at 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


More information about the openssl-commits mailing list