Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/wolfprovider/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@
/** Maximum supported digest name size. */
#define WP_MAX_PROPS_SIZE 80

/** Minimum accepted DH prime size in bits for parameter/key generation. */
#ifdef HAVE_FIPS
#define WP_DH_MIN_BITS 2048
#else
#define WP_DH_MIN_BITS 1024
#endif

/* DER key encoding/decoding formats. */
/** SubjectPublicKeyInfo encoding format. */
#define WP_ENC_FORMAT_SPKI 1
Expand Down
45 changes: 26 additions & 19 deletions src/wp_dh_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@ static const int wp_dh_decode_nids[] = {
/** Maximum size of the group name string. */
#define WP_MAX_DH_GROUP_NAME_SZ 10

/* Min accepted bitlen for keygen */
#ifdef HAVE_FIPS
#define WP_DH_MIN_BITS 2048
#else
#define WP_DH_MIN_BITS 1024
#endif

/**
* DH key.
*/
Expand Down Expand Up @@ -1574,18 +1567,19 @@ static wp_DhGenCtx* wp_dh_gen_init(WOLFPROV_CTX* provCtx,
WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, "wc_InitRng", rc);
ok = 0;
}
if (ok) {
if (!wp_dh_gen_set_params(ctx, params)) {
wc_FreeRng(&ctx->rng);
ok = 0;
}
}
/* Defaults first so init-time parameters override them. */
if (ok) {
ctx->provCtx = provCtx;
ctx->selection = selection;
ctx->bits = 2048;
ctx->generator = 2;
}
if (ok) {
if (!wp_dh_gen_set_params(ctx, params)) {
wc_FreeRng(&ctx->rng);
ok = 0;
}
}

if (!ok) {
/* Rng freed when parameters fail to set. */
Expand Down Expand Up @@ -1644,13 +1638,25 @@ static int wp_dh_gen_set_template(wp_DhGenCtx* ctx, const wp_Dh* dh)
static int wp_dh_gen_set_params(wp_DhGenCtx* ctx, const OSSL_PARAM params[])
{
int ok = 1;
int bits;
const OSSL_PARAM* p;

WOLFPROV_ENTER(WP_LOG_COMP_DH, "wp_dh_gen_set_params");

p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS);
if ((p != NULL) && (!OSSL_PARAM_get_int(p, &ctx->bits))) {
ok = 0;
if (p != NULL) {
if (!OSSL_PARAM_get_int(p, &bits)) {
ok = 0;
}
/* Reject a prime size below the provider minimum. */
if (ok && (bits < WP_DH_MIN_BITS)) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
ok = 0;
}
/* Only store the value once it has passed the size check. */
if (ok) {
ctx->bits = bits;
}
}
if (ok) {
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
Expand Down Expand Up @@ -1928,12 +1934,13 @@ static wp_Dh* wp_dh_gen(wp_DhGenCtx *ctx, OSSL_CALLBACK *cb, void *cbArg)
else if (!wp_dh_gen_copy_parameters(ctx, dh)) {
ok = 0;
}
/* Validate parameters meet minimum requirements in every path. */
if (ok && (!wp_dh_params_validate(dh))) {
Comment thread
ColtonWilley marked this conversation as resolved.
ok = 0;
}
/* Generate key pair if requested. */
if (ok && ((ctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)) {
if (!wp_dh_params_validate(dh)) {
ok = 0;
}
if (ok && (!wp_dh_gen_keypair(ctx, dh))) {
if (!wp_dh_gen_keypair(ctx, dh)) {
ok = 0;
}
}
Expand Down
95 changes: 95 additions & 0 deletions test/test_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "unit.h"
#include <openssl/core_names.h>
#include <openssl/decoder.h>
#include <wolfprovider/internal.h>

#ifdef WP_HAVE_DH

Expand Down Expand Up @@ -1546,4 +1547,98 @@ int test_dh_import_group_no_nul(void *data)
return err;
}

/* Enforce the minimum prime size: a below-minimum request must not produce
* parameters, while a request at the minimum must still succeed. Sizes come
* from the provider's own WP_DH_MIN_BITS so the two cannot diverge. */
#define TEST_DH_MIN_BITS WP_DH_MIN_BITS
#define TEST_DH_WEAK_BITS (WP_DH_MIN_BITS / 2)
int test_dh_pgen_min_bits(void *data)
{
int err = 0;
int rc;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *keyParams = NULL;
EVP_PKEY *weakParams = NULL;
BIGNUM *prime = NULL;

(void)data;

PRINT_MSG("Testing DH parameter generation minimum prime size enforcement");

/* Below-minimum size must be rejected at set-params time. */
Comment thread
aidangarske marked this conversation as resolved.
ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "DH", NULL);
if (ctx == NULL) {
err = 1;
}
if (err == 0) {
err = EVP_PKEY_paramgen_init(ctx) != 1;
}
if (err == 0) {
rc = EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, TEST_DH_WEAK_BITS);
if (rc == 1) {
PRINT_MSG("set_dh_paramgen_prime_len accepted a below-minimum size");
err = 1;
}
}
EVP_PKEY_CTX_free(ctx);
ctx = NULL;

/* A caller that ignores the set-params failure must never end up with
* below-minimum parameters: generation either fails, or the prime it
* produced is at least the minimum size. */
if (err == 0) {
ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "DH", NULL);
err = ctx == NULL;
}
if (err == 0) {
err = EVP_PKEY_paramgen_init(ctx) != 1;
}
if (err == 0) {
(void)EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, TEST_DH_WEAK_BITS);
if (EVP_PKEY_paramgen(ctx, &weakParams) == 1) {
err = EVP_PKEY_get_bn_param(weakParams, OSSL_PKEY_PARAM_FFC_P,
&prime) != 1;
if ((err == 0) && (BN_num_bits(prime) < TEST_DH_MIN_BITS)) {
PRINT_MSG("paramgen produced a prime below the minimum size");
err = 1;
}
}
}
EVP_PKEY_CTX_free(ctx);
ctx = NULL;

