Add the ability to set PKCS#3 DH padding in providers
authorMatt Caswell <matt@openssl.org>
Thu, 27 Jun 2019 15:37:44 +0000 (16:37 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 16 Jul 2019 09:16:32 +0000 (10:16 +0100)
This also adds the ability to set arbitrary parameters on key exchange
algorithms. The ability to pad the output is one such parameter for DH.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9266)

crypto/evp/evp_locl.h
crypto/evp/exchange.c
crypto/evp/pmeth_lib.c
include/openssl/core_names.h
include/openssl/core_numbers.h
include/openssl/dh.h
include/openssl/evp.h
providers/common/exchange/dh.c
util/libcrypto.num

index 659305b8d63f4156548929e44e6dfb814048e2a0..8aeb5d40037680a37cc12f6611e589f5cf9d52e9 100644 (file)
@@ -73,6 +73,7 @@ struct evp_keyexch_st {
     OSSL_OP_keyexch_derive_fn *derive;
     OSSL_OP_keyexch_freectx_fn *freectx;
     OSSL_OP_keyexch_dupctx_fn *dupctx;
+    OSSL_OP_keyexch_set_params_fn *set_params;
 } /* EVP_KEYEXCH */;
 
 
index 479cc0d42dcf79ce590af5d851ea3fe843f99bb9..208bb9885a3de082486735eb484477feab8d0e9b 100644 (file)
@@ -76,13 +76,19 @@ static void *evp_keyexch_from_dispatch(const OSSL_DISPATCH *fns,
                 break;
             exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns);
             break;
+        case OSSL_FUNC_KEYEXCH_SET_PARAMS:
+            if (exchange->set_params != NULL)
+                break;
+            exchange->set_params = OSSL_get_OP_keyexch_set_params(fns);
+            break;
         }
     }
     if (fncnt != 4) {
         /*
          * In order to be a consistent set of functions we must have at least
          * a complete set of "exchange" functions: init, derive, newctx,
-         * and freectx. The dupctx and set_peer functions are optional.
+         * and freectx. The dupctx, set_peer and set_params functions are
+         * optional.
          */
         EVP_KEYEXCH_free(exchange);
         EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH,
index b10663cf702d08bcb519f10380f86f0c97ac92b1..d444e7168d3f649a560d11352f42ea7dba50cf3c 100644 (file)
@@ -9,10 +9,12 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "internal/cryptlib.h"
 #include <openssl/engine.h>
 #include <openssl/evp.h>
 #include <openssl/x509v3.h>
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include "internal/cryptlib.h"
 #include "internal/asn1_int.h"
 #include "internal/evp_int.h"
 #include "internal/numbers.h"
@@ -384,12 +386,52 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
     OPENSSL_free(ctx);
 }
 
+int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
+{
+    if (ctx->exchprovctx != NULL && ctx->exchange != NULL)
+        return ctx->exchange->set_params(ctx->exchprovctx, params);
+    return 0;
+}
+
+int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
+{
+    OSSL_PARAM dh_pad_params[2];
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_DH_PAD, pad, NULL);
+
+    dh_pad_params[0] = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_PAD, &pad);
+    dh_pad_params[1] = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, dh_pad_params);
+}
+
+static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
+                                int cmd, int p1, void *p2)
+{
+    switch (cmd) {
+    case EVP_PKEY_CTRL_DH_PAD:
+        return EVP_PKEY_CTX_set_dh_pad(ctx, p1);
+    }
+    return 0;
+}
+
 int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
                       int cmd, int p1, void *p2)
 {
     int ret;
 
-    if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
+    if (ctx == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+        return -2;
+    }
+
+    if (ctx->exchprovctx != NULL)
+        return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
+
+    if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
         EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
     }
@@ -425,9 +467,29 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
     return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value);
 }
 
+static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
+                                    const char *value)
+{
+    if (strcmp(name, "dh_pad") == 0) {
+        int pad;
+
+        pad = atoi(value);
+        return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
+    }
+    return 0;
+}
+
 int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
                           const char *name, const char *value)
 {
+    if (ctx == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
+        return -2;
+    }
+
+    if (ctx->exchprovctx != NULL)
+        return legacy_ctrl_str_to_param(ctx, name, value);
+
     if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
         EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
index 143668a0b90e8a4cf9bee774f147c41d24e940f6..d1ba624d65dcc79339f98d572b97e2eb83cc7d99 100644 (file)
@@ -65,6 +65,10 @@ extern "C" {
 #define OSSL_PKEY_PARAM_DH_PUB_KEY   "dh-pub"
 #define OSSL_PKEY_PARAM_DH_PRIV_KEY  "dh-priv"
 
+/* Key Exchange parameters */
+
+#define OSSL_EXCHANGE_PARAM_PAD           "exchange-pad"
+
 # ifdef __cplusplus
 }
 # endif
index 0a61c21bf719b7fb5055a03728d7d64dfe6632a7..c5892431e49a2eebfd44a6165654821e26ce2b9b 100644 (file)
@@ -239,6 +239,7 @@ OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *cctx,
 # define OSSL_FUNC_KEYEXCH_SET_PEER                    4
 # define OSSL_FUNC_KEYEXCH_FREECTX                     5
 # define OSSL_FUNC_KEYEXCH_DUPCTX                      6
+# define OSSL_FUNC_KEYEXCH_SET_PARAMS                  7
 
 OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_newctx, (void *provctx))
 OSSL_CORE_MAKE_FUNC(int, OP_keyexch_init, (void *ctx,
@@ -249,6 +250,8 @@ OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_peer, (void *ctx,
                                                OSSL_PARAM params[]))
 OSSL_CORE_MAKE_FUNC(void, OP_keyexch_freectx, (void *ctx))
 OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_dupctx, (void *ctx))
+OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx,
+                                                 OSSL_PARAM params[]))
 
 # ifdef __cplusplus
 }
index 18858ebf20383b44479931204775d9e2cd25b810..e96c81154d836483504fce4298e31b090b4faee3 100644 (file)
@@ -253,9 +253,7 @@ int DH_meth_set_generate_params(DH_METHOD *dhm,
                         EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, \
                         EVP_PKEY_CTRL_DH_NID, nid, NULL)
 
-# define EVP_PKEY_CTX_set_dh_pad(ctx, pad) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_DERIVE, \
-                          EVP_PKEY_CTRL_DH_PAD, pad, NULL)
+int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad);
 
 # define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \
         EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \
index a2cb66aaf3dd9c72526363e9b888caf4777fab26..377b4b16c00ea5c1628337611a2b11debf9ad1dd 100644 (file)
@@ -1416,6 +1416,7 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
 
+int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
 int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
                       int cmd, int p1, void *p2);
 int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
index f3d49259fa2b4fc1b06a422410f0f242c5fed1bf..ca6f0fc2cb27a3fcbfa0e2c074baf71bf360291a 100644 (file)
@@ -25,6 +25,7 @@ static OSSL_OP_keyexch_dupctx_fn dh_dupctx;
 typedef struct {
     DH *dh;
     DH *dhpeer;
+    int pad;
 } PROV_DH_CTX;
 
 static void *dh_newctx(void *provctx)
@@ -122,7 +123,8 @@ static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen,
         return 0;
 
     DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
-    ret = DH_compute_key(key, pub_key, pdhctx->dh);
+    ret = (pdhctx->pad) ? DH_compute_key_padded(key, pub_key, pdhctx->dh)
+                        : DH_compute_key(key, pub_key, pdhctx->dh);
     if (ret <= 0)
         return 0;
 
@@ -162,6 +164,24 @@ static void *dh_dupctx(void *vpdhctx)
     return dstctx;
 }
 
+static int dh_set_params(void *vpdhctx, OSSL_PARAM params[])
+{
+    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+    const OSSL_PARAM *p;
+    int pad;
+
+    if (pdhctx == NULL || params == NULL)
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_PAD);
+    if (p == NULL || !OSSL_PARAM_get_int(p, &pad))
+        return 0;
+
+    pdhctx->pad = pad;
+
+    return 1;
+}
+
 const OSSL_DISPATCH dh_functions[] = {
     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
@@ -169,5 +189,6 @@ const OSSL_DISPATCH dh_functions[] = {
     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
+    { OSSL_FUNC_KEYEXCH_SET_PARAMS, (void (*)(void))dh_set_params },
     { 0, NULL }
 };
index 9e95e3ee765bb5a524346e80145b80c62badf2e9..d0362490bc2dc1ae3a0c8708f99aec099c8c8e4e 100644 (file)
@@ -4683,3 +4683,5 @@ EVP_PKEY_derive_init_ex                 4788      3_0_0   EXIST::FUNCTION:
 EVP_KEYEXCH_free                        4789   3_0_0   EXIST::FUNCTION:
 EVP_KEYEXCH_up_ref                      4790   3_0_0   EXIST::FUNCTION:
 EVP_KEYEXCH_fetch                       4791   3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_set_dh_pad                 4792   3_0_0   EXIST::FUNCTION:DH
+EVP_PKEY_CTX_set_params                 4793   3_0_0   EXIST::FUNCTION: