[openssl] master update

Richard Levitte levitte at openssl.org
Thu Jan 9 14:02:57 UTC 2020


The branch master has been updated
       via  2293032121d33299be4f21a599aab84413467f8d (commit)
       via  f23bc0b770efd229e27519786d9f28da56752d0a (commit)
       via  e62a45b60e3166d995eb83840f437debf575c328 (commit)
      from  cc4ff1061efd95f1560289f1bb726975cb7b83fc (commit)


- Log -----------------------------------------------------------------
commit 2293032121d33299be4f21a599aab84413467f8d
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Dec 18 13:26:47 2019 +0100

    PROV: Adjust the KEYMGMT name specs to include all names
    
    This is very simply to allow the common case, where the KEYMGMT is
    fetched first, and all names are needed at that time to secure that
    they are found.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10647)

commit f23bc0b770efd229e27519786d9f28da56752d0a
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Dec 18 13:24:27 2019 +0100

    EVP: Adapt KEYEXCH, SIGNATURE and ASYM_CIPHER to handle key types better
    
    The adaptation is to handle the case when key types and operations
    that use these keys have different names.  For example, EC keys can be
    used for ECDSA and ECDH.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10647)

commit e62a45b60e3166d995eb83840f437debf575c328
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Dec 18 13:20:55 2019 +0100

    CORE & EVP: Specify OP_query_operation_name() for KEYMGMT
    
    This will allow keymgmt implementation for key types that need it to
    specify the names of the diverse operation algorithms it can be used
    with.  Currently, only one name per key type and operation is allowed.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10647)

-----------------------------------------------------------------------

Summary of changes:
 crypto/evp/evp_local.h         |  1 +
 crypto/evp/exchange.c          | 34 ++++++++++++++-------
 crypto/evp/keymgmt_meth.c      |  6 ++++
 crypto/evp/m_sigver.c          | 34 +++++++++++++--------
 crypto/evp/pmeth_fn.c          | 69 ++++++++++++++++++++++++++++--------------
 crypto/evp/pmeth_gn.c          |  4 +--
 crypto/evp/pmeth_lib.c         |  4 +--
 doc/man3/EVP_PKEY_CTX_new.pod  | 20 ++++++++++--
 doc/man7/provider-keymgmt.pod  | 13 ++++++++
 include/crypto/evp.h           |  4 +--
 include/openssl/core_numbers.h |  5 +++
 providers/defltprov.c          |  6 ++--
 12 files changed, 142 insertions(+), 58 deletions(-)

diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 71e1258326..71051a6587 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -89,6 +89,7 @@ struct evp_keymgmt_st {
     OSSL_OP_keymgmt_exportkey_fn *exportkey;
     OSSL_OP_keymgmt_importkey_types_fn *importkey_types;
     OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
+    OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name;
 } /* EVP_KEYMGMT */ ;
 
 struct keymgmt_data_st {
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 3e7c00103c..ade1dc373d 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -173,20 +173,32 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
     evp_pkey_ctx_free_old_ops(ctx);
     ctx->operation = EVP_PKEY_OP_DERIVE;
 
-    if (ctx->engine != NULL || ctx->algorithm == NULL)
+    if (ctx->engine != NULL || ctx->keytype == NULL)
         goto legacy;
 
-    /*
-     * Because we cleared out old ops, we shouldn't need to worry about
-     * checking if exchange is already there.  Keymgmt is a different
-     * matter, as it isn't tied to a specific EVP_PKEY op.
-     */
-    exchange = EVP_KEYEXCH_fetch(ctx->libctx, ctx->algorithm, ctx->propquery);
-    if (exchange != NULL && ctx->keymgmt == NULL) {
-        int name_id = EVP_KEYEXCH_number(exchange);
-
+    if (ctx->keymgmt == NULL)
         ctx->keymgmt =
-            evp_keymgmt_fetch_by_number(ctx->libctx, name_id, ctx->propquery);
+            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
+    if (ctx->keymgmt != NULL) {
+        const char *supported_exch = NULL;
+
+        if (ctx->keymgmt->query_operation_name != NULL)
+            supported_exch =
+                ctx->keymgmt->query_operation_name(OSSL_OP_KEYEXCH);
+
+        /*
+         * If we didn't get a supported exch, assume there is one with the
+         * same name as the key type.
+         */
+        if (supported_exch == NULL)
+            supported_exch = ctx->keytype;
+
+        /*
+         * Because we cleared out old ops, we shouldn't need to worry about
+         * checking if exchange is already there.
+         */
+        exchange =
+            EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery);
     }
 
     if (ctx->keymgmt == NULL
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 8091bcadb8..6318ddd3fb 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -118,6 +118,12 @@ static void *keymgmt_from_dispatch(int name_id,
             keymgmt->exportkey_types =
                 OSSL_get_OP_keymgmt_exportkey_types(fns);
             break;
+        case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
+            if (keymgmt->query_operation_name != NULL)
+                break;
+            keymgmt->query_operation_name =
+                OSSL_get_OP_keymgmt_query_operation_name(fns);
+            break;
         }
     }
     /*
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 9d12e9b96a..ff94063181 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -52,7 +52,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     locpctx = ctx->pctx;
     evp_pkey_ctx_free_old_ops(locpctx);
 
-    if (locpctx->algorithm == NULL)
+    if (locpctx->keytype == NULL)
         goto legacy;
 
     if (mdname == NULL) {
@@ -71,18 +71,28 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
         }
     }
 
-    /*
-     * Because we cleared out old ops, we shouldn't need to worry about
-     * checking if signature is already there.  Keymgmt is a different
-     * matter, as it isn't tied to a specific EVP_PKEY op.
-     */
-    signature = EVP_SIGNATURE_fetch(locpctx->libctx, locpctx->algorithm,
-                                    locpctx->propquery);
-    if (signature != NULL && locpctx->keymgmt == NULL) {
-        int name_id = EVP_SIGNATURE_number(signature);
+    if (locpctx->keymgmt == NULL)
+        locpctx->keymgmt = EVP_KEYMGMT_fetch(locpctx->libctx, locpctx->keytype,
+                                             locpctx->propquery);
+    if (locpctx->keymgmt != NULL) {
+        const char *supported_sig = NULL;
+
+        if (locpctx->keymgmt->query_operation_name != NULL)
+            supported_sig =
+                locpctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE);
+
+        /*
+         * If we didn't get a supported sig, assume there is one with the
+         * same name as the key type.
+         */
+        if (supported_sig == NULL)
+            supported_sig = locpctx->keytype;
 
-        locpctx->keymgmt =
-            evp_keymgmt_fetch_by_number(locpctx->libctx, name_id,
+        /*
+         * Because we cleared out old ops, we shouldn't need to worry about
+         * checking if signature is already there.
+         */
+        signature = EVP_SIGNATURE_fetch(locpctx->libctx, supported_sig,
                                         locpctx->propquery);
     }
 
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index 0ce4ff9522..3d0ee2e646 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -331,21 +331,32 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
     evp_pkey_ctx_free_old_ops(ctx);
     ctx->operation = operation;
 
-    if (ctx->algorithm == NULL)
+    if (ctx->keytype == NULL)
         goto legacy;
 
-    /*
-     * Because we cleared out old ops, we shouldn't need to worry about
-     * checking if signature is already there.  Keymgmt is a different
-     * matter, as it isn't tied to a specific EVP_PKEY op.
-     */
-    signature = EVP_SIGNATURE_fetch(ctx->libctx, ctx->algorithm,
-                                    ctx->propquery);
-    if (signature != NULL && ctx->keymgmt == NULL) {
-        int name_id = EVP_SIGNATURE_number(signature);
+    if (ctx->keymgmt == NULL)
+        ctx->keymgmt =
+            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
+    if (ctx->keymgmt != NULL) {
+        const char *supported_sig = NULL;
+
+        if (ctx->keymgmt->query_operation_name != NULL)
+            supported_sig =
+                ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE);
+
+        /*
+         * If we didn't get a supported sig, assume there is one with the
+         * same name as the key type.
+         */
+        if (supported_sig == NULL)
+            supported_sig = ctx->keytype;
 
-        ctx->keymgmt = evp_keymgmt_fetch_by_number(ctx->libctx, name_id,
-                                                   ctx->propquery);
+        /*
+         * Because we cleared out old ops, we shouldn't need to worry about
+         * checking if signature is already there.
+         */
+        signature =
+            EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery);
     }
 
     if (ctx->keymgmt == NULL
@@ -582,20 +593,32 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
     evp_pkey_ctx_free_old_ops(ctx);
     ctx->operation = operation;
 
-    if (ctx->algorithm == NULL || ctx->engine != NULL)
+    if (ctx->keytype == NULL || ctx->engine != NULL)
         goto legacy;
 
-    /*
-     * Because we cleared out old ops, we shouldn't need to worry about
-     * checking if exchange is already there.  Keymgmt is a different
-     * matter, as it isn't tied to a specific EVP_PKEY op.
-     */
-    cipher = EVP_ASYM_CIPHER_fetch(ctx->libctx, ctx->algorithm, ctx->propquery);
-    if (cipher != NULL && ctx->keymgmt == NULL) {
-        int name_id = EVP_ASYM_CIPHER_number(cipher);
-
+    if (ctx->keymgmt == NULL)
         ctx->keymgmt =
-            evp_keymgmt_fetch_by_number(ctx->libctx, name_id, ctx->propquery);
+            EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery);
+    if (ctx->keymgmt != NULL) {
+        const char *supported_ciph = NULL;
+
+        if (ctx->keymgmt->query_operation_name != NULL)
+            supported_ciph =
+                ctx->keymgmt->query_operation_name(OSSL_OP_ASYM_CIPHER);
+
+        /*
+         * If we didn't get a supported ciph, assume there is one with the
+         * same name as the key type.
+         */
+        if (supported_ciph == NULL)
+            supported_ciph = ctx->keytype;
+
+        /*
+         * Because we cleared out old ops, we shouldn't need to worry about
+         * checking if cipher is already there.
+         */
+        cipher =
+            EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph, ctx->propquery);
     }
 
     if (ctx->keymgmt == NULL
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
index a5f7dbaf53..100931cda7 100644
--- a/crypto/evp/pmeth_gn.c
+++ b/crypto/evp/pmeth_gn.c
@@ -19,13 +19,13 @@
 
 static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
 {
-    if (ctx == NULL || ctx->algorithm == NULL)
+    if (ctx == NULL || ctx->keytype == NULL)
         goto not_supported;
 
     evp_pkey_ctx_free_old_ops(ctx);
     ctx->operation = operation;
     if (ctx->keymgmt == NULL)
-        ctx->keymgmt = EVP_KEYMGMT_fetch(NULL, ctx->algorithm, ctx->propquery);
+        ctx->keymgmt = EVP_KEYMGMT_fetch(NULL, ctx->keytype, ctx->propquery);
     if (ctx->keymgmt == NULL)
         goto not_supported;
 
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 8b49baf6ab..2ecc17734e 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -221,7 +221,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
         return NULL;
     }
     ret->libctx = libctx;
-    ret->algorithm = name;
+    ret->keytype = name;
     ret->propquery = propquery;
     ret->engine = e;
     ret->pmeth = pmeth;
@@ -382,7 +382,7 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
     rctx->pkey = pctx->pkey;
     rctx->operation = pctx->operation;
     rctx->libctx = pctx->libctx;
-    rctx->algorithm = pctx->algorithm;
+    rctx->keytype = pctx->keytype;
     rctx->propquery = pctx->propquery;
 
     if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) {
diff --git a/doc/man3/EVP_PKEY_CTX_new.pod b/doc/man3/EVP_PKEY_CTX_new.pod
index 5d18a04344..90486ae0dc 100644
--- a/doc/man3/EVP_PKEY_CTX_new.pod
+++ b/doc/man3/EVP_PKEY_CTX_new.pod
@@ -21,14 +21,14 @@ EVP_PKEY_CTX_dup, EVP_PKEY_CTX_free
 =head1 DESCRIPTION
 
 The EVP_PKEY_CTX_new() function allocates public key algorithm context using
-the algorithm specified in I<pkey> and ENGINE I<e>.
+the I<pkey> key type and ENGINE I<e>.
 
 The EVP_PKEY_CTX_new_id() function allocates public key algorithm context
-using the algorithm specified by I<id> and ENGINE I<e>.
+using the key type specified by I<id> and ENGINE I<e>.
 
 The EVP_PKEY_CTX_new_provided() function allocates a public key algorithm
 context using the library context I<libctx> (see L<OPENSSL_CTX(3)>), the
-algorithm specified by I<name> and the property query I<propquery>.  None
+key type specified by I<name> and the property query I<propquery>.  None
 of the arguments are duplicated, so they  must remain unchanged for the
 lifetime of the returned B<EVP_PKEY_CTX> or of any of its duplicates.
 
@@ -44,11 +44,25 @@ If I<ctx> is NULL, nothing is done.
 
 =head1 NOTES
 
+=over 4
+
+=item 1.
+
 The B<EVP_PKEY_CTX> structure is an opaque public key algorithm context used
 by the OpenSSL high level public key API. Contexts B<MUST NOT> be shared between
 threads: that is it is not permissible to use the same context simultaneously
 in two threads.
 
+=item 2.
+
+We mention "key type" in this manual, which is the same
+as "algorithm" in most cases, allowing either term to be used
+interchangeably.  There are algorithms where the I<key type> and the
+I<algorithm> of the operations that use the keys are not the same,
+such as EC keys being used for ECDSA and ECDH operations.
+
+=back
+
 =head1 RETURN VALUES
 
 EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id(), EVP_PKEY_CTX_dup() returns either
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index 40f1ad6327..1c868c5630 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -40,6 +40,9 @@ provider-keymgmt - The KEYMGMT library E<lt>-E<gt> provider functions
  const OSSL_PARAM *OP_keymgmt_importkey_types(void);
  const OSSL_PARAM *OP_keymgmt_exportkey_types(void);
 
+ /* Discovery of supported operations */
+ const char *OP_keymgmt_query_operation_name(int operation_id);
+
 =head1 DESCRIPTION
 
 The KEYMGMT operation doesn't have much public visibility in OpenSSL
@@ -158,6 +161,16 @@ OP_keymgmt_exportkey_types() should return a constant array of
 descriptor B<OSSL_PARAM>, for parameters that can be exported with
 OP_keymgmt_exportkeys().
 
+=head2 Supported operations
+
+OP_keymgmt_query_operation_name() should return the name of the
+supported algorithm for the operation I<operation_id>.  This is
+similar to provider_query_operation() (see L<provider-base(7)>),
+but only works as an advisory.  If this function is not present, or
+returns NULL, the caller is free to assume that there's an algorithm
+from the same provider, of the same name as the one used to fetch the
+keymgmt and try to use that.
+
 =head1 SEE ALSO
 
 L<provider(7)>
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index 592cbdd536..973ef203ba 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -22,11 +22,11 @@ struct evp_pkey_ctx_st {
     int operation;
 
     /*
-     * Library context, Algorithm name and properties associated
+     * Library context, Key type name and properties associated
      * with this context
      */
     OPENSSL_CTX *libctx;
-    const char *algorithm;
+    const char *keytype;
     const char *propquery;
 
     /* cached key manager */
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 6b4a205f1d..9f49599dab 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -395,6 +395,11 @@ OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportkey,
 OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_importkey_types, (void))
 OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportkey_types, (void))
 
+/* Discovery of supported operations */
+# define OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME    17
+OSSL_CORE_MAKE_FUNC(const char *,OP_keymgmt_query_operation_name,
+                    (int operation_id))
+
 /* Key Exchange */
 
 # define OSSL_FUNC_KEYEXCH_NEWCTX                      1
diff --git a/providers/defltprov.c b/providers/defltprov.c
index b4a17a5030..3220bc5220 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -388,12 +388,12 @@ static const OSSL_ALGORITHM deflt_asym_cipher[] = {
 
 static const OSSL_ALGORITHM deflt_keymgmt[] = {
 #ifndef OPENSSL_NO_DH
-    { "DH", "default=yes", dh_keymgmt_functions },
+    { "DH:dhKeyAgreement", "default=yes", dh_keymgmt_functions },
 #endif
 #ifndef OPENSSL_NO_DSA
-    { "DSA", "default=yes", dsa_keymgmt_functions },
+    { "DSA:dsaEncryption", "default=yes", dsa_keymgmt_functions },
 #endif
-    { "RSA", "default=yes", rsa_keymgmt_functions },
+    { "RSA:rsaEncryption", "default=yes", rsa_keymgmt_functions },
     { NULL, NULL, NULL }
 };
 


More information about the openssl-commits mailing list