Implement deterministic ECDSA sign (RFC6979)

This PR is based off the contributions in PR #9223 by Jemmy1228.

It has been modified and reworked to:
(1) Work with providers
(2) Support ECDSA and DSA
(3) Add a KDF HMAC_DRBG implementation that shares code with the RAND HMAC_DRBG.

A nonce_type is passed around inside the Signing API's, in order to support any
future deterministic algorithms.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18809)
This commit is contained in:
slontis 2022-07-15 21:22:01 +10:00 committed by Hugo Landau
parent 9ba4f489ec
commit f3090fc710
31 changed files with 964 additions and 63 deletions

View File

@ -108,7 +108,7 @@ SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \
cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \
punycode.c passphrase.c sleep.c
punycode.c passphrase.c sleep.c deterministic_nonce.c
SOURCE[../providers/libfips.a]=$UTIL_COMMON
SOURCE[../libcrypto]=$UPLINKSRC

View File

@ -0,0 +1,195 @@
/*
* Copyright 2022 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
#include <openssl/kdf.h>
#include "internal/deterministic_nonce.h"
/*
* Convert a Bit String to an Integer (See RFC 6979 Section 2.3.2)
*
* Params:
* out The returned Integer as a BIGNUM
* qlen_bits The maximum size of the returned integer in bits. The returned
* Integer is shifted right if inlen is larger than qlen_bits..
* in, inlen The input Bit String (in bytes).
* Returns: 1 if successful, or 0 otherwise.
*/
static int bits2int(BIGNUM *out, int qlen_bits,
const unsigned char *in, size_t inlen)
{
int blen_bits = inlen * 8;
int shift;
if (BN_bin2bn(in, (int)inlen, out) == NULL)
return 0;
shift = blen_bits - qlen_bits;
if (shift > 0)
return BN_rshift(out, out, shift);
return 1;
}
/*
* Convert an Integer to an Octet String (See RFC 6979 2.3.3).
* The value is zero padded if required.
*
* Params:
* out The returned Octet String
* num The input Integer
* rlen The required size of the returned Octet String in bytes
* Returns: 1 if successful, or 0 otherwis
*/
static int int2octets(unsigned char *out, const BIGNUM *num, int rlen)
{
return BN_bn2binpad(num, out, rlen) >= 0;
}
/*
* Convert a Bit String to an Octet String (See RFC 6979 Section 2.3.4)
*
* Params:
* out The returned octet string.
* q The modulus
* qlen_bits The length of q in bits
* rlen The value of qlen_bits rounded up to the nearest 8 bits.
* in, inlen The input bit string (in bytes)
* Returns: 1 if successful, or 0 otherwise.
*/
static int bits2octets(unsigned char *out, const BIGNUM *q, int qlen_bits,
int rlen, const unsigned char *in, size_t inlen)
{
int ret = 0;
BIGNUM *z = BN_new();
if (z == NULL
|| !bits2int(z, qlen_bits, in, inlen))
goto err;
/* z2 = z1 mod q (Do a simple subtract, since z1 < 2^qlen_bits) */
if (BN_cmp(z, q) >= 0
&& !BN_usub(z, z, q))
goto err;
ret = int2octets(out, z, rlen);
err:
BN_free(z);
return ret;
}
/*
* Setup a KDF HMAC_DRBG object using fixed entropy and nonce data.
*
* Params:
* digestname The digest name for the HMAC
* entropy, entropylen A fixed input entropy buffer
* nonce, noncelen A fixed input nonce buffer
* libctx, propq Are used for fetching algorithms
*
* Returns: The created KDF HMAC_DRBG object if successful, or NULL otherwise.
*/
static EVP_KDF_CTX *kdf_setup(const char *digestname,
const unsigned char *entropy, size_t entropylen,
const unsigned char *nonce, size_t noncelen,
OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_KDF_CTX *ctx = NULL;
EVP_KDF *kdf = NULL;
OSSL_PARAM params[5], *p;
kdf = EVP_KDF_fetch(libctx, "HMAC-DRBG-KDF", propq);
ctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
if (ctx == NULL)
goto err;
p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)digestname, 0);
if (propq != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_PROPERTIES,
(char *)propq, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY,
(void *)entropy, entropylen);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE,
(void *)nonce, noncelen);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_CTX_set_params(ctx, params) <= 0)
goto err;
return ctx;
err:
EVP_KDF_CTX_free(ctx);
return NULL;
}
/*
* Generate a Deterministic nonce 'k' for DSA/ECDSA as defined in
* RFC 6979 Section 3.3. "Alternate Description of the Generation of k"
*
* Params:
* out Returns the generated deterministic nonce 'k'
* q A large prime number used for modulus operations for DSA and ECDSA.
* priv The private key in the range [1, q-1]
* hm, hmlen The digested message buffer in bytes
* digestname The digest name used for signing. It is used as the HMAC digest.
* libctx, propq Used for fetching algorithms
*
* Returns: 1 if successful, or 0 otherwise.
*/
int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
const BIGNUM *priv,
const unsigned char *hm, size_t hmlen,
const char *digestname,
OSSL_LIB_CTX *libctx,
const char *propq)
{
EVP_KDF_CTX *kdfctx = NULL;
int ret = 0, rlen = 0, qlen_bits = 0;
unsigned char *entropyx = NULL, *nonceh = NULL, *T = NULL;
size_t allocsz = 0;
qlen_bits = BN_num_bits(q);
if (qlen_bits == 0)
goto end;
/* Note rlen used here is in bytes since the input values are byte arrays */
rlen = (qlen_bits + 7) / 8;
allocsz = 3 * rlen;
/* Use a single alloc for the buffers T, nonceh and entropyx */
T = (unsigned char *)OPENSSL_zalloc(allocsz);
if (T == NULL)
goto end;
nonceh = T + rlen;
entropyx = nonceh + rlen;
if (!int2octets(entropyx, priv, rlen)
|| !bits2octets(nonceh, q, qlen_bits, rlen, hm, hmlen))
goto end;
kdfctx = kdf_setup(digestname, entropyx, rlen, nonceh, rlen, libctx, propq);
if (kdfctx == NULL)
goto end;
do {
if (!EVP_KDF_derive(kdfctx, T, rlen, NULL)
|| !bits2int(out, qlen_bits, T, rlen))
goto end;
} while (BN_is_zero(out) || BN_is_one(out) || BN_cmp(out, q) >= 0);
ret = 1;
end:
EVP_KDF_CTX_free(kdfctx);
OPENSSL_clear_free(T, allocsz);
return ret;
}