/* Size at the minimum must still succeed. */
if (err == 0) {
ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "DH", NULL);
err = ctx == NULL;
}
if (err == 0) {
err = EVP_PKEY_paramgen_init(ctx) != 1;
}
if (err == 0) {
err = EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, TEST_DH_MIN_BITS)
!= 1;
}
if (err == 0) {
err = EVP_PKEY_paramgen(ctx, &keyParams) != 1;
if (err != 0) {
PRINT_MSG("DH paramgen failed at the minimum prime size");
}
}
if (err == 0) {
err = EVP_PKEY_get_bn_param(keyParams, OSSL_PKEY_PARAM_FFC_P,
&prime) != 1;
if ((err == 0) && (BN_num_bits(prime) < TEST_DH_MIN_BITS)) {
PRINT_MSG("paramgen produced a prime below the minimum size");
err = 1;
}
}

BN_free(prime);
EVP_PKEY_free(weakParams);
EVP_PKEY_free(keyParams);
EVP_PKEY_CTX_free(ctx);
return err;
}

#endif /* WP_HAVE_DH */
1 change: 1 addition & 0 deletions test/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ TEST_CASE test_case[] = {
TEST_DECL(test_dh_fromdata_oversize, NULL),
TEST_DECL(test_dh_param_check_explicit, NULL),
TEST_DECL(test_dh_import_group_no_nul, NULL),
TEST_DECL(test_dh_pgen_min_bits, NULL),
#ifndef WOLFPROV_QUICKTEST
TEST_DECL(test_dh_get_params, NULL),
#endif
Expand Down
1 change: 1 addition & 0 deletions test/unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ int test_dh_x963_kdf(void *data);
int test_dh_fromdata_oversize(void *data);
int test_dh_param_check_explicit(void *data);
int test_dh_import_group_no_nul(void *data);
int test_dh_pgen_min_bits(void *data);
#endif /* WP_HAVE_DH */

#ifdef WP_HAVE_ECC
Expand Down
Loading