Home | History | Annotate | Line # | Download | only in apps
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos #include <string.h>
     11      1.1  christos 
     12      1.1  christos #include "apps.h"
     13      1.1  christos #include "progs.h"
     14      1.1  christos #include <openssl/bn.h>
     15      1.1  christos 
     16      1.1  christos typedef enum OPTION_choice {
     17      1.1  christos     OPT_COMMON,
     18  1.1.1.2  christos     OPT_HEX,
     19  1.1.1.2  christos     OPT_GENERATE,
     20  1.1.1.2  christos     OPT_BITS,
     21  1.1.1.2  christos     OPT_SAFE,
     22  1.1.1.2  christos     OPT_CHECKS,
     23      1.1  christos     OPT_PROV_ENUM
     24      1.1  christos } OPTION_CHOICE;
     25      1.1  christos 
     26      1.1  christos static int check_num(const char *s, const int is_hex)
     27      1.1  christos {
     28      1.1  christos     int i;
     29      1.1  christos     /*
     30      1.1  christos      * It would make sense to use ossl_isxdigit and ossl_isdigit here,
     31      1.1  christos      * but ossl_ctype_check is a local symbol in libcrypto.so.
     32      1.1  christos      */
     33      1.1  christos     if (is_hex) {
     34      1.1  christos         for (i = 0; ('0' <= s[i] && s[i] <= '9')
     35  1.1.1.2  christos             || ('A' <= s[i] && s[i] <= 'F')
     36  1.1.1.2  christos             || ('a' <= s[i] && s[i] <= 'f');
     37  1.1.1.2  christos             i++)
     38  1.1.1.2  christos             ;
     39      1.1  christos     } else {
     40  1.1.1.2  christos         for (i = 0; '0' <= s[i] && s[i] <= '9'; i++)
     41  1.1.1.2  christos             ;
     42      1.1  christos     }
     43      1.1  christos     return s[i] == 0;
     44      1.1  christos }
     45      1.1  christos 
     46      1.1  christos const OPTIONS prime_options[] = {
     47  1.1.1.2  christos     { OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n" },
     48      1.1  christos 
     49      1.1  christos     OPT_SECTION("General"),
     50  1.1.1.2  christos     { "help", OPT_HELP, '-', "Display this summary" },
     51  1.1.1.2  christos     { "bits", OPT_BITS, 'p', "Size of number in bits" },
     52  1.1.1.2  christos     { "checks", OPT_CHECKS, 'p', "Number of checks" },
     53      1.1  christos 
     54      1.1  christos     OPT_SECTION("Output"),
     55  1.1.1.2  christos     { "hex", OPT_HEX, '-', "Hex output" },
     56  1.1.1.2  christos     { "generate", OPT_GENERATE, '-', "Generate a prime" },
     57  1.1.1.2  christos     { "safe", OPT_SAFE, '-',
     58  1.1.1.2  christos         "When used with -generate, generate a safe prime" },
     59      1.1  christos 
     60      1.1  christos     OPT_PROV_OPTIONS,
     61      1.1  christos 
     62      1.1  christos     OPT_PARAMETERS(),
     63  1.1.1.2  christos     { "number", 0, 0, "Number(s) to check for primality if not generating" },
     64  1.1.1.2  christos     { NULL }
     65      1.1  christos };
     66      1.1  christos 
     67      1.1  christos int prime_main(int argc, char **argv)
     68      1.1  christos {
     69      1.1  christos     BIGNUM *bn = NULL;
     70      1.1  christos     int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1;
     71      1.1  christos     char *prog;
     72      1.1  christos     OPTION_CHOICE o;
     73      1.1  christos 
     74      1.1  christos     prog = opt_init(argc, argv, prime_options);
     75      1.1  christos     while ((o = opt_next()) != OPT_EOF) {
     76      1.1  christos         switch (o) {
     77      1.1  christos         case OPT_EOF:
     78      1.1  christos         case OPT_ERR:
     79  1.1.1.2  christos         opthelp:
     80      1.1  christos             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
     81      1.1  christos             goto end;
     82      1.1  christos         case OPT_HELP:
     83      1.1  christos             opt_help(prime_options);
     84      1.1  christos             ret = 0;
     85      1.1  christos             goto end;
     86      1.1  christos         case OPT_HEX:
     87      1.1  christos             hex = 1;
     88      1.1  christos             break;
     89      1.1  christos         case OPT_GENERATE:
     90      1.1  christos             generate = 1;
     91      1.1  christos             break;
     92      1.1  christos         case OPT_BITS:
     93      1.1  christos             bits = atoi(opt_arg());
     94      1.1  christos             break;
     95      1.1  christos         case OPT_SAFE:
     96      1.1  christos             safe = 1;
     97      1.1  christos             break;
     98      1.1  christos         case OPT_CHECKS:
     99      1.1  christos             /* ignore parameter and argument */
    100      1.1  christos             opt_arg();
    101      1.1  christos             break;
    102      1.1  christos         case OPT_PROV_CASES:
    103      1.1  christos             if (!opt_provider(o))
    104      1.1  christos                 goto end;
    105      1.1  christos             break;
    106      1.1  christos         }
    107      1.1  christos     }
    108      1.1  christos 
    109      1.1  christos     /* Optional arguments are numbers to check. */
    110      1.1  christos     if (generate && !opt_check_rest_arg(NULL))
    111      1.1  christos         goto opthelp;
    112      1.1  christos     argc = opt_num_rest();
    113      1.1  christos     argv = opt_rest();
    114      1.1  christos     if (!generate && argc == 0) {
    115      1.1  christos         BIO_printf(bio_err, "Missing number (s) to check\n");
    116      1.1  christos         goto opthelp;
    117      1.1  christos     }
    118      1.1  christos 
    119      1.1  christos     if (generate) {
    120      1.1  christos         char *s;
    121      1.1  christos 
    122      1.1  christos         if (!bits) {
    123      1.1  christos             BIO_printf(bio_err, "Specify the number of bits.\n");
    124      1.1  christos             goto end;
    125      1.1  christos         }
    126      1.1  christos         bn = BN_new();
    127      1.1  christos         if (bn == NULL) {
    128      1.1  christos             BIO_printf(bio_err, "Out of memory.\n");
    129      1.1  christos             goto end;
    130      1.1  christos         }
    131      1.1  christos         if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) {
    132      1.1  christos             BIO_printf(bio_err, "Failed to generate prime.\n");
    133      1.1  christos             goto end;
    134      1.1  christos         }
    135      1.1  christos         s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn);
    136      1.1  christos         if (s == NULL) {
    137      1.1  christos             BIO_printf(bio_err, "Out of memory.\n");
    138      1.1  christos             goto end;
    139      1.1  christos         }
    140      1.1  christos         BIO_printf(bio_out, "%s\n", s);
    141      1.1  christos         OPENSSL_free(s);
    142      1.1  christos     } else {
    143  1.1.1.2  christos         for (; *argv; argv++) {
    144      1.1  christos             int r = check_num(argv[0], hex);
    145      1.1  christos 
    146      1.1  christos             if (r)
    147      1.1  christos                 r = hex ? BN_hex2bn(&bn, argv[0]) : BN_dec2bn(&bn, argv[0]);
    148      1.1  christos 
    149      1.1  christos             if (!r) {
    150      1.1  christos                 BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]);
    151      1.1  christos                 goto end;
    152      1.1  christos             }
    153      1.1  christos 
    154      1.1  christos             BN_print(bio_out, bn);
    155      1.1  christos             r = BN_check_prime(bn, NULL, NULL);
    156      1.1  christos             if (r < 0) {
    157      1.1  christos                 BIO_printf(bio_err, "Error checking prime\n");
    158      1.1  christos                 goto end;
    159      1.1  christos             }
    160      1.1  christos             BIO_printf(bio_out, " (%s) %s prime\n",
    161  1.1.1.2  christos                 argv[0],
    162  1.1.1.2  christos                 r == 1 ? "is" : "is not");
    163      1.1  christos         }
    164      1.1  christos     }
    165      1.1  christos 
    166      1.1  christos     ret = 0;
    167  1.1.1.2  christos end:
    168      1.1  christos     BN_free(bn);
    169      1.1  christos     return ret;
    170      1.1  christos }
    171