summaryrefslogtreecommitdiff
path: root/src/regress/lib
diff options
context:
space:
mode:
authortb <>2023-07-15 23:35:02 +0000
committertb <>2023-07-15 23:35:02 +0000
commita3de466a9035cfd69b15a0f9f811bc3d390abac0 (patch)
treeca53265baddfe5012b1fea46a97ee975ca002bc1 /src/regress/lib
parent6b86b41983f40fcc0b8c5b5cd3b747d9139c6a28 (diff)
downloadopenbsd-a3de466a9035cfd69b15a0f9f811bc3d390abac0.tar.gz
openbsd-a3de466a9035cfd69b15a0f9f811bc3d390abac0.tar.bz2
openbsd-a3de466a9035cfd69b15a0f9f811bc3d390abac0.zip
Rework the ecdhtest
Test keyshare for all built-in curves and simplify, especially printing on failure. Incorporate known answer tests from RFC 5114 and RFC 5903. All in all, this is a lot less code and a lot more test coverage and hopefully a little less eyebleed. Very loosely based on OpenSSL b438f0ed by Billy Brumley
Diffstat (limited to 'src/regress/lib')
-rw-r--r--src/regress/lib/libcrypto/ecdh/ecdhtest.c512
1 files changed, 252 insertions, 260 deletions
diff --git a/src/regress/lib/libcrypto/ecdh/ecdhtest.c b/src/regress/lib/libcrypto/ecdh/ecdhtest.c
index 6388343cfe..fc534f14bd 100644
--- a/src/regress/lib/libcrypto/ecdh/ecdhtest.c
+++ b/src/regress/lib/libcrypto/ecdh/ecdhtest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecdhtest.c,v 1.17 2023/07/15 20:11:37 tb Exp $ */ 1/* $OpenBSD: ecdhtest.c,v 1.18 2023/07/15 23:35:02 tb Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 * 4 *
@@ -67,6 +67,7 @@
67 * 67 *
68 */ 68 */
69 69
70#include <err.h>
70#include <stdio.h> 71#include <stdio.h>
71#include <stdlib.h> 72#include <stdlib.h>
72#include <string.h> 73#include <string.h>
@@ -81,6 +82,18 @@
81#include <openssl/ec.h> 82#include <openssl/ec.h>
82#include <openssl/ecdh.h> 83#include <openssl/ecdh.h>
83 84
85static void
86hexdump(const unsigned char *buf, size_t len)
87{
88 size_t i;
89
90 for (i = 1; i <= len; i++)
91 fprintf(stdout, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
92
93 if (len % 8)
94 fprintf(stdout, "\n");
95}
96
84static const int KDF1_SHA1_len = 20; 97static const int KDF1_SHA1_len = 20;
85static void * 98static void *
86KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) 99KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
@@ -96,335 +109,314 @@ KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
96#endif 109#endif
97} 110}
98 111
99
100static int 112static int
101test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) 113ecdh_keygen_test(int nid)
102{ 114{
103 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; 115 EC_KEY *keya = NULL, *keyb = NULL;
104 EC_KEY *a = NULL, *b = NULL; 116 const EC_POINT *puba, *pubb;
105 const EC_GROUP *group;
106 unsigned char *abuf = NULL, *bbuf = NULL; 117 unsigned char *abuf = NULL, *bbuf = NULL;
107 int i, alen, blen, aout, bout, ret = 0; 118 int len = KDF1_SHA1_len;
108 char buf[12]; 119 int failed = 1;
109 120
110 a = EC_KEY_new_by_curve_name(nid); 121 if ((keya = EC_KEY_new_by_curve_name(nid)) == NULL)
111 b = EC_KEY_new_by_curve_name(nid);
112 if (a == NULL || b == NULL)
113 goto err; 122 goto err;
114 123 if (!EC_KEY_generate_key(keya))
115 group = EC_KEY_get0_group(a);
116
117 if ((x_a = BN_new()) == NULL)
118 goto err; 124 goto err;
119 if ((y_a = BN_new()) == NULL) 125 if ((puba = EC_KEY_get0_public_key(keya)) == NULL)
120 goto err; 126 goto err;
121 if ((x_b = BN_new()) == NULL) 127
128 if ((keyb = EC_KEY_new_by_curve_name(nid)) == NULL)
122 goto err; 129 goto err;
123 if ((y_b = BN_new()) == NULL) 130 if (!EC_KEY_generate_key(keyb))
124 goto err; 131 goto err;
125 132 if ((pubb = EC_KEY_get0_public_key(keyb)) == NULL)
126 BIO_puts(out, "Testing key generation with ");
127 BIO_puts(out, text);
128 (void)BIO_flush(out);
129
130 if (!EC_KEY_generate_key(a))
131 goto err; 133 goto err;
132 134
133 if (!EC_POINT_get_affine_coordinates(group, 135 if ((abuf = calloc(1, len)) == NULL)
134 EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err; 136 goto err;
135 137 if ((bbuf = calloc(1, len)) == NULL)
136 BIO_printf(out, " .");
137 (void)BIO_flush(out);
138
139 if (!EC_KEY_generate_key(b))
140 goto err; 138 goto err;
141 139
142 if (!EC_POINT_get_affine_coordinates(group, 140 if (ECDH_compute_key(abuf, len, pubb, keya, KDF1_SHA1) != len)
143 EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err; 141 goto err;
144 142 if (ECDH_compute_key(bbuf, len, puba, keyb, KDF1_SHA1) != len)
145 BIO_printf(out, ".");
146 (void)BIO_flush(out);
147
148 alen = KDF1_SHA1_len;
149 if ((abuf = malloc(alen)) == NULL)
150 goto err; 143 goto err;
151 aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b),
152 a, KDF1_SHA1);
153 144
154 BIO_printf(out, "."); 145 if (memcmp(abuf, bbuf, len) != 0) {
155 (void)BIO_flush(out); 146 printf("key generation with %s failed\n", OBJ_nid2sn(nid));
156 147
157 blen = KDF1_SHA1_len; 148 EC_KEY_print_fp(stdout, keya, 1);
158 if ((bbuf = malloc(blen)) == NULL) 149 printf(" shared secret:\n");
159 goto err; 150 hexdump(abuf, len);
160 bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a),
161 b, KDF1_SHA1);
162 151
163 BIO_printf(out, "."); 152 printf("key b:\n");
164 (void)BIO_flush(out); 153 EC_KEY_print_fp(stdout, keyb, 1);
154 printf(" shared secret:\n");
155 hexdump(abuf, len);
165 156
166 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
167 BIO_printf(out, " failed\n\n");
168 BIO_printf(out, "key a:\n");
169 BIO_printf(out, "private key: ");
170 BN_print(out, EC_KEY_get0_private_key(a));
171 BIO_printf(out, "\n");
172 BIO_printf(out, "public key (x,y): ");
173 BN_print(out, x_a);
174 BIO_printf(out, ",");
175 BN_print(out, y_a);
176 BIO_printf(out, "\nkey b:\n");
177 BIO_printf(out, "private key: ");
178 BN_print(out, EC_KEY_get0_private_key(b));
179 BIO_printf(out, "\n");
180 BIO_printf(out, "public key (x,y): ");
181 BN_print(out, x_b);
182 BIO_printf(out, ",");
183 BN_print(out, y_b);
184 BIO_printf(out, "\n");
185 BIO_printf(out, "generated key a: ");
186 for (i = 0; i < bout; i++) {
187 snprintf(buf, sizeof buf, "%02X", bbuf[i]);
188 BIO_puts(out, buf);
189 }
190 BIO_printf(out, "\n");
191 BIO_printf(out, "generated key b: ");
192 for (i = 0; i < aout; i++) {
193 snprintf(buf, sizeof buf, "%02X", abuf[i]);
194 BIO_puts(out, buf);
195 }
196 BIO_printf(out, "\n");
197 fprintf(stderr, "Error in ECDH routines\n"); 157 fprintf(stderr, "Error in ECDH routines\n");
198 ret = 0; 158
199 } else { 159 goto err;
200 BIO_printf(out, " ok\n");
201 ret = 1;
202 } 160 }
203 161
204err: 162 failed = 0;
163 err:
205 ERR_print_errors_fp(stderr); 164 ERR_print_errors_fp(stderr);
206 165
207 free(abuf); 166 EC_KEY_free(keya);
208 free(bbuf); 167 EC_KEY_free(keyb);
209 BN_free(x_a); 168 freezero(abuf, len);
210 BN_free(y_a); 169 freezero(bbuf, len);
211 BN_free(x_b);
212 BN_free(y_b);
213 EC_KEY_free(b);
214 EC_KEY_free(a);
215 170
216 return (ret); 171 return failed;
217} 172}
218 173
219/* Keys and shared secrets from RFC 7027 */ 174static const struct ecdh_kat_test {
220 175 const int nid;
221static const unsigned char bp256_da[] = { 176 const char *keya;
222 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70, 177 const char *keyb;
223 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50, 178 const char *want;
224 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D 179} ecdh_kat_tests[] = {
225}; 180 /* Keys and shared secrets from RFC 5114 */
226 181 {
227static const unsigned char bp256_db[] = { 182 .nid = NID_X9_62_prime192v1,
228 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6, 183 .keya = "323fa3169d8e9c6593f59476bc142000ab5be0e249c43426",
229 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87, 184 .keyb = "631f95bb4a67632c9c476eee9ab695ab240a0499307fcf62",
230 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3 185 .want = "ad420182633f8526bfe954acda376f05e5ff4f837f54febe",
231}; 186 },
232 187 {
233static const unsigned char bp256_Z[] = { 188 .nid = NID_secp224r1,
234 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94, 189 .keya = "b558eb6c288da707bbb4f8fbae2ab9e9cb62e3bc5c7573e2"
235 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79, 190 "2e26d37f",
236 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B 191 .keyb = "ac3b1add3d9770e6f6a708ee9f3b8e0ab3b480e9f27f85c8"
237}; 192 "8b5e6d18",
238 193 .want = "52272f50f46f4edc9151569092f46df2d96ecc3b6dc1714a"
239static const unsigned char bp384_da[] = { 194 "4ea949fa",
240 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74, 195 },
241 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D, 196 {
242 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1, 197 .nid = NID_X9_62_prime256v1,
243 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42 198 .keya = "814264145f2f56f2e96a8e337a1284993faf432a5abce59e"
244}; 199 "867b7291d507a3af",
245 200 .keyb = "2ce1788ec197e096db95a200cc0ab26a19ce6bccad562b8e"
246static const unsigned char bp384_db[] = { 201 "ee1b593761cf7f41",
247 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C, 202 .want = "dd0f5396219d1ea393310412d19a08f1f5811e9dc8ec8eea"
248 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A, 203 "7f80d21c820c2788",
249 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32, 204 },
250 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70 205 {
251}; 206 .nid = NID_secp384r1,
252 207 .keya = "d27335ea71664af244dd14e9fd1260715dfd8a7965571c48"
253static const unsigned char bp384_Z[] = { 208 "d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1",
254 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4, 209 .keyb = "52d1791fdb4b70f89c0f00d456c2f7023b6125262c36a7df"
255 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC, 210 "1f80231121cce3d39be52e00c194a4132c4a6c768bcd94d2",
256 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37, 211 .want = "5ea1fc4af7256d2055981b110575e0a8cae53160137d904c"
257 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42 212 "59d926eb1b8456e427aa8a4540884c37de159a58028abc0e",
258}; 213 },
259 214 {
260static const unsigned char bp512_da[] = { 215 .nid = NID_secp521r1,
261 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71, 216 .keya = "0113f82da825735e3d97276683b2b74277bad27335ea7166"
262 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A, 217 "4af2430cc4f33459b9669ee78b3ffb9b8683015d344dcbfe"
263 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27, 218 "f6fb9af4c6c470be254516cd3c1a1fb47362",
264 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2, 219 .keyb = "00cee3480d8645a17d249f2776d28bae616952d1791fdb4b"
265 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD, 220 "70f7c3378732aa1b22928448bcd1dc2496d435b01048066e"
266 0x57, 0x66, 0x54, 0x22 221 "be4f72903c361b1a9dc1193dc2c9d0891b96",
267}; 222 .want = "00cdea89621cfa46b132f9e4cfe2261cde2d4368eb565663"
268 223 "4c7cc98c7a00cde54ed1866a0dd3e6126c9d2f845daff82c"
269static const unsigned char bp512_db[] = { 224 "eb1da08f5d87521bb0ebeca77911169c20cc",
270 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E, 225 },
271 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4, 226 /* Keys and shared secrets from RFC 5903 */
272 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96, 227 {
273 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7, 228 .nid = NID_X9_62_prime256v1,
274 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36, 229 .keya = "c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049"
275 0x66, 0xB2, 0x54, 0x29 230 "c62a9c57862d1433",
231 .keyb = "c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0"
232 "b283ab46476bee53",
233 .want = "d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03"
234 "812464d04b9442de",
235 },
236 {
237 .nid = NID_secp384r1,
238 .keya = "099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f16"
239 "0647b67414dce655e35b538041e649ee3faef896783ab194",
240 .keyb = "41cb0779b4bdb85d47846725fbec3c9430fab46cc8dc5060"
241 "855cc9bda0aa2942e0308312916b8ed2960e4bd55a7448fc",
242 .want = "11187331c279962d93d604243fd592cb9d0a926f422e4718"
243 "7521287e7156c5c4d603135569b9e9d09cf5d4a270f59746",
244 },
245 {
246 .nid = NID_secp521r1,
247 .keya = "0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5"
248 "393dce47608172a095aa85a30fe1c2952c6771d937ba9777"
249 "f5957b2639bab072462f68c27a57382d"
250 "4a52",
251 .keyb = "0145ba99a847af43793fdd0e872e7cdfa16be30fdc780f97"
252 "bccc3f078380201e9c677d600b343757a3bdbf2a3163e4c2"
253 "f869cca7458aa4a4effc311f5cb151685eb9",
254 .want = "01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f9"
255 "7894e5e6b2d79b04d1427e73ca4baa240a34786859810c06"
256 "b3c715a3a8cc3151f2bee417996d19f3ddea",
257 },
258 /* Keys and shared secrets from RFC 7027 */
259 {
260 .nid = NID_brainpoolP256r1,
261 .keya = "81db1ee100150ff2ea338d708271be38300cb54241d79950"
262 "f77b063039804f1d",
263 .keyb = "55e40bc41e37e3e2ad25c3c6654511ffa8474a91a0032087"
264 "593852d3e7d76bd3",
265 .want = "89afc39d41d3b327814b80940b042590f96556ec91e6ae79"
266 "39bce31f3a18bf2b",
267 },
268 {
269 .nid = NID_brainpoolP384r1,
270 .keya = "1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d"
271 "57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042",
272 .keyb = "032640bc6003c59260f7250c3db58ce647f98e1260acce4a"
273 "cda3dd869f74e01f8ba5e0324309db6a9831497abac96670",
274 .want = "0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc"
275 "51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42",
276 },
277 {
278 .nid = NID_brainpoolP512r1,
279 .keya = "16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a"
280 "56850a38bd87bd59b09e80279609ff333eb9d4c061231fb2"
281 "6f92eeb04982a5f1d1764cad57665422",
282 .keyb = "230e18e1bcc88a362fa54e4ea3902009292f7f8033624fd4"
283 "71b5d8ace49d12cfabbc19963dab8e2f1eba00bffb29e4d7"
284 "2d13f2224562f405cb80503666b25429",
285 .want = "a7927098655f1f9976fa50a9d566865dc530331846381c87"
286 "256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d"
287 "24f11a9b5c0bef679fe1454b21c4cd1f",
288 },
276}; 289};
277 290
278 291#define N_KATS (sizeof(ecdh_kat_tests) / sizeof(ecdh_kat_tests[0]))
279static const unsigned char bp512_Z[] = {
280 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
281 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
282 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
283 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
284 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
285 0x21, 0xC4, 0xCD, 0x1F
286};
287 292
288/* Given private value and NID, create EC_KEY structure */ 293/* Given private value and NID, create EC_KEY structure */
289 294
290static EC_KEY * 295static EC_KEY *
291mk_eckey(int nid, const unsigned char *p, size_t plen) 296mk_eckey(int nid, const char *priv_str)
292{ 297{
293 EC_KEY *k = NULL; 298 EC_KEY *key = NULL;
294 BIGNUM *priv = NULL; 299 BIGNUM *priv = NULL;
295 EC_POINT *pub = NULL; 300 EC_POINT *pub = NULL;
296 const EC_GROUP *grp; 301 const EC_GROUP *group;
297 int ok = 0; 302 EC_KEY *ret = NULL;
298 303
299 k = EC_KEY_new_by_curve_name(nid); 304 if ((key = EC_KEY_new_by_curve_name(nid)) == NULL)
300 if (!k)
301 goto err; 305 goto err;
302 priv = BN_bin2bn(p, plen, NULL); 306 if (!BN_hex2bn(&priv, priv_str))
303 if (!priv)
304 goto err; 307 goto err;
305 if (!EC_KEY_set_private_key(k, priv)) 308 if (!EC_KEY_set_private_key(key, priv))
306 goto err; 309 goto err;
307 grp = EC_KEY_get0_group(k); 310 if ((group = EC_KEY_get0_group(key)) == NULL)
308 pub = EC_POINT_new(grp);
309 if (!pub)
310 goto err; 311 goto err;
311 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL)) 312 if ((pub = EC_POINT_new(group)) == NULL)
312 goto err; 313 goto err;
313 if (!EC_KEY_set_public_key(k, pub)) 314 if (!EC_POINT_mul(group, pub, priv, NULL, NULL, NULL))
314 goto err; 315 goto err;
315 ok = 1; 316 if (!EC_KEY_set_public_key(key, pub))
316err: 317 goto err;
318
319 ret = key;
320 key = NULL;
321
322 err:
323 EC_KEY_free(key);
317 BN_free(priv); 324 BN_free(priv);
318 EC_POINT_free(pub); 325 EC_POINT_free(pub);
319 if (!ok) { 326
320 EC_KEY_free(k); 327 return ret;
321 k = NULL;
322 }
323 return (k);
324} 328}
325 329
326/* Known answer test: compute shared secret and check it matches 330/*
327 * expected value. 331 * Known answer test: compute shared secret and check it matches expected value.
328 */ 332 */
329
330static int 333static int
331ecdh_kat(BIO *out, const char *cname, int nid, 334ecdh_kat(const struct ecdh_kat_test *kat)
332 const unsigned char *k1, size_t k1_len,
333 const unsigned char *k2, size_t k2_len,
334 const unsigned char *Z, size_t Zlen)
335{ 335{
336 int rv = 0; 336 EC_KEY *keya = NULL, *keyb = NULL;
337 EC_KEY *key1 = NULL, *key2 = NULL; 337 const EC_POINT *puba, *pubb;
338 unsigned char *Ztmp = NULL; 338 BIGNUM *z = NULL;
339 size_t Ztmplen; 339 unsigned char *want = NULL, *got = NULL;
340 BIO_puts(out, "Testing ECDH shared secret with "); 340 int len = 0;
341 BIO_puts(out, cname); 341 int failed = 0;
342 key1 = mk_eckey(nid, k1, k1_len); 342
343 key2 = mk_eckey(nid, k2, k2_len); 343 if ((keya = mk_eckey(kat->nid, kat->keya)) == NULL)
344 if (!key1 || !key2) 344 goto err;
345 if ((puba = EC_KEY_get0_public_key(keya)) == NULL)
346 goto err;
347 if ((keyb = mk_eckey(kat->nid, kat->keyb)) == NULL)
348 goto err;
349 if ((pubb = EC_KEY_get0_public_key(keyb)) == NULL)
350 goto err;
351
352 if ((len = ECDH_size(keya)) != ECDH_size(keyb))
353 goto err;
354
355 if ((want = calloc(1, len)) == NULL)
356 goto err;
357 if ((got = calloc(1, len)) == NULL)
358 goto err;
359
360 if (!BN_hex2bn(&z, kat->want))
345 goto err; 361 goto err;
346 Ztmplen = ECDH_size(key1); 362 if (BN_num_bytes(z) > len)
347 if (Ztmplen != Zlen)
348 goto err; 363 goto err;
349 if ((Ztmp = malloc(Ztmplen)) == NULL) 364 if (BN_bn2binpad(z, want, len) != len)
350 goto err; 365 goto err;
351 if (ECDH_compute_key(Ztmp, Ztmplen, 366
352 EC_KEY_get0_public_key(key2), key1, 0) <= 0) 367 if (ECDH_compute_key(got, len, pubb, keya, NULL) != len)
353 goto err; 368 goto err;
354 if (memcmp(Ztmp, Z, Zlen)) 369 if (memcmp(got, want, len) != 0)
355 goto err; 370 goto err;
356 memset(Ztmp, 0, Zlen); 371
357 if (ECDH_compute_key(Ztmp, Ztmplen, 372 memset(got, 0, len);
358 EC_KEY_get0_public_key(key1), key2, 0) <= 0) 373
374 if (ECDH_compute_key(got, len, puba, keyb, NULL) != len)
359 goto err; 375 goto err;
360 if (memcmp(Ztmp, Z, Zlen)) 376 if (memcmp(got, want, len) != 0)
361 goto err; 377 goto err;
362 rv = 1;
363 378
364err: 379 failed = 0;
365 if (rv) 380
366 BIO_puts(out, " ok\n"); 381 err:
367 else { 382 if (failed) {
383 printf("ECDH shared secret with %s failed", OBJ_nid2sn(kat->nid));
384
368 fprintf(stderr, "Error in ECDH routines\n"); 385 fprintf(stderr, "Error in ECDH routines\n");
369 ERR_print_errors_fp(stderr); 386 ERR_print_errors_fp(stderr);
370 } 387 }
371 388
372 EC_KEY_free(key1); 389 EC_KEY_free(keya);
373 EC_KEY_free(key2); 390 EC_KEY_free(keyb);
374 free(Ztmp); 391 BN_free(z);
392 freezero(want, len);
393 freezero(got, len);
375 394
376 return rv; 395 return failed;
377} 396}
378 397
379#define test_ecdh_kat(bio, curve, bits) \
380 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
381 bp##bits##_da, sizeof(bp##bits##_da), \
382 bp##bits##_db, sizeof(bp##bits##_db), \
383 bp##bits##_Z, sizeof(bp##bits##_Z))
384
385int 398int
386main(int argc, char *argv[]) 399main(int argc, char *argv[])
387{ 400{
388 BN_CTX *ctx = NULL; 401 EC_builtin_curve *curves = NULL;
389 int ret = 1; 402 size_t i, n_curves;
390 BIO *out; 403 int failed = 0;
391 404
392 out = BIO_new(BIO_s_file()); 405 if ((n_curves = EC_get_builtin_curves(NULL, 0)) == 0)
393 if (out == NULL) 406 errx(1, "EC_get_builtin_curves failed");
394 exit(1); 407 if ((curves = calloc(n_curves, sizeof(*curves))) == NULL)
395 BIO_set_fp(out, stdout, BIO_NOCLOSE); 408 errx(1, NULL);
396 409 if (EC_get_builtin_curves(curves, n_curves) != n_curves)
397 if ((ctx = BN_CTX_new()) == NULL) 410 errx(1, "EC_get_builtin_curves failed");
398 goto err;
399 411
400 /* NIST PRIME CURVES TESTS */ 412 for (i = 0; i < n_curves; i++)
401 if (!test_ecdh_curve(NID_X9_62_prime192v1, "NIST Prime-Curve P-192", 413 failed |= ecdh_keygen_test(curves[i].nid);
402 ctx, out))
403 goto err;
404 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
405 goto err;
406 if (!test_ecdh_curve(NID_X9_62_prime256v1, "NIST Prime-Curve P-256",
407 ctx, out))
408 goto err;
409 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
410 goto err;
411 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
412 goto err;
413 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
414 goto err;
415 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
416 goto err;
417 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
418 goto err;
419 414
420 ret = 0; 415 for (i = 0; i < N_KATS; i++)
416 failed |= ecdh_kat(&ecdh_kat_tests[i]);
421 417
422err: 418 free(curves);
423 ERR_print_errors_fp(stderr); 419 ERR_print_errors_fp(stderr);
424 BN_CTX_free(ctx); 420
425 BIO_free(out); 421 return failed;
426 CRYPTO_cleanup_all_ex_data();
427 ERR_remove_thread_state(NULL);
428 CRYPTO_mem_leaks_fp(stderr);
429 exit(ret);
430} 422}