1/* $OpenBSD: bn_primes.c,v 1.3 2023/04/25 15:30:03 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 <stdint.h> 19#include <stdio.h> 20#include <stdlib.h> 21 22#include <openssl/bn.h> 23 24#include "bn_prime.h" 25 26static int 27test_bn_is_prime_fasttest(int do_trial_division) 28{ 29 BIGNUM *n = NULL; 30 char *descr = NULL; 31 uint16_t i, j, max; 32 int is_prime, ret; 33 int failed = 1; 34 35 if (asprintf(&descr, "with%s trial divisions", 36 do_trial_division ? "" : "out") == -1) { 37 descr = NULL; 38 fprintf(stderr, "asprintf failed\n"); 39 goto err; 40 } 41 42 if ((n = BN_new()) == NULL) { 43 fprintf(stderr, "BN_new failed\n"); 44 goto err; 45 } 46 47 max = primes[NUMPRIMES - 1] + 1; 48 49 failed = 0; 50 for (i = 1, j = 0; i < max && j < NUMPRIMES; i++) { 51 if (!BN_set_word(n, i)) { 52 fprintf(stderr, "BN_set_word(%d) failed", i); 53 failed = 1; 54 goto err; 55 } 56 57 is_prime = i == primes[j]; 58 if (is_prime) 59 j++; 60 61 ret = BN_is_prime_fasttest_ex(n, BN_prime_checks, NULL, 62 do_trial_division, NULL); 63 if (ret != is_prime) { 64 fprintf(stderr, 65 "BN_is_prime_fasttest_ex(%d) %s: want %d, got %d\n", 66 i, descr, is_prime, ret); 67 failed = 1; 68 } 69 } 70 71 if (i < max || j < NUMPRIMES) { 72 fprintf(stderr, "%s: %d < %d or %d < %d\n", descr, i, max, j, 73 NUMPRIMES); 74 failed = 1; 75 } 76 77 err: 78 BN_free(n); 79 free(descr); 80 return failed; 81} 82 83#define BN_PRIME_FN_INIT(a) { .fn = a, .name = #a } 84 85static const struct test_dynamic_api { 86 BIGNUM *(*fn)(BIGNUM *); 87 const char *name; 88} dynamic_api_data[] = { 89 BN_PRIME_FN_INIT(BN_get_rfc2409_prime_1024), 90 BN_PRIME_FN_INIT(BN_get_rfc2409_prime_768), 91 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_1536), 92 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_2048), 93 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_3072), 94 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_4096), 95 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_6144), 96 BN_PRIME_FN_INIT(BN_get_rfc3526_prime_8192), 97}; 98 99#define N_DYNAMIC_TESTS (sizeof(dynamic_api_data) / sizeof(dynamic_api_data[0])) 100 101static int 102test_prime_dynamic_api(const struct test_dynamic_api *tc) 103{ 104 BIGNUM *prime; 105 int ret; 106 int failed = 1; 107 108 if ((prime = tc->fn(NULL)) == NULL) { 109 fprintf(stderr, "%s failed\n", tc->name); 110 goto err; 111 } 112 113 if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) { 114 fprintf(stderr, "%s: %s want 1, got %d\n", tc->name, 115 "BN_is_prime_fasttest_ex", ret); 116 goto err; 117 } 118 119 failed = 0; 120 121 err: 122 BN_free(prime); 123 return failed; 124} 125 126static int 127test_prime_constants(void) 128{ 129 size_t i; 130 int failed = 0; 131 132 for (i = 0; i < N_DYNAMIC_TESTS; i++) 133 failed |= test_prime_dynamic_api(&dynamic_api_data[i]); 134 135 return failed; 136} 137 138int 139main(void) 140{ 141 int failed = 0; 142 143 failed |= test_bn_is_prime_fasttest(0); 144 failed |= test_bn_is_prime_fasttest(1); 145 failed |= test_prime_constants(); 146 147 return failed; 148} 149