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