1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  *
57  * The DSS routines are based on patches supplied by
58  * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
59 
60 #include <openssl/dsa.h>
61 
62 #include <string.h>
63 
64 #include <openssl/bn.h>
65 #include <openssl/crypto.h>
66 #include <openssl/err.h>
67 
68 #include "internal.h"
69 
70 
71 static int dsa_cb(int p, int n, BN_GENCB *arg);
72 
73 /* The following values are taken from the updated Appendix 5 to FIPS PUB 186
74  * and also appear in Appendix 5 to FIPS PUB 186-1. */
75 
76 static const uint8_t seed[20] = {
77     0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
78     0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
79 };
80 
81 static const uint8_t fips_p[] = {
82     0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75,
83     0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d,
84     0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0,
85     0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac,
86     0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
87     0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91,
88 };
89 
90 static const uint8_t fips_q[] = {
91     0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
92     0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
93 };
94 
95 static const uint8_t fips_g[] = {
96     0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63,
97     0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c,
98     0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71,
99     0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95,
100     0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
101     0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02,
102 };
103 
104 static const uint8_t fips_x[] = {
105     0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
106     0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
107 };
108 
109 static const uint8_t fips_y[] = {
110     0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
111     0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
112     0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
113     0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
114     0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
115     0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
116 };
117 
118 static const uint8_t fips_digest[] = {
119     0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
120     0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
121 };
122 
123 /* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */
124 static const uint8_t fips_sig[] = {
125     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
126     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
127     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
128     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
129     0xdc, 0xd8, 0xc8,
130 };
131 
132 /* fips_sig_negative is fips_sig with r encoded as a negative number. */
133 static const uint8_t fips_sig_negative[] = {
134     0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
135     0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
136     0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
137     0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
138     0xd8, 0xc8,
139 };
140 
141 /* fip_sig_extra is fips_sig with trailing data. */
142 static const uint8_t fips_sig_extra[] = {
143     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
144     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
145     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
146     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
147     0xdc, 0xd8, 0xc8, 0x00,
148 };
149 
150 /* fips_sig_lengths is fips_sig with a non-minimally encoded length. */
151 static const uint8_t fips_sig_bad_length[] = {
152     0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
153     0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
154     0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
155     0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
156     0xb6, 0xdc, 0xd8, 0xc8, 0x00,
157 };
158 
159 /* fips_sig_bad_r is fips_sig with a bad r value. */
160 static const uint8_t fips_sig_bad_r[] = {
161     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
162     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
163     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
164     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
165     0xdc, 0xd8, 0xc8,
166 };
167 
get_fips_dsa(void)168 static DSA *get_fips_dsa(void) {
169   DSA *dsa = DSA_new();
170   if (!dsa) {
171     return NULL;
172   }
173   dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL);
174   dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL);
175   dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL);
176   dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL);
177   dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL);
178   if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL ||
179       dsa->pub_key == NULL || dsa->priv_key == NULL) {
180     DSA_free(dsa);
181     return NULL;
182   }
183   return dsa;
184 }
185 
test_generate(FILE * out)186 static int test_generate(FILE *out) {
187   BN_GENCB cb;
188   DSA *dsa = NULL;
189   int counter, ok = 0, i, j;
190   uint8_t buf[256];
191   unsigned long h;
192   uint8_t sig[256];
193   unsigned int siglen;
194 
195   fprintf(out, "test generation of DSA parameters\n");
196 
197   BN_GENCB_set(&cb, dsa_cb, out);
198   dsa = DSA_new();
199   if (dsa == NULL ||
200       !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
201     goto end;
202   }
203 
204   fprintf(out, "seed\n");
205   for (i = 0; i < 20; i += 4) {
206     fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
207             seed[i + 3]);
208   }
209   fprintf(out, "\ncounter=%d h=%ld\n", counter, h);
210 
211   if (counter != 105) {
212     fprintf(stderr, "counter should be 105\n");
213     goto end;
214   }
215   if (h != 2) {
216     fprintf(stderr, "h should be 2\n");
217     goto end;
218   }
219 
220   i = BN_bn2bin(dsa->q, buf);
221   j = sizeof(fips_q);
222   if (i != j || memcmp(buf, fips_q, i) != 0) {
223     fprintf(stderr, "q value is wrong\n");
224     goto end;
225   }
226 
227   i = BN_bn2bin(dsa->p, buf);
228   j = sizeof(fips_p);
229   if (i != j || memcmp(buf, fips_p, i) != 0) {
230     fprintf(stderr, "p value is wrong\n");
231     goto end;
232   }
233 
234   i = BN_bn2bin(dsa->g, buf);
235   j = sizeof(fips_g);
236   if (i != j || memcmp(buf, fips_g, i) != 0) {
237     fprintf(stderr, "g value is wrong\n");
238     goto end;
239   }
240 
241   if (!DSA_generate_key(dsa) ||
242       !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa)) {
243     goto end;
244   }
245   if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
246     ok = 1;
247   } else {
248     fprintf(stderr, "verification failure\n");
249   }
250 
251 end:
252   DSA_free(dsa);
253 
254   return ok;
255 }
256 
test_verify(const uint8_t * sig,size_t sig_len,int expect)257 static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
258   int ok = 0;
259   DSA *dsa = get_fips_dsa();
260   if (dsa == NULL) {
261     goto end;
262   }
263 
264   int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
265   if (ret != expect) {
266     fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect);
267     goto end;
268   }
269   ok = 1;
270   /* Clear any errorrs from a test with expected failure. */
271   ERR_clear_error();
272 
273 end:
274   DSA_free(dsa);
275 
276   return ok;
277 }
278 
main(int argc,char ** argv)279 int main(int argc, char **argv) {
280   CRYPTO_library_init();
281 
282   if (!test_generate(stdout) ||
283       !test_verify(fips_sig, sizeof(fips_sig), 1) ||
284       !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
285       !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
286       !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
287       !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
288     ERR_print_errors_fp(stderr);
289     return 1;
290   }
291 
292   printf("PASS\n");
293   return 0;
294 }
295 
dsa_cb(int p,int n,BN_GENCB * arg)296 static int dsa_cb(int p, int n, BN_GENCB *arg) {
297   char c = '*';
298   static int ok = 0, num = 0;
299 
300   switch (p) {
301   case 0:
302     c = '.';
303     num++;
304     break;
305   case 1:
306     c = '+';
307     break;
308   case 2:
309     c = '*';
310     ok++;
311     break;
312   case 3:
313     c = '\n';
314   }
315 
316   fputc(c, arg->arg);
317   fflush(arg->arg);
318 
319   if (!ok && p == 0 && num > 1) {
320     fprintf(stderr, "error in dsatest\n");
321     return 0;
322   }
323 
324   return 1;
325 }
326