diff options
author | tb <> | 2023-07-15 23:35:02 +0000 |
---|---|---|
committer | tb <> | 2023-07-15 23:35:02 +0000 |
commit | a3de466a9035cfd69b15a0f9f811bc3d390abac0 (patch) | |
tree | ca53265baddfe5012b1fea46a97ee975ca002bc1 /src/regress/lib | |
parent | 6b86b41983f40fcc0b8c5b5cd3b747d9139c6a28 (diff) | |
download | openbsd-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.c | 512 |
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 | ||
85 | static void | ||
86 | hexdump(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 | |||
84 | static const int KDF1_SHA1_len = 20; | 97 | static const int KDF1_SHA1_len = 20; |
85 | static void * | 98 | static void * |
86 | KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) | 99 | KDF1_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 | |||
100 | static int | 112 | static int |
101 | test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) | 113 | ecdh_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 | ||
204 | err: | 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 */ | 174 | static const struct ecdh_kat_test { |
220 | 175 | const int nid; | |
221 | static 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 | { | |
227 | static 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 | { | |
233 | static 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" | |
239 | static 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" | |
246 | static 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" | |
253 | static 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 | { | |
260 | static 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" | |
269 | static 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])) | |
279 | static 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 | ||
290 | static EC_KEY * | 295 | static EC_KEY * |
291 | mk_eckey(int nid, const unsigned char *p, size_t plen) | 296 | mk_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)) |
316 | err: | 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 | |||
330 | static int | 333 | static int |
331 | ecdh_kat(BIO *out, const char *cname, int nid, | 334 | ecdh_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 | ||
364 | err: | 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 | |||
385 | int | 398 | int |
386 | main(int argc, char *argv[]) | 399 | main(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 | ||
422 | err: | 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 | } |