EVP: Add EVP_PKEY_get_group_name() to extract the group name of a pkey
authorRichard Levitte <levitte@openssl.org>
Fri, 4 Dec 2020 05:32:24 +0000 (06:32 +0100)
committerRichard Levitte <levitte@openssl.org>
Tue, 8 Dec 2020 19:13:54 +0000 (20:13 +0100)
This replaces the internal evp_pkey_get_EC_KEY_curve_nid()

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/13436)

crypto/err/openssl.txt
crypto/evp/evp_err.c
crypto/evp/p_lib.c
doc/man3/EVP_PKEY_get_group_name.pod [new file with mode: 0644]
include/internal/evp.h [deleted file]
include/openssl/evp.h
include/openssl/evperr.h
util/libcrypto.num
util/missingcrypto.txt

index a19ca7ceb959a492297175d069a55b392104841b..491f3a7cdbe202646cecc045a84d4c3a0e96844c 100644 (file)
@@ -2624,6 +2624,7 @@ EVP_R_UNSUPPORTED_KEYLENGTH:123:unsupported keylength
 EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION:124:\
        unsupported key derivation function
 EVP_R_UNSUPPORTED_KEY_SIZE:108:unsupported key size
+EVP_R_UNSUPPORTED_KEY_TYPE:224:unsupported key type
 EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds
 EVP_R_UNSUPPORTED_PRF:125:unsupported prf
 EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm
index 3a4253b353a3bd986997bda2251c8a197fd29b65..c2259f0beb4c230886881dbf37082072fbcc81d9 100644 (file)
@@ -176,6 +176,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "unsupported key derivation function"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_SIZE),
     "unsupported key size"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_TYPE),
+    "unsupported key type"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS),
     "unsupported number of rounds"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRF), "unsupported prf"},
index af14706939fc4c12b228470e349b6f0577b124ef..6211019b628b56e5d7d66fc8e0a10a95c0320fad 100644 (file)
 #include <openssl/encoder.h>
 #include <openssl/core_names.h>
 
+#include "internal/ffc.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 #include "crypto/ecx.h"
-#include "internal/evp.h"
 #include "internal/provider.h"
 #include "evp_local.h"
 
@@ -1056,48 +1056,6 @@ int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
     return 0;
 }
 
-#ifndef OPENSSL_NO_EC
-/*
- * TODO rewrite when we have proper data extraction functions
- * Note: an octet pointer would be desirable!
- */
-static OSSL_CALLBACK get_ec_curve_name_cb;
-static int get_ec_curve_name_cb(const OSSL_PARAM params[], void *arg)
-{
-    const OSSL_PARAM *p = NULL;
-
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME)) != NULL)
-        return OSSL_PARAM_get_utf8_string(p, arg, 0);
-
-    /* If there is no curve name, this is not an EC key */
-    return 0;
-}
-
-int evp_pkey_get_EC_KEY_curve_nid(const EVP_PKEY *pkey)
-{
-    int ret = NID_undef;
-
-    if (pkey->keymgmt == NULL) {
-        if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) {
-            EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
-
-            ret = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
-        }
-    } else if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "SM2")) {
-        char *curve_name = NULL;
-
-        ret = evp_keymgmt_util_export(pkey,
-                                      OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
-                                      get_ec_curve_name_cb, &curve_name);
-        if (ret)
-            ret = ec_curve_name2nid(curve_name);
-        OPENSSL_free(curve_name);
-    }
-
-    return ret;
-}
-#endif
-
 static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
 {
     BIO_set_indent(*out, saved_indent);
@@ -1259,6 +1217,59 @@ int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
     }
 }
 
+int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *gname, size_t gname_sz,
+                            size_t *gname_len)
+{
+    if (evp_pkey_is_legacy(pkey)) {
+        const char *name = NULL;
+
+        switch (EVP_PKEY_base_id(pkey)) {
+#ifndef OPENSSL_NO_EC
+        case EVP_PKEY_EC:
+            {
+                EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
+                int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+
+                if (nid != NID_undef)
+                    name = ec_curve_nid2name(nid);
+            }
+            break;
+#endif
+#ifndef OPENSSL_NO_DH
+        case EVP_PKEY_DH:
+            {
+                DH *dh = EVP_PKEY_get0_DH(pkey);
+                int uid = DH_get_nid(dh);
+
+                if (uid != NID_undef)
+                    name = ossl_ffc_named_group_from_uid(uid);
+            }
+            break;
+#endif
+        default:
+            break;
+        }
+
+        if (gname_len != NULL)
+            *gname_len = (name == NULL ? 0 : strlen(name));
+        if (name != NULL) {
+            if (gname != NULL)
+                OPENSSL_strlcpy(gname, name, gname_sz);
+            return 1;
+        }
+    } else if (evp_pkey_is_provided(pkey)) {
+        if (EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
+                                           gname, gname_sz, gname_len))
+            return 1;
+    } else {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
+        return 0;
+    }
+
+    ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+    return 0;
+}
+
 int EVP_PKEY_supports_digest_nid(EVP_PKEY *pkey, int nid)
 {
     int rv, default_nid;
diff --git a/doc/man3/EVP_PKEY_get_group_name.pod b/doc/man3/EVP_PKEY_get_group_name.pod
new file mode 100644 (file)
index 0000000..964d6b8
--- /dev/null
@@ -0,0 +1,46 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_get_group_name - get private key group name
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz,
+                             size_t *gname_len);
+
+=head1 DESCRIPTION
+
+EVP_PKEY_get_group_name() fills in the group name of the I<pkey> into
+I<gname>, up to at most I<gname_sz> bytes including the ending NUL byte
+and assigns I<*gname_len> the actual size of the name, if I<pkey>'s key type
+supports it.
+I<gname> as well as I<gname_len> may individually be NULL, and won't be
+filled in or assigned in that case.
+
+=head1 NOTES
+
+Among the standard OpenSSL key types, this is only supported for DH, EC and
+SM2 keys.  Other providers may support this for additional key types.
+
+=head1 RETURN VALUES
+
+EVP_PKEY_get_group_name() returns 1 if the group name could be filled in,
+otherwise 0.
+
+=head1 HISTORY
+
+This function was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/internal/evp.h b/include/internal/evp.h
deleted file mode 100644 (file)
index 404e483..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_INTERNAL_EVP_H
-# define OSSL_INTERNAL_EVP_H
-
-# include <openssl/evp.h>
-
-# ifndef OPENSSL_NO_EC
-/*
- * TODO(3.0) While waiting for more generic getters, we have these functions
- * as an interim solution.  This should be removed when the generic getters
- * appear.
- */
-int evp_pkey_get_EC_KEY_curve_nid(const EVP_PKEY *pkey);
-# endif
-#endif
index 28b6f4f399d53f37ab897d3f33e1722b6ea1f639..4978d6e2042d273f503a9f9c1bc1759caeb40877 100644 (file)
@@ -1984,6 +1984,8 @@ void EVP_add_alg_module(void);
 
 int EVP_PKEY_CTX_set_group_name(EVP_PKEY_CTX *ctx, const char *name);
 int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen);
+int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *name, size_t name_sz,
+                            size_t *gname_len);
 
 OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
 const char *EVP_PKEY_CTX_get0_propq(EVP_PKEY_CTX *ctx);
index f98cca31041736ab87634073c7b3dca2847a9017..2fdd99336f3588b86eaf31181cb396a587f89db3 100644 (file)
 # define EVP_R_UNSUPPORTED_KEYLENGTH                      123
 # define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION        124
 # define EVP_R_UNSUPPORTED_KEY_SIZE                       108
+# define EVP_R_UNSUPPORTED_KEY_TYPE                       224
 # define EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS               135
 # define EVP_R_UNSUPPORTED_PRF                            125
 # define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM          118
index e25e52442d1053c153bcd58bb88ba75ef36bbe65..50f0885f0b9aab626547e0b1320d66c8c49f92ab 100644 (file)
@@ -4996,7 +4996,6 @@ EVP_PKEY_get_utf8_string_param          ? 3_0_0   EXIST::FUNCTION:
 EVP_PKEY_get_octet_string_param         ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_is_a                           ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_can_sign                       ?      3_0_0   EXIST::FUNCTION:
-evp_pkey_get_EC_KEY_curve_nid           ?      3_0_0   EXIST::FUNCTION:EC
 X509_STORE_CTX_new_ex                   ?      3_0_0   EXIST::FUNCTION:
 CT_POLICY_EVAL_CTX_new_ex               ?      3_0_0   EXIST::FUNCTION:CT
 CTLOG_new_ex                            ?      3_0_0   EXIST::FUNCTION:CT
@@ -5284,3 +5283,4 @@ PEM_write_PrivateKey_ex                 ? 3_0_0   EXIST::FUNCTION:STDIO
 PEM_write_bio_PrivateKey_ex             ?      3_0_0   EXIST::FUNCTION:
 PEM_write_PUBKEY_ex                     ?      3_0_0   EXIST::FUNCTION:STDIO
 PEM_write_bio_PUBKEY_ex                 ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_get_group_name                 ?      3_0_0   EXIST::FUNCTION:
index 211a2c57370ec8e174f023a0e666c2ea5b46acab..915669ba26a99d029cec59eff9ccb92b264bac18 100644 (file)
@@ -1540,8 +1540,6 @@ conf_ssl_name_find(3)
 d2i_X509_bio(3)
 d2i_X509_fp(3)
 err_free_strings_int(3)
-# The following is internal but exported by libcrypto
-evp_pkey_get_EC_KEY_curve_nid(3)
 i2a_ACCESS_DESCRIPTION(3)
 i2a_ASN1_ENUMERATED(3)
 i2a_ASN1_INTEGER(3)