Browse Source

Add EVP_PKEY_CTX_new_provided()

This works as much as possible EVP_PKEY_CTX_new_id(), except it takes
data that's relevant for providers, algorithm name and property query
string instead of NID and engine.

Additionally, if EVP_PKEY_CTX_new() or EVP_PKEY_CTX_new_id() was
called, the algorithm name in the EVP_PKEY context will be set to the
short name of the given NID (explicit or the one of the given
EVP_PKEY), thereby giving an easier transition from legacy methods to
provided methods.

The intent is that operations will use this information to fetch
provider methods implicitly as needed.

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/10184)
Richard Levitte 4 years ago
parent
commit
a07c17ef57
6 changed files with 49 additions and 7 deletions
  1. 8 0
      CHANGES
  2. 17 3
      crypto/evp/pmeth_lib.c
  3. 17 4
      doc/man3/EVP_PKEY_CTX_new.pod
  4. 4 0
      include/crypto/evp.h
  5. 2 0
      include/openssl/evp.h
  6. 1 0
      util/libcrypto.num

+ 8 - 0
CHANGES

@@ -9,6 +9,14 @@
 
  Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
 
+  *) Added functionality to create an EVP_PKEY context based on data
+     for methods from providers.  This takes an algorithm name and a
+     property query string and simply stores them, with the intent
+     that any operation that uses this context will use those strings
+     to fetch the needed methods implicitly, thereby making the port
+     of application written for pre-3.0 OpenSSL easier.
+     [Richard Levitte]
+
   *) The undocumented function NCONF_WIN32() has been deprecated; for
      conversion details see the HISTORY section of doc/man5/config.pod
      [Rich Salz]

+ 17 - 3
crypto/evp/pmeth_lib.c

@@ -111,7 +111,9 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
     return (**ret)();
 }
 
-static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
+static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e,
+                                 const char *name, const char *propquery,
+                                 int id)
 {
     EVP_PKEY_CTX *ret;
     const EVP_PKEY_METHOD *pmeth = NULL;
@@ -130,6 +132,8 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
             return 0;
         id = pkey->type;
     }
+    name = OBJ_nid2sn(id);
+    propquery = NULL;
 #ifndef OPENSSL_NO_ENGINE
     if (e == NULL && pkey != NULL)
         e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
@@ -171,6 +175,8 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
         EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
+    ret->algorithm = name;
+    ret->propquery = propquery;
     ret->engine = e;
     ret->pmeth = pmeth;
     ret->operation = EVP_PKEY_OP_UNDEFINED;
@@ -277,12 +283,18 @@ void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
 {
-    return int_ctx_new(pkey, e, -1);
+    return int_ctx_new(pkey, e, NULL, NULL, -1);
 }
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
 {
-    return int_ctx_new(NULL, e, id);
+    return int_ctx_new(NULL, e, NULL, NULL, id);
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(const char *name,
+                                        const char *propquery)
+{
+    return int_ctx_new(NULL, NULL, name, propquery, -1);
 }
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
@@ -312,6 +324,8 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
         EVP_PKEY_up_ref(pctx->pkey);
     rctx->pkey = pctx->pkey;
     rctx->operation = pctx->operation;
+    rctx->algorithm = pctx->algorithm;
+    rctx->propquery = pctx->propquery;
 
     if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) {
         if (pctx->op.kex.exchange != NULL) {

+ 17 - 4
doc/man3/EVP_PKEY_CTX_new.pod

@@ -2,7 +2,9 @@
 
 =head1 NAME
 
-EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free - public key algorithm context functions
+EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_new_provided,
+EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free
+- public key algorithm context functions
 
 =head1 SYNOPSIS
 
@@ -10,6 +12,8 @@ EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free - pub
 
  EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
  EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
+ EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(const char *name,
+                                         const char *propquery);
  EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
  void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 
@@ -19,9 +23,18 @@ The EVP_PKEY_CTX_new() function allocates public key algorithm context using
 the algorithm specified in B<pkey> and ENGINE B<e>.
 
 The EVP_PKEY_CTX_new_id() function allocates public key algorithm context
-using the algorithm specified by B<id> and ENGINE B<e>. It is normally used
-when no B<EVP_PKEY> structure is associated with the operations, for example
-during parameter generation of key generation for some algorithms.
+using the algorithm specified by B<id> and ENGINE B<e>.
+
+The EVP_PKEY_CTX_new_provided() function allocates a public key
+algorithm context using the algorithm specified by I<name> and the
+property query I<propquery>.  The strings aren't duplicated, so they
+must remain unchanged for the lifetime of the returned B<EVP_PKEY_CTX>
+or of any of its duplicates.
+
+EVP_PKEY_CTX_new_id() and EVP_PKEY_CTX_new_provided() are normally
+used when no B<EVP_PKEY> structure is associated with the operations,
+for example during parameter generation or key generation for some
+algorithms.
 
 EVP_PKEY_CTX_dup() duplicates the context B<ctx>.
 

+ 4 - 0
include/crypto/evp.h

@@ -21,6 +21,10 @@ struct evp_pkey_ctx_st {
     /* Actual operation */
     int operation;
 
+    /* Algorithm name and properties associated with this context */
+    const char *algorithm;
+    const char *propquery;
+
     union {
         struct {
             EVP_KEYEXCH *exchange;

+ 2 - 0
include/openssl/evp.h

@@ -1441,6 +1441,8 @@ const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt);
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(const char *name,
+                                        const char *propquery);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 

+ 1 - 0
util/libcrypto.num

@@ -4827,3 +4827,4 @@ EVP_DigestSignUpdate                    4943	3_0_0	EXIST::FUNCTION:
 EVP_DigestVerifyInit_ex                 4944	3_0_0	EXIST::FUNCTION:
 EVP_DigestVerifyUpdate                  4945	3_0_0	EXIST::FUNCTION:
 BN_check_prime                          4946	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_new_provided               4947	3_0_0	EXIST::FUNCTION: