Home | History | Annotate | Download | only in dsa
      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  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 #include "tomcrypt.h"
     12 
     13 /**
     14    @file dsa_sign_hash.c
     15    DSA implementation, sign a hash, Tom St Denis
     16 */
     17 
     18 #ifdef MDSA
     19 
     20 /**
     21   Sign a hash with DSA
     22   @param in       The hash to sign
     23   @param inlen    The length of the hash to sign
     24   @param r        The "r" integer of the signature (caller must initialize with mp_init() first)
     25   @param s        The "s" integer of the signature (caller must initialize with mp_init() first)
     26   @param prng     An active PRNG state
     27   @param wprng    The index of the PRNG desired
     28   @param key      A private DSA key
     29   @return CRYPT_OK if successful
     30 */
     31 int dsa_sign_hash_raw(const unsigned char *in,  unsigned long inlen,
     32                                    void   *r,   void *s,
     33                                prng_state *prng, int wprng, dsa_key *key)
     34 {
     35    void         *k, *kinv, *tmp;
     36    unsigned char *buf;
     37    int            err;
     38 
     39    LTC_ARGCHK(in  != NULL);
     40    LTC_ARGCHK(r   != NULL);
     41    LTC_ARGCHK(s   != NULL);
     42    LTC_ARGCHK(key != NULL);
     43 
     44    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
     45       return err;
     46    }
     47    if (key->type != PK_PRIVATE) {
     48       return CRYPT_PK_NOT_PRIVATE;
     49    }
     50 
     51    /* check group order size  */
     52    if (key->qord >= MDSA_MAX_GROUP) {
     53       return CRYPT_INVALID_ARG;
     54    }
     55 
     56    buf = XMALLOC(MDSA_MAX_GROUP);
     57    if (buf == NULL) {
     58       return CRYPT_MEM;
     59    }
     60 
     61    /* Init our temps */
     62    if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK)                       { goto ERRBUF; }
     63 
     64 retry:
     65 
     66    do {
     67       /* gen random k */
     68       if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
     69          err = CRYPT_ERROR_READPRNG;
     70          goto error;
     71       }
     72 
     73       /* read k */
     74       if ((err = mp_read_unsigned_bin(k, buf, key->qord)) != CRYPT_OK)                 { goto error; }
     75 
     76       /* k > 1 ? */
     77       if (mp_cmp_d(k, 1) != LTC_MP_GT)                                                 { goto retry; }
     78 
     79       /* test gcd */
     80       if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK)                                  { goto error; }
     81    } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);
     82 
     83    /* now find 1/k mod q */
     84    if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK)                                 { goto error; }
     85 
     86    /* now find r = g^k mod p mod q */
     87    if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK)                           { goto error; }
     88    if ((err = mp_mod(r, key->q, r)) != CRYPT_OK)                                       { goto error; }
     89 
     90    if (mp_iszero(r) == LTC_MP_YES)                                                     { goto retry; }
     91 
     92    /* now find s = (in + xr)/k mod q */
     93    if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK)      { goto error; }
     94    if ((err = mp_mul(key->x, r, s)) != CRYPT_OK)                                       { goto error; }
     95    if ((err = mp_add(s, tmp, s)) != CRYPT_OK)                                          { goto error; }
     96    if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK)                              { goto error; }
     97 
     98    if (mp_iszero(s) == LTC_MP_YES)                                                     { goto retry; }
     99 
    100    err = CRYPT_OK;
    101 error:
    102    mp_clear_multi(k, kinv, tmp, NULL);
    103 ERRBUF:
    104 #ifdef LTC_CLEAN_STACK
    105    zeromem(buf, MDSA_MAX_GROUP);
    106 #endif
    107    XFREE(buf);
    108    return err;
    109 }
    110 
    111 /**
    112   Sign a hash with DSA
    113   @param in       The hash to sign
    114   @param inlen    The length of the hash to sign
    115   @param out      [out] Where to store the signature
    116   @param outlen   [in/out] The max size and resulting size of the signature
    117   @param prng     An active PRNG state
    118   @param wprng    The index of the PRNG desired
    119   @param key      A private DSA key
    120   @return CRYPT_OK if successful
    121 */
    122 int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
    123                         unsigned char *out, unsigned long *outlen,
    124                         prng_state *prng, int wprng, dsa_key *key)
    125 {
    126    void         *r, *s;
    127    int           err;
    128 
    129    LTC_ARGCHK(in      != NULL);
    130    LTC_ARGCHK(out     != NULL);
    131    LTC_ARGCHK(outlen  != NULL);
    132    LTC_ARGCHK(key     != NULL);
    133 
    134    if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) {
    135       return CRYPT_MEM;
    136    }
    137 
    138    if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) {
    139       goto error;
    140    }
    141 
    142    err = der_encode_sequence_multi(out, outlen,
    143                              LTC_ASN1_INTEGER, 1UL, r,
    144                              LTC_ASN1_INTEGER, 1UL, s,
    145                              LTC_ASN1_EOL,     0UL, NULL);
    146 
    147 error:
    148    mp_clear_multi(r, s, NULL);
    149    return err;
    150 }
    151 
    152 #endif
    153 
    154 /* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */
    155 /* $Revision: 1.12 $ */
    156 /* $Date: 2006/12/04 22:27:56 $ */
    157