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 #include <openssl/dh.h>
58
59 #include <stdio.h>
60 #include <string.h>
61
62 #include <vector>
63
64 #include <gtest/gtest.h>
65
66 #include <openssl/bn.h>
67 #include <openssl/bytestring.h>
68 #include <openssl/crypto.h>
69 #include <openssl/dh.h>
70 #include <openssl/err.h>
71 #include <openssl/mem.h>
72
73 #include "../internal.h"
74 #include "../test/test_util.h"
75
76
77 static bool RunBasicTests();
78 static bool TestBadY();
79 static bool TestASN1();
80 static bool TestRFC3526();
81
82 // TODO(davidben): Convert this file to GTest properly.
TEST(DHTest,AllTests)83 TEST(DHTest, AllTests) {
84 if (!RunBasicTests() ||
85 !TestBadY() ||
86 !TestASN1() ||
87 !TestRFC3526()) {
88 ADD_FAILURE() << "Tests failed.";
89 }
90 }
91
GenerateCallback(int p,int n,BN_GENCB * arg)92 static int GenerateCallback(int p, int n, BN_GENCB *arg) {
93 char c = '*';
94
95 if (p == 0) {
96 c = '.';
97 } else if (p == 1) {
98 c = '+';
99 } else if (p == 2) {
100 c = '*';
101 } else if (p == 3) {
102 c = '\n';
103 }
104 FILE *out = reinterpret_cast<FILE*>(arg->arg);
105 fputc(c, out);
106 fflush(out);
107
108 return 1;
109 }
110
RunBasicTests()111 static bool RunBasicTests() {
112 BN_GENCB cb;
113 BN_GENCB_set(&cb, &GenerateCallback, stdout);
114 bssl::UniquePtr<DH> a(DH_new());
115 if (!a || !DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, &cb)) {
116 return false;
117 }
118
119 int check_result;
120 if (!DH_check(a.get(), &check_result)) {
121 return false;
122 }
123 if (check_result & DH_CHECK_P_NOT_PRIME) {
124 printf("p value is not prime\n");
125 }
126 if (check_result & DH_CHECK_P_NOT_SAFE_PRIME) {
127 printf("p value is not a safe prime\n");
128 }
129 if (check_result & DH_CHECK_UNABLE_TO_CHECK_GENERATOR) {
130 printf("unable to check the generator value\n");
131 }
132 if (check_result & DH_CHECK_NOT_SUITABLE_GENERATOR) {
133 printf("the g value is not a generator\n");
134 }
135
136 printf("\np = ");
137 BN_print_fp(stdout, a->p);
138 printf("\ng = ");
139 BN_print_fp(stdout, a->g);
140 printf("\n");
141
142 bssl::UniquePtr<DH> b(DH_new());
143 if (!b) {
144 return false;
145 }
146
147 b->p = BN_dup(a->p);
148 b->g = BN_dup(a->g);
149 if (b->p == nullptr || b->g == nullptr) {
150 return false;
151 }
152
153 if (!DH_generate_key(a.get())) {
154 return false;
155 }
156 printf("pri1 = ");
157 BN_print_fp(stdout, a->priv_key);
158 printf("\npub1 = ");
159 BN_print_fp(stdout, a->pub_key);
160 printf("\n");
161
162 if (!DH_generate_key(b.get())) {
163 return false;
164 }
165 printf("pri2 = ");
166 BN_print_fp(stdout, b->priv_key);
167 printf("\npub2 = ");
168 BN_print_fp(stdout, b->pub_key);
169 printf("\n");
170
171 std::vector<uint8_t> key1(DH_size(a.get()));
172 int ret = DH_compute_key(key1.data(), b->pub_key, a.get());
173 if (ret < 0) {
174 return false;
175 }
176 key1.resize(ret);
177
178 printf("key1 = ");
179 for (size_t i = 0; i < key1.size(); i++) {
180 printf("%02x", key1[i]);
181 }
182 printf("\n");
183
184 std::vector<uint8_t> key2(DH_size(b.get()));
185 ret = DH_compute_key(key2.data(), a->pub_key, b.get());
186 if (ret < 0) {
187 return false;
188 }
189 key2.resize(ret);
190
191 printf("key2 = ");
192 for (size_t i = 0; i < key2.size(); i++) {
193 printf("%02x", key2[i]);
194 }
195 printf("\n");
196
197 if (key1.size() < 4 || key1 != key2) {
198 fprintf(stderr, "Error in DH routines\n");
199 return false;
200 }
201
202 return true;
203 }
204
205 // The following parameters are taken from RFC 5114, section 2.2. This is not a
206 // safe prime. Do not use these parameters.
207 static const uint8_t kRFC5114_2048_224P[] = {
208 0xad, 0x10, 0x7e, 0x1e, 0x91, 0x23, 0xa9, 0xd0, 0xd6, 0x60, 0xfa, 0xa7,
209 0x95, 0x59, 0xc5, 0x1f, 0xa2, 0x0d, 0x64, 0xe5, 0x68, 0x3b, 0x9f, 0xd1,
210 0xb5, 0x4b, 0x15, 0x97, 0xb6, 0x1d, 0x0a, 0x75, 0xe6, 0xfa, 0x14, 0x1d,
211 0xf9, 0x5a, 0x56, 0xdb, 0xaf, 0x9a, 0x3c, 0x40, 0x7b, 0xa1, 0xdf, 0x15,
212 0xeb, 0x3d, 0x68, 0x8a, 0x30, 0x9c, 0x18, 0x0e, 0x1d, 0xe6, 0xb8, 0x5a,
213 0x12, 0x74, 0xa0, 0xa6, 0x6d, 0x3f, 0x81, 0x52, 0xad, 0x6a, 0xc2, 0x12,
214 0x90, 0x37, 0xc9, 0xed, 0xef, 0xda, 0x4d, 0xf8, 0xd9, 0x1e, 0x8f, 0xef,
215 0x55, 0xb7, 0x39, 0x4b, 0x7a, 0xd5, 0xb7, 0xd0, 0xb6, 0xc1, 0x22, 0x07,
216 0xc9, 0xf9, 0x8d, 0x11, 0xed, 0x34, 0xdb, 0xf6, 0xc6, 0xba, 0x0b, 0x2c,
217 0x8b, 0xbc, 0x27, 0xbe, 0x6a, 0x00, 0xe0, 0xa0, 0xb9, 0xc4, 0x97, 0x08,
218 0xb3, 0xbf, 0x8a, 0x31, 0x70, 0x91, 0x88, 0x36, 0x81, 0x28, 0x61, 0x30,
219 0xbc, 0x89, 0x85, 0xdb, 0x16, 0x02, 0xe7, 0x14, 0x41, 0x5d, 0x93, 0x30,
220 0x27, 0x82, 0x73, 0xc7, 0xde, 0x31, 0xef, 0xdc, 0x73, 0x10, 0xf7, 0x12,
221 0x1f, 0xd5, 0xa0, 0x74, 0x15, 0x98, 0x7d, 0x9a, 0xdc, 0x0a, 0x48, 0x6d,
222 0xcd, 0xf9, 0x3a, 0xcc, 0x44, 0x32, 0x83, 0x87, 0x31, 0x5d, 0x75, 0xe1,
223 0x98, 0xc6, 0x41, 0xa4, 0x80, 0xcd, 0x86, 0xa1, 0xb9, 0xe5, 0x87, 0xe8,
224 0xbe, 0x60, 0xe6, 0x9c, 0xc9, 0x28, 0xb2, 0xb9, 0xc5, 0x21, 0x72, 0xe4,
225 0x13, 0x04, 0x2e, 0x9b, 0x23, 0xf1, 0x0b, 0x0e, 0x16, 0xe7, 0x97, 0x63,
226 0xc9, 0xb5, 0x3d, 0xcf, 0x4b, 0xa8, 0x0a, 0x29, 0xe3, 0xfb, 0x73, 0xc1,
227 0x6b, 0x8e, 0x75, 0xb9, 0x7e, 0xf3, 0x63, 0xe2, 0xff, 0xa3, 0x1f, 0x71,
228 0xcf, 0x9d, 0xe5, 0x38, 0x4e, 0x71, 0xb8, 0x1c, 0x0a, 0xc4, 0xdf, 0xfe,
229 0x0c, 0x10, 0xe6, 0x4f,
230 };
231 static const uint8_t kRFC5114_2048_224G[] = {
232 0xac, 0x40, 0x32, 0xef, 0x4f, 0x2d, 0x9a, 0xe3, 0x9d, 0xf3, 0x0b, 0x5c,
233 0x8f, 0xfd, 0xac, 0x50, 0x6c, 0xde, 0xbe, 0x7b, 0x89, 0x99, 0x8c, 0xaf,
234 0x74, 0x86, 0x6a, 0x08, 0xcf, 0xe4, 0xff, 0xe3, 0xa6, 0x82, 0x4a, 0x4e,
235 0x10, 0xb9, 0xa6, 0xf0, 0xdd, 0x92, 0x1f, 0x01, 0xa7, 0x0c, 0x4a, 0xfa,
236 0xab, 0x73, 0x9d, 0x77, 0x00, 0xc2, 0x9f, 0x52, 0xc5, 0x7d, 0xb1, 0x7c,
237 0x62, 0x0a, 0x86, 0x52, 0xbe, 0x5e, 0x90, 0x01, 0xa8, 0xd6, 0x6a, 0xd7,
238 0xc1, 0x76, 0x69, 0x10, 0x19, 0x99, 0x02, 0x4a, 0xf4, 0xd0, 0x27, 0x27,
239 0x5a, 0xc1, 0x34, 0x8b, 0xb8, 0xa7, 0x62, 0xd0, 0x52, 0x1b, 0xc9, 0x8a,
240 0xe2, 0x47, 0x15, 0x04, 0x22, 0xea, 0x1e, 0xd4, 0x09, 0x93, 0x9d, 0x54,
241 0xda, 0x74, 0x60, 0xcd, 0xb5, 0xf6, 0xc6, 0xb2, 0x50, 0x71, 0x7c, 0xbe,
242 0xf1, 0x80, 0xeb, 0x34, 0x11, 0x8e, 0x98, 0xd1, 0x19, 0x52, 0x9a, 0x45,
243 0xd6, 0xf8, 0x34, 0x56, 0x6e, 0x30, 0x25, 0xe3, 0x16, 0xa3, 0x30, 0xef,
244 0xbb, 0x77, 0xa8, 0x6f, 0x0c, 0x1a, 0xb1, 0x5b, 0x05, 0x1a, 0xe3, 0xd4,
245 0x28, 0xc8, 0xf8, 0xac, 0xb7, 0x0a, 0x81, 0x37, 0x15, 0x0b, 0x8e, 0xeb,
246 0x10, 0xe1, 0x83, 0xed, 0xd1, 0x99, 0x63, 0xdd, 0xd9, 0xe2, 0x63, 0xe4,
247 0x77, 0x05, 0x89, 0xef, 0x6a, 0xa2, 0x1e, 0x7f, 0x5f, 0x2f, 0xf3, 0x81,
248 0xb5, 0x39, 0xcc, 0xe3, 0x40, 0x9d, 0x13, 0xcd, 0x56, 0x6a, 0xfb, 0xb4,
249 0x8d, 0x6c, 0x01, 0x91, 0x81, 0xe1, 0xbc, 0xfe, 0x94, 0xb3, 0x02, 0x69,
250 0xed, 0xfe, 0x72, 0xfe, 0x9b, 0x6a, 0xa4, 0xbd, 0x7b, 0x5a, 0x0f, 0x1c,
251 0x71, 0xcf, 0xff, 0x4c, 0x19, 0xc4, 0x18, 0xe1, 0xf6, 0xec, 0x01, 0x79,
252 0x81, 0xbc, 0x08, 0x7f, 0x2a, 0x70, 0x65, 0xb3, 0x84, 0xb8, 0x90, 0xd3,
253 0x19, 0x1f, 0x2b, 0xfa,
254 };
255 static const uint8_t kRFC5114_2048_224Q[] = {
256 0x80, 0x1c, 0x0d, 0x34, 0xc5, 0x8d, 0x93, 0xfe, 0x99, 0x71,
257 0x77, 0x10, 0x1f, 0x80, 0x53, 0x5a, 0x47, 0x38, 0xce, 0xbc,
258 0xbf, 0x38, 0x9a, 0x99, 0xb3, 0x63, 0x71, 0xeb,
259 };
260
261 // kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP
262 // Group with 224-bit Prime Order Subgroup (section 2.2).
263 static const uint8_t kRFC5114_2048_224BadY[] = {
264 0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3,
265 0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad,
266 0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20,
267 0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67,
268 0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88,
269 0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83,
270 0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f,
271 0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8,
272 0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2,
273 0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70,
274 0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f,
275 0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66,
276 0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22,
277 0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44,
278 0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d,
279 0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed,
280 0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01,
281 0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a,
282 0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72,
283 0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2,
284 0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89,
285 0x93, 0x74, 0x89, 0x59,
286 };
287
TestBadY()288 static bool TestBadY() {
289 bssl::UniquePtr<DH> dh(DH_new());
290 dh->p = BN_bin2bn(kRFC5114_2048_224P, sizeof(kRFC5114_2048_224P), nullptr);
291 dh->g = BN_bin2bn(kRFC5114_2048_224G, sizeof(kRFC5114_2048_224G), nullptr);
292 dh->q = BN_bin2bn(kRFC5114_2048_224Q, sizeof(kRFC5114_2048_224Q), nullptr);
293 if (!dh->p || !dh->g || !dh->q) {
294 return false;
295 }
296
297 bssl::UniquePtr<BIGNUM> pub_key(
298 BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr));
299 if (!dh || !pub_key || !DH_generate_key(dh.get())) {
300 return false;
301 }
302
303 int flags;
304 if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) {
305 return false;
306 }
307 if (!(flags & DH_CHECK_PUBKEY_INVALID)) {
308 fprintf(stderr, "DH_check_pub_key did not reject the key.\n");
309 return false;
310 }
311
312 std::vector<uint8_t> result(DH_size(dh.get()));
313 if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) {
314 fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n");
315 return false;
316 }
317 ERR_clear_error();
318
319 return true;
320 }
321
BIGNUMEqualsHex(const BIGNUM * bn,const char * hex)322 static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) {
323 BIGNUM *hex_bn = NULL;
324 if (!BN_hex2bn(&hex_bn, hex)) {
325 return false;
326 }
327 bssl::UniquePtr<BIGNUM> free_hex_bn(hex_bn);
328 return BN_cmp(bn, hex_bn) == 0;
329 }
330
TestASN1()331 static bool TestASN1() {
332 // kParams are a set of Diffie-Hellman parameters generated with
333 // openssl dhparam 256
334 static const uint8_t kParams[] = {
335 0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27,
336 0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56,
337 0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c,
338 0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02,
339 };
340
341 CBS cbs;
342 CBS_init(&cbs, kParams, sizeof(kParams));
343 bssl::UniquePtr<DH> dh(DH_parse_parameters(&cbs));
344 if (!dh || CBS_len(&cbs) != 0 ||
345 !BIGNUMEqualsHex(
346 dh->p,
347 "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313") ||
348 !BIGNUMEqualsHex(dh->g, "2") || dh->priv_length != 0) {
349 return false;
350 }
351
352 bssl::ScopedCBB cbb;
353 uint8_t *der;
354 size_t der_len;
355 if (!CBB_init(cbb.get(), 0) ||
356 !DH_marshal_parameters(cbb.get(), dh.get()) ||
357 !CBB_finish(cbb.get(), &der, &der_len)) {
358 return false;
359 }
360 bssl::UniquePtr<uint8_t> free_der(der);
361 if (der_len != sizeof(kParams) ||
362 OPENSSL_memcmp(der, kParams, der_len) != 0) {
363 return false;
364 }
365
366 // kParamsDSA are a set of Diffie-Hellman parameters generated with
367 // openssl dhparam 256 -dsaparam
368 static const uint8_t kParamsDSA[] = {
369 0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6,
370 0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10,
371 0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19,
372 0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab,
373 0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4,
374 0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40,
375 0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75,
376 0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c,
377 0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f,
378 0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26,
379 0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07,
380 0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0,
381 };
382
383 CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA));
384 dh.reset(DH_parse_parameters(&cbs));
385 if (!dh || CBS_len(&cbs) != 0 ||
386 !BIGNUMEqualsHex(dh->p,
387 "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8"
388 "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467"
389 "3451952aac11e26a55") ||
390 !BIGNUMEqualsHex(dh->g,
391 "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86"
392 "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec"
393 "a6a8ba1a078a77f55f") ||
394 dh->priv_length != 160) {
395 return false;
396 }
397
398 if (!CBB_init(cbb.get(), 0) ||
399 !DH_marshal_parameters(cbb.get(), dh.get()) ||
400 !CBB_finish(cbb.get(), &der, &der_len)) {
401 return false;
402 }
403 bssl::UniquePtr<uint8_t> free_der2(der);
404 if (der_len != sizeof(kParamsDSA) ||
405 OPENSSL_memcmp(der, kParamsDSA, der_len) != 0) {
406 return false;
407 }
408
409 return true;
410 }
411
TestRFC3526()412 static bool TestRFC3526() {
413 bssl::UniquePtr<BIGNUM> bn(BN_get_rfc3526_prime_1536(nullptr));
414 if (!bn) {
415 return false;
416 }
417
418 static const uint8_t kPrime1536[] = {
419 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
420 0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
421 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
422 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
423 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
424 0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
425 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
426 0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
427 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
428 0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
429 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
430 0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
431 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
432 0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
433 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
434 0xca, 0x23, 0x73, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
435 };
436
437 uint8_t buffer[sizeof(kPrime1536)];
438 if (BN_num_bytes(bn.get()) != sizeof(kPrime1536) ||
439 BN_bn2bin(bn.get(), buffer) != sizeof(kPrime1536) ||
440 OPENSSL_memcmp(buffer, kPrime1536, sizeof(kPrime1536)) != 0) {
441 fprintf(stderr, "1536-bit MODP prime did not match.\n");
442 return false;
443 }
444
445 return true;
446 }
447
TEST(DHTest,LeadingZeros)448 TEST(DHTest, LeadingZeros) {
449 bssl::UniquePtr<BIGNUM> p(BN_get_rfc3526_prime_1536(nullptr));
450 ASSERT_TRUE(p);
451 bssl::UniquePtr<BIGNUM> g(BN_new());
452 ASSERT_TRUE(g);
453 ASSERT_TRUE(BN_set_word(g.get(), 2));
454
455 bssl::UniquePtr<DH> dh(DH_new());
456 ASSERT_TRUE(dh);
457 ASSERT_TRUE(DH_set0_pqg(dh.get(), p.get(), /*q=*/nullptr, g.get()));
458 p.release();
459 g.release();
460
461 // These values are far too small to be reasonable Diffie-Hellman keys, but
462 // they are an easy way to get a shared secret with leading zeros.
463 bssl::UniquePtr<BIGNUM> priv_key(BN_new()), peer_key(BN_new());
464 ASSERT_TRUE(priv_key);
465 ASSERT_TRUE(BN_set_word(priv_key.get(), 2));
466 ASSERT_TRUE(peer_key);
467 ASSERT_TRUE(BN_set_word(peer_key.get(), 3));
468 ASSERT_TRUE(DH_set0_key(dh.get(), /*pub_key=*/nullptr, priv_key.get()));
469 priv_key.release();
470
471 uint8_t padded[192] = {0};
472 padded[191] = 9;
473 static const uint8_t kTruncated[] = {9};
474 EXPECT_EQ(int(sizeof(padded)), DH_size(dh.get()));
475
476 std::vector<uint8_t> buf(DH_size(dh.get()));
477 int len = DH_compute_key(buf.data(), peer_key.get(), dh.get());
478 ASSERT_GT(len, 0);
479 EXPECT_EQ(Bytes(buf.data(), len), Bytes(kTruncated));
480
481 len = DH_compute_key_padded(buf.data(), peer_key.get(), dh.get());
482 ASSERT_GT(len, 0);
483 EXPECT_EQ(Bytes(buf.data(), len), Bytes(padded));
484 }
485