]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/dsa.c
6aded3e3a74f9b76df9062b077d66ee15e27717a
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / dsa.c
1 /* dsa.c
2  *
3  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL 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  * CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #ifndef NO_DSA
27
28 #include <cyassl/ctaocrypt/dsa.h>
29 #include <cyassl/ctaocrypt/sha.h>
30 #include <cyassl/ctaocrypt/random.h>
31 #include <cyassl/ctaocrypt/error.h>
32
33
34 enum {
35     DSA_HALF_SIZE = 20,   /* r and s size  */
36     DSA_SIG_SIZE  = 40    /* signature size */
37 };
38
39
40 #ifndef min
41
42     static INLINE word32 min(word32 a, word32 b)
43     {
44         return a > b ? b : a;
45     }
46
47 #endif /* min */
48
49
50 void InitDsaKey(DsaKey* key)
51 {
52     key->type = -1;  /* haven't decided yet */
53
54 /* TomsFastMath doesn't use memory allocation */
55 #ifndef USE_FAST_MATH
56     key->p.dp = 0;   /* public  alloc parts */
57     key->q.dp = 0;    
58     key->g.dp = 0;    
59     key->y.dp = 0;    
60
61     key->x.dp = 0;   /* private alloc parts */
62 #endif
63 }
64
65
66 void FreeDsaKey(DsaKey* key)
67 {
68     (void)key;
69 /* TomsFastMath doesn't use memory allocation */
70 #ifndef USE_FAST_MATH
71     if (key->type == DSA_PRIVATE)
72         mp_clear(&key->x);
73     mp_clear(&key->y);
74     mp_clear(&key->g);
75     mp_clear(&key->q);
76     mp_clear(&key->p);
77 #endif
78 }
79
80
81 int DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng)
82 {
83     mp_int k, kInv, r, s, H;
84     int    ret = 0, sz;
85     byte   buffer[DSA_HALF_SIZE];
86
87     if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY)
88         return MP_INIT_E;
89
90     sz = min(sizeof(buffer), mp_unsigned_bin_size(&key->q)); 
91
92     /* generate k */
93     RNG_GenerateBlock(rng, buffer, sz);
94     buffer[0] |= 0x0C;
95
96     if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY)
97         ret = MP_READ_E;
98
99     if (mp_cmp_d(&k, 1) != MP_GT)
100         ret = MP_CMP_E;
101
102     /* inverse k mod q */
103     if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY)
104         ret = MP_INVMOD_E;
105
106     /* generate r, r = (g exp k mod p) mod q */
107     if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY)
108         ret = MP_EXPTMOD_E;
109
110     if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY)
111         ret = MP_MOD_E;
112
113     /* generate H from sha digest */
114     if (ret == 0 && mp_read_unsigned_bin(&H, digest,SHA_DIGEST_SIZE) != MP_OKAY)
115         ret = MP_READ_E;
116
117     /* generate s, s = (kInv * (H + x*r)) % q */
118     if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY)
119         ret = MP_MUL_E;
120
121     if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY)
122         ret = MP_ADD_E;
123
124     if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY)
125         ret = MP_MULMOD_E;
126
127     /* write out */
128     if (ret == 0)  {
129         int rSz = mp_unsigned_bin_size(&r);
130         int sSz = mp_unsigned_bin_size(&s);
131
132         if (rSz == DSA_HALF_SIZE - 1) {
133             out[0] = 0;
134             out++;
135         }
136
137         if (mp_to_unsigned_bin(&r, out) != MP_OKAY)
138             ret = MP_TO_E;
139         else {
140             if (sSz == DSA_HALF_SIZE - 1) {
141                 out[rSz] = 0;
142                 out++;
143             }    
144             ret = mp_to_unsigned_bin(&s, out + rSz);
145         }
146     }
147
148     mp_clear(&H);
149     mp_clear(&s);
150     mp_clear(&r);
151     mp_clear(&kInv);
152     mp_clear(&k);
153
154     return ret;
155 }
156
157
158 int DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
159 {
160     mp_int w, u1, u2, v, r, s;
161     int    ret = 0;
162
163     if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
164         return MP_INIT_E;
165
166     /* set r and s from signature */
167     if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
168         mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
169         ret = MP_READ_E;
170
171     /* sanity checks */
172
173
174     /* put H into u1 from sha digest */
175     if (ret == 0 && mp_read_unsigned_bin(&u1,digest,SHA_DIGEST_SIZE) != MP_OKAY)
176         ret = MP_READ_E;
177
178     /* w = s invmod q */
179     if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
180         ret = MP_INVMOD_E;
181
182     /* u1 = (H * w) % q */
183     if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
184         ret = MP_MULMOD_E;
185
186     /* u2 = (r * w) % q */
187     if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
188         ret = MP_MULMOD_E;
189
190     /* verify v = ((g^u1 * y^u2) mod p) mod q */
191     if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
192         ret = MP_EXPTMOD_E;
193
194     if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
195         ret = MP_EXPTMOD_E;
196
197     if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
198         ret = MP_MULMOD_E;
199
200     if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
201         ret = MP_MULMOD_E;
202
203     /* do they match */
204     if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
205         *answer = 1;
206     else
207         *answer = 0;
208
209     mp_clear(&s);
210     mp_clear(&r);
211     mp_clear(&u1);
212     mp_clear(&u2);
213     mp_clear(&w);
214     mp_clear(&v);
215
216     return ret;
217 }
218
219
220 #endif /* NO_DSA */
221