123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /*
- * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- #include <string.h>
- #include "apps.h"
- #include "progs.h"
- #include <openssl/bn.h>
- typedef enum OPTION_choice {
- OPT_COMMON,
- OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
- OPT_PROV_ENUM
- } OPTION_CHOICE;
- static int check_num(const char *s, const int is_hex)
- {
- int i;
- /*
- * It would make sense to use ossl_isxdigit and ossl_isdigit here,
- * but ossl_ctype_check is a local symbol in libcrypto.so.
- */
- if (is_hex) {
- for (i = 0; ('0' <= s[i] && s[i] <= '9')
- || ('A' <= s[i] && s[i] <= 'F')
- || ('a' <= s[i] && s[i] <= 'f'); i++);
- } else {
- for (i = 0; '0' <= s[i] && s[i] <= '9'; i++);
- }
- return s[i] == 0;
- }
- const OPTIONS prime_options[] = {
- {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"},
- OPT_SECTION("General"),
- {"help", OPT_HELP, '-', "Display this summary"},
- {"bits", OPT_BITS, 'p', "Size of number in bits"},
- {"checks", OPT_CHECKS, 'p', "Number of checks"},
- OPT_SECTION("Output"),
- {"hex", OPT_HEX, '-', "Hex output"},
- {"generate", OPT_GENERATE, '-', "Generate a prime"},
- {"safe", OPT_SAFE, '-',
- "When used with -generate, generate a safe prime"},
- OPT_PROV_OPTIONS,
- OPT_PARAMETERS(),
- {"number", 0, 0, "Number(s) to check for primality if not generating"},
- {NULL}
- };
- int prime_main(int argc, char **argv)
- {
- BIGNUM *bn = NULL;
- int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1;
- char *prog;
- OPTION_CHOICE o;
- prog = opt_init(argc, argv, prime_options);
- while ((o = opt_next()) != OPT_EOF) {
- switch (o) {
- case OPT_EOF:
- case OPT_ERR:
- opthelp:
- BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
- goto end;
- case OPT_HELP:
- opt_help(prime_options);
- ret = 0;
- goto end;
- case OPT_HEX:
- hex = 1;
- break;
- case OPT_GENERATE:
- generate = 1;
- break;
- case OPT_BITS:
- bits = atoi(opt_arg());
- break;
- case OPT_SAFE:
- safe = 1;
- break;
- case OPT_CHECKS:
- /* ignore parameter and argument */
- opt_arg();
- break;
- case OPT_PROV_CASES:
- if (!opt_provider(o))
- goto end;
- break;
- }
- }
- /* Optional arguments are numbers to check. */
- if (generate && !opt_check_rest_arg(NULL))
- goto opthelp;
- argc = opt_num_rest();
- argv = opt_rest();
- if (!generate && argc == 0) {
- BIO_printf(bio_err, "Missing number (s) to check\n");
- goto opthelp;
- }
- if (generate) {
- char *s;
- if (!bits) {
- BIO_printf(bio_err, "Specify the number of bits.\n");
- goto end;
- }
- bn = BN_new();
- if (bn == NULL) {
- BIO_printf(bio_err, "Out of memory.\n");
- goto end;
- }
- if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) {
- BIO_printf(bio_err, "Failed to generate prime.\n");
- goto end;
- }
- s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn);
- if (s == NULL) {
- BIO_printf(bio_err, "Out of memory.\n");
- goto end;
- }
- BIO_printf(bio_out, "%s\n", s);
- OPENSSL_free(s);
- } else {
- for ( ; *argv; argv++) {
- int r = check_num(argv[0], hex);
- if (r)
- r = hex ? BN_hex2bn(&bn, argv[0]) : BN_dec2bn(&bn, argv[0]);
- if (!r) {
- BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]);
- goto end;
- }
- BN_print(bio_out, bn);
- BIO_printf(bio_out, " (%s) %s prime\n",
- argv[0],
- BN_check_prime(bn, NULL, NULL)
- ? "is" : "is not");
- }
- }
- ret = 0;
- end:
- BN_free(bn);
- return ret;
- }
|