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