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