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 <stdio.h>
63 #include <string.h>
64
65 #include <vector>
66
67 #include <gtest/gtest.h>
68
69 #include <openssl/bn.h>
70 #include <openssl/crypto.h>
71 #include <openssl/err.h>
72
73 #include "../internal.h"
74
75
76 // The following values are taken from the updated Appendix 5 to FIPS PUB 186
77 // and also appear in Appendix 5 to FIPS PUB 186-1.
78
79 static const uint8_t seed[20] = {
80 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
81 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
82 };
83
84 static const uint8_t fips_p[] = {
85 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75,
86 0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d,
87 0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0,
88 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac,
89 0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
90 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91,
91 };
92
93 static const uint8_t fips_q[] = {
94 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
95 0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
96 };
97
98 static const uint8_t fips_g[] = {
99 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63,
100 0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c,
101 0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71,
102 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95,
103 0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
104 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02,
105 };
106
107 static const uint8_t fips_x[] = {
108 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
109 0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
110 };
111
112 static const uint8_t fips_y[] = {
113 0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
114 0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
115 0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
116 0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
117 0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
118 0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
119 };
120
121 static const uint8_t fips_digest[] = {
122 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
123 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
124 };
125
126 // fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1.
127 static const uint8_t fips_sig[] = {
128 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
129 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
130 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
131 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
132 0xdc, 0xd8, 0xc8,
133 };
134
135 // fips_sig_negative is fips_sig with r encoded as a negative number.
136 static const uint8_t fips_sig_negative[] = {
137 0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
138 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
139 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
140 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
141 0xd8, 0xc8,
142 };
143
144 // fip_sig_extra is fips_sig with trailing data.
145 static const uint8_t fips_sig_extra[] = {
146 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
147 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
148 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
149 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
150 0xdc, 0xd8, 0xc8, 0x00,
151 };
152
153 // fips_sig_lengths is fips_sig with a non-minimally encoded length.
154 static const uint8_t fips_sig_bad_length[] = {
155 0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
156 0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
157 0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
158 0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
159 0xb6, 0xdc, 0xd8, 0xc8, 0x00,
160 };
161
162 // fips_sig_bad_r is fips_sig with a bad r value.
163 static const uint8_t fips_sig_bad_r[] = {
164 0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
165 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
166 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
167 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
168 0xdc, 0xd8, 0xc8,
169 };
170
GetFIPSDSA(void)171 static bssl::UniquePtr<DSA> GetFIPSDSA(void) {
172 bssl::UniquePtr<DSA> dsa(DSA_new());
173 if (!dsa) {
174 return nullptr;
175 }
176 dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), nullptr);
177 dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), nullptr);
178 dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), nullptr);
179 dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), nullptr);
180 dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), nullptr);
181 if (dsa->p == nullptr || dsa->q == nullptr || dsa->g == nullptr ||
182 dsa->pub_key == nullptr || dsa->priv_key == nullptr) {
183 return nullptr;
184 }
185 return dsa;
186 }
187
188 struct GenerateContext {
189 FILE *out = nullptr;
190 int ok = 0;
191 int num = 0;
192 };
193
GenerateCallback(int p,int n,BN_GENCB * arg)194 static int GenerateCallback(int p, int n, BN_GENCB *arg) {
195 GenerateContext *ctx = reinterpret_cast<GenerateContext *>(arg->arg);
196 char c = '*';
197 switch (p) {
198 case 0:
199 c = '.';
200 ctx->num++;
201 break;
202 case 1:
203 c = '+';
204 break;
205 case 2:
206 c = '*';
207 ctx->ok++;
208 break;
209 case 3:
210 c = '\n';
211 }
212 fputc(c, ctx->out);
213 fflush(ctx->out);
214 if (!ctx->ok && p == 0 && ctx->num > 1) {
215 fprintf(stderr, "error in dsatest\n");
216 return 0;
217 }
218 return 1;
219 }
220
TestGenerate(FILE * out)221 static int TestGenerate(FILE *out) {
222 BN_GENCB cb;
223 int counter, i, j;
224 uint8_t buf[256];
225 unsigned long h;
226 uint8_t sig[256];
227 unsigned int siglen;
228
229 fprintf(out, "test generation of DSA parameters\n");
230
231 GenerateContext ctx;
232 ctx.out = out;
233 BN_GENCB_set(&cb, GenerateCallback, &ctx);
234 bssl::UniquePtr<DSA> dsa(DSA_new());
235 if (!dsa ||
236 !DSA_generate_parameters_ex(dsa.get(), 512, seed, 20, &counter, &h,
237 &cb)) {
238 return false;
239 }
240
241 fprintf(out, "seed\n");
242 for (i = 0; i < 20; i += 4) {
243 fprintf(out, "%02X%02X%02X%02X ", seed[i], seed[i + 1], seed[i + 2],
244 seed[i + 3]);
245 }
246 fprintf(out, "\ncounter=%d h=%ld\n", counter, h);
247
248 if (counter != 105) {
249 fprintf(stderr, "counter should be 105\n");
250 return false;
251 }
252 if (h != 2) {
253 fprintf(stderr, "h should be 2\n");
254 return false;
255 }
256
257 i = BN_bn2bin(dsa->q, buf);
258 j = sizeof(fips_q);
259 if (i != j || OPENSSL_memcmp(buf, fips_q, i) != 0) {
260 fprintf(stderr, "q value is wrong\n");
261 return false;
262 }
263
264 i = BN_bn2bin(dsa->p, buf);
265 j = sizeof(fips_p);
266 if (i != j || OPENSSL_memcmp(buf, fips_p, i) != 0) {
267 fprintf(stderr, "p value is wrong\n");
268 return false;
269 }
270
271 i = BN_bn2bin(dsa->g, buf);
272 j = sizeof(fips_g);
273 if (i != j || OPENSSL_memcmp(buf, fips_g, i) != 0) {
274 fprintf(stderr, "g value is wrong\n");
275 return false;
276 }
277
278 if (!DSA_generate_key(dsa.get()) ||
279 !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa.get())) {
280 return false;
281 }
282 if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa.get()) !=
283 1) {
284 fprintf(stderr, "verification failure\n");
285 return false;
286 }
287
288 return true;
289 }
290
TestVerify(const uint8_t * sig,size_t sig_len,int expect)291 static bool TestVerify(const uint8_t *sig, size_t sig_len, int expect) {
292 bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
293 if (!dsa) {
294 return false;
295 }
296
297 int ret =
298 DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa.get());
299 if (ret != expect) {
300 fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect);
301 return false;
302 }
303
304 // Clear any errors from a test with expected failure.
305 ERR_clear_error();
306 return true;
307 }
308
309 // TODO(davidben): Convert this file to GTest properly.
TEST(DSATest,AllTests)310 TEST(DSATest, AllTests) {
311 if (!TestGenerate(stdout) ||
312 !TestVerify(fips_sig, sizeof(fips_sig), 1) ||
313 !TestVerify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
314 !TestVerify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
315 !TestVerify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
316 !TestVerify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
317 ADD_FAILURE() << "Tests failed";
318 }
319 }
320
TEST(DSATest,InvalidGroup)321 TEST(DSATest, InvalidGroup) {
322 bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
323 ASSERT_TRUE(dsa);
324 BN_zero(dsa->g);
325
326 std::vector<uint8_t> sig(DSA_size(dsa.get()));
327 unsigned sig_len;
328 static const uint8_t kDigest[32] = {0};
329 EXPECT_FALSE(
330 DSA_sign(0, kDigest, sizeof(kDigest), sig.data(), &sig_len, dsa.get()));
331 uint32_t err = ERR_get_error();
332 EXPECT_EQ(ERR_LIB_DSA, ERR_GET_LIB(err));
333 EXPECT_EQ(DSA_R_INVALID_PARAMETERS, ERR_GET_REASON(err));
334 }
335