SLH-DSA - restrict keygen seed length to exact value of 3*n

It was allowing the seed to be larger, and then just ignoring the
trailing bytes.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26858)
This commit is contained in:
slontis 2025-02-21 08:54:36 +11:00
parent 5b52a6395c
commit 6e770d38c7
5 changed files with 50 additions and 7 deletions

View file

@ -357,7 +357,7 @@ int ossl_slh_dsa_generate_key(SLH_DSA_HASH_CTX *ctx, SLH_DSA_KEY *out,
uint8_t *pub = SLH_DSA_PUB(out);
if (entropy != NULL && entropy_len != 0) {
if (entropy_len < entropy_len_expected)
if (entropy_len != entropy_len_expected)
goto err;
memcpy(priv, entropy, entropy_len_expected);
} else {

View file

@ -18,6 +18,7 @@
# include "crypto/types.h"
# define SLH_DSA_MAX_CONTEXT_STRING_LEN 255
# define SLH_DSA_MAX_N 32
typedef struct slh_dsa_hash_ctx_st SLH_DSA_HASH_CTX;
typedef struct slh_dsa_key_st SLH_DSA_KEY;

View file

@ -41,7 +41,7 @@ struct slh_dsa_gen_ctx {
SLH_DSA_HASH_CTX *ctx;
OSSL_LIB_CTX *libctx;
char *propq;
uint8_t entropy[32 * 3];
uint8_t entropy[SLH_DSA_MAX_N * 3];
size_t entropy_len;
};

View file

@ -1,5 +1,5 @@
/*
* Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -7,9 +7,6 @@
* https://www.openssl.org/source/license.html
*/
#include "internal/deprecated.h"
#include <assert.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/rand.h>
@ -284,7 +281,6 @@ static int slh_dsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
void *vp = pctx->add_random;
size_t n = ossl_slh_dsa_key_get_n(pctx->key);
assert(n <= sizeof(pctx->add_random));
if (!OSSL_PARAM_get_octet_string(p, &vp, n, &(pctx->add_random_len))
|| pctx->add_random_len != n) {
pctx->add_random_len = 0;

View file

@ -570,6 +570,51 @@ err:
return ret;
}
static int slh_dsa_keygen_invalid_test(void)
{
int ret = 0;
const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM params[2], *p = params;
size_t key_len = tst->priv_len;
size_t n = key_len / 4;
uint8_t seed[128] = {0};
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, tst->name, NULL))
|| !TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1))
goto err;
/* Test the set fails if the seed is larger than the internal buffer */
p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
seed, 97);
p[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 0))
goto err;
/* Test the generate fails if the seed is not the correct size */
p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
seed, n * 3 - 1);
p[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1)
|| !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0))
goto err;
/* Test the generate fails if the seed is not the correct size */
p[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_SLH_DSA_SEED,
seed, n * 3 + 1);
p[1] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_PKEY_CTX_set_params(ctx, params), 1)
|| !TEST_int_eq(EVP_PKEY_generate(ctx, &pkey), 0))
goto err;
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
const OPTIONS *test_get_options(void)
{
static const OPTIONS options[] = {
@ -610,6 +655,7 @@ int setup_tests(void)
ADD_ALL_TESTS(slh_dsa_sign_verify_test, OSSL_NELEM(slh_dsa_sig_testdata));
ADD_ALL_TESTS(slh_dsa_keygen_test, OSSL_NELEM(slh_dsa_keygen_testdata));
ADD_TEST(slh_dsa_digest_sign_verify_test);
ADD_TEST(slh_dsa_keygen_invalid_test);
return 1;
}