• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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