Browse Source

Add the ability to set PKCS#3 DH padding in providers

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)
Matt Caswell 4 years ago
parent
commit
35aca9eccb

+ 1 - 0
crypto/evp/evp_locl.h

@@ -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 */;
 
 

+ 7 - 1
crypto/evp/exchange.c

@@ -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,

+ 64 - 2
crypto/evp/pmeth_lib.c

@@ -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;

+ 4 - 0
include/openssl/core_names.h

@@ -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

+ 3 - 0
include/openssl/core_numbers.h

@@ -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
 }

+ 1 - 3
include/openssl/dh.h

@@ -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, \

+ 1 - 0
include/openssl/evp.h

@@ -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,

+ 22 - 1
providers/common/exchange/dh.c

@@ -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 }
 };

+ 2 - 0
util/libcrypto.num

@@ -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: