]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Remove a TODO(3.0) from EVP_PKEY_derive_set_peer()
authorMatt Caswell <matt@openssl.org>
Mon, 15 Mar 2021 16:21:45 +0000 (16:21 +0000)
committerMatt Caswell <matt@openssl.org>
Wed, 17 Mar 2021 09:56:33 +0000 (09:56 +0000)
The TODO described a case where a legacy derive operation is called, but
the peer key is provider based. In practice this will almost never be a
problem. We should never end up in our own legacy EVP_PKEY_METHOD
implementations if no ENGINE has been configured. If an ENGINE has been
configured then we we will be using a third party EVP_PKEY_METHOD
implementation and public APIs will be used to obtain the key data from the
peer key so there will be no "reaching inside" the pkey.

There is a theoretical case where a third party ENGINE wraps our own
internal EVP_PKEY_METHODs using EVP_PKEY_meth_find() or
EVP_PKEY_meth_get0(). For these cases we just ensure all our
EVP_PKEY_METHODs never reach "inside" the implementation of a peer key. We
can never assume that it is a legacy key.

Fixes #14399

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14555)

crypto/dh/dh_pmeth.c
crypto/ec/ec_pmeth.c
crypto/ec/ecx_meth.c
crypto/evp/exchange.c

index fdd9194f1aceab3a4da0617ea0f5d818816af31f..584a174ae27568ac24ccedb19db37e4b8b6fabaf 100644 (file)
@@ -421,23 +421,30 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
 {
     int ret;
     DH *dh;
+    const DH *dhpub;
     DH_PKEY_CTX *dctx = ctx->data;
-    BIGNUM *dhpub;
-    if (!ctx->pkey || !ctx->peerkey) {
+    BIGNUM *dhpubbn;
+
+    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
         ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
         return 0;
     }
     dh = ctx->pkey->pkey.dh;
-    dhpub = ctx->peerkey->pkey.dh->pub_key;
+    dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
+    if (dhpub == NULL) {
+        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
+        return 0;
+    }
+    dhpubbn = dhpub->pub_key;
     if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
         if (key == NULL) {
             *keylen = DH_size(dh);
             return 1;
         }
         if (dctx->pad)
-            ret = DH_compute_key_padded(key, dhpub, dh);
+            ret = DH_compute_key_padded(key, dhpubbn, dh);
         else
-            ret = DH_compute_key(key, dhpub, dh);
+            ret = DH_compute_key(key, dhpubbn, dh);
         if (ret < 0)
             return ret;
         *keylen = ret;
@@ -461,7 +468,7 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
         if (Z == NULL) {
             goto err;
         }
-        if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
+        if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
             goto err;
         if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
                           dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
index 2280189e2868b4839fd8ea9827f207f7a9d069ff..e4f3549d3048e5f268c14b3d8fdefc2e52126820 100644 (file)
@@ -161,8 +161,15 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
     size_t outlen;
     const EC_POINT *pubkey = NULL;
     EC_KEY *eckey;
+    const EC_KEY *eckeypub;
     EC_PKEY_CTX *dctx = ctx->data;
-    if (!ctx->pkey || !ctx->peerkey) {
+
+    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
+        ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
+        return 0;
+    }
+    eckeypub = EVP_PKEY_get0_EC_KEY(ctx->peerkey);
+    if (eckeypub == NULL) {
         ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
         return 0;
     }
@@ -178,7 +185,7 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
         *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
         return 1;
     }
-    pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
+    pubkey = EC_KEY_get0_public_key(eckeypub);
 
     /*
      * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
index cd73a15847111df2f1c61b3b5773dd10c60595ee..9a812c875bceca556af23b9230f094f62831282a 100644 (file)
@@ -766,7 +766,7 @@ static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
         return 0;
     }
     ecxkey = ctx->pkey->pkey.ecx;
-    peerkey = ctx->peerkey->pkey.ecx;
+    peerkey = EVP_PKEY_get0(ctx->peerkey);
     if (ecxkey == NULL || ecxkey->privkey == NULL) {
         ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
         return 0;
index e0e0597b3bf029d3cdc4d3b695bb051e48b9d9e1..5e098f0c3f753636a25fd6440afadb7537b7b8dc 100644 (file)
@@ -349,10 +349,6 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
 #ifdef FIPS_MODULE
     return ret;
 #else
-    /*
-     * TODO(3.0) investigate the case where the operation is deemed legacy,
-     * but the given peer key is provider only.
-     */
     if (ctx->pmeth == NULL
         || !(ctx->pmeth->derive != NULL
              || ctx->pmeth->encrypt != NULL