View File

@ -69,4 +69,6 @@ struct dsa_method {
int (*dsa_keygen) (DSA *dsa);
};
DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa);
DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);

View File

@ -20,12 +20,15 @@
#include <openssl/sha.h>
#include "dsa_local.h"
#include <openssl/asn1.h>
#include "internal/deterministic_nonce.h"
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp, const unsigned char *dgst, int dlen);
BIGNUM **rp, const unsigned char *dgst, int dlen,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa);
static int dsa_init(DSA *dsa);
@ -67,7 +70,9 @@ const DSA_METHOD *DSA_OpenSSL(void)
return &openssl_dsa_meth;
}
DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
BIGNUM *kinv = NULL;
BIGNUM *m, *blind, *blindm, *tmp;
@ -106,7 +111,8 @@ DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
goto err;
redo:
if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen))
if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen,
nonce_type, digestname, libctx, propq))
goto err;
if (dlen > BN_num_bytes(dsa->params.q))
@ -185,18 +191,22 @@ DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
return ossl_dsa_do_sign_int(dgst, dlen, dsa);
return ossl_dsa_do_sign_int(dgst, dlen, dsa,
0, NULL, NULL, NULL);
}
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp)
{
return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0);
return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0,
0, NULL, NULL, NULL);
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen)
const unsigned char *dgst, int dlen,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
BN_CTX *ctx = NULL;
BIGNUM *k, *kinv = NULL, *r = *rp;
@ -243,13 +253,24 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
/* Get random k */
do {
if (dgst != NULL) {
/*
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst,
dlen, ctx))
goto err;
if (nonce_type == 1) {
#ifndef FIPS_MODULE
if (!ossl_gen_deterministic_nonce_rfc6979(k, dsa->params.q,
dsa->priv_key,
dgst, dlen,
digestname,
libctx, propq))
#endif
goto err;
} else {
/*
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst,
dlen, ctx))
goto err;
}
} else if (!BN_priv_rand_range_ex(k, dsa->params.q, 0, ctx))
goto err;
} while (BN_is_zero(k));

View File

@ -151,7 +151,9 @@ int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
}
int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa)
unsigned char *sig, unsigned int *siglen, DSA *dsa,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
DSA_SIG *s;
@ -159,7 +161,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method())
s = DSA_do_sign(dgst, dlen, dsa);
else
s = ossl_dsa_do_sign_int(dgst, dlen, dsa);
s = ossl_dsa_do_sign_int(dgst, dlen, dsa,
nonce_type, digestname, libctx, propq);
if (s == NULL) {
*siglen = 0;
return 0;
@ -172,7 +175,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
int DSA_sign(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa)
{
return ossl_dsa_sign_int(type, dgst, dlen, sig, siglen, dsa);
return ossl_dsa_sign_int(type, dgst, dlen, sig, siglen, dsa,
0, NULL, NULL, NULL);
}
/* data has already been hashed (probably with SHA or SHA-1). */

View File

@ -19,6 +19,13 @@
#include <openssl/rand.h>
#include "crypto/bn.h"
#include "ec_local.h"
#include "internal/deterministic_nonce.h"
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp)
@ -71,9 +78,39 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
return 1;
}
int ossl_ecdsa_deterministic_sign(const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
EC_KEY *eckey, unsigned int nonce_type,
const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
ECDSA_SIG *s;
BIGNUM *kinv = NULL, *r = NULL;
int ret = 0;
*siglen = 0;
if (!ecdsa_sign_setup(eckey, NULL, &kinv, &r, dgst, dlen,
nonce_type, digestname, libctx, propq))
return 0;
s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
if (s == NULL)
goto end;
*siglen = i2d_ECDSA_SIG(s, &sig);
ECDSA_SIG_free(s);
ret = 1;
end:
BN_clear_free(kinv);
BN_clear_free(r);
return ret;
}
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen)
const unsigned char *dgst, int dlen,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq)
{
BN_CTX *ctx = NULL;
BIGNUM *k = NULL, *r = NULL, *X = NULL;
@ -126,19 +163,29 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
goto err;
do {
/* get random k */
/* get random or determinstic value of k */
do {
int res = 0;
if (dgst != NULL) {
if (!BN_generate_dsa_nonce(k, order, priv_key,
dgst, dlen, ctx)) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
if (nonce_type == 1) {
#ifndef FIPS_MODULE
res = ossl_gen_deterministic_nonce_rfc6979(k, order,
priv_key,
dgst, dlen,
digestname,
libctx, propq);
#endif
} else {
res = BN_generate_dsa_nonce(k, order, priv_key, dgst, dlen,
ctx);
}
} else {
if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
res = BN_priv_rand_range_ex(k, order, 0, ctx);
}
if (!res) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
} while (BN_is_zero(k));
@ -187,7 +234,8 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp)
{
return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0,
0, NULL, NULL, NULL);
}
ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
@ -256,7 +304,8 @@ ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
}
do {
if (in_kinv == NULL || in_r == NULL) {
if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len,
0, NULL, NULL, NULL)) {
ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB);
goto err;
}

