diff options
Diffstat (limited to 'src/regress/lib/libcrypto/ec/ec_asn1_test.c')
-rw-r--r-- | src/regress/lib/libcrypto/ec/ec_asn1_test.c | 321 |
1 files changed, 199 insertions, 122 deletions
diff --git a/src/regress/lib/libcrypto/ec/ec_asn1_test.c b/src/regress/lib/libcrypto/ec/ec_asn1_test.c index 03358e69ca..50e6304baf 100644 --- a/src/regress/lib/libcrypto/ec/ec_asn1_test.c +++ b/src/regress/lib/libcrypto/ec/ec_asn1_test.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* $OpenBSD: ec_asn1_test.c,v 1.32 2025/03/08 20:09:35 tb Exp $ */ | 1 | /* $OpenBSD: ec_asn1_test.c,v 1.36 2025/07/23 07:42:33 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2024, 2025 Theo Buehler <tb@openbsd.org> |
5 | * | 5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any | 6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,12 +17,17 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <err.h> | 19 | #include <err.h> |
20 | #include <stdio.h> | ||
21 | #include <stdint.h> | ||
22 | #include <stdlib.h> | ||
20 | #include <string.h> | 23 | #include <string.h> |
21 | 24 | ||
22 | #include <openssl/bio.h> | 25 | #include <openssl/bio.h> |
26 | #include <openssl/bn.h> | ||
23 | #include <openssl/ec.h> | 27 | #include <openssl/ec.h> |
24 | #include <openssl/err.h> | 28 | #include <openssl/err.h> |
25 | #include <openssl/objects.h> | 29 | #include <openssl/objects.h> |
30 | #include <openssl/sha.h> | ||
26 | 31 | ||
27 | #include "ec_local.h" | 32 | #include "ec_local.h" |
28 | 33 | ||
@@ -1281,126 +1286,6 @@ static const struct ec_private_key { | |||
1281 | }, | 1286 | }, |
1282 | }, | 1287 | }, |
1283 | { | 1288 | { |
1284 | .name = "prime239v1", | ||
1285 | .der_len = 115, | ||
1286 | .der = { | ||
1287 | 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x6e, | ||
1288 | 0x26, 0x5e, 0xde, 0x5b, 0x67, 0xd6, 0x38, 0x52, | ||
1289 | 0xe7, 0x1e, 0x8d, 0x44, 0xb1, 0xfb, 0xf8, 0xaf, | ||
1290 | 0xf9, 0x94, 0x2c, 0xe2, 0x0d, 0xa8, 0x5f, 0x03, | ||
1291 | 0x67, 0x53, 0x7b, 0x8b, 0x2e, 0xa0, 0x0a, 0x06, | ||
1292 | 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, | ||
1293 | 0x04, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x33, | ||
1294 | 0xc6, 0xe5, 0x8a, 0xc1, 0x8b, 0x7c, 0x96, 0x19, | ||
1295 | 0xc9, 0xe1, 0x54, 0x7f, 0x81, 0x9e, 0x59, 0x62, | ||
1296 | 0xec, 0xc0, 0x1e, 0xe5, 0x53, 0xd5, 0xae, 0x6b, | ||
1297 | 0xd3, 0xe0, 0x09, 0x07, 0xc5, 0x27, 0x81, 0xa6, | ||
1298 | 0x8d, 0x39, 0x8e, 0xfe, 0x01, 0xc2, 0x1d, 0xda, | ||
1299 | 0xde, 0x7b, 0xdc, 0x76, 0x27, 0x17, 0xf9, 0x6f, | ||
1300 | 0xe3, 0x04, 0xef, 0x5d, 0x65, 0x75, 0x98, 0x7f, | ||
1301 | 0x2d, 0xd0, 0x68, | ||
1302 | }, | ||
1303 | .hex = "0433C6E58AC18B7C" | ||
1304 | "9619C9E1547F819E" | ||
1305 | "5962ECC01EE553D5" | ||
1306 | "AE6BD3E00907C527" | ||
1307 | "81A68D398EFE01C2" | ||
1308 | "1DDADE7BDC762717" | ||
1309 | "F96FE304EF5D6575" | ||
1310 | "987F2DD068", | ||
1311 | .oct_len = 61, | ||
1312 | .oct = { | ||
1313 | 0x04, 0x33, 0xc6, 0xe5, 0x8a, 0xc1, 0x8b, 0x7c, | ||
1314 | 0x96, 0x19, 0xc9, 0xe1, 0x54, 0x7f, 0x81, 0x9e, | ||
1315 | 0x59, 0x62, 0xec, 0xc0, 0x1e, 0xe5, 0x53, 0xd5, | ||
1316 | 0xae, 0x6b, 0xd3, 0xe0, 0x09, 0x07, 0xc5, 0x27, | ||
1317 | 0x81, 0xa6, 0x8d, 0x39, 0x8e, 0xfe, 0x01, 0xc2, | ||
1318 | 0x1d, 0xda, 0xde, 0x7b, 0xdc, 0x76, 0x27, 0x17, | ||
1319 | 0xf9, 0x6f, 0xe3, 0x04, 0xef, 0x5d, 0x65, 0x75, | ||
1320 | 0x98, 0x7f, 0x2d, 0xd0, 0x68, | ||
1321 | }, | ||
1322 | }, | ||
1323 | { | ||
1324 | .name = "prime239v2", | ||
1325 | .der_len = 115, | ||
1326 | .der = { | ||
1327 | 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x30, | ||
1328 | 0x2f, 0x01, 0x10, 0xe9, 0x09, 0x15, 0xdd, 0xe3, | ||
1329 | 0xdd, 0xae, 0xcb, 0x9d, 0x3a, 0x58, 0x92, 0x02, | ||
1330 | 0x1e, 0x6e, 0x02, 0x57, 0xa8, 0x36, 0x0b, 0x20, | ||
1331 | 0x0b, 0x7e, 0xf4, 0xad, 0x0b, 0xa0, 0x0a, 0x06, | ||
1332 | 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, | ||
1333 | 0x05, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x3c, | ||
1334 | 0x10, 0x27, 0x7b, 0xac, 0xdf, 0x86, 0xc9, 0x4f, | ||
1335 | 0xf8, 0x39, 0x87, 0x02, 0x39, 0xaf, 0x41, 0xbc, | ||
1336 | 0x4b, 0x67, 0xd8, 0x5e, 0x04, 0x96, 0x84, 0xb5, | ||
1337 | 0x60, 0x50, 0x48, 0x6a, 0x20, 0x1d, 0x2b, 0x7e, | ||
1338 | 0x9f, 0xaf, 0xf8, 0x8e, 0x7e, 0xa4, 0xcd, 0x00, | ||
1339 | 0xad, 0xb1, 0xad, 0x22, 0x69, 0x32, 0x10, 0x6c, | ||
1340 | 0xe0, 0xcc, 0xdd, 0x45, 0xd8, 0xa6, 0x29, 0x2f, | ||
1341 | 0xad, 0x6b, 0xf9, | ||
1342 | }, | ||
1343 | .hex = "043C10277BACDF86" | ||
1344 | "C94FF839870239AF" | ||
1345 | "41BC4B67D85E0496" | ||
1346 | "84B56050486A201D" | ||
1347 | "2B7E9FAFF88E7EA4" | ||
1348 | "CD00ADB1AD226932" | ||
1349 | "106CE0CCDD45D8A6" | ||
1350 | "292FAD6BF9", | ||
1351 | .oct_len = 61, | ||
1352 | .oct = { | ||
1353 | 0x04, 0x3c, 0x10, 0x27, 0x7b, 0xac, 0xdf, 0x86, | ||
1354 | 0xc9, 0x4f, 0xf8, 0x39, 0x87, 0x02, 0x39, 0xaf, | ||
1355 | 0x41, 0xbc, 0x4b, 0x67, 0xd8, 0x5e, 0x04, 0x96, | ||
1356 | 0x84, 0xb5, 0x60, 0x50, 0x48, 0x6a, 0x20, 0x1d, | ||
1357 | 0x2b, 0x7e, 0x9f, 0xaf, 0xf8, 0x8e, 0x7e, 0xa4, | ||
1358 | 0xcd, 0x00, 0xad, 0xb1, 0xad, 0x22, 0x69, 0x32, | ||
1359 | 0x10, 0x6c, 0xe0, 0xcc, 0xdd, 0x45, 0xd8, 0xa6, | ||
1360 | 0x29, 0x2f, 0xad, 0x6b, 0xf9, | ||
1361 | }, | ||
1362 | }, | ||
1363 | { | ||
1364 | .name = "prime239v3", | ||
1365 | .der_len = 115, | ||
1366 | .der = { | ||
1367 | 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x26, | ||
1368 | 0x3f, 0x23, 0x4c, 0xe7, 0xbd, 0xa8, 0xe4, 0xfe, | ||
1369 | 0x7c, 0xf6, 0x18, 0x6a, 0xb2, 0xa6, 0x39, 0x15, | ||
1370 | 0x6d, 0x72, 0xe8, 0x9e, 0x3f, 0x0f, 0x10, 0x1e, | ||
1371 | 0xe5, 0xdf, 0xac, 0xe8, 0x2f, 0xa0, 0x0a, 0x06, | ||
1372 | 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, | ||
1373 | 0x06, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x37, | ||
1374 | 0xba, 0x07, 0x7f, 0xd9, 0x46, 0x5a, 0x33, 0x03, | ||
1375 | 0x31, 0x77, 0x38, 0xef, 0xee, 0xcc, 0x3d, 0xe1, | ||
1376 | 0xaa, 0x57, 0xe3, 0x8d, 0xb7, 0xcd, 0xe3, 0x01, | ||
1377 | 0xf4, 0xd6, 0x75, 0x49, 0x72, 0x61, 0x4c, 0xbf, | ||
1378 | 0xc0, 0x1f, 0x8b, 0x5f, 0x98, 0x9b, 0xa7, 0xe5, | ||
1379 | 0x6a, 0xb7, 0xfe, 0x63, 0xdb, 0xb0, 0x40, 0xcb, | ||
1380 | 0x26, 0x81, 0x2a, 0x91, 0x14, 0x0f, 0xc7, 0x31, | ||
1381 | 0x13, 0x78, 0x16, | ||
1382 | }, | ||
1383 | .hex = "0437BA077FD9465A" | ||
1384 | "3303317738EFEECC" | ||
1385 | "3DE1AA57E38DB7CD" | ||
1386 | "E301F4D675497261" | ||
1387 | "4CBFC01F8B5F989B" | ||
1388 | "A7E56AB7FE63DBB0" | ||
1389 | "40CB26812A91140F" | ||
1390 | "C731137816", | ||
1391 | .oct_len = 61, | ||
1392 | .oct = { | ||
1393 | 0x04, 0x37, 0xba, 0x07, 0x7f, 0xd9, 0x46, 0x5a, | ||
1394 | 0x33, 0x03, 0x31, 0x77, 0x38, 0xef, 0xee, 0xcc, | ||
1395 | 0x3d, 0xe1, 0xaa, 0x57, 0xe3, 0x8d, 0xb7, 0xcd, | ||
1396 | 0xe3, 0x01, 0xf4, 0xd6, 0x75, 0x49, 0x72, 0x61, | ||
1397 | 0x4c, 0xbf, 0xc0, 0x1f, 0x8b, 0x5f, 0x98, 0x9b, | ||
1398 | 0xa7, 0xe5, 0x6a, 0xb7, 0xfe, 0x63, 0xdb, 0xb0, | ||
1399 | 0x40, 0xcb, 0x26, 0x81, 0x2a, 0x91, 0x14, 0x0f, | ||
1400 | 0xc7, 0x31, 0x13, 0x78, 0x16, | ||
1401 | }, | ||
1402 | }, | ||
1403 | { | ||
1404 | .name = "prime256v1", | 1289 | .name = "prime256v1", |
1405 | .der_len = 121, | 1290 | .der_len = 121, |
1406 | .der = { | 1291 | .der = { |
@@ -2468,6 +2353,197 @@ ec_group_check_private_keys(void) | |||
2468 | return failed; | 2353 | return failed; |
2469 | } | 2354 | } |
2470 | 2355 | ||
2356 | static void | ||
2357 | ec_group_sha1_bignum(BIGNUM *out, const BIGNUM *in) | ||
2358 | { | ||
2359 | char md[SHA_DIGEST_LENGTH]; | ||
2360 | unsigned char *bin; | ||
2361 | size_t bin_len; | ||
2362 | |||
2363 | if (BN_num_bytes(in) <= 0) | ||
2364 | errx(1, "%s: invalid bignum", __func__); | ||
2365 | |||
2366 | bin_len = BN_num_bytes(in); | ||
2367 | if ((bin = calloc(1, bin_len)) == NULL) | ||
2368 | err(1, "calloc"); | ||
2369 | if (BN_bn2bin(in, bin) <= 0) | ||
2370 | errx(1, "BN_bn2bin"); | ||
2371 | |||
2372 | SHA1(bin, bin_len, md); | ||
2373 | free(bin); | ||
2374 | |||
2375 | if (BN_bin2bn(md, sizeof(md), out) == NULL) | ||
2376 | errx(1, "BN_bin2bn"); | ||
2377 | } | ||
2378 | |||
2379 | static int | ||
2380 | ec_group_check_seed(const EC_builtin_curve *curve, BN_CTX *ctx) | ||
2381 | { | ||
2382 | EC_GROUP *group = NULL; | ||
2383 | BIGNUM *p, *a, *b, *pow2, *r, *seed_bn, *w; | ||
2384 | const unsigned char *seed; | ||
2385 | size_t seed_len; | ||
2386 | int i, g, h, s, t; | ||
2387 | int failed = 1; | ||
2388 | |||
2389 | if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL) | ||
2390 | errx(1, "EC_GROUP_new_by_curve_name"); | ||
2391 | |||
2392 | BN_CTX_start(ctx); | ||
2393 | |||
2394 | if ((p = BN_CTX_get(ctx)) == NULL) | ||
2395 | errx(1, "p = BN_CTX_get()"); | ||
2396 | if ((a = BN_CTX_get(ctx)) == NULL) | ||
2397 | errx(1, "a = BN_CTX_get()"); | ||
2398 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
2399 | errx(1, "b = BN_CTX_get()"); | ||
2400 | if ((r = BN_CTX_get(ctx)) == NULL) | ||
2401 | errx(1, "r = BN_CTX_get()"); | ||
2402 | if ((pow2 = BN_CTX_get(ctx)) == NULL) | ||
2403 | errx(1, "pow2 = BN_CTX_get()"); | ||
2404 | if ((seed_bn = BN_CTX_get(ctx)) == NULL) | ||
2405 | errx(1, "seed_bn = BN_CTX_get()"); | ||
2406 | if ((w = BN_CTX_get(ctx)) == NULL) | ||
2407 | errx(1, "w = BN_CTX_get()"); | ||
2408 | |||
2409 | /* | ||
2410 | * If the curve has a seed, verify that its parameters a and b have | ||
2411 | * been selected using that seed, loosely following X9.62, F.3.4.b. | ||
2412 | * Otherwise there's nothing to do. | ||
2413 | */ | ||
2414 | if ((seed = EC_GROUP_get0_seed(group)) == NULL) | ||
2415 | goto done; | ||
2416 | seed_len = EC_GROUP_get_seed_len(group); | ||
2417 | |||
2418 | /* | ||
2419 | * This isn't a requirement but happens to be the case for NIST | ||
2420 | * curves - the only built-in curves that have a seed. | ||
2421 | */ | ||
2422 | if (seed_len != SHA_DIGEST_LENGTH) { | ||
2423 | fprintf(stderr, "%s FAIL: unexpected seed length. " | ||
2424 | "want %d, got %zu\n", __func__, SHA_DIGEST_LENGTH, seed_len); | ||
2425 | goto err; | ||
2426 | } | ||
2427 | |||
2428 | /* Seed length in bits, per F.3.3.b. */ | ||
2429 | g = 8 * seed_len; | ||
2430 | |||
2431 | /* | ||
2432 | * Prepare to build the verifiably random element r of GFp by | ||
2433 | * concatenating the SHA-1 of modifications of the seed as a number. | ||
2434 | */ | ||
2435 | if (BN_bin2bn(seed, seed_len, seed_bn) == NULL) | ||
2436 | errx(1, "BN_bin2bn"); | ||
2437 | |||
2438 | if (!EC_GROUP_get_curve(group, p, a, b, ctx)) | ||
2439 | errx(1, "EC_GROUP_get_curve"); | ||
2440 | |||
2441 | t = BN_num_bits(p); /* bit length needed. */ | ||
2442 | s = (t - 1) / 160; /* number of SHA-1 fitting in bit length. */ | ||
2443 | h = t - 160 * s; /* remaining number of bits in r. */ | ||
2444 | |||
2445 | /* | ||
2446 | * Steps 1 - 3: compute hash of the seed and take h - 1 rightmost bits. | ||
2447 | */ | ||
2448 | |||
2449 | ec_group_sha1_bignum(r, seed_bn); | ||
2450 | BN_zero(pow2); | ||
2451 | if (!BN_set_bit(pow2, h - 1)) | ||
2452 | errx(1, "BN_set_bit"); | ||
2453 | if (!BN_mod(r, r, pow2, ctx)) | ||
2454 | errx(1, "BN_nnmod"); | ||
2455 | |||
2456 | /* | ||
2457 | * Steps 4 - 6: for i from 1 to s do Wi = SHA-1(SEED + i mod 2^g), | ||
2458 | * With W0 = r as already computed, let r = W0 || W1 || ... || Ws. | ||
2459 | */ | ||
2460 | |||
2461 | BN_zero(pow2); | ||
2462 | if (!BN_set_bit(pow2, g)) | ||
2463 | errx(1, "BN_set_bit"); | ||
2464 | |||
2465 | for (i = 0; i < s; i++) { | ||
2466 | /* | ||
2467 | * This is a bit silly since the seed isn't going to have all | ||
2468 | * its bits set, so BN_add_word(seed_bn, 1) would do, but for | ||
2469 | * the sake of correctness... | ||
2470 | */ | ||
2471 | if (!BN_mod_add(seed_bn, seed_bn, BN_value_one(), pow2, ctx)) | ||
2472 | errx(1, "BN_mod_add"); | ||
2473 | |||
2474 | ec_group_sha1_bignum(w, seed_bn); | ||
2475 | |||
2476 | if (!BN_lshift(r, r, 8 * SHA_DIGEST_LENGTH)) | ||
2477 | errx(1, "BN_lshift"); | ||
2478 | if (!BN_add(r, r, w)) | ||
2479 | errx(1, "BN_add"); | ||
2480 | } | ||
2481 | |||
2482 | /* | ||
2483 | * Step 7: check that r * b^2 == a^3 (mod p) | ||
2484 | */ | ||
2485 | |||
2486 | /* Compute r = r * b^2 (mod p). */ | ||
2487 | if (!BN_mod_sqr(b, b, p, ctx)) | ||
2488 | errx(1, "BN_mod_sqr"); | ||
2489 | if (!BN_mod_mul(r, r, b, p, ctx)) | ||
2490 | errx(1, "BN_mod_mul"); | ||
2491 | |||
2492 | /* Compute a = a^3 (mod p). */ | ||
2493 | if (!BN_mod_sqr(b, a, p, ctx)) | ||
2494 | errx(1, "BN_mod_sqr"); | ||
2495 | if (!BN_mod_mul(a, a, b, p, ctx)) | ||
2496 | errx(1, "BN_mod_mul"); | ||
2497 | |||
2498 | /* | ||
2499 | * XXX - this assumes that a, b, p >= 0, so the results are in [0, p). | ||
2500 | * This is currently enforced in the EC code. | ||
2501 | */ | ||
2502 | if (BN_cmp(r, a) != 0) { | ||
2503 | fprintf(stderr, "FAIL: %s verification failed for %s\nr * b^2:\t", | ||
2504 | __func__, curve->comment); | ||
2505 | BN_print_fp(stderr, r); | ||
2506 | fprintf(stderr, "\na^3:\t\t"); | ||
2507 | BN_print_fp(stderr, a); | ||
2508 | fprintf(stderr, "\n"); | ||
2509 | goto err; | ||
2510 | } | ||
2511 | |||
2512 | done: | ||
2513 | failed = 0; | ||
2514 | |||
2515 | err: | ||
2516 | BN_CTX_end(ctx); | ||
2517 | EC_GROUP_free(group); | ||
2518 | |||
2519 | return failed; | ||
2520 | } | ||
2521 | |||
2522 | static int | ||
2523 | ec_group_check_seeds(void) | ||
2524 | { | ||
2525 | BN_CTX *ctx = NULL; | ||
2526 | EC_builtin_curve *all_curves = NULL; | ||
2527 | size_t curve_id, ncurves; | ||
2528 | int failed = 0; | ||
2529 | |||
2530 | if ((ctx = BN_CTX_new()) == NULL) | ||
2531 | errx(1, "BN_CTX_new"); | ||
2532 | |||
2533 | ncurves = EC_get_builtin_curves(NULL, 0); | ||
2534 | if ((all_curves = calloc(ncurves, sizeof(*all_curves))) == NULL) | ||
2535 | err(1, "calloc builtin curves"); | ||
2536 | EC_get_builtin_curves(all_curves, ncurves); | ||
2537 | |||
2538 | for (curve_id = 0; curve_id < ncurves; curve_id++) | ||
2539 | failed |= ec_group_check_seed(&all_curves[curve_id], ctx); | ||
2540 | |||
2541 | free(all_curves); | ||
2542 | BN_CTX_free(ctx); | ||
2543 | |||
2544 | return failed; | ||
2545 | } | ||
2546 | |||
2471 | int | 2547 | int |
2472 | main(int argc, char **argv) | 2548 | main(int argc, char **argv) |
2473 | { | 2549 | { |
@@ -2479,6 +2555,7 @@ main(int argc, char **argv) | |||
2479 | failed |= ec_group_roundtrip_builtin_curves(); | 2555 | failed |= ec_group_roundtrip_builtin_curves(); |
2480 | failed |= ec_group_non_builtin_curves(); | 2556 | failed |= ec_group_non_builtin_curves(); |
2481 | failed |= ec_group_check_private_keys(); | 2557 | failed |= ec_group_check_private_keys(); |
2558 | failed |= ec_group_check_seeds(); | ||
2482 | 2559 | ||
2483 | return failed; | 2560 | return failed; |
2484 | } | 2561 | } |