diff options
| author | tb <> | 2022-07-25 20:48:57 +0000 |
|---|---|---|
| committer | tb <> | 2022-07-25 20:48:57 +0000 |
| commit | dddbce9d185f80b869ab0e56fb12f8cbb6ee132f (patch) | |
| tree | 7e50d6ce59b316501132cf86504c150035b1ab49 | |
| parent | c3a86f16bf9b403fa5e35013eac4b5c2a82573df (diff) | |
| download | openbsd-dddbce9d185f80b869ab0e56fb12f8cbb6ee132f.tar.gz openbsd-dddbce9d185f80b869ab0e56fb12f8cbb6ee132f.tar.bz2 openbsd-dddbce9d185f80b869ab0e56fb12f8cbb6ee132f.zip | |
Add a regression test for bn_isqrt.c
This validates the tables used in bn_is_perfect_square() and checks that
for randomly generated numbers the isqrt() is what it is expected to be.
Diffstat (limited to '')
| -rw-r--r-- | src/regress/lib/libcrypto/bn/general/Makefile | 11 | ||||
| -rw-r--r-- | src/regress/lib/libcrypto/bn/general/bn_isqrt.c | 292 |
2 files changed, 302 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/bn/general/Makefile b/src/regress/lib/libcrypto/bn/general/Makefile index 913a3db19b..ab642e0769 100644 --- a/src/regress/lib/libcrypto/bn/general/Makefile +++ b/src/regress/lib/libcrypto/bn/general/Makefile | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | # $OpenBSD: Makefile,v 1.13 2022/06/23 18:09:19 tb Exp $ | 1 | # $OpenBSD: Makefile,v 1.14 2022/07/25 20:48:57 tb Exp $ |
| 2 | 2 | ||
| 3 | .include "../../Makefile.inc" | 3 | .include "../../Makefile.inc" |
| 4 | 4 | ||
| 5 | PROGS += bntest | 5 | PROGS += bntest |
| 6 | PROGS += bn_isqrt | ||
| 6 | PROGS += bn_mod_exp2_mont | 7 | PROGS += bn_mod_exp2_mont |
| 7 | PROGS += bn_mod_sqrt | 8 | PROGS += bn_mod_sqrt |
| 8 | PROGS += bn_primes | 9 | PROGS += bn_primes |
| @@ -42,4 +43,12 @@ REGRESS_TARGETS += run-bn_to_string | |||
| 42 | run-bn_to_string: bn_to_string | 43 | run-bn_to_string: bn_to_string |
| 43 | ./bn_to_string | 44 | ./bn_to_string |
| 44 | 45 | ||
| 46 | LDADD_bn_isqrt = ${CRYPTO_INT} | ||
| 47 | REGRESS_TARGETS += run-bn_isqrt | ||
| 48 | run-bn_isqrt: bn_isqrt | ||
| 49 | ./bn_isqrt | ||
| 50 | |||
| 51 | print-tables: bn_isqrt | ||
| 52 | @./bn_isqrt -C | ||
| 53 | |||
| 45 | .include <bsd.regress.mk> | 54 | .include <bsd.regress.mk> |
diff --git a/src/regress/lib/libcrypto/bn/general/bn_isqrt.c b/src/regress/lib/libcrypto/bn/general/bn_isqrt.c new file mode 100644 index 0000000000..24e15a8aee --- /dev/null +++ b/src/regress/lib/libcrypto/bn/general/bn_isqrt.c | |||
| @@ -0,0 +1,292 @@ | |||
| 1 | /* $OpenBSD: bn_isqrt.c,v 1.1 2022/07/25 20:48:57 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <err.h> | ||
| 19 | #include <string.h> | ||
| 20 | #include <unistd.h> | ||
| 21 | |||
| 22 | #include <openssl/bn.h> | ||
| 23 | |||
| 24 | #include "bn_lcl.h" | ||
| 25 | |||
| 26 | #define N_TESTS 400 | ||
| 27 | |||
| 28 | /* Sample squares between 2^128 and 2^4096. */ | ||
| 29 | #define LOWER_BITS 128 | ||
| 30 | #define UPPER_BITS 4096 | ||
| 31 | |||
| 32 | extern const uint8_t is_square_mod_11[]; | ||
| 33 | extern const uint8_t is_square_mod_63[]; | ||
| 34 | extern const uint8_t is_square_mod_64[]; | ||
| 35 | extern const uint8_t is_square_mod_65[]; | ||
| 36 | |||
| 37 | static void | ||
| 38 | hexdump(const unsigned char *buf, size_t len) | ||
| 39 | { | ||
| 40 | size_t i; | ||
| 41 | |||
| 42 | for (i = 1; i <= len; i++) | ||
| 43 | fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); | ||
| 44 | |||
| 45 | if (len % 8) | ||
| 46 | fprintf(stderr, "\n"); | ||
| 47 | } | ||
| 48 | |||
| 49 | static const uint8_t * | ||
| 50 | get_table(int modulus) | ||
| 51 | { | ||
| 52 | switch (modulus) { | ||
| 53 | case 11: | ||
| 54 | return is_square_mod_11; | ||
| 55 | case 63: | ||
| 56 | return is_square_mod_63; | ||
| 57 | case 64: | ||
| 58 | return is_square_mod_64; | ||
| 59 | case 65: | ||
| 60 | return is_square_mod_65; | ||
| 61 | default: | ||
| 62 | return NULL; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | static int | ||
| 67 | check_tables(int print) | ||
| 68 | { | ||
| 69 | int fill[] = {11, 63, 64, 65}; | ||
| 70 | const uint8_t *table; | ||
| 71 | uint8_t q[65]; | ||
| 72 | size_t i; | ||
| 73 | int j; | ||
| 74 | int failed = 0; | ||
| 75 | |||
| 76 | for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) { | ||
| 77 | memset(q, 0, sizeof(q)); | ||
| 78 | |||
| 79 | for (j = 0; j <= fill[i]; j++) | ||
| 80 | q[(j * j) % fill[i]] = 1; | ||
| 81 | |||
| 82 | if ((table = get_table(fill[i])) == NULL) { | ||
| 83 | fprintf(stderr, "failed to get table %d\n", fill[i]); | ||
| 84 | failed |= 1; | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (memcmp(table, q, fill[i]) != 0) { | ||
| 89 | fprintf(stderr, "table %d does not match:\n", fill[i]); | ||
| 90 | fprintf(stderr, "want:\n"); | ||
| 91 | hexdump(table, fill[i]); | ||
| 92 | fprintf(stderr, "got:\n"); | ||
| 93 | hexdump(q, fill[i]); | ||
| 94 | failed |= 1; | ||
| 95 | continue; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (!print) | ||
| 99 | continue; | ||
| 100 | |||
| 101 | printf("const uint8_t is_square_mod_%d[] = {\n\t", | ||
| 102 | fill[i]); | ||
| 103 | for (j = 0; j < fill[i]; j++) { | ||
| 104 | const char *end = " "; | ||
| 105 | |||
| 106 | if (j % 16 == 15) | ||
| 107 | end = "\n\t"; | ||
| 108 | if (j + 1 == fill[i]) | ||
| 109 | end = ""; | ||
| 110 | |||
| 111 | printf("%d,%s", q[j], end); | ||
| 112 | } | ||
| 113 | printf("\n};\nCTASSERT(sizeof(is_square_mod_%d) == %d);\n\n", | ||
| 114 | fill[i], fill[i]); | ||
| 115 | } | ||
| 116 | |||
| 117 | return failed; | ||
| 118 | } | ||
| 119 | |||
| 120 | /* | ||
| 121 | * Choose a random number n between 2^10 and 2^16384 and check n == isqrt(n^2). | ||
| 122 | * Random numbers n^2 <= test < (n + 1)^2 are checked to have isqrt(test) == n. | ||
| 123 | */ | ||
| 124 | static int | ||
| 125 | isqrt_test(void) | ||
| 126 | { | ||
| 127 | BN_CTX *ctx; | ||
| 128 | BIGNUM *n, *n_sqr, *lower, *upper, *testcase, *isqrt; | ||
| 129 | int cmp, is_perfect_square; | ||
| 130 | int i; | ||
| 131 | int failed = 0; | ||
| 132 | |||
| 133 | if ((ctx = BN_CTX_new()) == NULL) | ||
| 134 | errx(1, "BN_CTX_new"); | ||
| 135 | |||
| 136 | BN_CTX_start(ctx); | ||
| 137 | |||
| 138 | if ((lower = BN_CTX_get(ctx)) == NULL) | ||
| 139 | errx(1, "lower = BN_CTX_get(ctx)"); | ||
| 140 | if ((upper = BN_CTX_get(ctx)) == NULL) | ||
| 141 | errx(1, "upper = BN_CTX_get(ctx)"); | ||
| 142 | if ((n = BN_CTX_get(ctx)) == NULL) | ||
| 143 | errx(1, "n = BN_CTX_get(ctx)"); | ||
| 144 | if ((n_sqr = BN_CTX_get(ctx)) == NULL) | ||
| 145 | errx(1, "n = BN_CTX_get(ctx)"); | ||
| 146 | if ((isqrt = BN_CTX_get(ctx)) == NULL) | ||
| 147 | errx(1, "result = BN_CTX_get(ctx)"); | ||
| 148 | if ((testcase = BN_CTX_get(ctx)) == NULL) | ||
| 149 | errx(1, "testcase = BN_CTX_get(ctx)"); | ||
| 150 | |||
| 151 | /* lower = 2^LOWER_BITS, upper = 2^UPPER_BITS. */ | ||
| 152 | if (!BN_set_bit(lower, LOWER_BITS)) | ||
| 153 | errx(1, "BN_set_bit(lower, %d)", LOWER_BITS); | ||
| 154 | if (!BN_set_bit(upper, UPPER_BITS)) | ||
| 155 | errx(1, "BN_set_bit(upper, %d)", UPPER_BITS); | ||
| 156 | |||
| 157 | if (!bn_rand_interval(n, lower, upper)) | ||
| 158 | errx(1, "bn_rand_interval n"); | ||
| 159 | |||
| 160 | /* n_sqr = n^2 */ | ||
| 161 | if (!BN_sqr(n_sqr, n, ctx)) | ||
| 162 | errx(1, "BN_sqr"); | ||
| 163 | |||
| 164 | if (!bn_isqrt(isqrt, &is_perfect_square, n_sqr, ctx)) | ||
| 165 | errx(1, "bn_isqrt n_sqr"); | ||
| 166 | |||
| 167 | if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) { | ||
| 168 | fprintf(stderr, "n = "); | ||
| 169 | BN_print_fp(stderr, n); | ||
| 170 | fprintf(stderr, "n^2 is_perfect_square: %d, cmp: %d\n", | ||
| 171 | is_perfect_square, cmp); | ||
| 172 | failed = 1; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* upper = 2 * n + 1 */ | ||
| 176 | if (!BN_lshift1(upper, n)) | ||
| 177 | errx(1, "BN_lshift1(upper, n)"); | ||
| 178 | if (!BN_add_word(upper, 1)) | ||
| 179 | errx(1, "BN_sub_word(upper, 1)"); | ||
| 180 | |||
| 181 | /* upper = (n + 1)^2 = n^2 + upper */ | ||
| 182 | if (!BN_add(upper, n_sqr, upper)) | ||
| 183 | errx(1, "BN_add"); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Check that isqrt((n + 1)^2) - 1 == n. | ||
| 187 | */ | ||
| 188 | |||
| 189 | if (!bn_isqrt(isqrt, &is_perfect_square, upper, ctx)) | ||
| 190 | errx(1, "bn_isqrt(upper)"); | ||
| 191 | |||
| 192 | if (!BN_sub_word(isqrt, 1)) | ||
| 193 | errx(1, "BN_add_word(isqrt, 1)"); | ||
| 194 | |||
| 195 | if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) { | ||
| 196 | fprintf(stderr, "n = "); | ||
| 197 | BN_print_fp(stderr, n); | ||
| 198 | fprintf(stderr, "\n(n + 1)^2 is_perfect_square: %d, cmp: %d\n", | ||
| 199 | is_perfect_square, cmp); | ||
| 200 | failed = 1; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Test N_TESTS random numbers n^2 <= testcase < (n + 1)^2 and check | ||
| 205 | * that their isqrt is n. | ||
| 206 | */ | ||
| 207 | |||
| 208 | for (i = 1; i < N_TESTS; i++) { | ||
| 209 | if (!bn_rand_interval(testcase, n_sqr, upper)) | ||
| 210 | errx(1, "bn_rand_interval testcase"); | ||
| 211 | |||
| 212 | if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx)) | ||
| 213 | errx(1, "bn_isqrt testcase"); | ||
| 214 | |||
| 215 | if ((cmp = BN_cmp(n, isqrt)) != 0 || is_perfect_square) { | ||
| 216 | fprintf(stderr, "n = "); | ||
| 217 | BN_print_fp(stderr, n); | ||
| 218 | fprintf(stderr, "\ntestcase = "); | ||
| 219 | BN_print_fp(stderr, testcase); | ||
| 220 | fprintf(stderr, | ||
| 221 | "\ntestcase is_perfect_square: %d, cmp: %d\n", | ||
| 222 | is_perfect_square, cmp); | ||
| 223 | failed = 1; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | /* | ||
| 228 | * Finally check that isqrt(n^2 - 1) + 1 = n. | ||
| 229 | */ | ||
| 230 | |||
| 231 | if (!BN_sub(testcase, n_sqr, BN_value_one())) | ||
| 232 | errx(1, "BN_sub(testcase, n_sqr, 1)"); | ||
| 233 | |||
| 234 | if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx)) | ||
| 235 | errx(1, "bn_isqrt(n_sqr - 1)"); | ||
| 236 | |||
| 237 | if (!BN_add_word(isqrt, 1)) | ||
| 238 | errx(1, "BN_add_word(isqrt, 1)"); | ||
| 239 | |||
| 240 | if ((cmp = BN_cmp(n, isqrt)) != 0 || is_perfect_square) { | ||
| 241 | fprintf(stderr, "n = "); | ||
| 242 | BN_print_fp(stderr, n); | ||
| 243 | fprintf(stderr, "\nn_sqr - 1 is_perfect_square: %d, cmp: %d\n", | ||
| 244 | is_perfect_square, cmp); | ||
| 245 | failed = 1; | ||
| 246 | } | ||
| 247 | |||
| 248 | |||
| 249 | BN_CTX_end(ctx); | ||
| 250 | BN_CTX_free(ctx); | ||
| 251 | |||
| 252 | return failed; | ||
| 253 | } | ||
| 254 | |||
| 255 | static void | ||
| 256 | usage(void) | ||
| 257 | { | ||
| 258 | fprintf(stderr, "usage: bn_isqrt [-C]\n"); | ||
| 259 | exit(1); | ||
| 260 | } | ||
| 261 | |||
| 262 | int | ||
| 263 | main(int argc, char *argv[]) | ||
| 264 | { | ||
| 265 | size_t i; | ||
| 266 | int ch; | ||
| 267 | int failed = 0, print = 0; | ||
| 268 | |||
| 269 | while ((ch = getopt(argc, argv, "C")) != -1) { | ||
| 270 | switch (ch) { | ||
| 271 | case 'C': | ||
| 272 | print = 1; | ||
| 273 | break; | ||
| 274 | default: | ||
| 275 | usage(); | ||
| 276 | break; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | if (print) | ||
| 281 | return check_tables(1); | ||
| 282 | |||
| 283 | for (i = 0; i < N_TESTS; i++) | ||
| 284 | failed |= isqrt_test(); | ||
| 285 | |||
| 286 | failed |= check_tables(0); | ||
| 287 | |||
| 288 | if (!failed) | ||
| 289 | printf("SUCCESS\n"); | ||
| 290 | |||
| 291 | return failed; | ||
| 292 | } | ||
