source: asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/wolfcrypt/src/dsa.c@ 352

Last change on this file since 352 was 352, checked in by coas-nagasima, 6 years ago

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 12.9 KB
Line 
1/* dsa.c
2 *
3 * Copyright (C) 2006-2017 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23#ifdef HAVE_CONFIG_H
24 #include <config.h>
25#endif
26
27#include <wolfssl/wolfcrypt/settings.h>
28
29#ifndef NO_DSA
30
31#include <wolfssl/wolfcrypt/random.h>
32#include <wolfssl/wolfcrypt/integer.h>
33#include <wolfssl/wolfcrypt/error-crypt.h>
34#include <wolfssl/wolfcrypt/logging.h>
35#include <wolfssl/wolfcrypt/sha.h>
36#include <wolfssl/wolfcrypt/dsa.h>
37
38#ifdef NO_INLINE
39 #include <wolfssl/wolfcrypt/misc.h>
40#else
41 #define WOLFSSL_MISC_INCLUDED
42 #include <wolfcrypt/src/misc.c>
43#endif
44
45
46enum {
47 DSA_HALF_SIZE = 20, /* r and s size */
48 DSA_SIG_SIZE = 40 /* signature size */
49};
50
51
52
53int wc_InitDsaKey(DsaKey* key)
54{
55 if (key == NULL)
56 return BAD_FUNC_ARG;
57
58 key->type = -1; /* haven't decided yet */
59 key->heap = NULL;
60
61 return mp_init_multi(
62 /* public alloc parts */
63 &key->p,
64 &key->q,
65 &key->g,
66 &key->y,
67
68 /* private alloc parts */
69 &key->x,
70 NULL
71 );
72}
73
74
75int wc_InitDsaKey_h(DsaKey* key, void* h)
76{
77 int ret = wc_InitDsaKey(key);
78 if (ret == 0)
79 key->heap = h;
80
81 return ret;
82}
83
84
85void wc_FreeDsaKey(DsaKey* key)
86{
87 if (key == NULL)
88 return;
89
90 if (key->type == DSA_PRIVATE)
91 mp_forcezero(&key->x);
92
93 mp_clear(&key->x);
94 mp_clear(&key->y);
95 mp_clear(&key->g);
96 mp_clear(&key->q);
97 mp_clear(&key->p);
98}
99
100#ifdef WOLFSSL_KEY_GEN
101
102int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa)
103{
104 unsigned char *buf;
105 int qsize, err;
106
107 if (rng == NULL || dsa == NULL)
108 return BAD_FUNC_ARG;
109
110 qsize = mp_unsigned_bin_size(&dsa->q);
111 if (qsize == 0)
112 return BAD_FUNC_ARG;
113
114 /* allocate ram */
115 buf = (unsigned char *)XMALLOC(qsize, dsa->heap,
116 DYNAMIC_TYPE_TMP_BUFFER);
117 if (buf == NULL)
118 return MEMORY_E;
119
120 if (mp_init(&dsa->x) != MP_OKAY) {
121 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
122 return MP_INIT_E;
123 }
124
125 do {
126 /* make a random exponent mod q */
127 err = wc_RNG_GenerateBlock(rng, buf, qsize);
128 if (err != MP_OKAY) {
129 mp_clear(&dsa->x);
130 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
131 return err;
132 }
133
134 err = mp_read_unsigned_bin(&dsa->x, buf, qsize);
135 if (err != MP_OKAY) {
136 mp_clear(&dsa->x);
137 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
138 return err;
139 }
140 } while (mp_cmp_d(&dsa->x, 1) != MP_GT);
141
142 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
143
144 if (mp_init(&dsa->y) != MP_OKAY) {
145 mp_clear(&dsa->x);
146 return MP_INIT_E;
147 }
148
149 /* public key : y = g^x mod p */
150 err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y);
151 if (err != MP_OKAY) {
152 mp_clear(&dsa->x);
153 mp_clear(&dsa->y);
154 return err;
155 }
156
157 dsa->type = DSA_PRIVATE;
158
159 return MP_OKAY;
160}
161
162/* modulus_size in bits */
163int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa)
164{
165 mp_int tmp, tmp2;
166 int err, msize, qsize,
167 loop_check_prime = 0,
168 check_prime = MP_NO;
169 unsigned char *buf;
170
171 if (rng == NULL || dsa == NULL)
172 return BAD_FUNC_ARG;
173
174 /* set group size in bytes from modulus size
175 * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256)
176 */
177 switch (modulus_size) {
178 case 1024:
179 qsize = 20;
180 break;
181 case 2048:
182 case 3072:
183 qsize = 32;
184 break;
185 default:
186 return BAD_FUNC_ARG;
187 break;
188 }
189
190 /* modulus size in bytes */
191 msize = modulus_size / 8;
192
193 /* allocate ram */
194 buf = (unsigned char *)XMALLOC(msize - qsize,
195 dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
196 if (buf == NULL) {
197 return MEMORY_E;
198 }
199
200 /* make a random string that will be multplied against q */
201 err = wc_RNG_GenerateBlock(rng, buf, msize - qsize);
202 if (err != MP_OKAY) {
203 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
204 return err;
205 }
206
207 /* force magnitude */
208 buf[0] |= 0xC0;
209
210 /* force even */
211 buf[msize - qsize - 1] &= ~1;
212
213 if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) {
214 mp_clear(&dsa->q);
215 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
216 return MP_INIT_E;
217 }
218
219 err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize);
220 if (err != MP_OKAY) {
221 mp_clear(&dsa->q);
222 mp_clear(&dsa->p);
223 mp_clear(&tmp2);
224 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
225 return err;
226 }
227 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
228
229 /* make our prime q */
230 err = mp_rand_prime(&dsa->q, qsize, rng, NULL);
231 if (err != MP_OKAY) {
232 mp_clear(&dsa->q);
233 mp_clear(&dsa->p);
234 mp_clear(&tmp2);
235 return err;
236 }
237
238 /* p = random * q */
239 err = mp_mul(&dsa->q, &tmp2, &dsa->p);
240 if (err != MP_OKAY) {
241 mp_clear(&dsa->q);
242 mp_clear(&dsa->p);
243 mp_clear(&tmp2);
244 return err;
245 }
246
247 /* p = random * q + 1, so q is a prime divisor of p-1 */
248 err = mp_add_d(&dsa->p, 1, &dsa->p);
249 if (err != MP_OKAY) {
250 mp_clear(&dsa->q);
251 mp_clear(&dsa->p);
252 mp_clear(&tmp2);
253 return err;
254 }
255
256 if (mp_init(&tmp) != MP_OKAY) {
257 mp_clear(&dsa->q);
258 mp_clear(&dsa->p);
259 mp_clear(&tmp2);
260 return MP_INIT_E;
261 }
262
263 /* tmp = 2q */
264 err = mp_add(&dsa->q, &dsa->q, &tmp);
265 if (err != MP_OKAY) {
266 mp_clear(&dsa->q);
267 mp_clear(&dsa->p);
268 mp_clear(&tmp);
269 mp_clear(&tmp2);
270 return err;
271 }
272
273 /* loop until p is prime */
274 while (check_prime == MP_NO) {
275 err = mp_prime_is_prime(&dsa->p, 8, &check_prime);
276 if (err != MP_OKAY) {
277 mp_clear(&dsa->q);
278 mp_clear(&dsa->p);
279 mp_clear(&tmp);
280 mp_clear(&tmp2);
281 return err;
282 }
283
284 if (check_prime != MP_YES) {
285 /* p += 2q */
286 err = mp_add(&tmp, &dsa->p, &dsa->p);
287 if (err != MP_OKAY) {
288 mp_clear(&dsa->q);
289 mp_clear(&dsa->p);
290 mp_clear(&tmp);
291 mp_clear(&tmp2);
292 return err;
293 }
294
295 loop_check_prime++;
296 }
297 }
298
299 /* tmp2 += (2*loop_check_prime)
300 * to have p = (q * tmp2) + 1 prime
301 */
302 if (loop_check_prime) {
303 err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2);
304 if (err != MP_OKAY) {
305 mp_clear(&dsa->q);
306 mp_clear(&dsa->p);
307 mp_clear(&tmp);
308 mp_clear(&tmp2);
309 return err;
310 }
311 }
312
313 if (mp_init(&dsa->g) != MP_OKAY) {
314 mp_clear(&dsa->q);
315 mp_clear(&dsa->p);
316 mp_clear(&tmp);
317 mp_clear(&tmp2);
318 return MP_INIT_E;
319 }
320
321 /* find a value g for which g^tmp2 != 1 */
322 if (mp_set(&dsa->g, 1) != MP_OKAY) {
323 mp_clear(&dsa->q);
324 mp_clear(&dsa->p);
325 mp_clear(&tmp);
326 mp_clear(&tmp2);
327 return MP_INIT_E;
328 }
329
330 do {
331 err = mp_add_d(&dsa->g, 1, &dsa->g);
332 if (err != MP_OKAY) {
333 mp_clear(&dsa->q);
334 mp_clear(&dsa->p);
335 mp_clear(&dsa->g);
336 mp_clear(&tmp);
337 mp_clear(&tmp2);
338 return err;
339 }
340
341 err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp);
342 if (err != MP_OKAY) {
343 mp_clear(&dsa->q);
344 mp_clear(&dsa->p);
345 mp_clear(&dsa->g);
346 mp_clear(&tmp);
347 mp_clear(&tmp2);
348 return err;
349 }
350
351 } while (mp_cmp_d(&tmp, 1) == MP_EQ);
352
353 /* at this point tmp generates a group of order q mod p */
354 mp_exch(&tmp, &dsa->g);
355
356 mp_clear(&tmp);
357 mp_clear(&tmp2);
358
359 return MP_OKAY;
360}
361#endif /* WOLFSSL_KEY_GEN */
362
363
364int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng)
365{
366 mp_int k, kInv, r, s, H;
367 int ret, sz;
368 byte buffer[DSA_HALF_SIZE];
369 byte* tmp; /* initial output pointer */
370
371 if (digest == NULL || out == NULL || key == NULL || rng == NULL) {
372 return BAD_FUNC_ARG;
373 }
374
375 tmp = out;
376
377 sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q));
378
379 if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY)
380 return MP_INIT_E;
381
382 do {
383 /* generate k */
384 ret = wc_RNG_GenerateBlock(rng, buffer, sz);
385 if (ret != 0)
386 return ret;
387
388 buffer[0] |= 0x0C;
389
390 if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY)
391 ret = MP_READ_E;
392
393 /* k is a random numnber and it should be less than q
394 * if k greater than repeat
395 */
396 } while (mp_cmp(&k, &key->q) != MP_LT);
397
398 if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT)
399 ret = MP_CMP_E;
400
401 /* inverse k mod q */
402 if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
403 ret = MP_INVMOD_E;
404
405 /* generate r, r = (g exp k mod p) mod q */
406 if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY)
407 ret = MP_EXPTMOD_E;
408
409 if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
410 ret = MP_MOD_E;
411
412 /* generate H from sha digest */
413 if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
414 ret = MP_READ_E;
415
416 /* generate s, s = (kInv * (H + x*r)) % q */
417 if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
418 ret = MP_MUL_E;
419
420 if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
421 ret = MP_ADD_E;
422
423 if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
424 ret = MP_MULMOD_E;
425
426 /* detect zero r or s */
427 if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES))
428 ret = MP_ZERO_E;
429
430 /* write out */
431 if (ret == 0) {
432 int rSz = mp_unsigned_bin_size(&r);
433 int sSz = mp_unsigned_bin_size(&s);
434
435 while (rSz++ < DSA_HALF_SIZE) {
436 *out++ = 0x00; /* pad front with zeros */
437 }
438
439 if (mp_to_unsigned_bin(&r, out) != MP_OKAY)
440 ret = MP_TO_E;
441 else {
442 out = tmp + DSA_HALF_SIZE; /* advance to s in output */
443 while (sSz++ < DSA_HALF_SIZE) {
444 *out++ = 0x00; /* pad front with zeros */
445 }
446 ret = mp_to_unsigned_bin(&s, out);
447 }
448 }
449
450 mp_clear(&H);
451 mp_clear(&s);
452 mp_clear(&r);
453 mp_clear(&kInv);
454 mp_clear(&k);
455
456 return ret;
457}
458
459
460int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
461{
462 mp_int w, u1, u2, v, r, s;
463 int ret = 0;
464
465 if (digest == NULL || sig == NULL || key == NULL || answer == NULL) {
466 return BAD_FUNC_ARG;
467 }
468
469 if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
470 return MP_INIT_E;
471
472 /* set r and s from signature */
473 if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
474 mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
475 ret = MP_READ_E;
476
477 /* sanity checks */
478 if (ret == 0) {
479 if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES ||
480 mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) {
481 ret = MP_ZERO_E;
482 }
483 }
484
485 /* put H into u1 from sha digest */
486 if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY)
487 ret = MP_READ_E;
488
489 /* w = s invmod q */
490 if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
491 ret = MP_INVMOD_E;
492
493 /* u1 = (H * w) % q */
494 if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
495 ret = MP_MULMOD_E;
496
497 /* u2 = (r * w) % q */
498 if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
499 ret = MP_MULMOD_E;
500
501 /* verify v = ((g^u1 * y^u2) mod p) mod q */
502 if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
503 ret = MP_EXPTMOD_E;
504
505 if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
506 ret = MP_EXPTMOD_E;
507
508 if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
509 ret = MP_MULMOD_E;
510
511 if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
512 ret = MP_MULMOD_E;
513
514 /* do they match */
515 if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
516 *answer = 1;
517 else
518 *answer = 0;
519
520 mp_clear(&s);
521 mp_clear(&r);
522 mp_clear(&u1);
523 mp_clear(&u2);
524 mp_clear(&w);
525 mp_clear(&v);
526
527 return ret;
528}
529
530
531#endif /* NO_DSA */
532
Note: See TracBrowser for help on using the repository browser.