View File

@ -4193,6 +4193,10 @@ DEPEND[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
GENERATE[html/man7/EVP_KDF-HKDF.html]=man7/EVP_KDF-HKDF.pod
DEPEND[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
GENERATE[man/man7/EVP_KDF-HKDF.7]=man7/EVP_KDF-HKDF.pod
DEPEND[html/man7/EVP_KDF-HMAC-DRBG.html]=man7/EVP_KDF-HMAC-DRBG.pod
GENERATE[html/man7/EVP_KDF-HMAC-DRBG.html]=man7/EVP_KDF-HMAC-DRBG.pod
DEPEND[man/man7/EVP_KDF-HMAC-DRBG.7]=man7/EVP_KDF-HMAC-DRBG.pod
GENERATE[man/man7/EVP_KDF-HMAC-DRBG.7]=man7/EVP_KDF-HMAC-DRBG.pod
DEPEND[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
GENERATE[html/man7/EVP_KDF-KB.html]=man7/EVP_KDF-KB.pod
DEPEND[man/man7/EVP_KDF-KB.7]=man7/EVP_KDF-KB.pod
@ -4665,6 +4669,7 @@ html/man7/EVP_CIPHER-RC5.html \
html/man7/EVP_CIPHER-SEED.html \
html/man7/EVP_CIPHER-SM4.html \
html/man7/EVP_KDF-HKDF.html \
html/man7/EVP_KDF-HMAC-DRBG.html \
html/man7/EVP_KDF-KB.html \
html/man7/EVP_KDF-KRB5KDF.html \
html/man7/EVP_KDF-PBKDF1.html \
@ -4793,6 +4798,7 @@ man/man7/EVP_CIPHER-RC5.7 \
man/man7/EVP_CIPHER-SEED.7 \
man/man7/EVP_CIPHER-SM4.7 \
man/man7/EVP_KDF-HKDF.7 \
man/man7/EVP_KDF-HMAC-DRBG.7 \
man/man7/EVP_KDF-KB.7 \
man/man7/EVP_KDF-KRB5KDF.7 \
man/man7/EVP_KDF-PBKDF1.7 \

View File

@ -0,0 +1,71 @@
=pod
=head1 NAME
EVP_KDF-HMAC-DRBG
- The HMAC DRBG DETERMINISTIC EVP_KDF implementation
=head1 DESCRIPTION
Support for a deterministic HMAC DRBG using the B<EVP_KDF> API. This is similiar
to L<EVP_RAND-HMAC-DRBG(7)>, but uses fixed values for its entropy and nonce
values. This is used to generate deterministic nonce value required by ECDSA
and DSA (as defined in RFC 6979).
=head2 Identity
"HMAC-DRBG-KDF" is the name for this implementation; it can be used
with the EVP_KDF_fetch() function.
=head2 Supported parameters
The supported parameters are:
=over 4
=item "digest" (B<OSSL_DRBG_PARAM_DIGEST>) <UTF8 string>
=item "properties" (B<OSSL_DRBG_PARAM_PROPERTIES>) <UTF8 string>
These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
=item "entropy" (B<OSSL_KDF_PARAM_HMACDRBG_ENTROPY>) <octet string>
Sets the entropy bytes supplied to the HMAC-DRBG.
=item "nonce" (B<OSSL_KDF_PARAM_HMACDRBG_NONCE>) <octet string>
Sets the nonce bytes supplied to the HMAC-DRBG.
=back
=head1 NOTES
A context for KDF HMAC DRBG can be obtained by calling:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HMAC-DRBG-KDF", NULL);
EVP_KDF_CTX *kdf_ctx = EVP_KDF_CTX_new(kdf, NULL);
=head1 CONFORMING TO
RFC 6979
=head1 SEE ALSO
L<EVP_KDF(3)>,
L<EVP_KDF(3)/PARAMETERS>
=head1 HISTORY
The EVP_KDF-HMAC-DRBG functionality was added in OpenSSL 3.2.
=head1 COPYRIGHT
Copyright 2022 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
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut

View File

@ -59,7 +59,7 @@ These parameters work as described in L<EVP_RAND(3)/PARAMETERS>.
A context for HMAC DRBG can be obtained by calling:
EVP_RAND *rand = EVP_RAND_fetch(NULL, "HMAC-DRBG", NULL);
EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand);
EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL);
=head1 EXAMPLES

View File

@ -22,6 +22,8 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
=item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer>
The settable parameters are described in L<provider-signature(7)>.
=back

View File

@ -21,6 +21,8 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify().
=item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string>
=item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer>
These parameters are described in L<provider-signature(7)>.
=back

View File

@ -145,6 +145,7 @@ The OpenSSL default provider supports these operations and algorithms:
=item KRB5KDF, see L<EVP_KDF-KRB5KDF(7)>
=item HMAC-DRBG, see L<EVP_KDF-HMAC-DRBG(7)>
=back

View File

@ -363,6 +363,15 @@ The length of the "digest-size" parameter should not exceed that of a B<size_t>.
Gets the DER encoded AlgorithmIdentifier that corresponds to the combination of
signature algorithm and digest algorithm for the signature operation.
=item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer>
Set this to 1 to use a deterministic ECDSA or DSA digital signature as
defined in RFC #6979 (See Section 3.2 "Generation of k").
The default value of 0 uses a random value for the nonce B<k> as defined in
FIPS 186-4 Section 6.3 "Secret Number Generation".
Before using deterministic digital signature please read
RFC #6979 Section 4 "Security Considerations".
=item "kat" (B<OSSL_SIGNATURE_PARAM_KAT>) <unsigned integer>
Sets a flag to modify the sign operation to return an error if the initial

View File

@ -26,7 +26,9 @@ int ossl_dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits,
BN_GENCB *cb);
int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa);
unsigned char *sig, unsigned int *siglen, DSA *dsa,
unsigned int nonce_type, const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa);
int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]);

View File

@ -97,5 +97,10 @@ char *ossl_ec_check_group_type_id2name(int flags);
int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name);
int ossl_ec_generate_key_dhkem(EC_KEY *eckey,
const unsigned char *ikm, size_t ikmlen);
int ossl_ecdsa_deterministic_sign(const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
EC_KEY *eckey, unsigned int nonce_type,
const char *digestname,
OSSL_LIB_CTX *libctx, const char *propq);
# endif /* OPENSSL_NO_EC */
#endif

View File

@ -0,0 +1,24 @@
/*
* Copyright 2022 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_INTERNAL_DETERMINISTIC_NONCE_H
# define OSSL_INTERNAL_DETERMINISTIC_NONCE_H
# pragma once
# include <openssl/bn.h>
int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
const BIGNUM *priv,
const unsigned char *message,
size_t message_len,
const char *digestname,
OSSL_LIB_CTX *libctx,
const char *propq);
#endif /*OSSL_INTERNAL_DETERMINISTIC_NONCE_H */

View File

@ -230,6 +230,8 @@ extern "C" {
#define OSSL_KDF_PARAM_X942_SUPP_PUBINFO "supp-pubinfo"
#define OSSL_KDF_PARAM_X942_SUPP_PRIVINFO "supp-privinfo"
#define OSSL_KDF_PARAM_X942_USE_KEYBITS "use-keybits"
#define OSSL_KDF_PARAM_HMACDRBG_ENTROPY "entropy"
#define OSSL_KDF_PARAM_HMACDRBG_NONCE "nonce"
/* Known KDF names */
#define OSSL_KDF_NAME_HKDF "HKDF"
@ -245,6 +247,7 @@ extern "C" {
#define OSSL_KDF_NAME_X963KDF "X963KDF"
#define OSSL_KDF_NAME_KBKDF "KBKDF"
#define OSSL_KDF_NAME_KRB5KDF "KRB5KDF"
#define OSSL_KDF_NAME_HMACDRBGKDF "HMAC-DRBG-KDF"
/* Known RAND names */
#define OSSL_RAND_PARAM_STATE "state"
@ -461,6 +464,7 @@ extern "C" {
#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \
OSSL_PKEY_PARAM_MGF1_PROPERTIES
#define OSSL_SIGNATURE_PARAM_DIGEST_SIZE OSSL_PKEY_PARAM_DIGEST_SIZE
#define OSSL_SIGNATURE_PARAM_NONCE_TYPE "nonce_type"
/* Asym cipher parameters */
#define OSSL_ASYM_CIPHER_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST

View File

@ -353,6 +353,8 @@ static const OSSL_ALGORITHM deflt_kdfs[] = {
{ PROV_NAMES_SCRYPT, "provider=default", ossl_kdf_scrypt_functions },
#endif
{ PROV_NAMES_KRB5KDF, "provider=default", ossl_kdf_krb5kdf_functions },
{ PROV_NAMES_HMAC_DRBG_KDF, "provider=default",
ossl_kdf_hmac_drbg_functions },
{ NULL, NULL, NULL }
};

View File

@ -0,0 +1,33 @@
/*
* Copyright 2022 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_PROV_HMAC_DRBG_H
# define OSSL_PROV_HMAC_DRBG_H
# pragma once
#include <openssl/evp.h>
#include "prov/provider_util.h"
typedef struct drbg_hmac_st {
EVP_MAC_CTX *ctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
PROV_DIGEST digest; /* H(x) = hash(x) */
size_t blocklen;
unsigned char K[EVP_MAX_MD_SIZE];
unsigned char V[EVP_MAX_MD_SIZE];
} PROV_DRBG_HMAC;
int ossl_drbg_hmac_init(PROV_DRBG_HMAC *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len);
int ossl_drbg_hmac_generate(PROV_DRBG_HMAC *hmac,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len);
#endif /* OSSL_PROV_HMAC_DRBG_H */

View File

@ -279,6 +279,7 @@ extern const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_kbkdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_x942_kdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[];
extern const OSSL_DISPATCH ossl_kdf_hmac_drbg_functions[];
/* RNGs */
extern const OSSL_DISPATCH ossl_test_rng_functions[];

View File

@ -278,6 +278,7 @@
#define PROV_NAMES_SCRYPT "SCRYPT:id-scrypt:1.3.6.1.4.1.11591.4.11"
#define PROV_DESCS_SCRYPT_SIGN "OpenSSL SCRYPT via EVP_PKEY implementation"
#define PROV_NAMES_KRB5KDF "KRB5KDF"
#define PROV_NAMES_HMAC_DRBG_KDF "HMAC-DRBG-KDF"
/*-
* MACs

View File

@ -13,6 +13,7 @@ $SSKDF_GOAL=../../libdefault.a ../../libfips.a
$SCRYPT_GOAL=../../libdefault.a
$SSHKDF_GOAL=../../libdefault.a ../../libfips.a
$X942KDF_GOAL=../../libdefault.a ../../libfips.a
$HMAC_DRBG_KDF_GOAL=../../libdefault.a
SOURCE[$TLS1_PRF_GOAL]=tls1_prf.c
@ -39,3 +40,5 @@ SOURCE[$SCRYPT_GOAL]=scrypt.c
SOURCE[$SSHKDF_GOAL]=sshkdf.c
SOURCE[$X942KDF_GOAL]=x942kdf.c
DEPEND[x942kdf.o]=../../common/include/prov/der_wrap.h
SOURCE[$HMAC_DRBG_KDF_GOAL]=hmacdrbg_kdf.c

View File

@ -0,0 +1,259 @@
/*
* Copyright 2022 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/kdf.h>
#include <openssl/proverr.h>
#include <openssl/core_names.h>
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/hmac_drbg.h"
#include "prov/provider_ctx.h"
static OSSL_FUNC_kdf_newctx_fn hmac_drbg_kdf_new;
static OSSL_FUNC_kdf_dupctx_fn hmac_drbg_kdf_dup;
static OSSL_FUNC_kdf_freectx_fn hmac_drbg_kdf_free;
static OSSL_FUNC_kdf_reset_fn hmac_drbg_kdf_reset;
static OSSL_FUNC_kdf_derive_fn hmac_drbg_kdf_derive;
static OSSL_FUNC_kdf_settable_ctx_params_fn hmac_drbg_kdf_settable_ctx_params;
static OSSL_FUNC_kdf_set_ctx_params_fn hmac_drbg_kdf_set_ctx_params;
static OSSL_FUNC_kdf_gettable_ctx_params_fn hmac_drbg_kdf_gettable_ctx_params;
static OSSL_FUNC_kdf_get_ctx_params_fn hmac_drbg_kdf_get_ctx_params;
typedef struct {
PROV_DRBG_HMAC base;
void *provctx;
unsigned char *entropy, *nonce;
size_t entropylen, noncelen;
int init;
} KDF_HMAC_DRBG;
static void *hmac_drbg_kdf_new(void *provctx)
{
KDF_HMAC_DRBG *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->provctx = provctx;
return ctx;
}
static void hmac_drbg_kdf_reset(void *vctx)
{
KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
PROV_DRBG_HMAC *drbg = &ctx->base;
void *provctx = ctx->provctx;
EVP_MAC_CTX_free(drbg->ctx);
ossl_prov_digest_reset(&drbg->digest);
OPENSSL_clear_free(ctx->entropy, ctx->entropylen);
OPENSSL_clear_free(ctx->nonce, ctx->noncelen);
OPENSSL_cleanse(ctx, sizeof(*ctx));
ctx->provctx = provctx;
}
static void hmac_drbg_kdf_free(void *vctx)
{
KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
if (ctx != NULL) {
hmac_drbg_kdf_reset(ctx);
OPENSSL_free(ctx);
}
}
static int ossl_drbg_hmac_dup(PROV_DRBG_HMAC *dst, const PROV_DRBG_HMAC *src) {
if (src->ctx != NULL) {
dst->ctx = EVP_MAC_CTX_dup(src->ctx);
if (dst->ctx == NULL)
return 0;
}
if (!ossl_prov_digest_copy(&dst->digest, &src->digest))
return 0;
memcpy(dst->K, src->K, sizeof(dst->K));
memcpy(dst->V, src->V, sizeof(dst->V));
dst->blocklen = src->blocklen;
return 1;
}
static void *hmac_drbg_kdf_dup(void *vctx)
{
const KDF_HMAC_DRBG *src = (const KDF_HMAC_DRBG *)vctx;
KDF_HMAC_DRBG *dst;
dst = hmac_drbg_kdf_new(src->provctx);
if (dst != NULL) {
if (!ossl_drbg_hmac_dup(&dst->base, &src->base)
|| !ossl_prov_memdup(src->entropy, src->entropylen,
&dst->entropy , &dst->entropylen)
|| !ossl_prov_memdup(src->nonce, src->noncelen,
&dst->nonce, &dst->noncelen))
goto err;
dst->init = src->init;
}
return dst;
err:
hmac_drbg_kdf_free(dst);
return NULL;
}
static int hmac_drbg_kdf_derive(void *vctx, unsigned char *out, size_t outlen,
const OSSL_PARAM params[])
{
KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
PROV_DRBG_HMAC *drbg = &ctx->base;
if (!ossl_prov_is_running()
|| !hmac_drbg_kdf_set_ctx_params(vctx, params))
return 0;
if (!ctx->init) {
if (ctx->entropy == NULL
|| ctx->entropylen == 0
|| ctx->nonce == NULL
|| ctx->noncelen == 0
|| !ossl_drbg_hmac_init(drbg, ctx->entropy, ctx->entropylen,
ctx->nonce, ctx->noncelen, NULL, 0))
return 0;
ctx->init = 1;
}
return ossl_drbg_hmac_generate(drbg, out, outlen, NULL, 0);
}
static int hmac_drbg_kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
KDF_HMAC_DRBG *hmac = (KDF_HMAC_DRBG *)vctx;
PROV_DRBG_HMAC *drbg = &hmac->base;
const char *name;
const EVP_MD *md;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_MAC);
if (p != NULL) {
if (drbg->ctx == NULL)
return 0;
name = EVP_MAC_get0_name(EVP_MAC_CTX_get0_mac(drbg->ctx));
if (!OSSL_PARAM_set_utf8_string(p, name))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST);
if (p != NULL) {
md = ossl_prov_digest_md(&drbg->digest);
if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
return 0;
}
return 1;
}
static const OSSL_PARAM *hmac_drbg_kdf_gettable_ctx_params(
ossl_unused void *vctx, ossl_unused void *p_ctx)
{
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_END
};
return known_gettable_ctx_params;
}
static int hmac_drbg_kdf_set_ctx_params(void *vctx,
const OSSL_PARAM params[])
{
KDF_HMAC_DRBG *hmac = (KDF_HMAC_DRBG *)vctx;
PROV_DRBG_HMAC *drbg = &hmac->base;
OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(hmac->provctx);
const EVP_MD *md;
const OSSL_PARAM *p;
void *ptr = NULL;
size_t size = 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_HMACDRBG_ENTROPY);
if (p != NULL) {
if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
return 0;
OPENSSL_free(hmac->entropy);
hmac->entropy = ptr;
hmac->entropylen = size;
hmac->init = 0;
ptr = NULL;
}
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_HMACDRBG_NONCE);
if (p != NULL) {
if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
return 0;
OPENSSL_free(hmac->nonce);
hmac->nonce = ptr;
hmac->noncelen = size;
hmac->init = 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
if (p != NULL) {
if (!ossl_prov_digest_load_from_params(&drbg->digest, params, libctx))
return 0;
/* Confirm digest is allowed. Allow all digests that are not XOF */
md = ossl_prov_digest_md(&drbg->digest);
if (md != NULL) {
if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
return 0;
}
drbg->blocklen = EVP_MD_get_size(md);
}
return ossl_prov_macctx_load_from_params(&drbg->ctx, params,
"HMAC", NULL, NULL, libctx);
}
return 1;
}
static const OSSL_PARAM *hmac_drbg_kdf_settable_ctx_params(
ossl_unused void *vctx, ossl_unused void *p_ctx)
{
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END
};
return known_settable_ctx_params;
}
const OSSL_DISPATCH ossl_kdf_hmac_drbg_functions[] = {
{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))hmac_drbg_kdf_new },
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))hmac_drbg_kdf_free },
{ OSSL_FUNC_KDF_DUPCTX, (void(*)(void))hmac_drbg_kdf_dup },
{ OSSL_FUNC_KDF_RESET, (void(*)(void))hmac_drbg_kdf_reset },
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))hmac_drbg_kdf_derive },
{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
(void(*)(void))hmac_drbg_kdf_settable_ctx_params },
{ OSSL_FUNC_KDF_SET_CTX_PARAMS,
(void(*)(void))hmac_drbg_kdf_set_ctx_params },
{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
(void(*)(void))hmac_drbg_kdf_gettable_ctx_params },
{ OSSL_FUNC_KDF_GET_CTX_PARAMS,
(void(*)(void))hmac_drbg_kdf_get_ctx_params },
{ 0, NULL }
};

