1 // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <openssl/dh.h>
16 
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 
24 #include <openssl/bn.h>
25 #include <openssl/bytestring.h>
26 #include <openssl/crypto.h>
27 #include <openssl/dh.h>
28 #include <openssl/err.h>
29 #include <openssl/mem.h>
30 
31 #include "../fipsmodule/dh/internal.h"
32 #include "../test/test_util.h"
33 
34 
TEST(DHTest,Basic)35 TEST(DHTest, Basic) {
36   bssl::UniquePtr<DH> a(DH_new());
37   ASSERT_TRUE(a);
38   ASSERT_TRUE(DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, nullptr));
39 
40   int check_result;
41   ASSERT_TRUE(DH_check(a.get(), &check_result));
42   EXPECT_FALSE(check_result & DH_CHECK_P_NOT_PRIME);
43   EXPECT_FALSE(check_result & DH_CHECK_P_NOT_SAFE_PRIME);
44   EXPECT_FALSE(check_result & DH_CHECK_UNABLE_TO_CHECK_GENERATOR);
45   EXPECT_FALSE(check_result & DH_CHECK_NOT_SUITABLE_GENERATOR);
46 
47   bssl::UniquePtr<DH> b(DHparams_dup(a.get()));
48   ASSERT_TRUE(b);
49 
50   ASSERT_TRUE(DH_generate_key(a.get()));
51   ASSERT_TRUE(DH_generate_key(b.get()));
52 
53   std::vector<uint8_t> key1(DH_size(a.get()));
54   int ret = DH_compute_key(key1.data(), DH_get0_pub_key(b.get()), a.get());
55   ASSERT_GE(ret, 0);
56   key1.resize(ret);
57 
58   std::vector<uint8_t> key2(DH_size(b.get()));
59   ret = DH_compute_key(key2.data(), DH_get0_pub_key(a.get()), b.get());
60   ASSERT_GE(ret, 0);
61   key2.resize(ret);
62 
63   EXPECT_EQ(Bytes(key1), Bytes(key2));
64 
65   // |DH_compute_key|, unlike |DH_compute_key_padded|, removes leading zeros
66   // from the output, so the key will not have a fixed length. This test uses a
67   // small, 64-bit prime, so check for at least 32 bits of output after removing
68   // leading zeros.
69   EXPECT_GE(key1.size(), 4u);
70 }
71 
72 // The following parameters are taken from RFC 5114, section 2.2. This is not a
73 // safe prime. Do not use these parameters.
74 static const uint8_t kRFC5114_2048_224P[] = {
75     0xad, 0x10, 0x7e, 0x1e, 0x91, 0x23, 0xa9, 0xd0, 0xd6, 0x60, 0xfa, 0xa7,
76     0x95, 0x59, 0xc5, 0x1f, 0xa2, 0x0d, 0x64, 0xe5, 0x68, 0x3b, 0x9f, 0xd1,
77     0xb5, 0x4b, 0x15, 0x97, 0xb6, 0x1d, 0x0a, 0x75, 0xe6, 0xfa, 0x14, 0x1d,
78     0xf9, 0x5a, 0x56, 0xdb, 0xaf, 0x9a, 0x3c, 0x40, 0x7b, 0xa1, 0xdf, 0x15,
79     0xeb, 0x3d, 0x68, 0x8a, 0x30, 0x9c, 0x18, 0x0e, 0x1d, 0xe6, 0xb8, 0x5a,
80     0x12, 0x74, 0xa0, 0xa6, 0x6d, 0x3f, 0x81, 0x52, 0xad, 0x6a, 0xc2, 0x12,
81     0x90, 0x37, 0xc9, 0xed, 0xef, 0xda, 0x4d, 0xf8, 0xd9, 0x1e, 0x8f, 0xef,
82     0x55, 0xb7, 0x39, 0x4b, 0x7a, 0xd5, 0xb7, 0xd0, 0xb6, 0xc1, 0x22, 0x07,
83     0xc9, 0xf9, 0x8d, 0x11, 0xed, 0x34, 0xdb, 0xf6, 0xc6, 0xba, 0x0b, 0x2c,
84     0x8b, 0xbc, 0x27, 0xbe, 0x6a, 0x00, 0xe0, 0xa0, 0xb9, 0xc4, 0x97, 0x08,
85     0xb3, 0xbf, 0x8a, 0x31, 0x70, 0x91, 0x88, 0x36, 0x81, 0x28, 0x61, 0x30,
86     0xbc, 0x89, 0x85, 0xdb, 0x16, 0x02, 0xe7, 0x14, 0x41, 0x5d, 0x93, 0x30,
87     0x27, 0x82, 0x73, 0xc7, 0xde, 0x31, 0xef, 0xdc, 0x73, 0x10, 0xf7, 0x12,
88     0x1f, 0xd5, 0xa0, 0x74, 0x15, 0x98, 0x7d, 0x9a, 0xdc, 0x0a, 0x48, 0x6d,
89     0xcd, 0xf9, 0x3a, 0xcc, 0x44, 0x32, 0x83, 0x87, 0x31, 0x5d, 0x75, 0xe1,
90     0x98, 0xc6, 0x41, 0xa4, 0x80, 0xcd, 0x86, 0xa1, 0xb9, 0xe5, 0x87, 0xe8,
91     0xbe, 0x60, 0xe6, 0x9c, 0xc9, 0x28, 0xb2, 0xb9, 0xc5, 0x21, 0x72, 0xe4,
92     0x13, 0x04, 0x2e, 0x9b, 0x23, 0xf1, 0x0b, 0x0e, 0x16, 0xe7, 0x97, 0x63,
93     0xc9, 0xb5, 0x3d, 0xcf, 0x4b, 0xa8, 0x0a, 0x29, 0xe3, 0xfb, 0x73, 0xc1,
94     0x6b, 0x8e, 0x75, 0xb9, 0x7e, 0xf3, 0x63, 0xe2, 0xff, 0xa3, 0x1f, 0x71,
95     0xcf, 0x9d, 0xe5, 0x38, 0x4e, 0x71, 0xb8, 0x1c, 0x0a, 0xc4, 0xdf, 0xfe,
96     0x0c, 0x10, 0xe6, 0x4f,
97 };
98 static const uint8_t kRFC5114_2048_224G[] = {
99     0xac, 0x40, 0x32, 0xef, 0x4f, 0x2d, 0x9a, 0xe3, 0x9d, 0xf3, 0x0b, 0x5c,
100     0x8f, 0xfd, 0xac, 0x50, 0x6c, 0xde, 0xbe, 0x7b, 0x89, 0x99, 0x8c, 0xaf,
101     0x74, 0x86, 0x6a, 0x08, 0xcf, 0xe4, 0xff, 0xe3, 0xa6, 0x82, 0x4a, 0x4e,
102     0x10, 0xb9, 0xa6, 0xf0, 0xdd, 0x92, 0x1f, 0x01, 0xa7, 0x0c, 0x4a, 0xfa,
103     0xab, 0x73, 0x9d, 0x77, 0x00, 0xc2, 0x9f, 0x52, 0xc5, 0x7d, 0xb1, 0x7c,
104     0x62, 0x0a, 0x86, 0x52, 0xbe, 0x5e, 0x90, 0x01, 0xa8, 0xd6, 0x6a, 0xd7,
105     0xc1, 0x76, 0x69, 0x10, 0x19, 0x99, 0x02, 0x4a, 0xf4, 0xd0, 0x27, 0x27,
106     0x5a, 0xc1, 0x34, 0x8b, 0xb8, 0xa7, 0x62, 0xd0, 0x52, 0x1b, 0xc9, 0x8a,
107     0xe2, 0x47, 0x15, 0x04, 0x22, 0xea, 0x1e, 0xd4, 0x09, 0x93, 0x9d, 0x54,
108     0xda, 0x74, 0x60, 0xcd, 0xb5, 0xf6, 0xc6, 0xb2, 0x50, 0x71, 0x7c, 0xbe,
109     0xf1, 0x80, 0xeb, 0x34, 0x11, 0x8e, 0x98, 0xd1, 0x19, 0x52, 0x9a, 0x45,
110     0xd6, 0xf8, 0x34, 0x56, 0x6e, 0x30, 0x25, 0xe3, 0x16, 0xa3, 0x30, 0xef,
111     0xbb, 0x77, 0xa8, 0x6f, 0x0c, 0x1a, 0xb1, 0x5b, 0x05, 0x1a, 0xe3, 0xd4,
112     0x28, 0xc8, 0xf8, 0xac, 0xb7, 0x0a, 0x81, 0x37, 0x15, 0x0b, 0x8e, 0xeb,
113     0x10, 0xe1, 0x83, 0xed, 0xd1, 0x99, 0x63, 0xdd, 0xd9, 0xe2, 0x63, 0xe4,
114     0x77, 0x05, 0x89, 0xef, 0x6a, 0xa2, 0x1e, 0x7f, 0x5f, 0x2f, 0xf3, 0x81,
115     0xb5, 0x39, 0xcc, 0xe3, 0x40, 0x9d, 0x13, 0xcd, 0x56, 0x6a, 0xfb, 0xb4,
116     0x8d, 0x6c, 0x01, 0x91, 0x81, 0xe1, 0xbc, 0xfe, 0x94, 0xb3, 0x02, 0x69,
117     0xed, 0xfe, 0x72, 0xfe, 0x9b, 0x6a, 0xa4, 0xbd, 0x7b, 0x5a, 0x0f, 0x1c,
118     0x71, 0xcf, 0xff, 0x4c, 0x19, 0xc4, 0x18, 0xe1, 0xf6, 0xec, 0x01, 0x79,
119     0x81, 0xbc, 0x08, 0x7f, 0x2a, 0x70, 0x65, 0xb3, 0x84, 0xb8, 0x90, 0xd3,
120     0x19, 0x1f, 0x2b, 0xfa,
121 };
122 static const uint8_t kRFC5114_2048_224Q[] = {
123     0x80, 0x1c, 0x0d, 0x34, 0xc5, 0x8d, 0x93, 0xfe, 0x99, 0x71,
124     0x77, 0x10, 0x1f, 0x80, 0x53, 0x5a, 0x47, 0x38, 0xce, 0xbc,
125     0xbf, 0x38, 0x9a, 0x99, 0xb3, 0x63, 0x71, 0xeb,
126 };
127 
128 // kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP
129 // Group with 224-bit Prime Order Subgroup (section 2.2).
130 static const uint8_t kRFC5114_2048_224BadY[] = {
131     0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3,
132     0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad,
133     0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20,
134     0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67,
135     0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88,
136     0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83,
137     0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f,
138     0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8,
139     0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2,
140     0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70,
141     0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f,
142     0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66,
143     0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22,
144     0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44,
145     0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d,
146     0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed,
147     0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01,
148     0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a,
149     0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72,
150     0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2,
151     0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89,
152     0x93, 0x74, 0x89, 0x59,
153 };
154 
NewDHGroup(const BIGNUM * p,const BIGNUM * q,const BIGNUM * g)155 static bssl::UniquePtr<DH> NewDHGroup(const BIGNUM *p, const BIGNUM *q,
156                                       const BIGNUM *g) {
157   bssl::UniquePtr<BIGNUM> p_copy(BN_dup(p));
158   bssl::UniquePtr<BIGNUM> q_copy(q != nullptr ? BN_dup(q) : nullptr);
159   bssl::UniquePtr<BIGNUM> g_copy(BN_dup(g));
160   bssl::UniquePtr<DH> dh(DH_new());
161   if (p_copy == nullptr || (q != nullptr && q_copy == nullptr) ||
162       g_copy == nullptr || dh == nullptr ||
163       !DH_set0_pqg(dh.get(), p_copy.get(), q_copy.get(), g_copy.get())) {
164     return nullptr;
165   }
166   p_copy.release();
167   q_copy.release();
168   g_copy.release();
169   return dh;
170 }
171 
TEST(DHTest,BadY)172 TEST(DHTest, BadY) {
173   bssl::UniquePtr<BIGNUM> p(
174       BN_bin2bn(kRFC5114_2048_224P, sizeof(kRFC5114_2048_224P), nullptr));
175   bssl::UniquePtr<BIGNUM> q(
176       BN_bin2bn(kRFC5114_2048_224Q, sizeof(kRFC5114_2048_224Q), nullptr));
177   bssl::UniquePtr<BIGNUM> g(
178       BN_bin2bn(kRFC5114_2048_224G, sizeof(kRFC5114_2048_224G), nullptr));
179   ASSERT_TRUE(p);
180   ASSERT_TRUE(q);
181   ASSERT_TRUE(g);
182   bssl::UniquePtr<DH> dh = NewDHGroup(p.get(), q.get(), g.get());
183   ASSERT_TRUE(dh);
184 
185   bssl::UniquePtr<BIGNUM> pub_key(
186       BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr));
187   ASSERT_TRUE(pub_key);
188   ASSERT_TRUE(DH_generate_key(dh.get()));
189 
190   int flags;
191   ASSERT_TRUE(DH_check_pub_key(dh.get(), pub_key.get(), &flags));
192   EXPECT_TRUE(flags & DH_CHECK_PUBKEY_INVALID)
193       << "DH_check_pub_key did not reject the key";
194 
195   std::vector<uint8_t> result(DH_size(dh.get()));
196   EXPECT_LT(DH_compute_key(result.data(), pub_key.get(), dh.get()), 0)
197       << "DH_compute_key unexpectedly succeeded";
198   ERR_clear_error();
199 }
200 
BIGNUMEqualsHex(const BIGNUM * bn,const char * hex)201 static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) {
202   BIGNUM *hex_bn = NULL;
203   if (!BN_hex2bn(&hex_bn, hex)) {
204     return false;
205   }
206   bssl::UniquePtr<BIGNUM> free_hex_bn(hex_bn);
207   return BN_cmp(bn, hex_bn) == 0;
208 }
209 
TEST(DHTest,ASN1)210 TEST(DHTest, ASN1) {
211   // kParams are a set of Diffie-Hellman parameters generated with
212   // openssl dhparam 256
213   static const uint8_t kParams[] = {
214       0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27,
215       0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56,
216       0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c,
217       0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02,
218   };
219 
220   CBS cbs;
221   CBS_init(&cbs, kParams, sizeof(kParams));
222   bssl::UniquePtr<DH> dh(DH_parse_parameters(&cbs));
223   ASSERT_TRUE(dh);
224   EXPECT_EQ(CBS_len(&cbs), 0u);
225   EXPECT_TRUE(BIGNUMEqualsHex(
226       DH_get0_p(dh.get()),
227       "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313"));
228   EXPECT_TRUE(BIGNUMEqualsHex(DH_get0_g(dh.get()), "2"));
229   EXPECT_EQ(dh->priv_length, 0u);
230 
231   bssl::ScopedCBB cbb;
232   uint8_t *der;
233   size_t der_len;
234   ASSERT_TRUE(CBB_init(cbb.get(), 0));
235   ASSERT_TRUE(DH_marshal_parameters(cbb.get(), dh.get()));
236   ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
237   bssl::UniquePtr<uint8_t> free_der(der);
238   EXPECT_EQ(Bytes(kParams), Bytes(der, der_len));
239 
240   // kParamsDSA are a set of Diffie-Hellman parameters generated with
241   // openssl dhparam 256 -dsaparam
242   static const uint8_t kParamsDSA[] = {
243       0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6,
244       0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10,
245       0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19,
246       0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab,
247       0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4,
248       0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40,
249       0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75,
250       0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c,
251       0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f,
252       0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26,
253       0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07,
254       0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0,
255   };
256 
257   CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA));
258   dh.reset(DH_parse_parameters(&cbs));
259   ASSERT_TRUE(dh);
260   EXPECT_EQ(CBS_len(&cbs), 0u);
261   EXPECT_TRUE(
262       BIGNUMEqualsHex(DH_get0_p(dh.get()),
263                       "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8"
264                       "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467"
265                       "3451952aac11e26a55"));
266   EXPECT_TRUE(
267       BIGNUMEqualsHex(DH_get0_g(dh.get()),
268                       "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86"
269                       "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec"
270                       "a6a8ba1a078a77f55f"));
271   EXPECT_EQ(dh->priv_length, 160u);
272 
273   ASSERT_TRUE(CBB_init(cbb.get(), 0));
274   ASSERT_TRUE(DH_marshal_parameters(cbb.get(), dh.get()));
275   ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
276   bssl::UniquePtr<uint8_t> free_der2(der);
277   EXPECT_EQ(Bytes(kParamsDSA), Bytes(der, der_len));
278 }
279 
TEST(DHTest,RFC3526)280 TEST(DHTest, RFC3526) {
281   bssl::UniquePtr<BIGNUM> bn(BN_get_rfc3526_prime_1536(nullptr));
282   ASSERT_TRUE(bn);
283 
284   static const uint8_t kPrime1536[] = {
285       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
286       0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
287       0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
288       0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
289       0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
290       0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
291       0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
292       0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
293       0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
294       0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
295       0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
296       0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
297       0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
298       0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
299       0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
300       0xca, 0x23, 0x73, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
301   };
302 
303   uint8_t buffer[sizeof(kPrime1536)];
304   ASSERT_EQ(BN_num_bytes(bn.get()), sizeof(kPrime1536));
305   ASSERT_EQ(BN_bn2bin(bn.get(), buffer), sizeof(kPrime1536));
306   EXPECT_EQ(Bytes(buffer), Bytes(kPrime1536));
307 }
308 
TEST(DHTest,LeadingZeros)309 TEST(DHTest, LeadingZeros) {
310   bssl::UniquePtr<BIGNUM> p(BN_get_rfc3526_prime_1536(nullptr));
311   ASSERT_TRUE(p);
312   bssl::UniquePtr<BIGNUM> g(BN_new());
313   ASSERT_TRUE(g);
314   ASSERT_TRUE(BN_set_word(g.get(), 2));
315 
316   bssl::UniquePtr<DH> dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
317   ASSERT_TRUE(dh);
318 
319   // These values are far too small to be reasonable Diffie-Hellman keys, but
320   // they are an easy way to get a shared secret with leading zeros.
321   bssl::UniquePtr<BIGNUM> priv_key(BN_new()), peer_key(BN_new());
322   ASSERT_TRUE(priv_key);
323   ASSERT_TRUE(BN_set_word(priv_key.get(), 2));
324   ASSERT_TRUE(peer_key);
325   ASSERT_TRUE(BN_set_word(peer_key.get(), 3));
326   ASSERT_TRUE(DH_set0_key(dh.get(), /*pub_key=*/nullptr, priv_key.get()));
327   priv_key.release();
328 
329   uint8_t padded[192] = {0};
330   padded[191] = 9;
331   static const uint8_t kTruncated[] = {9};
332   EXPECT_EQ(int(sizeof(padded)), DH_size(dh.get()));
333 
334   std::vector<uint8_t> buf(DH_size(dh.get()));
335   int len = DH_compute_key(buf.data(), peer_key.get(), dh.get());
336   ASSERT_GT(len, 0);
337   EXPECT_EQ(Bytes(buf.data(), len), Bytes(kTruncated));
338 
339   len = DH_compute_key_padded(buf.data(), peer_key.get(), dh.get());
340   ASSERT_GT(len, 0);
341   EXPECT_EQ(Bytes(buf.data(), len), Bytes(padded));
342 }
343 
TEST(DHTest,Overwrite)344 TEST(DHTest, Overwrite) {
345   // Generate a DH key with the 1536-bit MODP group.
346   bssl::UniquePtr<BIGNUM> p(BN_get_rfc3526_prime_1536(nullptr));
347   ASSERT_TRUE(p);
348   bssl::UniquePtr<BIGNUM> g(BN_new());
349   ASSERT_TRUE(g);
350   ASSERT_TRUE(BN_set_word(g.get(), 2));
351 
352   bssl::UniquePtr<DH> key1 = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
353   ASSERT_TRUE(key1);
354   ASSERT_TRUE(DH_generate_key(key1.get()));
355 
356   bssl::UniquePtr<BIGNUM> peer_key(BN_new());
357   ASSERT_TRUE(peer_key);
358   ASSERT_TRUE(BN_set_word(peer_key.get(), 42));
359 
360   // Use the key to fill in cached values.
361   std::vector<uint8_t> buf1(DH_size(key1.get()));
362   ASSERT_GT(DH_compute_key_padded(buf1.data(), peer_key.get(), key1.get()), 0);
363 
364   // Generate a different key with a different group.
365   p.reset(BN_get_rfc3526_prime_2048(nullptr));
366   ASSERT_TRUE(p);
367   bssl::UniquePtr<DH> key2 = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
368   ASSERT_TRUE(key2);
369   ASSERT_TRUE(DH_generate_key(key2.get()));
370 
371   // Overwrite |key1|'s contents with |key2|.
372   p.reset(BN_dup(DH_get0_p(key2.get())));
373   ASSERT_TRUE(p);
374   g.reset(BN_dup(DH_get0_g(key2.get())));
375   ASSERT_TRUE(g);
376   bssl::UniquePtr<BIGNUM> pub(BN_dup(DH_get0_pub_key(key2.get())));
377   ASSERT_TRUE(pub);
378   bssl::UniquePtr<BIGNUM> priv(BN_dup(DH_get0_priv_key(key2.get())));
379   ASSERT_TRUE(priv);
380   ASSERT_TRUE(DH_set0_pqg(key1.get(), p.get(), /*q=*/nullptr, g.get()));
381   p.release();
382   g.release();
383   ASSERT_TRUE(DH_set0_key(key1.get(), pub.get(), priv.get()));
384   pub.release();
385   priv.release();
386 
387   // Verify that |key1| and |key2| behave equivalently.
388   buf1.resize(DH_size(key1.get()));
389   ASSERT_GT(DH_compute_key_padded(buf1.data(), peer_key.get(), key1.get()), 0);
390   std::vector<uint8_t> buf2(DH_size(key2.get()));
391   ASSERT_GT(DH_compute_key_padded(buf2.data(), peer_key.get(), key2.get()), 0);
392   EXPECT_EQ(Bytes(buf1), Bytes(buf2));
393 }
394 
TEST(DHTest,GenerateKeyTwice)395 TEST(DHTest, GenerateKeyTwice) {
396   bssl::UniquePtr<BIGNUM> p(BN_get_rfc3526_prime_2048(nullptr));
397   ASSERT_TRUE(p);
398   bssl::UniquePtr<BIGNUM> g(BN_new());
399   ASSERT_TRUE(g);
400   ASSERT_TRUE(BN_set_word(g.get(), 2));
401   bssl::UniquePtr<DH> key1 = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
402   ASSERT_TRUE(key1);
403   ASSERT_TRUE(DH_generate_key(key1.get()));
404 
405   // Copy the parameters and private key to a new DH object.
406   bssl::UniquePtr<DH> key2(DHparams_dup(key1.get()));
407   ASSERT_TRUE(key2);
408   bssl::UniquePtr<BIGNUM> priv_key(BN_dup(DH_get0_priv_key(key1.get())));
409   ASSERT_TRUE(DH_set0_key(key2.get(), /*pub_key=*/NULL, priv_key.get()));
410   priv_key.release();
411 
412   // This time, calling |DH_generate_key| preserves the old key and recomputes
413   // the public key.
414   ASSERT_TRUE(DH_generate_key(key2.get()));
415   EXPECT_EQ(BN_cmp(DH_get0_priv_key(key1.get()), DH_get0_priv_key(key2.get())),
416             0);
417   EXPECT_EQ(BN_cmp(DH_get0_pub_key(key1.get()), DH_get0_pub_key(key2.get())),
418             0);
419 }
420 
421 // Bad parameters should be rejected, rather than cause a DoS risk in the
422 // event that an application uses Diffie-Hellman incorrectly, with untrusted
423 // domain parameters.
TEST(DHTest,InvalidParameters)424 TEST(DHTest, InvalidParameters) {
425   auto check_invalid_group = [](DH *dh) {
426     // All operations on egregiously invalid groups should fail.
427     EXPECT_FALSE(DH_generate_key(dh));
428     int check_result;
429     EXPECT_FALSE(DH_check(dh, &check_result));
430     bssl::UniquePtr<BIGNUM> pub_key(BN_new());
431     ASSERT_TRUE(pub_key);
432     ASSERT_TRUE(BN_set_u64(pub_key.get(), 42));
433     EXPECT_FALSE(DH_check_pub_key(dh, pub_key.get(), &check_result));
434     uint8_t buf[1024];
435     EXPECT_EQ(DH_compute_key(buf, pub_key.get(), dh), -1);
436     EXPECT_EQ(DH_compute_key_padded(buf, pub_key.get(), dh), -1);
437   };
438 
439   bssl::UniquePtr<BIGNUM> p(BN_get_rfc3526_prime_2048(nullptr));
440   ASSERT_TRUE(p);
441   bssl::UniquePtr<BIGNUM> g(BN_new());
442   ASSERT_TRUE(g);
443   ASSERT_TRUE(BN_set_word(g.get(), 2));
444 
445   // p is negative.
446   BN_set_negative(p.get(), 1);
447   bssl::UniquePtr<DH> dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
448   ASSERT_TRUE(dh);
449   BN_set_negative(p.get(), 0);
450   check_invalid_group(dh.get());
451 
452   // g is negative.
453   BN_set_negative(g.get(), 1);
454   dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
455   ASSERT_TRUE(dh);
456   BN_set_negative(g.get(), 0);
457   check_invalid_group(dh.get());
458 
459   // g is not reduced mod p.
460   dh = NewDHGroup(p.get(), /*q=*/nullptr, p.get());
461   ASSERT_TRUE(dh);
462   BN_set_negative(g.get(), 0);
463   check_invalid_group(dh.get());
464 
465   // p is too large.
466   bssl::UniquePtr<BIGNUM> large(BN_new());
467   ASSERT_TRUE(BN_set_bit(large.get(), 0));
468   ASSERT_TRUE(BN_set_bit(large.get(), 10000000));
469   dh = NewDHGroup(large.get(), /*q=*/nullptr, g.get());
470   ASSERT_TRUE(dh);
471   check_invalid_group(dh.get());
472 
473   // q is too large.
474   dh = NewDHGroup(p.get(), large.get(), g.get());
475   ASSERT_TRUE(dh);
476   check_invalid_group(dh.get());
477 
478   // Attempting to generate too large of a Diffie-Hellman group should fail.
479   EXPECT_FALSE(
480       DH_generate_parameters_ex(dh.get(), 20000, DH_GENERATOR_5, nullptr));
481 }
482 
TEST(DHTest,PrivateKeyLength)483 TEST(DHTest, PrivateKeyLength) {
484   // Use a custom P, rather than one of the MODP primes, to pick one which does
485   // not begin with all ones. Otherwise some of the tests for boundary
486   // conditions below will not notice mistakes.
487   static const uint8_t kP[] = {
488       0xb6, 0xfa, 0x00, 0x07, 0x0a, 0x1f, 0xfb, 0x28, 0x7e, 0x6e, 0x6a, 0x97,
489       0xca, 0xa4, 0x6d, 0xf5, 0x25, 0x84, 0x76, 0xc6, 0xc4, 0xa5, 0x47, 0xb6,
490       0xb2, 0x7d, 0x76, 0x46, 0xf2, 0xb5, 0x7c, 0xc6, 0xc6, 0xb4, 0xb4, 0x82,
491       0xc5, 0xed, 0x7b, 0xd9, 0x30, 0x6e, 0x41, 0xdb, 0x7f, 0x93, 0x2f, 0xb5,
492       0x85, 0xa7, 0x38, 0x9e, 0x08, 0xc4, 0x25, 0x92, 0x7d, 0x5d, 0x2b, 0x77,
493       0x09, 0xe0, 0x2f, 0x4e, 0x14, 0x36, 0x8a, 0x08, 0x0b, 0xfd, 0x89, 0x22,
494       0x47, 0xb4, 0xbd, 0xff, 0x79, 0x4e, 0x78, 0x66, 0x2a, 0x77, 0x74, 0xbd,
495       0x85, 0xb6, 0xce, 0x5a, 0x89, 0xb7, 0x60, 0xc3, 0x8d, 0x2a, 0x1f, 0xb7,
496       0x30, 0x33, 0x1a, 0xc4, 0x51, 0xa8, 0x18, 0x62, 0x40, 0xb6, 0x5a, 0xb5,
497       0x6c, 0xf5, 0xf9, 0xbc, 0x94, 0x50, 0xba, 0xeb, 0xa2, 0xe9, 0xb3, 0x99,
498       0xde, 0xf8, 0x55, 0xfd, 0xed, 0x46, 0x1b, 0x69, 0xa5, 0x6a, 0x04, 0xe3,
499       0xa9, 0x2c, 0x0c, 0x89, 0x41, 0xfe, 0xe4, 0xa0, 0x85, 0x85, 0x2c, 0x45,
500       0xf1, 0xcb, 0x96, 0x04, 0x23, 0x4a, 0x7d, 0x56, 0x38, 0xd8, 0x86, 0x9d,
501       0xfc, 0xe0, 0x33, 0x65, 0x1a, 0xff, 0x07, 0xf0, 0xfb, 0xc6, 0x5d, 0x26,
502       0xa2, 0x96, 0xd4, 0xb5, 0xe8, 0xcd, 0x48, 0xd7, 0x8e, 0x53, 0xfe, 0xcb,
503       0x4b, 0xf2, 0x3a, 0x8b, 0x35, 0x87, 0x0a, 0x79, 0xbe, 0x8d, 0x36, 0x45,
504       0x12, 0x6e, 0x1b, 0xd4, 0xa5, 0x57, 0xe0, 0x98, 0xb7, 0x59, 0xba, 0xc2,
505       0xd8, 0x2e, 0x05, 0x0f, 0xe1, 0x70, 0x39, 0x5b, 0xe6, 0x4e, 0xdb, 0xb0,
506       0xdd, 0x7e, 0xe6, 0x66, 0x13, 0x85, 0x26, 0x32, 0x27, 0xa1, 0x00, 0x7f,
507       0x6a, 0xa9, 0xda, 0x2e, 0x50, 0x25, 0x87, 0x73, 0xab, 0x71, 0xfb, 0xa0,
508       0x92, 0xba, 0x8e, 0x9c, 0x4e, 0xea, 0x18, 0x32, 0xc4, 0x02, 0x8f, 0xe8,
509       0x95, 0x9e, 0xcb, 0x9f};
510   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
511   ASSERT_TRUE(p);
512   bssl::UniquePtr<BIGNUM> g(BN_new());
513   ASSERT_TRUE(g);
514   ASSERT_TRUE(BN_set_word(g.get(), 2));
515   bssl::UniquePtr<BIGNUM> q(BN_new());
516   ASSERT_TRUE(q);
517   ASSERT_TRUE(BN_rshift1(q.get(), p.get()));  // (p-1)/2
518 
519   EXPECT_EQ(BN_num_bits(p.get()), 2048u);
520   EXPECT_EQ(BN_num_bits(q.get()), 2047u);
521 
522   // This test will only probabilistically notice some kinds of failures, so we
523   // repeat it for several iterations.
524   constexpr unsigned kIterations = 100;
525 
526   // If the private key was chosen from the range [1, M), num_bits(priv_key)
527   // should be very close to num_bits(M), but may be a few bits short. Allow 128
528   // leading zeros, which should fail with negligible probability.
529   constexpr unsigned kMaxLeadingZeros = 128;
530 
531   for (unsigned i = 0; i < kIterations; i++) {
532     // If unspecified, the private key is bounded by q = (p-1)/2.
533     bssl::UniquePtr<DH> dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
534     ASSERT_TRUE(dh);
535     ASSERT_TRUE(DH_generate_key(dh.get()));
536     EXPECT_LT(BN_cmp(DH_get0_priv_key(dh.get()), q.get()), 0);
537     EXPECT_LE(BN_num_bits(q.get()) - kMaxLeadingZeros,
538               BN_num_bits(DH_get0_priv_key(dh.get())));
539 
540     // Setting too large of a private key length should not be a DoS vector. The
541     // key is clamped to q = (p-1)/2.
542     dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
543     ASSERT_TRUE(dh);
544     DH_set_length(dh.get(), 10000000);
545     ASSERT_TRUE(DH_generate_key(dh.get()));
546     EXPECT_LT(BN_cmp(DH_get0_priv_key(dh.get()), q.get()), 0);
547     EXPECT_LE(BN_num_bits(q.get()) - kMaxLeadingZeros,
548               BN_num_bits(DH_get0_priv_key(dh.get())));
549 
550     // A small private key size should bound the private key.
551     dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
552     ASSERT_TRUE(dh);
553     unsigned bits = 1024;
554     DH_set_length(dh.get(), bits);
555     ASSERT_TRUE(DH_generate_key(dh.get()));
556     EXPECT_LE(BN_num_bits(DH_get0_priv_key(dh.get())), bits);
557     EXPECT_LE(bits - kMaxLeadingZeros, BN_num_bits(DH_get0_priv_key(dh.get())));
558 
559     // If the private key length is num_bits(q) - 1, the length should be the
560     // limiting factor.
561     dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
562     ASSERT_TRUE(dh);
563     bits = BN_num_bits(q.get()) - 1;
564     DH_set_length(dh.get(), bits);
565     ASSERT_TRUE(DH_generate_key(dh.get()));
566     EXPECT_LE(BN_num_bits(DH_get0_priv_key(dh.get())), bits);
567     EXPECT_LE(bits - kMaxLeadingZeros, BN_num_bits(DH_get0_priv_key(dh.get())));
568 
569     // If the private key length is num_bits(q), q should be the limiting
570     // factor.
571     dh = NewDHGroup(p.get(), /*q=*/nullptr, g.get());
572     ASSERT_TRUE(dh);
573     DH_set_length(dh.get(), BN_num_bits(q.get()));
574     ASSERT_TRUE(DH_generate_key(dh.get()));
575     EXPECT_LT(BN_cmp(DH_get0_priv_key(dh.get()), q.get()), 0);
576     EXPECT_LE(BN_num_bits(q.get()) - kMaxLeadingZeros,
577               BN_num_bits(DH_get0_priv_key(dh.get())));
578   }
579 }
580