• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 */
dsa_sign_hash_raw(const unsigned char * in,unsigned long inlen,void * r,void * s,prng_state * prng,int wprng,dsa_key * key)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 */
dsa_sign_hash(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen,prng_state * prng,int wprng,dsa_key * key)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