View File

@ -13,11 +13,11 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/proverr.h>
#include "prov/provider_util.h"
#include "internal/thread_once.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/hmac_drbg.h"
#include "drbg_local.h"
static OSSL_FUNC_rand_newctx_fn drbg_hmac_new_wrapper;
@ -32,14 +32,6 @@ static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hmac_gettable_ctx_params;
static OSSL_FUNC_rand_get_ctx_params_fn drbg_hmac_get_ctx_params;
static OSSL_FUNC_rand_verify_zeroization_fn drbg_hmac_verify_zeroization;
typedef struct rand_drbg_hmac_st {
EVP_MAC_CTX *ctx; /* H(x) = HMAC_hash OR H(x) = KMAC */
PROV_DIGEST digest; /* H(x) = hash(x) */
size_t blocklen;
unsigned char K[EVP_MAX_MD_SIZE];
unsigned char V[EVP_MAX_MD_SIZE];
} PROV_DRBG_HMAC;
/*
* Called twice by SP800-90Ar1 10.1.2.2 HMAC_DRBG_Update_Process.
*
@ -91,13 +83,11 @@ static int do_hmac(PROV_DRBG_HMAC *hmac, unsigned char inbyte,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_update(PROV_DRBG *drbg,
static int drbg_hmac_update(PROV_DRBG_HMAC *hmac,
const unsigned char *in1, size_t in1len,
const unsigned char *in2, size_t in2len,
const unsigned char *in3, size_t in3len)
{
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
/* (Steps 1-2) K = HMAC(K, V||0x00||provided_data). V = HMAC(K,V) */
if (!do_hmac(hmac, 0x00, in1, in1len, in2, in2len, in3, in3len))
return 0;
@ -119,13 +109,11 @@ static int drbg_hmac_update(PROV_DRBG *drbg,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_instantiate(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len)
int ossl_drbg_hmac_init(PROV_DRBG_HMAC *hmac,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len)
{
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
if (hmac->ctx == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
return 0;
@ -136,9 +124,17 @@ static int drbg_hmac_instantiate(PROV_DRBG *drbg,
/* (Step 3) V = 0x01 01...01 */
memset(hmac->V, 0x01, hmac->blocklen);
/* (Step 4) (K,V) = HMAC_DRBG_Update(entropy||nonce||pers string, K, V) */
return drbg_hmac_update(drbg, ent, ent_len, nonce, nonce_len, pstr,
return drbg_hmac_update(hmac, ent, ent_len, nonce, nonce_len, pstr,
pstr_len);
}
static int drbg_hmac_instantiate(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *pstr, size_t pstr_len)
{
return ossl_drbg_hmac_init((PROV_DRBG_HMAC *)drbg->data, ent, ent_len,
nonce, nonce_len, pstr, pstr_len);
}
static int drbg_hmac_instantiate_wrapper(void *vdrbg, unsigned int strength,
int prediction_resistance,
@ -168,8 +164,10 @@ static int drbg_hmac_reseed(PROV_DRBG *drbg,
const unsigned char *ent, size_t ent_len,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
/* (Step 2) (K,V) = HMAC_DRBG_Update(entropy||additional_input, K, V) */
return drbg_hmac_update(drbg, ent, ent_len, adin, adin_len, NULL, 0);
return drbg_hmac_update(hmac, ent, ent_len, adin, adin_len, NULL, 0);
}
static int drbg_hmac_reseed_wrapper(void *vdrbg, int prediction_resistance,
@ -191,18 +189,17 @@ static int drbg_hmac_reseed_wrapper(void *vdrbg, int prediction_resistance,
*
* Returns zero if an error occurs otherwise it returns 1.
*/
static int drbg_hmac_generate(PROV_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len)
int ossl_drbg_hmac_generate(PROV_DRBG_HMAC *hmac,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len)
{
PROV_DRBG_HMAC *hmac = (PROV_DRBG_HMAC *)drbg->data;
EVP_MAC_CTX *ctx = hmac->ctx;
const unsigned char *temp = hmac->V;
/* (Step 2) if adin != NULL then (K,V) = HMAC_DRBG_Update(adin, K, V) */
if (adin != NULL
&& adin_len > 0
&& !drbg_hmac_update(drbg, adin, adin_len, NULL, 0, NULL, 0))
&& !drbg_hmac_update(hmac, adin, adin_len, NULL, 0, NULL, 0))
return 0;
/*
@ -231,14 +228,22 @@ static int drbg_hmac_generate(PROV_DRBG *drbg,
outlen -= hmac->blocklen;
}
/* (Step 6) (K,V) = HMAC_DRBG_Update(adin, K, V) */
if (!drbg_hmac_update(drbg, adin, adin_len, NULL, 0, NULL, 0))
if (!drbg_hmac_update(hmac, adin, adin_len, NULL, 0, NULL, 0))
return 0;
return 1;
}
static int drbg_hmac_generate_wrapper
(void *vdrbg, unsigned char *out, size_t outlen, unsigned int strength,
static int drbg_hmac_generate(PROV_DRBG *drbg,
unsigned char *out, size_t outlen,
const unsigned char *adin, size_t adin_len)
{
return ossl_drbg_hmac_generate((PROV_DRBG_HMAC *)drbg->data, out, outlen,
adin, adin_len);
}
static int drbg_hmac_generate_wrapper(void *vdrbg,
unsigned char *out, size_t outlen, unsigned int strength,
int prediction_resistance, const unsigned char *adin, size_t adin_len)
{
PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;

View File

@ -224,7 +224,7 @@ OSSL_FUNC_rand_unlock_fn ossl_drbg_unlock;
int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[]);
int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]);
#define OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON \
#define OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON \
OSSL_PARAM_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, NULL), \
OSSL_PARAM_uint64(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, NULL)

View File

@ -74,6 +74,9 @@ typedef struct {
*/
unsigned int flag_allow_md : 1;
/* If this is set to 1 then the generated k is not random */
unsigned int nonce_type;
char mdname[OSSL_MAX_NAME_SIZE];
/* The Algorithm Identifier of the combined signature algorithm */
@ -249,7 +252,9 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
if (mdsize != 0 && tbslen != mdsize)
return 0;
ret = ossl_dsa_sign_int(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa);
ret = ossl_dsa_sign_int(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa,
pdsactx->nonce_type, pdsactx->mdname,
pdsactx->libctx, pdsactx->propq);
if (ret <= 0)
return 0;
@ -497,6 +502,10 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
if (!dsa_setup_md(pdsactx, mdname, mdprops))
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
if (p != NULL
&& !OSSL_PARAM_get_uint(p, &pdsactx->nonce_type))
return 0;
return 1;
}
@ -504,6 +513,7 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
static const OSSL_PARAM settable_ctx_params[] = {
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),
OSSL_PARAM_END
};

View File

@ -25,6 +25,7 @@
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "internal/cryptlib.h"
#include "internal/deterministic_nonce.h"
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
@ -102,6 +103,8 @@ typedef struct {
*/
unsigned int kattest;
#endif
/* If this is set then the generated k is not random */
unsigned int nonce_type;
} PROV_ECDSA_CTX;
static void *ecdsa_newctx(void *provctx, const char *propq)
@ -192,7 +195,15 @@ static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
return 0;
ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r, ctx->ec);
if (ctx->nonce_type != 0) {
ret = ossl_ecdsa_deterministic_sign(tbs, tbslen, sig, &sltmp,
ctx->ec, ctx->nonce_type,
ctx->mdname,
ctx->libctx, ctx->propq);
} else {
ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r,
ctx->ec);
}
if (ret <= 0)
return 0;
@ -513,6 +524,10 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
return 0;
ctx->mdsize = mdsize;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
if (p != NULL
&& !OSSL_PARAM_get_uint(p, &ctx->nonce_type))
return 0;
return 1;
}
@ -522,6 +537,7 @@ static const OSSL_PARAM settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),
OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),
OSSL_PARAM_END
};

