blob: 12736381ca07484ebc870b3b6c1645125c48a13b [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* 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
Adam Langley2b2d66d2015-01-30 17:08:37 -080062#include <string.h>
63
Adam Langley95c29f32014-06-20 12:00:00 -070064#include <openssl/bio.h>
65#include <openssl/bn.h>
David Benjamina70c75c2014-09-11 19:11:15 -040066#include <openssl/crypto.h>
David Benjamin95e18c52015-01-10 23:37:17 -050067#include <openssl/err.h>
Adam Langley95c29f32014-06-20 12:00:00 -070068
69#include "internal.h"
70
71
72static int dsa_cb(int p, int n, BN_GENCB *arg);
73
David Benjamin95e18c52015-01-10 23:37:17 -050074/* The following values are taken from the updated Appendix 5 to FIPS PUB 186
75 * and also appear in Appendix 5 to FIPS PUB 186-1. */
Adam Langley95c29f32014-06-20 12:00:00 -070076
David Benjamin95e18c52015-01-10 23:37:17 -050077static const uint8_t seed[20] = {
78 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
79 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
80};
81
82static const uint8_t fips_p[] = {
Adam Langley95c29f32014-06-20 12:00:00 -070083 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75,
84 0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d,
85 0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0,
86 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac,
87 0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
David Benjamin95e18c52015-01-10 23:37:17 -050088 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91,
89};
Adam Langley95c29f32014-06-20 12:00:00 -070090
David Benjamin95e18c52015-01-10 23:37:17 -050091static const uint8_t fips_q[] = {
92 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
93 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
94};
Adam Langley95c29f32014-06-20 12:00:00 -070095
David Benjamin95e18c52015-01-10 23:37:17 -050096static const uint8_t fips_g[] = {
Adam Langley95c29f32014-06-20 12:00:00 -070097 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63,
98 0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c,
99 0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71,
100 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95,
101 0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
David Benjamin95e18c52015-01-10 23:37:17 -0500102 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02,
103};
Adam Langley95c29f32014-06-20 12:00:00 -0700104
David Benjamin95e18c52015-01-10 23:37:17 -0500105static const uint8_t fips_x[] = {
106 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
107 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
108};
109
110static const uint8_t fips_y[] = {
111 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
112 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
113 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
114 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
115 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
116 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
117};
118
119static const uint8_t fips_digest[] = {
120 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
121 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
122};
123
124/* fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1. */
125static const uint8_t fips_sig[] = {
126 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
127 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
128 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
129 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
130 0xdc, 0xd8, 0xc8,
131};
132
133/* fips_sig_negative is fips_sig with r encoded as a negative number. */
134static const uint8_t fips_sig_negative[] = {
135 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
136 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
137 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
138 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
139 0xd8, 0xc8,
140};
141
142/* fip_sig_extra is fips_sig with trailing data. */
143static const uint8_t fips_sig_extra[] = {
144 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
145 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
146 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
147 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
148 0xdc, 0xd8, 0xc8, 0x00,
149};
150
151/* fips_sig_lengths is fips_sig with a non-minimally encoded length. */
152static const uint8_t fips_sig_bad_length[] = {
153 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
154 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
155 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
156 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
157 0xb6, 0xdc, 0xd8, 0xc8, 0x00,
158};
159
160/* fips_sig_bad_r is fips_sig with a bad r value. */
161static const uint8_t fips_sig_bad_r[] = {
162 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
163 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
164 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
165 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
166 0xdc, 0xd8, 0xc8,
167};
Adam Langley95c29f32014-06-20 12:00:00 -0700168
169static BIO *bio_err = NULL;
170static BIO *bio_out = NULL;
171
David Benjamin95e18c52015-01-10 23:37:17 -0500172static DSA *get_fips_dsa(void) {
173 DSA *dsa = DSA_new();
174 if (!dsa) {
175 return NULL;
176 }
177 dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL);
178 dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL);
179 dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL);
180 dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL);
181 dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL);
182 if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL ||
183 dsa->pub_key == NULL || dsa->priv_key == NULL) {
184 DSA_free(dsa);
185 return NULL;
186 }
187 return dsa;
188}
189
190static int test_generate(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700191 BN_GENCB cb;
192 DSA *dsa = NULL;
193 int counter, ok = 0, i, j;
David Benjamin95e18c52015-01-10 23:37:17 -0500194 uint8_t buf[256];
Adam Langley95c29f32014-06-20 12:00:00 -0700195 unsigned long h;
David Benjamin95e18c52015-01-10 23:37:17 -0500196 uint8_t sig[256];
Adam Langley95c29f32014-06-20 12:00:00 -0700197 unsigned int siglen;
198
Adam Langley95c29f32014-06-20 12:00:00 -0700199 BIO_printf(bio_out, "test generation of DSA parameters\n");
200
201 BN_GENCB_set(&cb, dsa_cb, bio_out);
202 dsa = DSA_new();
203 if (dsa == NULL ||
204 !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
205 goto end;
206 }
207
208 BIO_printf(bio_out, "seed\n");
209 for (i = 0; i < 20; i += 4) {
210 BIO_printf(bio_out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
211 seed[i + 3]);
212 }
213 BIO_printf(bio_out, "\ncounter=%d h=%ld\n", counter, h);
214
215 if (counter != 105) {
216 BIO_printf(bio_err, "counter should be 105\n");
217 goto end;
218 }
219 if (h != 2) {
220 BIO_printf(bio_err, "h should be 2\n");
221 goto end;
222 }
223
224 i = BN_bn2bin(dsa->q, buf);
David Benjamin95e18c52015-01-10 23:37:17 -0500225 j = sizeof(fips_q);
226 if (i != j || memcmp(buf, fips_q, i) != 0) {
Adam Langley95c29f32014-06-20 12:00:00 -0700227 BIO_printf(bio_err, "q value is wrong\n");
228 goto end;
229 }
230
231 i = BN_bn2bin(dsa->p, buf);
David Benjamin95e18c52015-01-10 23:37:17 -0500232 j = sizeof(fips_p);
233 if (i != j || memcmp(buf, fips_p, i) != 0) {
Adam Langley95c29f32014-06-20 12:00:00 -0700234 BIO_printf(bio_err, "p value is wrong\n");
235 goto end;
236 }
237
238 i = BN_bn2bin(dsa->g, buf);
David Benjamin95e18c52015-01-10 23:37:17 -0500239 j = sizeof(fips_g);
240 if (i != j || memcmp(buf, fips_g, i) != 0) {
Adam Langley95c29f32014-06-20 12:00:00 -0700241 BIO_printf(bio_err, "g value is wrong\n");
242 goto end;
243 }
244
245 DSA_generate_key(dsa);
David Benjamin95e18c52015-01-10 23:37:17 -0500246 DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa);
247 if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
Adam Langley95c29f32014-06-20 12:00:00 -0700248 ok = 1;
249 } else {
250 BIO_printf(bio_err, "verification failure\n");
251 }
252
253end:
Adam Langley95c29f32014-06-20 12:00:00 -0700254 if (dsa != NULL) {
255 DSA_free(dsa);
256 }
257
David Benjamin95e18c52015-01-10 23:37:17 -0500258 return ok;
259}
Adam Langley95c29f32014-06-20 12:00:00 -0700260
David Benjamin95e18c52015-01-10 23:37:17 -0500261static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
262 int ok = 0;
263 DSA *dsa = get_fips_dsa();
264 if (dsa == NULL) {
265 goto end;
Adam Langley95c29f32014-06-20 12:00:00 -0700266 }
267
David Benjamin95e18c52015-01-10 23:37:17 -0500268 int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
269 if (ret != expect) {
270 BIO_printf(bio_err, "DSA_verify returned %d, want %d\n", ret, expect);
271 goto end;
272 }
273 ok = 1;
274 /* Clear any errorrs from a test with expected failure. */
275 ERR_clear_error();
276
277end:
278 if (dsa != NULL) {
279 DSA_free(dsa);
280 }
281
282 return ok;
283}
284
285int main(int argc, char **argv) {
286 CRYPTO_library_init();
287
288 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
289 bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
290
291 if (!test_generate() ||
292 !test_verify(fips_sig, sizeof(fips_sig), 1) ||
293 !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
294 !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
295 !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
296 !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
297 BIO_print_errors(bio_err);
298 BIO_free(bio_err);
299 BIO_free(bio_out);
300 return 1;
301 }
302
303 BIO_free(bio_err);
304 BIO_free(bio_out);
305 printf("PASS\n");
306 return 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700307}
308
309static int dsa_cb(int p, int n, BN_GENCB *arg) {
310 char c = '*';
311 static int ok = 0, num = 0;
312
313 switch (p) {
314 case 0:
315 c = '.';
316 num++;
317 break;
318 case 1:
319 c = '+';
320 break;
321 case 2:
322 c = '*';
323 ok++;
324 break;
325 case 3:
326 c = '\n';
327 }
328
329 BIO_write(arg->arg, &c, 1);
330 (void)BIO_flush(arg->arg);
331
332 if (!ok && p == 0 && num > 1) {
333 BIO_printf((BIO *)arg, "error in dsatest\n");
334 return 0;
335 }
336
337 return 1;
338}