Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dsa.c
00001 /* dsa.c 00002 * 00003 * Copyright (C) 2006-2017 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfcrypt/settings.h> 00028 00029 #ifndef NO_DSA 00030 00031 #include <wolfcrypt/random.h> 00032 #include <wolfcrypt/integer.h> 00033 #include <wolfcrypt/error-crypt.h> 00034 #include <wolfcrypt/logging.h> 00035 #include <wolfcrypt/sha.h> 00036 #include <wolfcrypt/dsa.h> 00037 00038 #ifdef NO_INLINE 00039 #include <wolfcrypt/misc.h> 00040 #else 00041 #define WOLFSSL_MISC_INCLUDED 00042 #include <wolfcrypt/src/misc.c> 00043 #endif 00044 00045 00046 enum { 00047 DSA_HALF_SIZE = 20, /* r and s size */ 00048 DSA_SIG_SIZE = 40 /* signature size */ 00049 }; 00050 00051 00052 00053 int wc_InitDsaKey(DsaKey* key) 00054 { 00055 if (key == NULL) 00056 return BAD_FUNC_ARG; 00057 00058 key->type = -1; /* haven't decided yet */ 00059 key->heap = NULL; 00060 00061 return mp_init_multi( 00062 /* public alloc parts */ 00063 &key->p, 00064 &key->q, 00065 &key->g, 00066 &key->y, 00067 00068 /* private alloc parts */ 00069 &key->x, 00070 NULL 00071 ); 00072 } 00073 00074 00075 int wc_InitDsaKey_h(DsaKey* key, void* h) 00076 { 00077 int ret = wc_InitDsaKey(key); 00078 if (ret == 0) 00079 key->heap = h; 00080 00081 return ret; 00082 } 00083 00084 00085 void wc_FreeDsaKey(DsaKey* key) 00086 { 00087 if (key == NULL) 00088 return; 00089 00090 if (key->type == DSA_PRIVATE) 00091 mp_forcezero(&key->x); 00092 00093 mp_clear(&key->x); 00094 mp_clear(&key->y); 00095 mp_clear(&key->g); 00096 mp_clear(&key->q); 00097 mp_clear(&key->p); 00098 } 00099 00100 00101 /* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2. 00102 * modLen - represents L, the size of p (prime modulus) in bits 00103 * divLen - represents N, the size of q (prime divisor) in bits 00104 * return 0 on success, -1 on error */ 00105 static int CheckDsaLN(int modLen, int divLen) 00106 { 00107 int ret = -1; 00108 00109 switch (modLen) { 00110 case 1024: 00111 if (divLen == 160) 00112 ret = 0; 00113 break; 00114 case 2048: 00115 if (divLen == 224 || divLen == 256) 00116 ret = 0; 00117 break; 00118 case 3072: 00119 if (divLen == 256) 00120 ret = 0; 00121 break; 00122 default: 00123 break; 00124 } 00125 00126 return ret; 00127 } 00128 00129 00130 #ifdef WOLFSSL_KEY_GEN 00131 00132 /* Create DSA key pair (&dsa->x, &dsa->y) 00133 * 00134 * Based on NIST FIPS 186-4, 00135 * "B.1.1 Key Pair Generation Using Extra Random Bits" 00136 * 00137 * rng - pointer to initialized WC_RNG structure 00138 * dsa - pointer to initialized DsaKey structure, will hold generated key 00139 * 00140 * return 0 on success, negative on error */ 00141 int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) 00142 { 00143 byte* cBuf; 00144 int qSz, pSz, cSz, err; 00145 mp_int tmpQ; 00146 00147 if (rng == NULL || dsa == NULL) 00148 return BAD_FUNC_ARG; 00149 00150 qSz = mp_unsigned_bin_size(&dsa->q); 00151 pSz = mp_unsigned_bin_size(&dsa->p); 00152 00153 /* verify (L,N) pair bit lengths */ 00154 if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) 00155 return BAD_FUNC_ARG; 00156 00157 /* generate extra 64 bits so that bias from mod function is negligible */ 00158 cSz = qSz + (64 / WOLFSSL_BIT_SIZE); 00159 cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00160 if (cBuf == NULL) { 00161 return MEMORY_E; 00162 } 00163 00164 if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL)) 00165 != MP_OKAY) { 00166 XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00167 return err; 00168 } 00169 00170 do { 00171 /* generate N+64 bits (c) from RBG into &dsa->x, making sure positive. 00172 * Hash_DRBG uses SHA-256 which matches maximum 00173 * requested_security_strength of (L,N) */ 00174 err = wc_RNG_GenerateBlock(rng, cBuf, cSz); 00175 if (err != MP_OKAY) { 00176 mp_clear(&dsa->x); 00177 mp_clear(&dsa->y); 00178 mp_clear(&tmpQ); 00179 XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00180 return err; 00181 } 00182 00183 err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz); 00184 if (err != MP_OKAY) { 00185 mp_clear(&dsa->x); 00186 mp_clear(&dsa->y); 00187 mp_clear(&tmpQ); 00188 XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00189 return err; 00190 } 00191 } while (mp_cmp_d(&dsa->x, 1) != MP_GT); 00192 00193 XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00194 00195 /* tmpQ = q - 1 */ 00196 if (err == MP_OKAY) 00197 err = mp_copy(&dsa->q, &tmpQ); 00198 00199 if (err == MP_OKAY) 00200 err = mp_sub_d(&tmpQ, 1, &tmpQ); 00201 00202 /* x = c mod (q-1), &dsa->x holds c */ 00203 if (err == MP_OKAY) 00204 err = mp_mod(&dsa->x, &tmpQ, &dsa->x); 00205 00206 /* x = c mod (q-1) + 1 */ 00207 if (err == MP_OKAY) 00208 err = mp_add_d(&dsa->x, 1, &dsa->x); 00209 00210 /* public key : y = g^x mod p */ 00211 if (err == MP_OKAY) 00212 err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y); 00213 00214 if (err == MP_OKAY) 00215 dsa->type = DSA_PRIVATE; 00216 00217 if (err != MP_OKAY) { 00218 mp_clear(&dsa->x); 00219 mp_clear(&dsa->y); 00220 } 00221 mp_clear(&tmpQ); 00222 00223 return err; 00224 } 00225 00226 00227 /* modulus_size in bits */ 00228 int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) 00229 { 00230 mp_int tmp, tmp2; 00231 int err, msize, qsize, 00232 loop_check_prime = 0, 00233 check_prime = MP_NO; 00234 unsigned char *buf; 00235 00236 if (rng == NULL || dsa == NULL) 00237 return BAD_FUNC_ARG; 00238 00239 /* set group size in bytes from modulus size 00240 * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256) 00241 */ 00242 switch (modulus_size) { 00243 case 1024: 00244 qsize = 20; 00245 break; 00246 case 2048: 00247 case 3072: 00248 qsize = 32; 00249 break; 00250 default: 00251 return BAD_FUNC_ARG; 00252 break; 00253 } 00254 00255 /* modulus size in bytes */ 00256 msize = modulus_size / WOLFSSL_BIT_SIZE; 00257 00258 /* allocate ram */ 00259 buf = (unsigned char *)XMALLOC(msize - qsize, 00260 dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00261 if (buf == NULL) { 00262 return MEMORY_E; 00263 } 00264 00265 /* make a random string that will be multplied against q */ 00266 err = wc_RNG_GenerateBlock(rng, buf, msize - qsize); 00267 if (err != MP_OKAY) { 00268 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00269 return err; 00270 } 00271 00272 /* force magnitude */ 00273 buf[0] |= 0xC0; 00274 00275 /* force even */ 00276 buf[msize - qsize - 1] &= ~1; 00277 00278 if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) { 00279 mp_clear(&dsa->q); 00280 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00281 return MP_INIT_E; 00282 } 00283 00284 err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize); 00285 if (err != MP_OKAY) { 00286 mp_clear(&dsa->q); 00287 mp_clear(&dsa->p); 00288 mp_clear(&tmp2); 00289 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00290 return err; 00291 } 00292 XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); 00293 00294 /* make our prime q */ 00295 err = mp_rand_prime(&dsa->q, qsize, rng, NULL); 00296 if (err != MP_OKAY) { 00297 mp_clear(&dsa->q); 00298 mp_clear(&dsa->p); 00299 mp_clear(&tmp2); 00300 return err; 00301 } 00302 00303 /* p = random * q */ 00304 err = mp_mul(&dsa->q, &tmp2, &dsa->p); 00305 if (err != MP_OKAY) { 00306 mp_clear(&dsa->q); 00307 mp_clear(&dsa->p); 00308 mp_clear(&tmp2); 00309 return err; 00310 } 00311 00312 /* p = random * q + 1, so q is a prime divisor of p-1 */ 00313 err = mp_add_d(&dsa->p, 1, &dsa->p); 00314 if (err != MP_OKAY) { 00315 mp_clear(&dsa->q); 00316 mp_clear(&dsa->p); 00317 mp_clear(&tmp2); 00318 return err; 00319 } 00320 00321 if (mp_init(&tmp) != MP_OKAY) { 00322 mp_clear(&dsa->q); 00323 mp_clear(&dsa->p); 00324 mp_clear(&tmp2); 00325 return MP_INIT_E; 00326 } 00327 00328 /* tmp = 2q */ 00329 err = mp_add(&dsa->q, &dsa->q, &tmp); 00330 if (err != MP_OKAY) { 00331 mp_clear(&dsa->q); 00332 mp_clear(&dsa->p); 00333 mp_clear(&tmp); 00334 mp_clear(&tmp2); 00335 return err; 00336 } 00337 00338 /* loop until p is prime */ 00339 while (check_prime == MP_NO) { 00340 err = mp_prime_is_prime(&dsa->p, 8, &check_prime); 00341 if (err != MP_OKAY) { 00342 mp_clear(&dsa->q); 00343 mp_clear(&dsa->p); 00344 mp_clear(&tmp); 00345 mp_clear(&tmp2); 00346 return err; 00347 } 00348 00349 if (check_prime != MP_YES) { 00350 /* p += 2q */ 00351 err = mp_add(&tmp, &dsa->p, &dsa->p); 00352 if (err != MP_OKAY) { 00353 mp_clear(&dsa->q); 00354 mp_clear(&dsa->p); 00355 mp_clear(&tmp); 00356 mp_clear(&tmp2); 00357 return err; 00358 } 00359 00360 loop_check_prime++; 00361 } 00362 } 00363 00364 /* tmp2 += (2*loop_check_prime) 00365 * to have p = (q * tmp2) + 1 prime 00366 */ 00367 if (loop_check_prime) { 00368 err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2); 00369 if (err != MP_OKAY) { 00370 mp_clear(&dsa->q); 00371 mp_clear(&dsa->p); 00372 mp_clear(&tmp); 00373 mp_clear(&tmp2); 00374 return err; 00375 } 00376 } 00377 00378 if (mp_init(&dsa->g) != MP_OKAY) { 00379 mp_clear(&dsa->q); 00380 mp_clear(&dsa->p); 00381 mp_clear(&tmp); 00382 mp_clear(&tmp2); 00383 return MP_INIT_E; 00384 } 00385 00386 /* find a value g for which g^tmp2 != 1 */ 00387 if (mp_set(&dsa->g, 1) != MP_OKAY) { 00388 mp_clear(&dsa->q); 00389 mp_clear(&dsa->p); 00390 mp_clear(&tmp); 00391 mp_clear(&tmp2); 00392 return MP_INIT_E; 00393 } 00394 00395 do { 00396 err = mp_add_d(&dsa->g, 1, &dsa->g); 00397 if (err != MP_OKAY) { 00398 mp_clear(&dsa->q); 00399 mp_clear(&dsa->p); 00400 mp_clear(&dsa->g); 00401 mp_clear(&tmp); 00402 mp_clear(&tmp2); 00403 return err; 00404 } 00405 00406 err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp); 00407 if (err != MP_OKAY) { 00408 mp_clear(&dsa->q); 00409 mp_clear(&dsa->p); 00410 mp_clear(&dsa->g); 00411 mp_clear(&tmp); 00412 mp_clear(&tmp2); 00413 return err; 00414 } 00415 00416 } while (mp_cmp_d(&tmp, 1) == MP_EQ); 00417 00418 /* at this point tmp generates a group of order q mod p */ 00419 mp_exch(&tmp, &dsa->g); 00420 00421 mp_clear(&tmp); 00422 mp_clear(&tmp2); 00423 00424 return MP_OKAY; 00425 } 00426 #endif /* WOLFSSL_KEY_GEN */ 00427 00428 00429 /* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), 00430 * input parameters (p,q,g) should be represented as ASCII hex values. 00431 * 00432 * dsa - pointer to initialized DsaKey structure 00433 * p - DSA (p) parameter, ASCII hex string 00434 * pSz - length of p 00435 * q - DSA (q) parameter, ASCII hex string 00436 * qSz - length of q 00437 * g - DSA (g) parameter, ASCII hex string 00438 * gSz - length of g 00439 * 00440 * returns 0 on success, negative upon failure 00441 */ 00442 int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, 00443 const char* g) 00444 { 00445 int err; 00446 word32 pSz, qSz; 00447 00448 if (dsa == NULL || p == NULL || q == NULL || g == NULL) 00449 return BAD_FUNC_ARG; 00450 00451 /* read p */ 00452 err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX); 00453 00454 /* read q */ 00455 if (err == MP_OKAY) 00456 err = mp_read_radix(&dsa->q, q, MP_RADIX_HEX); 00457 00458 /* read g */ 00459 if (err == MP_OKAY) 00460 err = mp_read_radix(&dsa->g, g, MP_RADIX_HEX); 00461 00462 /* verify (L,N) pair bit lengths */ 00463 pSz = mp_unsigned_bin_size(&dsa->p); 00464 qSz = mp_unsigned_bin_size(&dsa->q); 00465 00466 if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) { 00467 WOLFSSL_MSG("Invalid DSA p or q parameter size"); 00468 err = BAD_FUNC_ARG; 00469 } 00470 00471 if (err != MP_OKAY) { 00472 mp_clear(&dsa->p); 00473 mp_clear(&dsa->q); 00474 mp_clear(&dsa->g); 00475 } 00476 00477 return err; 00478 } 00479 00480 00481 /* Export raw DSA parameters from DsaKey structure 00482 * 00483 * dsa - pointer to initialized DsaKey structure 00484 * p - output location for DSA (p) parameter 00485 * pSz - [IN/OUT] size of output buffer for p, size of p 00486 * q - output location for DSA (q) parameter 00487 * qSz - [IN/OUT] size of output buffer for q, size of q 00488 * g - output location for DSA (g) parameter 00489 * gSz - [IN/OUT] size of output buffer for g, size of g 00490 * 00491 * If p, q, and g pointers are all passed in as NULL, the function 00492 * will set pSz, qSz, and gSz to the required output buffer sizes for p, 00493 * q, and g. In this case, the function will return LENGTH_ONLY_E. 00494 * 00495 * returns 0 on success, negative upon failure 00496 */ 00497 int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, 00498 byte* q, word32* qSz, byte* g, word32* gSz) 00499 { 00500 int err; 00501 word32 pLen, qLen, gLen; 00502 00503 if (dsa == NULL || pSz == NULL || qSz == NULL || gSz == NULL) 00504 return BAD_FUNC_ARG; 00505 00506 /* get required output buffer sizes */ 00507 pLen = mp_unsigned_bin_size(&dsa->p); 00508 qLen = mp_unsigned_bin_size(&dsa->q); 00509 gLen = mp_unsigned_bin_size(&dsa->g); 00510 00511 /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ 00512 if (p == NULL && q == NULL && g == NULL) { 00513 *pSz = pLen; 00514 *qSz = qLen; 00515 *gSz = gLen; 00516 return LENGTH_ONLY_E; 00517 } 00518 00519 if (p == NULL || q == NULL || g == NULL) 00520 return BAD_FUNC_ARG; 00521 00522 /* export p */ 00523 if (*pSz < pLen) { 00524 WOLFSSL_MSG("Output buffer for DSA p parameter too small, " 00525 "required size placed into pSz"); 00526 *pSz = pLen; 00527 return BUFFER_E; 00528 } 00529 *pSz = pLen; 00530 err = mp_to_unsigned_bin(&dsa->p, p); 00531 00532 /* export q */ 00533 if (err == MP_OKAY) { 00534 if (*qSz < qLen) { 00535 WOLFSSL_MSG("Output buffer for DSA q parameter too small, " 00536 "required size placed into qSz"); 00537 *qSz = qLen; 00538 return BUFFER_E; 00539 } 00540 *qSz = qLen; 00541 err = mp_to_unsigned_bin(&dsa->q, q); 00542 } 00543 00544 /* export g */ 00545 if (err == MP_OKAY) { 00546 if (*gSz < gLen) { 00547 WOLFSSL_MSG("Output buffer for DSA g parameter too small, " 00548 "required size placed into gSz"); 00549 *gSz = gLen; 00550 return BUFFER_E; 00551 } 00552 *gSz = gLen; 00553 err = mp_to_unsigned_bin(&dsa->g, g); 00554 } 00555 00556 return err; 00557 } 00558 00559 00560 /* Export raw DSA key (x, y) from DsaKey structure 00561 * 00562 * dsa - pointer to initialized DsaKey structure 00563 * x - output location for private key 00564 * xSz - [IN/OUT] size of output buffer for x, size of x 00565 * y - output location for public key 00566 * ySz - [IN/OUT] size of output buffer for y, size of y 00567 * 00568 * If x and y pointers are all passed in as NULL, the function 00569 * will set xSz and ySz to the required output buffer sizes for x 00570 * and y. In this case, the function will return LENGTH_ONLY_E. 00571 * 00572 * returns 0 on success, negative upon failure 00573 */ 00574 int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz) 00575 { 00576 int err; 00577 word32 xLen, yLen; 00578 00579 if (dsa == NULL || xSz == NULL || ySz == NULL) 00580 return BAD_FUNC_ARG; 00581 00582 /* get required output buffer sizes */ 00583 xLen = mp_unsigned_bin_size(&dsa->x); 00584 yLen = mp_unsigned_bin_size(&dsa->y); 00585 00586 /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ 00587 if (x == NULL && y == NULL) { 00588 *xSz = xLen; 00589 *ySz = yLen; 00590 return LENGTH_ONLY_E; 00591 } 00592 00593 if (x == NULL || y == NULL) 00594 return BAD_FUNC_ARG; 00595 00596 /* export x */ 00597 if (*xSz < xLen) { 00598 WOLFSSL_MSG("Output buffer for DSA private key (x) too small, " 00599 "required size placed into xSz"); 00600 *xSz = xLen; 00601 return BUFFER_E; 00602 } 00603 *xSz = xLen; 00604 err = mp_to_unsigned_bin(&dsa->x, x); 00605 00606 /* export y */ 00607 if (err == MP_OKAY) { 00608 if (*ySz < yLen) { 00609 WOLFSSL_MSG("Output buffer to DSA public key (y) too small, " 00610 "required size placed into ySz"); 00611 *ySz = yLen; 00612 return BUFFER_E; 00613 } 00614 *ySz = yLen; 00615 err = mp_to_unsigned_bin(&dsa->y, y); 00616 } 00617 00618 return err; 00619 } 00620 00621 00622 int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) 00623 { 00624 mp_int k, kInv, r, s, H; 00625 int ret, sz; 00626 byte buffer[DSA_HALF_SIZE]; 00627 byte* tmp; /* initial output pointer */ 00628 00629 if (digest == NULL || out == NULL || key == NULL || rng == NULL) { 00630 return BAD_FUNC_ARG; 00631 } 00632 00633 tmp = out; 00634 00635 sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); 00636 00637 if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) 00638 return MP_INIT_E; 00639 00640 do { 00641 /* generate k */ 00642 ret = wc_RNG_GenerateBlock(rng, buffer, sz); 00643 if (ret != 0) 00644 return ret; 00645 00646 buffer[0] |= 0x0C; 00647 00648 if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) 00649 ret = MP_READ_E; 00650 00651 /* k is a random numnber and it should be less than q 00652 * if k greater than repeat 00653 */ 00654 } while (mp_cmp(&k, &key->q) != MP_LT); 00655 00656 if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) 00657 ret = MP_CMP_E; 00658 00659 /* inverse k mod q */ 00660 if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) 00661 ret = MP_INVMOD_E; 00662 00663 /* generate r, r = (g exp k mod p) mod q */ 00664 if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY) 00665 ret = MP_EXPTMOD_E; 00666 00667 if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) 00668 ret = MP_MOD_E; 00669 00670 /* generate H from sha digest */ 00671 if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) 00672 ret = MP_READ_E; 00673 00674 /* generate s, s = (kInv * (H + x*r)) % q */ 00675 if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY) 00676 ret = MP_MUL_E; 00677 00678 if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY) 00679 ret = MP_ADD_E; 00680 00681 if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) 00682 ret = MP_MULMOD_E; 00683 00684 /* detect zero r or s */ 00685 if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES)) 00686 ret = MP_ZERO_E; 00687 00688 /* write out */ 00689 if (ret == 0) { 00690 int rSz = mp_unsigned_bin_size(&r); 00691 int sSz = mp_unsigned_bin_size(&s); 00692 00693 while (rSz++ < DSA_HALF_SIZE) { 00694 *out++ = 0x00; /* pad front with zeros */ 00695 } 00696 00697 if (mp_to_unsigned_bin(&r, out) != MP_OKAY) 00698 ret = MP_TO_E; 00699 else { 00700 out = tmp + DSA_HALF_SIZE; /* advance to s in output */ 00701 while (sSz++ < DSA_HALF_SIZE) { 00702 *out++ = 0x00; /* pad front with zeros */ 00703 } 00704 ret = mp_to_unsigned_bin(&s, out); 00705 } 00706 } 00707 00708 mp_clear(&H); 00709 mp_clear(&s); 00710 mp_clear(&r); 00711 mp_clear(&kInv); 00712 mp_clear(&k); 00713 00714 return ret; 00715 } 00716 00717 00718 int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) 00719 { 00720 mp_int w, u1, u2, v, r, s; 00721 int ret = 0; 00722 00723 if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { 00724 return BAD_FUNC_ARG; 00725 } 00726 00727 if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY) 00728 return MP_INIT_E; 00729 00730 /* set r and s from signature */ 00731 if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY || 00732 mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY) 00733 ret = MP_READ_E; 00734 00735 /* sanity checks */ 00736 if (ret == 0) { 00737 if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES || 00738 mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) { 00739 ret = MP_ZERO_E; 00740 } 00741 } 00742 00743 /* put H into u1 from sha digest */ 00744 if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) 00745 ret = MP_READ_E; 00746 00747 /* w = s invmod q */ 00748 if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY) 00749 ret = MP_INVMOD_E; 00750 00751 /* u1 = (H * w) % q */ 00752 if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY) 00753 ret = MP_MULMOD_E; 00754 00755 /* u2 = (r * w) % q */ 00756 if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY) 00757 ret = MP_MULMOD_E; 00758 00759 /* verify v = ((g^u1 * y^u2) mod p) mod q */ 00760 if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY) 00761 ret = MP_EXPTMOD_E; 00762 00763 if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY) 00764 ret = MP_EXPTMOD_E; 00765 00766 if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY) 00767 ret = MP_MULMOD_E; 00768 00769 if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY) 00770 ret = MP_MULMOD_E; 00771 00772 /* do they match */ 00773 if (ret == 0 && mp_cmp(&r, &v) == MP_EQ) 00774 *answer = 1; 00775 else 00776 *answer = 0; 00777 00778 mp_clear(&s); 00779 mp_clear(&r); 00780 mp_clear(&u1); 00781 mp_clear(&u2); 00782 mp_clear(&w); 00783 mp_clear(&v); 00784 00785 return ret; 00786 } 00787 00788 00789 #endif /* NO_DSA */ 00790 00791
Generated on Tue Jul 12 2022 16:58:05 by
1.7.2