View File

@ -1649,6 +1649,114 @@ static int test_kdf_krb5kdf(void)
return ret;
}
static int test_kdf_hmac_drbg_settables(void)
{
int ret = 0, i = 0, j = 0;
EVP_KDF_CTX *kctx = NULL;
const OSSL_PARAM *settableparams;
OSSL_PARAM params[5];
static const unsigned char ent[32] = { 0 };
unsigned char out[32];
char digestname[32];
char macname[32];
EVP_MD *shake256 = NULL;
/* Test there are settables */
if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HMACDRBGKDF))
|| !TEST_ptr(settableparams = EVP_KDF_CTX_settable_params(kctx)))
goto err;
/* Fail if no params have been set when doing a derive */
if (!TEST_int_le(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
goto err;
/* Fail if we pass the wrong type for params */
params[1] = OSSL_PARAM_construct_end();
for (i = 0; settableparams[i].key != NULL; ++i) {
/* Skip "properties" key since it returns 1 unless the digest is also set */
if (OPENSSL_strcasecmp(settableparams[i].key,
OSSL_KDF_PARAM_PROPERTIES) != 0) {
TEST_note("Testing set int into %s fails", settableparams[i].key);
params[0] = OSSL_PARAM_construct_int(settableparams[i].key, &j);
if (!TEST_int_le(EVP_KDF_CTX_set_params(kctx, params), 0))
goto err;
}
}
/* Test that we can set values multiple times */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY,
(char *)ent, sizeof(ent));
params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE,
(char *)ent, sizeof(ent));
params[2] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, "SHA256",
0);
params[3] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_PROPERTIES, "",
0);
params[4] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 1))
goto err;
if (!TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 1))
goto err;
/* Test we can retrieve values back */
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST,
digestname, sizeof(digestname));
params[1] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC,
macname, sizeof(macname));
params[2] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params), 1)
|| !TEST_mem_eq(digestname, params[0].return_size, "SHA2-256", 8)
|| !TEST_mem_eq(macname, params[1].return_size, "HMAC", 4))
goto err;
/* Test the derive */
if (!TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 1))
goto err;
/* test that XOF digests are not allowed */
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST,
"shake256", 0);
params[1] = OSSL_PARAM_construct_end();
if (!TEST_int_le(EVP_KDF_CTX_set_params(kctx, params), 0))
goto err;
ret = 1;
err:
EVP_MD_free(shake256);
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_hmac_drbg_gettables(void)
{
int ret = 0, i, j = 0;
EVP_KDF_CTX *kctx = NULL;
const OSSL_PARAM *gettableparams;
OSSL_PARAM params[3];
char buf[64];
/* Test there are gettables */
if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HMACDRBGKDF))
|| !TEST_ptr(gettableparams = EVP_KDF_CTX_gettable_params(kctx)))
goto err;
/* Fail if we pass the wrong type for params */
params[1] = OSSL_PARAM_construct_end();
for (i = 0; gettableparams[i].key != NULL; ++i) {
params[0] = OSSL_PARAM_construct_int(gettableparams[i].key, &j);
if (!TEST_int_le(EVP_KDF_CTX_get_params(kctx, params), 0))
goto err;
}
/* fail to get params if they are not set yet */
for (i = 0; gettableparams[i].key != NULL; ++i) {
params[0] = OSSL_PARAM_construct_utf8_string(gettableparams[i].key,
buf, sizeof(buf));
if (!TEST_int_le(EVP_KDF_CTX_get_params(kctx, params), 0))
goto err;
}
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
return ret;
}
int setup_tests(void)
{
ADD_TEST(test_kdf_pbkdf1);
@ -1707,5 +1815,7 @@ int setup_tests(void)
ADD_TEST(test_kdf_x942_asn1);
#endif
ADD_TEST(test_kdf_krb5kdf);
ADD_TEST(test_kdf_hmac_drbg_settables);
ADD_TEST(test_kdf_hmac_drbg_gettables);
return 1;
}

