Upgrade libtomcrypt
This commit is contained in:
162
Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c
Normal file
162
Sources/DataLiteC/libtomcrypt/pk/ecc/ecc_rfc6979_key.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
|
||||
/* SPDX-License-Identifier: Unlicense */
|
||||
|
||||
#include "tomcrypt_private.h"
|
||||
|
||||
/**
|
||||
@file ecc_rfc6979_key.c
|
||||
ECC Crypto, Russ Williams
|
||||
*/
|
||||
|
||||
#ifdef LTC_MECC
|
||||
#ifdef LTC_SHA256
|
||||
|
||||
/**
|
||||
Make deterministic ECC key using the RFC6979 method
|
||||
@param priv [in] Private key for HMAC
|
||||
@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, unsigned long inlen, ecc_key *key)
|
||||
{
|
||||
int err, hash = -1;
|
||||
unsigned char v[MAXBLOCKSIZE], k[MAXBLOCKSIZE];
|
||||
unsigned char buffer[256], sep[1], privkey[128];
|
||||
unsigned long order_bits, len_diff, pk_len, zero_extend, outlen, klen, vlen, buflen, qlen, hashsize;
|
||||
void *r, *d;
|
||||
|
||||
LTC_ARGCHK(ltc_mp.name != NULL);
|
||||
LTC_ARGCHK(priv != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(key->dp.size > 0);
|
||||
|
||||
if (priv->rfc6979_hash_alg == NULL) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
hash = find_hash(priv->rfc6979_hash_alg);
|
||||
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
hashsize = hash_descriptor[hash].hashsize;
|
||||
|
||||
if ((err = ltc_mp_init_multi(&r, &d, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Length, in bytes, of key */
|
||||
order_bits = ltc_mp_count_bits(key->dp.order);
|
||||
qlen = (order_bits+7) >> 3;
|
||||
len_diff = qlen > inlen ? qlen - inlen : 0;
|
||||
pk_len = (ltc_mp_count_bits(priv->k)+7) >> 3;
|
||||
zero_extend = qlen - pk_len;
|
||||
XMEMSET(buffer, 0x00, len_diff + zero_extend);
|
||||
|
||||
/* RFC6979 3.2b, set V */
|
||||
XMEMSET(v, 0x01, hashsize);
|
||||
|
||||
/* RFC6979 3.2c, set K */
|
||||
XMEMSET(k, 0x00, hashsize);
|
||||
|
||||
if ((err = ltc_mp_to_unsigned_bin(priv->k, privkey) != CRYPT_OK)) { goto error; }
|
||||
/* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */
|
||||
sep[0] = 0;
|
||||
klen = sizeof(k);
|
||||
if((err = hmac_memory_multi(hash,
|
||||
k, hashsize,
|
||||
k, &klen,
|
||||
v, hashsize,
|
||||
sep, 1,
|
||||
buffer, zero_extend,
|
||||
privkey, qlen - zero_extend,
|
||||
buffer, len_diff,
|
||||
in, qlen - len_diff,
|
||||
LTC_NULL)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* RFC6979 3.2e, set V = HMAC_K(V) */
|
||||
vlen = sizeof(v);
|
||||
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &vlen)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */
|
||||
sep[0] = 0x01;
|
||||
outlen = sizeof(k);
|
||||
if((err = hmac_memory_multi(hash,
|
||||
k, klen,
|
||||
k, &klen,
|
||||
v, hashsize,
|
||||
sep, 1,
|
||||
buffer, zero_extend,
|
||||
privkey, qlen - zero_extend,
|
||||
buffer, len_diff,
|
||||
in, qlen - len_diff,
|
||||
LTC_NULL)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* RFC6979 3.2g, set V = HMAC_K(V) */
|
||||
outlen = sizeof(v);
|
||||
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* RFC6979 3.2h, generate and check key */
|
||||
do {
|
||||
/* concatenate hash bits into T */
|
||||
buflen = 0;
|
||||
while (buflen < qlen) {
|
||||
if (buflen + hashsize >= sizeof(buffer) || buflen + hashsize < buflen) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto error;
|
||||
}
|
||||
outlen = sizeof(v);
|
||||
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
|
||||
XMEMCPY(&buffer[buflen], v, hashsize);
|
||||
buflen += hashsize;
|
||||
}
|
||||
|
||||
/* key->k = bits2int(T) */
|
||||
if ((err = ltc_mp_read_unsigned_bin(r, buffer, qlen)) != CRYPT_OK) { goto error; }
|
||||
if ((qlen * 8) > order_bits) {
|
||||
if ((err = ltc_mp_2expt(d, (qlen * 8) - order_bits)) != CRYPT_OK) { goto error; }
|
||||
if ((err = ltc_mp_div(r, d, r, NULL)) != CRYPT_OK) { goto error; }
|
||||
if ((err = ltc_mp_to_unsigned_bin(r, buffer)) != CRYPT_OK) { goto error; }
|
||||
qlen = ltc_mp_unsigned_bin_size(r);
|
||||
}
|
||||
|
||||
if ((err = ecc_set_key(buffer, qlen, PK_PRIVATE, key))!= CRYPT_OK) { goto error; }
|
||||
|
||||
/* check that k is in range [1,q-1] */
|
||||
if (ltc_mp_cmp_d(key->k, 0) == LTC_MP_GT && ltc_mp_cmp(key->k, key->dp.order) == LTC_MP_LT) {
|
||||
/* Check that pubkey.x != 0 (mod p) */
|
||||
if ((err = ltc_mp_mod(key->pubkey.x, key->dp.order, r)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* if we have a valid key, exit loop */
|
||||
if (ltc_mp_iszero(r) == LTC_MP_NO)
|
||||
break;
|
||||
} else {
|
||||
/* K = HMAC_K(V::0x00) */
|
||||
buffer[0] = 0x0;
|
||||
outlen = sizeof(k);
|
||||
if((err = hmac_memory_multi(hash, k, klen, k, &klen, v, hashsize, buffer, 1, LTC_NULL)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* V = HMAC_K(V) */
|
||||
outlen = sizeof(v);
|
||||
if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* ... and try again! */
|
||||
}
|
||||
} while (1);
|
||||
|
||||
key->type = PK_PRIVATE;
|
||||
|
||||
/* success */
|
||||
err = CRYPT_OK;
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
ecc_free(key);
|
||||
cleanup:
|
||||
ltc_mp_cleanup_multi(&d, &r, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user