xref: /openbsd-src/regress/lib/libcrypto/bn/bn_mod_inverse.c (revision b505647788ae15f0ce76d3e2351b7fba333e6bd5)
1*b5056477Stb /*	$OpenBSD: bn_mod_inverse.c,v 1.2 2023/06/04 07:14:47 tb Exp $ */
299463a0cStb 
399463a0cStb /*
499463a0cStb  * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
599463a0cStb  *
699463a0cStb  * Permission to use, copy, modify, and distribute this software for any
799463a0cStb  * purpose with or without fee is hereby granted, provided that the above
899463a0cStb  * copyright notice and this permission notice appear in all copies.
999463a0cStb  *
1099463a0cStb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1199463a0cStb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1299463a0cStb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1399463a0cStb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1499463a0cStb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1599463a0cStb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1699463a0cStb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1799463a0cStb  */
1899463a0cStb 
1999463a0cStb #include <err.h>
2099463a0cStb #include <stdio.h>
2199463a0cStb 
2299463a0cStb #include <openssl/bn.h>
2399463a0cStb 
24*b5056477Stb BIGNUM *BN_mod_inverse(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
25*b5056477Stb 
2699463a0cStb static const struct mod_inv_test {
2799463a0cStb 	const char *i;
2899463a0cStb 	const char *a;
2999463a0cStb 	const char *m;
3099463a0cStb } mod_inv_tests[] = {
3199463a0cStb 	{
3299463a0cStb 		.i = "0",
3399463a0cStb 		.a = "0",
3499463a0cStb 		.m = "1",
3599463a0cStb 	},
3699463a0cStb 	{
3799463a0cStb 		.i = "0",
3899463a0cStb 		.a = "1",
3999463a0cStb 		.m = "1",
4099463a0cStb 	},
4199463a0cStb 	{
4299463a0cStb 		.i = "0",
4399463a0cStb 		.a = "2",
4499463a0cStb 		.m = "1",
4599463a0cStb 	},
4699463a0cStb 	{
4799463a0cStb 		.i = "0",
4899463a0cStb 		.a = "3",
4999463a0cStb 		.m = "1",
5099463a0cStb 	},
5199463a0cStb 	{
5299463a0cStb 		.i = "64",
5399463a0cStb 		.a = "54",
5499463a0cStb 		.m = "e3",
5599463a0cStb 	},
5699463a0cStb 	{
5799463a0cStb 		.i = "13",
5899463a0cStb 		.a = "2b",
5999463a0cStb 		.m = "30",
6099463a0cStb 	},
6199463a0cStb 	{
6299463a0cStb 		.i = "2f",
6399463a0cStb 		.a = "30",
6499463a0cStb 		.m = "37",
6599463a0cStb 	},
6699463a0cStb 	{
6799463a0cStb 		.i = "4",
6899463a0cStb 		.a = "13",
6999463a0cStb 		.m = "4b",
7099463a0cStb 	},
7199463a0cStb 	{
7299463a0cStb 		.i = "1c47",
7399463a0cStb 		.a = "cd4",
7499463a0cStb 		.m = "6a21",
7599463a0cStb 	},
7699463a0cStb 	{
7799463a0cStb 		.i = "2b97",
7899463a0cStb 		.a = "8e7",
7999463a0cStb 		.m = "49c0",
8099463a0cStb 	},
8199463a0cStb 	{
8299463a0cStb 		.i = "29b9",
8399463a0cStb 		.a = "fcb",
8499463a0cStb 		.m = "3092",
8599463a0cStb 	},
8699463a0cStb 	{
8799463a0cStb 		.i = "a83",
8899463a0cStb 		.a = "14bf",
8999463a0cStb 		.m = "41ae",
9099463a0cStb 	},
9199463a0cStb 	{
9299463a0cStb 		.i = "18f15fe1",
9399463a0cStb 		.a = "11b5d53e",
9499463a0cStb 		.m = "322e92a1",
9599463a0cStb 	},
9699463a0cStb 	{
9799463a0cStb 		.i = "32f9453b",
9899463a0cStb 		.a = "8af6df6",
9999463a0cStb 		.m = "33d45eb7",
10099463a0cStb 	},
10199463a0cStb 	{
10299463a0cStb 		.i = "d696369",
10399463a0cStb 		.a = "c5f89dd5",
10499463a0cStb 		.m = "fc09c17c",
10599463a0cStb 	},
10699463a0cStb 	{
10799463a0cStb 		.i = "622839d8",
10899463a0cStb 		.a = "60c2526",
10999463a0cStb 		.m = "74200493",
11099463a0cStb 	},
11199463a0cStb 	{
11299463a0cStb 		.i = "fb5a8aee7bbc4ef",
11399463a0cStb 		.a = "24ebd835a70be4e2",
11499463a0cStb 		.m = "9c7256574e0c5e93",
11599463a0cStb 	},
11699463a0cStb 	{
11799463a0cStb 		.i = "846bc225402419c",
11899463a0cStb 		.a = "23026003ab1fbdb",
11999463a0cStb 		.m = "1683cbe32779c59b",
12099463a0cStb 	},
12199463a0cStb 	{
12299463a0cStb 		.i = "5ff84f63a78982f9",
12399463a0cStb 		.a = "4a2420dc733e1a0f",
12499463a0cStb 		.m = "a73c6bfabefa09e6",
12599463a0cStb 	},
12699463a0cStb 	{
12799463a0cStb 		.i = "133e74d28ef42b43",
12899463a0cStb 		.a = "2e9511ae29cdd41",
12999463a0cStb 		.m = "15234df99f19fcda",
13099463a0cStb 	},
13199463a0cStb 	{
13299463a0cStb 		.i = "46ae1fabe9521e4b99b198fc84396090"
13399463a0cStb 		     "23aa69be2247c0d1e27c2a0ea332f9c5",
13499463a0cStb 		.a = "6331fec5f01014046788c919ed50dc86"
13599463a0cStb 		     "ac7a80c085f1b6f645dd179c0f0dc9cd",
13699463a0cStb 		.m = "8ef409de82318259a8655a39293b1e76"
13799463a0cStb 		     "2fa2cc7e0aeb4c59713a1e1fff6af640",
13899463a0cStb 	},
13999463a0cStb 	{
14099463a0cStb 		.i = "444ccea3a7b21677dd294d34de53cc8a"
14199463a0cStb 		     "5b51e69b37782310a00fc6bcc975709b",
14299463a0cStb 		.a = "679280bd880994c08322143a4ea8a082"
14399463a0cStb 		     "5d0466fda1bb6b3eb86fc8e90747512b",
14499463a0cStb 		.m = "e4fecab84b365c63a0dab4244ce3f921"
14599463a0cStb 		     "a9c87ec64d69a2031939f55782e99a2e",
14699463a0cStb 	},
14799463a0cStb 	{
14899463a0cStb 		.i = "1ac7d7a03ceec5f690f567c9d61bf346"
14999463a0cStb 		     "9c078285bcc5cf00ac944596e887ca17",
15099463a0cStb 		.a = "1593ef32d9c784f5091bdff952f5c5f5"
15199463a0cStb 		     "92a3aed6ba8ea865efa6d7df87be1805",
15299463a0cStb 		.m = "1e276882f90c95e0c1976eb079f97af0"
15399463a0cStb 		     "75445b1361c02018d6bd7191162e67b2",
15499463a0cStb 	},
15599463a0cStb 	{
15699463a0cStb 		.i = "639108b90dfe946f498be21303058413"
15799463a0cStb 		     "bbb0e59d0bd6a6115788705abd0666d6",
15899463a0cStb 		.a = "9258d6238e4923d120b2d1033573ffca"
15999463a0cStb 		     "c691526ad0842a3b174dccdbb79887bd",
16099463a0cStb 		.m = "ce62909c39371d463aaba3d4b72ea6da"
16199463a0cStb 		     "49cb9b529e39e1972ef3ccd9a66fe08f",
16299463a0cStb 	},
16399463a0cStb 	{
16499463a0cStb 		.i = "aebde7654cb17833a106231c4b9e2f51"
16599463a0cStb 		     "9140e85faee1bfb4192830f03f385e77"
16699463a0cStb 		     "3c0f4767e93e874ffdc3b7a6b7e6a710"
16799463a0cStb 		     "e5619901c739ee8760a26128e8c91ef8"
16899463a0cStb 		     "cf761d0e505d8b28ae078d17e6071c37"
16999463a0cStb 		     "2893bb7b72538e518ebc57efa70b7615"
17099463a0cStb 		     "e406756c49729b7c6e74f84aed7a316b"
17199463a0cStb 		     "6fa748ff4b9f143129d29dad1bff98bb",
17299463a0cStb 		.a = "a29dacaf5487d354280fdd2745b9ace4"
17399463a0cStb 		     "cd50f2bde41d0ee529bf26a1913244f7"
17499463a0cStb 		     "08085452ff32feab19a7418897990da4"
17599463a0cStb 		     "6a0633f7c8375d583367319091bbbe06"
17699463a0cStb 		     "9b0052c5e48a7daac9fb650db5af768c"
17799463a0cStb 		     "d2508ec3e2cda7456d4b9ce1c3945962"
17899463a0cStb 		     "7a8b77e038b826cd7e326d0685b0cd0c"
17999463a0cStb 		     "b50f026f18300dae9f5fd42aa150ee8b",
18099463a0cStb 		.m = "d686f9b86697313251685e995c09b9f1"
18199463a0cStb 		     "e337ddfaa050bd2df15bf4ca1dc46c55"
18299463a0cStb 		     "65021314765299c434ea1a6ec42bf92a"
18399463a0cStb 		     "29a7d1ffff599f4e50b79a82243fb248"
18499463a0cStb 		     "13060580c770d4c1140aeb2ab2685007"
18599463a0cStb 		     "e948b6f1f62e8001a0545619477d4981"
18699463a0cStb 		     "32c907774479f6d95899e6251e7136f7"
18799463a0cStb 		     "9ab6d3b7c82e4aca421e7d22fe7db19c",
18899463a0cStb 	},
18999463a0cStb 	{
19099463a0cStb 		.i = "1ec872f4f20439e203597ca4de9d1296"
19199463a0cStb 		     "743f95781b2fe85d5def808558bbadef"
19299463a0cStb 		     "02a46b8955f47c83e1625f8bb40228ea"
19399463a0cStb 		     "b09cad2a35c9ad62ab77a30e39328729"
19499463a0cStb 		     "59c5898674162da244a0ec1f68c0ed89"
19599463a0cStb 		     "f4b0f3572bfdc658ad15bf1b1c6e1176"
19699463a0cStb 		     "b0784c9935bd3ff1f49bb43753eacee1"
19799463a0cStb 		     "d8ca1c0b652d39ec727da83984fe3a0f",
19899463a0cStb 		.a = "2e527b0a1dc32460b2dd94ec446c6929"
19999463a0cStb 		     "89f7b3c7451a5cbeebf69fc0ea9c4871"
20099463a0cStb 		     "fbe78682d5dc5b66689f7ed889b52161"
20199463a0cStb 		     "cd9830b589a93d21ab26dbede6c33959"
20299463a0cStb 		     "f5a0f0d107169e2daaac78bac8cf2d41"
20399463a0cStb 		     "a1eb1369cb6dc9e865e73bb2e51b886f"
20499463a0cStb 		     "4e896082db199175e3dde0c4ed826468"
20599463a0cStb 		     "f238a77bd894245d0918efc9ca84f945",
20699463a0cStb 		.m = "b13133a9ebe0645f987d170c077eea2a"
20799463a0cStb 		     "a44e85c9ab10386d02867419a590cb18"
20899463a0cStb 		     "2d9826a882306c212dbe75225adde23f"
20999463a0cStb 		     "80f5b37ca75ed09df20fc277cc7fbbfa"
21099463a0cStb 		     "c8d9ef37a50f6b68ea158f5447283618"
21199463a0cStb 		     "e64e1426406d26ea85232afb22bf546c"
21299463a0cStb 		     "75018c1c55cb84c374d58d9d44c0a13b"
21399463a0cStb 		     "a88ac2e387765cb4c3269e3a983250fa",
21499463a0cStb 	},
21599463a0cStb 	{
21699463a0cStb 		.i = "30ffa1876313a69de1e4e6ee132ea1d3"
21799463a0cStb 		     "a3da32f3b56f5cfb11402b0ad517dce6"
21899463a0cStb 		     "05cf8e91d69fa375dd887fa8507bd8a2"
21999463a0cStb 		     "8b2d5ce745799126e86f416047709f93"
22099463a0cStb 		     "f07fbd88918a047f13100ea71b1d48f6"
22199463a0cStb 		     "fc6d12e5c917646df3041b302187af64"
22299463a0cStb 		     "1eaedf4908abc36f12c204e1526a7d80"
22399463a0cStb 		     "e96e302fb0779c28d7da607243732f26",
22499463a0cStb 		.a = "31157208bde6b85ebecaa63735947b3b"
22599463a0cStb 		     "36fa351b5c47e9e1c40c947339b78bf9"
22699463a0cStb 		     "6066e5dbe21bb42629e6fcdb81f5f88d"
22799463a0cStb 		     "b590bfdd5f4c0a6a0c3fc6377e5c1fd8"
22899463a0cStb 		     "235e46e291c688b6d6ecfb36604891c2"
22999463a0cStb 		     "a7c9cbcc58c26e44b43beecb9c5044b5"
23099463a0cStb 		     "8bb58e35de3cf1128f3c116534fe4e42"
23199463a0cStb 		     "1a33f83603c3df1ae36ec88092f67f2a",
23299463a0cStb 		.m = "53408b23d6cb733e6c9bc3d1e2ea2286"
23399463a0cStb 		     "a5c83cc4e3e7470f8af3a1d9f28727f5"
23499463a0cStb 		     "b1f8ae348c1678f5d1105dc3edf2de64"
23599463a0cStb 		     "e65b9c99545c47e64b770b17c8b4ef5c"
23699463a0cStb 		     "f194b43a0538053e87a6b95ade1439ce"
23799463a0cStb 		     "bf3d34c6aa72a11c1497f58f76011e16"
23899463a0cStb 		     "c5be087936d88aba7a740113120e939e"
23999463a0cStb 		     "27bd3ddcb6580c2841aa406566e33c35",
24099463a0cStb 	},
24199463a0cStb 	{
24299463a0cStb 		.i = "87355002f305c81ba0dc97ca2234a2bc"
24399463a0cStb 		     "02528cefde38b94ac5bd95efc7bf4c14"
24499463a0cStb 		     "0899107fff47f0df9e3c6aa70017ebc9"
24599463a0cStb 		     "0610a750f112cd4f475b9c76b204a953"
24699463a0cStb 		     "444b4e7196ccf17e93fdaed160b7345c"
24799463a0cStb 		     "a9b397eddf9446e8ea8ee3676102ce70"
24899463a0cStb 		     "eaafbe9038a34639789e6f2f1e3f3526"
24999463a0cStb 		     "38f2e8a8f5fc56aaea7ec705ee068dd5",
25099463a0cStb 		.a = "42a25d0bc96f71750f5ac8a51a1605a4"
25199463a0cStb 		     "1b506cca51c9a7ecf80cad713e56f70f"
25299463a0cStb 		     "1b4b6fa51cbb101f55fd74f318adefb3"
25399463a0cStb 		     "af04e0c8a7e281055d5a40dd40913c0e"
25499463a0cStb 		     "1211767c5be915972c73886106dc4932"
25599463a0cStb 		     "5df6c2df49e9eea4536f0343a8e7d332"
25699463a0cStb 		     "c6159e4f5bdb20d89f90e67597c4a2a6"
25799463a0cStb 		     "32c31b2ef2534080a9ac61f52303990d",
25899463a0cStb 		.m = "d3d3f95d50570351528a76ab1e806bae"
25999463a0cStb 		     "1968bd420899bdb3d87c823fac439a43"
26099463a0cStb 		     "54c31f6c888c939784f18fe10a95e6d2"
26199463a0cStb 		     "03b1901caa18937ba6f8be033af10c35"
26299463a0cStb 		     "fc869cf3d16bef479f280f53b3499e64"
26399463a0cStb 		     "5d0387554623207ca4989e5de00bfeaa"
26499463a0cStb 		     "5e9ab56474fc60dd4967b100e0832eaa"
26599463a0cStb 		     "f2fcb2ef82a181567057b880b3afef62",
26699463a0cStb 	},
26799463a0cStb 	{
26899463a0cStb 		.i = "9b8c28a4",
26999463a0cStb 		.a = "135935f57",
27099463a0cStb 		.m = "c24242ff",
27199463a0cStb 	},
27299463a0cStb };
27399463a0cStb 
27499463a0cStb #define N_MOD_INV_TESTS (sizeof(mod_inv_tests) / sizeof(mod_inv_tests[0]))
27599463a0cStb 
27699463a0cStb static int
bn_mod_inverse_test(const struct mod_inv_test * test,BN_CTX * ctx,int flags)27799463a0cStb bn_mod_inverse_test(const struct mod_inv_test *test, BN_CTX *ctx, int flags)
27899463a0cStb {
27999463a0cStb 	BIGNUM *i, *a, *m, *inv, *elt, *mod;
28099463a0cStb 	int failed_step;
28199463a0cStb 	int failed = 0;
28299463a0cStb 
28399463a0cStb 	BN_CTX_start(ctx);
28499463a0cStb 
28599463a0cStb 	if ((i = BN_CTX_get(ctx)) == NULL)
28699463a0cStb 		errx(1, "i = BN_CTX_get()");
28799463a0cStb 	if ((a = BN_CTX_get(ctx)) == NULL)
28899463a0cStb 		errx(1, "a = BN_CTX_get()");
28999463a0cStb 	if ((m = BN_CTX_get(ctx)) == NULL)
29099463a0cStb 		errx(1, "m = BN_CTX_get()");
29199463a0cStb 	if ((inv = BN_CTX_get(ctx)) == NULL)
29299463a0cStb 		errx(1, "inv = BN_CTX_get()");
29399463a0cStb 	if ((elt = BN_CTX_get(ctx)) == NULL)
29499463a0cStb 		errx(1, "elt = BN_CTX_get()");
29599463a0cStb 	if ((mod = BN_CTX_get(ctx)) == NULL)
29699463a0cStb 		errx(1, "mod = BN_CTX_get()");
29799463a0cStb 
29899463a0cStb 	BN_set_flags(i, flags);
29999463a0cStb 	BN_set_flags(a, flags);
30099463a0cStb 	BN_set_flags(m, flags);
30199463a0cStb 	BN_set_flags(inv, flags);
30299463a0cStb 	BN_set_flags(elt, flags);
30399463a0cStb 	BN_set_flags(mod, flags);
30499463a0cStb 
30599463a0cStb 	if (BN_hex2bn(&i, test->i) == 0)
30699463a0cStb 		errx(1, "BN_hex2bn(%s)", test->i);
30799463a0cStb 	if (BN_hex2bn(&a, test->a) == 0)
30899463a0cStb 		errx(1, "BN_hex2bn(%s)", test->a);
30999463a0cStb 	if (BN_hex2bn(&m, test->m) == 0)
31099463a0cStb 		errx(1, "BN_hex2bn(%s)", test->m);
31199463a0cStb 
31299463a0cStb 	if (BN_copy(elt, a) == NULL)
31399463a0cStb 		errx(1, "BN_copy(elt, a)");
31499463a0cStb 	if (BN_copy(mod, m) == NULL)
31599463a0cStb 		errx(1, "BN_copy(mod, m)");
31699463a0cStb 
31799463a0cStb 	if (BN_mod_inverse(inv, elt, mod, ctx) == NULL)
31899463a0cStb 		errx(1, "BN_mod_inverse(inv, elt, mod)");
31999463a0cStb 
32099463a0cStb 	failed_step = BN_cmp(i, inv) != 0;
32199463a0cStb 	if (failed_step)
32299463a0cStb 		fprintf(stderr, "FAIL (simple), %x:\ni: %s\na: %s\nm: %s\n",
32399463a0cStb 		    flags, test->i, test->a, test->m);
32499463a0cStb 	failed |= failed_step;
32599463a0cStb 
32699463a0cStb 	if (BN_copy(elt, a) == NULL)
32799463a0cStb 		errx(1, "BN_copy(elt, a)");
32899463a0cStb 	if (BN_copy(inv, m) == NULL)
32999463a0cStb 		errx(1, "BN_copy(inv, m)");
33099463a0cStb 
33199463a0cStb 	if (BN_mod_inverse(inv, elt, inv, ctx) == NULL)
33299463a0cStb 		errx(1, "BN_mod_inverse(inv, elt, inv)");
33399463a0cStb 	failed_step = BN_cmp(i, inv) != 0;
33499463a0cStb 	if (failed_step)
33599463a0cStb 		fprintf(stderr, "FAIL (inv == mod), %x:\ni: %s\na: %s\nm: %s\n",
33699463a0cStb 		    flags, test->i, test->a, test->m);
33799463a0cStb 	failed |= failed_step;
33899463a0cStb 
33999463a0cStb 	if (BN_copy(inv, a) == NULL)
34099463a0cStb 		errx(1, "BN_copy(elt, a)");
34199463a0cStb 	if (BN_copy(mod, m) == NULL)
34299463a0cStb 		errx(1, "BN_copy(inv, m)");
34399463a0cStb 
34499463a0cStb 	if (BN_mod_inverse(inv, inv, mod, ctx) == NULL)
34599463a0cStb 		errx(1, "BN_mod_inverse(inv, inv, mod)");
34699463a0cStb 	failed_step = BN_cmp(i, inv) != 0;
34799463a0cStb 	if (failed_step)
34899463a0cStb 		fprintf(stderr, "FAIL (inv == elt), %x:\ni: %s\na: %s\nm: %s\n",
34999463a0cStb 		    flags, test->i, test->a, test->m);
35099463a0cStb 	failed |= failed_step;
35199463a0cStb 
35299463a0cStb 	BN_CTX_end(ctx);
35399463a0cStb 
35499463a0cStb 	return failed;
35599463a0cStb }
35699463a0cStb 
35799463a0cStb static int
test_bn_mod_inverse(void)35899463a0cStb test_bn_mod_inverse(void)
35999463a0cStb {
36099463a0cStb 	BN_CTX *ctx;
36199463a0cStb 	size_t i;
36299463a0cStb 	int failed = 0;
36399463a0cStb 
36499463a0cStb 	if ((ctx = BN_CTX_new()) == NULL)
36599463a0cStb 		errx(1, "BN_CTX_new");
36699463a0cStb 
36799463a0cStb 	for (i = 0; i < N_MOD_INV_TESTS; i++)
36899463a0cStb 		failed |= bn_mod_inverse_test(&mod_inv_tests[i], ctx, 0);
36999463a0cStb 
37099463a0cStb 	for (i = 0; i < N_MOD_INV_TESTS; i++)
37199463a0cStb 		failed |= bn_mod_inverse_test(&mod_inv_tests[i], ctx,
37299463a0cStb 		    BN_FLG_CONSTTIME);
37399463a0cStb 
37499463a0cStb 	BN_CTX_free(ctx);
37599463a0cStb 
37699463a0cStb 	return failed;
37799463a0cStb }
37899463a0cStb 
37999463a0cStb int
main(void)38099463a0cStb main(void)
38199463a0cStb {
38299463a0cStb 	int failed = 0;
38399463a0cStb 
384*b5056477Stb 	failed |= test_bn_mod_inverse();
38599463a0cStb 
38699463a0cStb 	return failed;
38799463a0cStb }
388