summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/gost/gostr341001.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001.c')
-rw-r--r--src/lib/libcrypto/gost/gostr341001.c256
1 files changed, 167 insertions, 89 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001.c b/src/lib/libcrypto/gost/gostr341001.c
index 3c314765f7..171cf1b80a 100644
--- a/src/lib/libcrypto/gost/gostr341001.c
+++ b/src/lib/libcrypto/gost/gostr341001.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: gostr341001.c,v 1.1 2014/11/09 19:17:13 miod Exp $ */ 1/* $OpenBSD: gostr341001.c,v 1.2 2014/11/13 20:29:55 miod Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4 * Copyright (c) 2005-2006 Cryptocom LTD 4 * Copyright (c) 2005-2006 Cryptocom LTD
@@ -59,10 +59,12 @@
59#include "gost_locl.h" 59#include "gost_locl.h"
60 60
61/* Convert little-endian byte array into bignum */ 61/* Convert little-endian byte array into bignum */
62BIGNUM *GOST_le2bn(const unsigned char * buf, size_t len, BIGNUM * bn) 62BIGNUM *
63GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn)
63{ 64{
64 unsigned char temp[64]; 65 unsigned char temp[64];
65 int i; 66 int i;
67
66 if (len > 64) 68 if (len > 64)
67 return NULL; 69 return NULL;
68 70
@@ -73,7 +75,8 @@ BIGNUM *GOST_le2bn(const unsigned char * buf, size_t len, BIGNUM * bn)
73 return BN_bin2bn(temp, len, bn); 75 return BN_bin2bn(temp, len, bn);
74} 76}
75 77
76int GOST_bn2le(BIGNUM * bn, unsigned char * buf, int len) 78int
79GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len)
77{ 80{
78 unsigned char temp[64]; 81 unsigned char temp[64];
79 int i, bytes; 82 int i, bytes;
@@ -93,8 +96,8 @@ int GOST_bn2le(BIGNUM * bn, unsigned char * buf, int len)
93 return 1; 96 return 1;
94} 97}
95 98
96 99int
97int gost2001_compute_public(GOST_KEY * ec) 100gost2001_compute_public(GOST_KEY *ec)
98{ 101{
99 const EC_GROUP *group = GOST_KEY_get0_group(ec); 102 const EC_GROUP *group = GOST_KEY_get0_group(ec);
100 EC_POINT *pub_key = NULL; 103 EC_POINT *pub_key = NULL;
@@ -102,36 +105,44 @@ int gost2001_compute_public(GOST_KEY * ec)
102 BN_CTX *ctx = NULL; 105 BN_CTX *ctx = NULL;
103 int ok = 0; 106 int ok = 0;
104 107
105 if (!group) { 108 if (group == NULL) {
106 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, 109 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,
107 GOST_R_KEY_IS_NOT_INITIALIZED); 110 GOST_R_KEY_IS_NOT_INITIALIZED);
108 return 0; 111 return 0;
109 } 112 }
110 ctx = BN_CTX_new(); 113 ctx = BN_CTX_new();
114 if (ctx == NULL) {
115 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,
116 ERR_R_MALLOC_FAILURE);
117 return 0;
118 }
111 BN_CTX_start(ctx); 119 BN_CTX_start(ctx);
112 if (!(priv_key = GOST_KEY_get0_private_key(ec))) { 120 if ((priv_key = GOST_KEY_get0_private_key(ec)) == NULL)
113 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
114 goto err; 121 goto err;
115 }
116 122
117 pub_key = EC_POINT_new(group); 123 pub_key = EC_POINT_new(group);
118 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { 124 if (pub_key == NULL)
119 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
120 goto err; 125 goto err;
121 } 126 if (EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx) == 0)
122 if (!GOST_KEY_set_public_key(ec, pub_key)) {
123 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
124 goto err; 127 goto err;
125 } 128 if (GOST_KEY_set_public_key(ec, pub_key) == 0)
126 ok = 256; 129 goto err;
130 ok = 1;
131
132 if (ok == 0) {
127err: 133err:
128 BN_CTX_end(ctx); 134 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
135 }
129 EC_POINT_free(pub_key); 136 EC_POINT_free(pub_key);
130 BN_CTX_free(ctx); 137 if (ctx != NULL) {
138 BN_CTX_end(ctx);
139 BN_CTX_free(ctx);
140 }
131 return ok; 141 return ok;
132} 142}
133 143
134ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey) 144ECDSA_SIG *
145gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey)
135{ 146{
136 ECDSA_SIG *newsig = NULL; 147 ECDSA_SIG *newsig = NULL;
137 BIGNUM *order = NULL; 148 BIGNUM *order = NULL;
@@ -141,9 +152,15 @@ ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey)
141 NULL, *e = NULL; 152 NULL, *e = NULL;
142 EC_POINT *C = NULL; 153 EC_POINT *C = NULL;
143 BN_CTX *ctx = BN_CTX_new(); 154 BN_CTX *ctx = BN_CTX_new();
155 int ok = 0;
156
157 if (ctx == NULL) {
158 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
159 return NULL;
160 }
144 BN_CTX_start(ctx); 161 BN_CTX_start(ctx);
145 newsig = ECDSA_SIG_new(); 162 newsig = ECDSA_SIG_new();
146 if (!newsig) { 163 if (newsig == NULL) {
147 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 164 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
148 goto err; 165 goto err;
149 } 166 }
@@ -151,70 +168,88 @@ ECDSA_SIG *gost2001_do_sign(BIGNUM * md, GOST_KEY * eckey)
151 r = newsig->r; 168 r = newsig->r;
152 group = GOST_KEY_get0_group(eckey); 169 group = GOST_KEY_get0_group(eckey);
153 order = BN_CTX_get(ctx); 170 order = BN_CTX_get(ctx);
154 EC_GROUP_get_order(group, order, ctx); 171 if (order == NULL)
172 goto err;
173 if (EC_GROUP_get_order(group, order, ctx) == 0)
174 goto err;
155 priv_key = GOST_KEY_get0_private_key(eckey); 175 priv_key = GOST_KEY_get0_private_key(eckey);
156 e = BN_CTX_get(ctx); 176 e = BN_CTX_get(ctx);
157 BN_mod(e, md, order, ctx); 177 if (e == NULL)
158 if (BN_is_zero(e)) { 178 goto err;
179 if (BN_mod(e, md, order, ctx) == 0)
180 goto err;
181 if (BN_is_zero(e))
159 BN_one(e); 182 BN_one(e);
160 }
161 k = BN_CTX_get(ctx); 183 k = BN_CTX_get(ctx);
162 X = BN_CTX_get(ctx); 184 X = BN_CTX_get(ctx);
163 C = EC_POINT_new(group); 185 C = EC_POINT_new(group);
186 if (C == NULL)
187 goto err;
164 do { 188 do {
165 do { 189 do {
166 if (!BN_rand_range(k, order)) { 190 if (!BN_rand_range(k, order)) {
167 GOSTerr(GOST_F_GOST2001_DO_SIGN, 191 GOSTerr(GOST_F_GOST2001_DO_SIGN,
168 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 192 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
169 ECDSA_SIG_free(newsig);
170 newsig = NULL;
171 goto err; 193 goto err;
172 } 194 }
173 /* We do not want timing information to leak the length of k, 195 /*
174 * so we compute G*k using an equivalent scalar of fixed 196 * We do not want timing information to leak the length
175 * bit-length. */ 197 * of k, so we compute G*k using an equivalent scalar
176 if (!BN_add(k, k, order)) 198 * of fixed bit-length.
199 */
200 if (BN_add(k, k, order) == 0)
177 goto err; 201 goto err;
178 if (BN_num_bits(k) <= BN_num_bits(order)) 202 if (BN_num_bits(k) <= BN_num_bits(order))
179 if (!BN_add(k, k, order)) 203 if (BN_add(k, k, order) == 0)
180 goto err; 204 goto err;
181 205
182 if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { 206 if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) {
183 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 207 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
184 ECDSA_SIG_free(newsig);
185 newsig = NULL;
186 goto err; 208 goto err;
187 } 209 }
188 if (!EC_POINT_get_affine_coordinates_GFp 210 if (EC_POINT_get_affine_coordinates_GFp(group, C, X,
189 (group, C, X, NULL, ctx)) { 211 NULL, ctx) == 0) {
190 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 212 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
191 ECDSA_SIG_free(newsig);
192 newsig = NULL;
193 goto err; 213 goto err;
194 } 214 }
195 BN_nnmod(r, X, order, ctx); 215 if (BN_nnmod(r, X, order, ctx) == 0)
196 } 216 goto err;
197 while (BN_is_zero(r)); 217 } while (BN_is_zero(r));
198 /* s = (r*priv_key+k*e) mod order */ 218 /* s = (r*priv_key+k*e) mod order */
199 if (!tmp) 219 if (tmp == NULL) {
200 tmp = BN_CTX_get(ctx); 220 tmp = BN_CTX_get(ctx);
201 BN_mod_mul(tmp, priv_key, r, order, ctx); 221 if (tmp == NULL)
202 if (!tmp2) 222 goto err;
223 }
224 if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0)
225 goto err;
226 if (tmp2 == NULL) {
203 tmp2 = BN_CTX_get(ctx); 227 tmp2 = BN_CTX_get(ctx);
204 BN_mod_mul(tmp2, k, e, order, ctx); 228 if (tmp2 == NULL)
205 BN_mod_add(s, tmp, tmp2, order, ctx); 229 goto err;
206 } 230 }
207 while (BN_is_zero(s)); 231 if (BN_mod_mul(tmp2, k, e, order, ctx) == 0)
232 goto err;
233 if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0)
234 goto err;
235 } while (BN_is_zero(s));
236 ok = 1;
208 237
209err: 238err:
210 BN_CTX_end(ctx);
211 BN_CTX_free(ctx);
212 EC_POINT_free(C); 239 EC_POINT_free(C);
213 BN_free(md); 240 if (ctx != NULL) {
241 BN_CTX_end(ctx);
242 BN_CTX_free(ctx);
243 }
244 if (ok == 0) {
245 ECDSA_SIG_free(newsig);
246 newsig = NULL;
247 }
214 return newsig; 248 return newsig;
215} 249}
216 250
217int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec) 251int
252gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec)
218{ 253{
219 BN_CTX *ctx = BN_CTX_new(); 254 BN_CTX *ctx = BN_CTX_new();
220 const EC_GROUP *group = GOST_KEY_get0_group(ec); 255 const EC_GROUP *group = GOST_KEY_get0_group(ec);
@@ -225,6 +260,8 @@ int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec)
225 const EC_POINT *pub_key = NULL; 260 const EC_POINT *pub_key = NULL;
226 int ok = 0; 261 int ok = 0;
227 262
263 if (ctx == NULL)
264 goto err;
228 BN_CTX_start(ctx); 265 BN_CTX_start(ctx);
229 order = BN_CTX_get(ctx); 266 order = BN_CTX_get(ctx);
230 e = BN_CTX_get(ctx); 267 e = BN_CTX_get(ctx);
@@ -234,88 +271,129 @@ int gost2001_do_verify(BIGNUM * md, ECDSA_SIG * sig, GOST_KEY * ec)
234 X = BN_CTX_get(ctx); 271 X = BN_CTX_get(ctx);
235 R = BN_CTX_get(ctx); 272 R = BN_CTX_get(ctx);
236 v = BN_CTX_get(ctx); 273 v = BN_CTX_get(ctx);
274 if (v == NULL)
275 goto err;
237 276
238 EC_GROUP_get_order(group, order, ctx); 277 if (EC_GROUP_get_order(group, order, ctx) == 0)
278 goto err;
239 pub_key = GOST_KEY_get0_public_key(ec); 279 pub_key = GOST_KEY_get0_public_key(ec);
240 if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || 280 if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
241 (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { 281 BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) {
242 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 282 GOSTerr(GOST_F_GOST2001_DO_VERIFY,
283 GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
243 goto err; 284 goto err;
244
245 } 285 }
246 286
247 BN_mod(e, md, order, ctx); 287 if (BN_mod(e, md, order, ctx) == 0)
288 goto err;
248 if (BN_is_zero(e)) 289 if (BN_is_zero(e))
249 BN_one(e); 290 BN_one(e);
250 v = BN_mod_inverse(v, e, order, ctx); 291 v = BN_mod_inverse(v, e, order, ctx);
251 BN_mod_mul(z1, sig->s, v, order, ctx); 292 if (v == NULL)
252 BN_sub(tmp, order, sig->r); 293 goto err;
253 BN_mod_mul(z2, tmp, v, order, ctx); 294 if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0)
295 goto err;
296 if (BN_sub(tmp, order, sig->r) == 0)
297 goto err;
298 if (BN_mod_mul(z2, tmp, v, order, ctx) == 0)
299 goto err;
254 C = EC_POINT_new(group); 300 C = EC_POINT_new(group);
255 if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { 301 if (C == NULL)
302 goto err;
303 if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) {
256 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 304 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
257 goto err; 305 goto err;
258 } 306 }
259 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 307 if (EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx) == 0) {
260 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 308 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
261 goto err; 309 goto err;
262 } 310 }
263 BN_mod(R, X, order, ctx); 311 if (BN_mod(R, X, order, ctx) == 0)
312 goto err;
264 if (BN_cmp(R, sig->r) != 0) { 313 if (BN_cmp(R, sig->r) != 0) {
265 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 314 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH);
266 } else { 315 } else {
267 ok = 1; 316 ok = 1;
268 } 317 }
269 err: 318err:
270 EC_POINT_free(C); 319 EC_POINT_free(C);
271 BN_CTX_end(ctx); 320 if (ctx != NULL) {
272 BN_CTX_free(ctx); 321 BN_CTX_end(ctx);
322 BN_CTX_free(ctx);
323 }
273 return ok; 324 return ok;
274} 325}
275 326
276
277/* Implementation of CryptoPro VKO 34.10-2001 algorithm */ 327/* Implementation of CryptoPro VKO 34.10-2001 algorithm */
278void VKO_compute_key(BIGNUM * X, BIGNUM * Y, 328int
279 const GOST_KEY * pkey, GOST_KEY * priv_key, 329VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key,
280 const BIGNUM * ukm) 330 const BIGNUM *ukm)
281{ 331{
282 BIGNUM *p = NULL, *order = NULL; 332 BIGNUM *p = NULL, *order = NULL;
283 const BIGNUM *key = GOST_KEY_get0_private_key(priv_key); 333 const BIGNUM *key = GOST_KEY_get0_private_key(priv_key);
334 const EC_GROUP *group = GOST_KEY_get0_group(priv_key);
284 const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey); 335 const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey);
285 EC_POINT *pnt = EC_POINT_new(GOST_KEY_get0_group(priv_key)); 336 EC_POINT *pnt;
286 BN_CTX *ctx = BN_CTX_new(); 337 BN_CTX *ctx = NULL;
338 int ok = 0;
287 339
340 pnt = EC_POINT_new(group);
341 if (pnt == NULL)
342 goto err;
343 ctx = BN_CTX_new();
344 if (ctx == NULL)
345 goto err;
288 BN_CTX_start(ctx); 346 BN_CTX_start(ctx);
289 p = BN_CTX_get(ctx); 347 p = BN_CTX_get(ctx);
290 order = BN_CTX_get(ctx); 348 order = BN_CTX_get(ctx);
291 EC_GROUP_get_order(GOST_KEY_get0_group(priv_key), order, ctx); 349 if (order == NULL)
292 BN_mod_mul(p, key, ukm, order, ctx); 350 goto err;
293 EC_POINT_mul(GOST_KEY_get0_group(priv_key), pnt, NULL, pub_key, p, ctx); 351 if (EC_GROUP_get_order(group, order, ctx) == 0)
294 EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(priv_key), 352 goto err;
295 pnt, X, Y, ctx); 353 if (BN_mod_mul(p, key, ukm, order, ctx) == 0)
296 BN_CTX_end(ctx); 354 goto err;
297 BN_CTX_free(ctx); 355 if (EC_POINT_mul(group, pnt, NULL, pub_key, p, ctx) == 0)
356 goto err;
357 if (EC_POINT_get_affine_coordinates_GFp(group, pnt, X, Y, ctx) == 0)
358 goto err;
359 ok = 1;
360
361err:
362 if (ctx != NULL) {
363 BN_CTX_end(ctx);
364 BN_CTX_free(ctx);
365 }
298 EC_POINT_free(pnt); 366 EC_POINT_free(pnt);
367 return ok;
299} 368}
300 369
301int gost2001_keygen(GOST_KEY * ec) 370int
371gost2001_keygen(GOST_KEY *ec)
302{ 372{
303 BIGNUM *order = BN_new(), *d = BN_new(); 373 BIGNUM *order = BN_new(), *d = BN_new();
304 const EC_GROUP *group = GOST_KEY_get0_group(ec); 374 const EC_GROUP *group = GOST_KEY_get0_group(ec);
305 EC_GROUP_get_order(group, order, NULL); 375 int rc = 0;
376
377 if (order == NULL || d == NULL)
378 goto err;
379 if (EC_GROUP_get_order(group, order, NULL) == 0)
380 goto err;
306 381
307 do { 382 do {
308 if (!BN_rand_range(d, order)) { 383 if (BN_rand_range(d, order) == 0) {
309 GOSTerr(GOST_F_GOST2001_KEYGEN, 384 GOSTerr(GOST_F_GOST2001_KEYGEN,
310 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 385 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
311 BN_free(d); 386 goto err;
312 BN_free(order);
313 return 0;
314 } 387 }
315 } while (BN_is_zero(d)); 388 } while (BN_is_zero(d));
316 GOST_KEY_set_private_key(ec, d); 389
390 if (GOST_KEY_set_private_key(ec, d) == 0)
391 goto err;
392 rc = gost2001_compute_public(ec);
393
394err:
317 BN_free(d); 395 BN_free(d);
318 BN_free(order); 396 BN_free(order);
319 return gost2001_compute_public(ec); 397 return rc;
320} 398}
321#endif 399#endif