View File

@ -3234,6 +3234,7 @@ typedef struct {
size_t osin_len; /* Input length data if one shot */
unsigned char *output; /* Expected output */
size_t output_len; /* Expected output length */
const char *nonce_type;
} DIGESTSIGN_DATA;
static int digestsigver_test_init(EVP_TEST *t, const char *alg, int is_verify,
@ -3330,6 +3331,20 @@ static int digestsigver_test_parse(EVP_TEST *t,
return -1;
return pkey_test_ctrl(t, mdata->pctx, value);
}
if (strcmp(keyword, "NonceType") == 0) {
if (strcmp(value, "deterministic") == 0) {
OSSL_PARAM params[2];
unsigned int nonce_type = 1;
params[0] =
OSSL_PARAM_construct_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE,
&nonce_type);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_PKEY_CTX_set_params(mdata->pctx, params))
t->err = "EVP_PKEY_CTX_set_params_ERROR";
}
return 1;
}
return 0;
}

View File

@ -102,6 +102,7 @@ my @defltfiles = qw(
evpkdf_krb5.txt
evpkdf_scrypt.txt
evpkdf_tls11_prf.txt
evpkdf_hmac_drbg.txt
evpmac_blake.txt
evpmac_poly1305.txt
evpmac_siphash.txt

View File

@ -0,0 +1,48 @@
#
# Copyright 2022 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
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# The Test data (for the positive tests) was derived from a subset of evppkey_dsa_rfc6979.txt
# using the intermediate outputs.
Title = HMAC-DRBG-KDF Tests
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHA1
Ctrl.properties = properties:provider=default
Ctrl.hexentropy = hexentropy:411602cb19a6ccc34494d79d98ef1e7ed5af25f7
Ctrl.hexnonce = hexnonce:8151325dcdbae9e0ff95f9f9658432dbedfdb209
Output = 7bdb6b0ff756e1bb5d53583ef979082f9ad5bd5b
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHA1
Ctrl.hexentropy = hexentropy:69c7548c21d0dfea6b9a51c9ead4e27c33d3b3f180316e5bcab92c933f0e4dbc
Ctrl.hexnonce = hexnonce:0000000000000000000000008151325dcdbae9e0ff95f9f9658432dbedfdb209
Output = 888fa6f7738a41bdc9846466abdb8174c0338250ae50ce955ca16230f9cbd53e
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHA256
Ctrl.hexentropy = hexentropy:69c7548c21d0dfea6b9a51c9ead4e27c33d3b3f180316e5bcab92c933f0e4dbc
Ctrl.hexnonce = hexnonce:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Output = 1d6ce6dda1c5d37307839cd03ab0a5cbb18e60d800937d67dfb4479aac8dead7
# Fail if nonce input missing
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHA256
Ctrl.hexentropy = hexentropy:69
Result = KDF_DERIVE_ERROR
# Fail if entropy input missing
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHA256
Ctrl.hexnonce = hexnonce:9f
Result = KDF_DERIVE_ERROR
# Fail if XOF Digest used
KDF = HMAC-DRBG-KDF
Ctrl.digest = digest:SHAKE-256
Result = KDF_CTRL_ERROR