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 */
9
3
10
4
#include "tomcrypt_private.h"
11
5
25
19
@param key [out] Newly created deterministic key
26
20
@return CRYPT_OK if successful, upon error all allocated memory will be freed
27
21
*/
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)
29
23
{
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;
34
29
35
30
LTC_ARGCHK(ltc_mp.name != NULL);
31
+ LTC_ARGCHK(priv != NULL);
36
32
LTC_ARGCHK(key != NULL);
37
33
LTC_ARGCHK(key->dp.size > 0);
38
34
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
+ }
41
48
42
49
/* 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);
45
56
46
57
/* RFC6979 3.2b, set V */
47
- for (i=0; i<32; i++) v[i] = 0x01;
58
+ XMEMSET(v, 0x01, hashsize) ;
48
59
49
60
/* RFC6979 3.2c, set K */
50
- for (i=0; i<32; i++) k[i] = 0x00;
61
+ XMEMSET(k, 0x00, hashsize) ;
51
62
63
+ if ((err = ltc_mp_to_unsigned_bin(priv->k, privkey) != CRYPT_OK)) { goto error; }
52
64
/* 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; }
61
77
62
78
/* 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; }
66
81
67
82
/* 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; }
76
95
77
96
/* 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; }
81
99
82
100
/* RFC6979 3.2h, generate and check key */
83
101
do {
84
102
/* concatenate hash bits into T */
85
103
buflen = 0;
86
104
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
+ outlen = sizeof(v);
106
+ if((err = hmac_memory(hash, k, klen, v, hashsize, v, &outlen)) != CRYPT_OK) { goto error; }
107
+ XMEMCPY(&buffer[buflen], v, hashsize);
108
+ buflen += hashsize;
92
109
}
93
110
94
111
/* 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;
112
+ if ((err = ltc_mp_read_unsigned_bin(r, buffer, qlen)) != CRYPT_OK) { goto error; }
113
+ if ((qlen * 8) > order_bits) {
114
+ if ((err = ltc_mp_2expt(d, (qlen * 8) - order_bits)) != CRYPT_OK) { goto error; }
115
+ if ((err = ltc_mp_div(r, d, r, NULL)) != CRYPT_OK) { goto error; }
116
+ if ((err = ltc_mp_to_unsigned_bin(r, buffer)) != CRYPT_OK) { goto error; }
117
+ qlen = ltc_mp_unsigned_bin_size(r);
100
118
}
101
119
120
+ if ((err = ecc_set_key(buffer, qlen, PK_PRIVATE, key))!= CRYPT_OK) { goto error; }
121
+
102
122
/* 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) */
123
+ if (ltc_mp_cmp_d(key->k, 0) == LTC_MP_GT && ltc_mp_cmp(key->k, key->dp.order) == LTC_MP_LT) {
124
+ /* Check that pubkey.x != 0 (mod p) */
125
+ if ((err = ltc_mp_mod(key->pubkey.x, key->dp.order, r)) != CRYPT_OK) { goto error; }
105
126
106
127
/* if we have a valid key, exit loop */
107
- break;
128
+ if (ltc_mp_iszero(r) == LTC_MP_NO)
129
+ break;
108
130
} else {
131
+ if (hashsize == sizeof(buffer)) {
132
+ err = CRYPT_BUFFER_OVERFLOW;
133
+ goto error;
134
+ }
109
135
/* 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; }
116
139
117
140
/* 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; }
121
143
122
144
/* ... and try again! */
123
145
}
@@ -132,12 +154,9 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, int inlen, ecc
132
154
error:
133
155
ecc_free(key);
134
156
cleanup:
157
+ ltc_mp_cleanup_multi(&d, &r, NULL);
135
158
return err;
136
159
}
137
160
138
161
#endif
139
162
#endif
140
- /* ref: $Format:%D$ */
141
- /* git commit: $Format:%H$ */
142
- /* commit time: $Format:%ai$ */
143
-
0 commit comments