1- /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2- *
3- * LibTomCrypt is a library that provides various cryptographic
4- * algorithms in a highly modular and flexible manner.
5- *
6- * The library is free for all purposes without any express
7- * guarantee it works.
8- */
1+ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+ /* SPDX-License-Identifier: Unlicense */
93
104#include "tomcrypt_private.h"
115
2519 @param key [out] Newly created deterministic key
2620 @return CRYPT_OK if successful, upon error all allocated memory will be freed
2721*/
28- int ecc_rfc6979_key (const ecc_key * priv , const unsigned char * in , int inlen , ecc_key * key )
22+ int ecc_rfc6979_key (const ecc_key * priv , const unsigned char * in , unsigned long inlen , ecc_key * key )
2923{
30- int err , hash , i ;
31- unsigned char v [32 ], k [32 ], digest [32 ]; /* No way to determine hash so always use SHA256 */
32- unsigned char buffer [256 ];
33- unsigned long outlen , buflen , qlen ;
24+ int err , hash = -1 ;
25+ unsigned char v [MAXBLOCKSIZE ], k [MAXBLOCKSIZE ];
26+ unsigned char buffer [256 ], sep [1 ], privkey [128 ];
27+ unsigned long order_bits , len_diff , pk_len , zero_extend , outlen , klen , vlen , buflen , qlen , hashsize ;
28+ void * r , * d ;
3429
3530 LTC_ARGCHK (ltc_mp .name != NULL );
31+ LTC_ARGCHK (priv != NULL );
3632 LTC_ARGCHK (key != NULL );
3733 LTC_ARGCHK (key -> dp .size > 0 );
3834
39- hash = find_hash ("sha256" );
40- if (hash == -1 ) {err = CRYPT_ERROR ; goto error ;}
35+ if (priv -> rfc6979_hash_alg == NULL ) {
36+ return CRYPT_INVALID_ARG ;
37+ }
38+ hash = find_hash (priv -> rfc6979_hash_alg );
39+ if ((err = hash_is_valid (hash )) != CRYPT_OK ) {
40+ return err ;
41+ }
42+
43+ hashsize = hash_descriptor [hash ].hashsize ;
44+
45+ if ((err = ltc_mp_init_multi (& r , & d , NULL )) != CRYPT_OK ) {
46+ return err ;
47+ }
4148
4249 /* Length, in bytes, of key */
43- i = mp_count_bits (key -> dp .order );
44- qlen = (i + 7 ) >> 3 ;
50+ order_bits = ltc_mp_count_bits (key -> dp .order );
51+ qlen = (order_bits + 7 ) >> 3 ;
52+ len_diff = qlen > inlen ? qlen - inlen : 0 ;
53+ pk_len = (ltc_mp_count_bits (priv -> k )+ 7 ) >> 3 ;
54+ zero_extend = qlen - pk_len ;
55+ XMEMSET (buffer , 0x00 , len_diff + zero_extend );
4556
4657 /* RFC6979 3.2b, set V */
47- for ( i = 0 ; i < 32 ; i ++ ) v [ i ] = 0x01 ;
58+ XMEMSET ( v , 0x01 , hashsize ) ;
4859
4960 /* RFC6979 3.2c, set K */
50- for ( i = 0 ; i < 32 ; i ++ ) k [ i ] = 0x00 ;
61+ XMEMSET ( k , 0x00 , hashsize ) ;
5162
63+ if ((err = ltc_mp_to_unsigned_bin (priv -> k , privkey ) != CRYPT_OK )) { goto error ; }
5264 /* RFC6979 3.2d, set K to HMAC_K(V::0x00::priv::in) */
53- XMEMCPY (& buffer [0 ], v , 32 );
54- buffer [32 ] = 0x00 ;
55- if ((err = mp_to_unsigned_bin (priv -> k , & buffer [33 ]) != CRYPT_OK )) { goto error ; }
56- XMEMCPY (& buffer [33 + qlen ], in , inlen );
57- buflen = 32 + 1 + qlen + inlen ;
58- outlen = sizeof (digest );
59- if ((err = hmac_memory (hash , k , 32 , buffer , buflen , digest , & outlen )) != CRYPT_OK ) { goto error ; }
60- XMEMCPY (k , digest , 32 );
65+ sep [0 ] = 0 ;
66+ klen = sizeof (k );
67+ if ((err = hmac_memory_multi (hash ,
68+ k , hashsize ,
69+ k , & klen ,
70+ v , hashsize ,
71+ sep , 1 ,
72+ buffer , zero_extend ,
73+ privkey , qlen - zero_extend ,
74+ buffer , len_diff ,
75+ in , qlen - len_diff ,
76+ LTC_NULL )) != CRYPT_OK ) { goto error ; }
6177
6278 /* RFC6979 3.2e, set V = HMAC_K(V) */
63- outlen = sizeof (digest );
64- if ((err = hmac_memory (hash , k , 32 , v , 32 , digest , & outlen )) != CRYPT_OK ) { goto error ; }
65- XMEMCPY (v , digest , 32 );
79+ vlen = sizeof (v );
80+ if ((err = hmac_memory (hash , k , klen , v , hashsize , v , & vlen )) != CRYPT_OK ) { goto error ; }
6681
6782 /* RFC6979 3.2f, set K to HMAC_K(V::0x01::priv::in) */
68- XMEMCPY (& buffer [0 ], v , 32 );
69- buffer [32 ] = 0x01 ;
70- if ((err = mp_to_unsigned_bin (priv -> k , & buffer [33 ]) != CRYPT_OK )) { goto error ; }
71- XMEMCPY (& buffer [33 + qlen ], in , inlen );
72- buflen = 32 + 1 + qlen + inlen ;
73- outlen = sizeof (digest );
74- if ((err = hmac_memory (hash , k , 32 , buffer , buflen , digest , & outlen )) != CRYPT_OK ) { goto error ; }
75- XMEMCPY (k , digest , 32 );
83+ sep [0 ] = 0x01 ;
84+ outlen = sizeof (k );
85+ if ((err = hmac_memory_multi (hash ,
86+ k , klen ,
87+ k , & klen ,
88+ v , hashsize ,
89+ sep , 1 ,
90+ buffer , zero_extend ,
91+ privkey , qlen - zero_extend ,
92+ buffer , len_diff ,
93+ in , qlen - len_diff ,
94+ LTC_NULL )) != CRYPT_OK ) { goto error ; }
7695
7796 /* RFC6979 3.2g, set V = HMAC_K(V) */
78- outlen = sizeof (digest );
79- if ((err = hmac_memory (hash , k , 32 , v , 32 , digest , & outlen )) != CRYPT_OK ) { goto error ; }
80- XMEMCPY (v , digest , 32 );
97+ outlen = sizeof (v );
98+ if ((err = hmac_memory (hash , k , klen , v , hashsize , v , & outlen )) != CRYPT_OK ) { goto error ; }
8199
82100 /* RFC6979 3.2h, generate and check key */
83101 do {
84102 /* concatenate hash bits into T */
85103 buflen = 0 ;
86104 while (buflen < qlen ) {
87- outlen = sizeof (digest );
88- if ((err = hmac_memory (hash , k , 32 , v , 32 , digest , & outlen )) != CRYPT_OK ) { goto error ; }
89- XMEMCPY (v , digest , 32 );
90- XMEMCPY (& buffer [buflen ], v , 32 );
91- buflen += 32 ;
105+ if (buflen + hashsize >= sizeof (buffer ) || buflen + hashsize < buflen ) {
106+ err = CRYPT_BUFFER_OVERFLOW ;
107+ goto error ;
108+ }
109+ outlen = sizeof (v );
110+ if ((err = hmac_memory (hash , k , klen , v , hashsize , v , & outlen )) != CRYPT_OK ) { goto error ; }
111+ XMEMCPY (& buffer [buflen ], v , hashsize );
112+ buflen += hashsize ;
92113 }
93114
94115 /* key->k = bits2int(T) */
95- if ((err = mp_read_unsigned_bin (key -> k , (unsigned char * )buffer , qlen )) != CRYPT_OK ) { goto error ; }
96-
97- /* make the public key */
98- if ((err = ltc_mp .ecc_ptmul (key -> k , & key -> dp .base , & key -> pubkey , key -> dp .A , key -> dp .prime , 1 )) != CRYPT_OK ) {
99- goto error ;
116+ if ((err = ltc_mp_read_unsigned_bin (r , buffer , qlen )) != CRYPT_OK ) { goto error ; }
117+ if ((qlen * 8 ) > order_bits ) {
118+ if ((err = ltc_mp_2expt (d , (qlen * 8 ) - order_bits )) != CRYPT_OK ) { goto error ; }
119+ if ((err = ltc_mp_div (r , d , r , NULL )) != CRYPT_OK ) { goto error ; }
120+ if ((err = ltc_mp_to_unsigned_bin (r , buffer )) != CRYPT_OK ) { goto error ; }
121+ qlen = ltc_mp_unsigned_bin_size (r );
100122 }
101123
124+ if ((err = ecc_set_key (buffer , qlen , PK_PRIVATE , key ))!= CRYPT_OK ) { goto error ; }
125+
102126 /* check that k is in range [1,q-1] */
103- if (mp_cmp_d (key -> k , 0 ) == LTC_MP_GT && mp_cmp (key -> k , key -> dp .order ) == LTC_MP_LT ) {
104- /* TODO: Check that pubkey.x != 0 (mod p) */
127+ if (ltc_mp_cmp_d (key -> k , 0 ) == LTC_MP_GT && ltc_mp_cmp (key -> k , key -> dp .order ) == LTC_MP_LT ) {
128+ /* Check that pubkey.x != 0 (mod p) */
129+ if ((err = ltc_mp_mod (key -> pubkey .x , key -> dp .order , r )) != CRYPT_OK ) { goto error ; }
105130
106131 /* if we have a valid key, exit loop */
107- break ;
132+ if (ltc_mp_iszero (r ) == LTC_MP_NO )
133+ break ;
108134 } else {
109135 /* K = HMAC_K(V::0x00) */
110- XMEMCPY (& buffer [0 ], v , 32 );
111- buffer [32 ] = 0x00 ;
112- buflen = 32 + 1 ;
113- outlen = sizeof (digest );
114- if ((err = hmac_memory (hash , k , 32 , buffer , buflen , digest , & outlen )) != CRYPT_OK ) { goto error ; }
115- XMEMCPY (k , digest , 32 );
136+ buffer [0 ] = 0x0 ;
137+ outlen = sizeof (k );
138+ if ((err = hmac_memory_multi (hash , k , klen , k , & klen , v , hashsize , buffer , 1 , LTC_NULL )) != CRYPT_OK ) { goto error ; }
116139
117140 /* V = HMAC_K(V) */
118- outlen = sizeof (digest );
119- if ((err = hmac_memory (hash , k , 32 , v , 32 , digest , & outlen )) != CRYPT_OK ) { goto error ; }
120- XMEMCPY (v , digest , 32 );
141+ outlen = sizeof (v );
142+ if ((err = hmac_memory (hash , k , klen , v , hashsize , v , & outlen )) != CRYPT_OK ) { goto error ; }
121143
122144 /* ... and try again! */
123145 }
@@ -132,12 +154,9 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc
132154error :
133155 ecc_free (key );
134156cleanup :
157+ ltc_mp_cleanup_multi (& d , & r , NULL );
135158 return err ;
136159}
137160
138161#endif
139162#endif
140- /* ref: $Format:%D$ */
141- /* git commit: $Format:%H$ */
142- /* commit time: $Format:%ai$ */
143-
0 commit comments