This commit is contained in:
Steffen Jaeckel 2025-01-10 17:03:02 +01:00
parent 5127af0550
commit 39e8c51e4b

View file

@ -1,11 +1,5 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
@ -20,14 +14,15 @@
/**
Make deterministic ECC key using the RFC6979 method
@param priv [in] Private key for HMAC
@param hash The hash idx to use or -1 for automatic determination depending on `inlen`.
@param in Message to sign for HMAC
@param inlen Length of the message
@param key [out] Newly created deterministic key
@return CRYPT_OK if successful, upon error all allocated memory will be freed
*/
int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc_key *key)
int ecc_rfc6979_key(const ecc_key *priv, int hash, const unsigned char *in, unsigned long inlen, ecc_key *key)
{
int err, hash, i;
int err, hash_ = -1, i;
unsigned char v[32], k[32], digest[32]; /* No way to determine hash so always use SHA256 */
unsigned char buffer[256];
unsigned long outlen, buflen, qlen;
@ -36,8 +31,22 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(key->dp.size > 0);
hash = find_hash("sha256");
if (hash == -1) {err = CRYPT_ERROR; goto error;}
if (hash_is_valid(hash) == CRYPT_OK) {
hash_ = hash;
} else {
if (inlen == 20)
hash_ = find_hash("sha1");
else if (inlen == 28)
hash_ = find_hash("sha224");
else if (inlen == 32)
hash_ = find_hash("sha256");
else if (inlen == 48)
hash_ = find_hash("sha384");
else if (inlen == 64)
hash_ = find_hash("sha512");
if ((err = hash_is_valid(hash_)) != CRYPT_OK)
goto error;
}
/* Length, in bytes, of key */
i = mp_count_bits(key->dp.order);
@ -52,47 +61,47 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc
/* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */
XMEMCPY(&buffer[0], v, 32);
buffer[32] = 0x00;
if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; }
if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; }
XMEMCPY(&buffer[33+qlen], in, inlen);
buflen = 32 + 1 + qlen + inlen;
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(k, digest, 32);
/* RFC6979 3.2e, set V = HMAC_K(V) */
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(v, digest, 32);
/* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */
XMEMCPY(&buffer[0], v, 32);
buffer[32] = 0x01;
if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; }
if ((err = mp_to_unsigned_bin(priv->k, &buffer[33]) != CRYPT_OK)) { goto error; }
XMEMCPY(&buffer[33+qlen], in, inlen);
buflen = 32 + 1 + qlen + inlen;
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(k, digest, 32);
/* RFC6979 3.2g, set V = HMAC_K(V) */
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(v, digest, 32);
/* RFC6979 3.2h, generate and check key */
do {
/* concatenate hash bits into T */
/* concatenate hash_ bits into T */
buflen = 0;
while (buflen < qlen) {
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(v, digest, 32);
XMEMCPY(&buffer[buflen], v, 32);
buflen += 32;
}
/* key->k = bits2int(T) */
if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buffer, qlen)) != CRYPT_OK) { goto error; }
if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buffer, qlen)) != CRYPT_OK) { goto error; }
/* make the public key */
if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) {
@ -111,12 +120,12 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc
buffer[32] = 0x00;
buflen = 32 + 1;
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, buffer, buflen, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(k, digest, 32);
/* V = HMAC_K(V) */
outlen = sizeof(digest);
if((err = hmac_memory(hash, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
if((err = hmac_memory(hash_, k, 32, v, 32, digest, &outlen)) != CRYPT_OK) { goto error; }
XMEMCPY(v, digest, 32);
/* ... and try again! */
@ -137,7 +146,3 @@ cleanup:
#endif
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */