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