Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dsa.c Source File

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