/*
 * Copyright 2004-2025 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>

/* Consistent with RSA modulus size limit and the size of plausible individual primes */
#define BUFSIZE 4098

typedef enum OPTION_choice {
    OPT_COMMON,
    OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
    OPT_PROV_ENUM,
    OPT_IN_FILE
} 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;
}

static void process_num(const char *s, const int is_hex)
{
    int r;
    BIGNUM *bn = NULL;

    r = check_num(s, is_hex);

    if (r)
        r = is_hex ? BN_hex2bn(&bn, s) : BN_dec2bn(&bn, s);

    if (!r) {
        BIO_printf(bio_err, "Failed to process value (%s)\n", s);
        BN_free(bn);
        return;
    }

    BN_print(bio_out, bn);
    r = BN_check_prime(bn, NULL, NULL);
    BN_free(bn);
    if (r < 0) {
        BIO_printf(bio_err, "Error checking prime\n");
        return;
    }

    BIO_printf(bio_out, " (%s) %s prime\n", s, r == 1 ? "is" : "is not");
}

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"},
    {"hex", OPT_HEX, '-',
     "Enables hex format for output from prime generation or input to primality checking"},
    {"in", OPT_IN_FILE, '-', "Provide file names containing numbers for primality checking"},

    OPT_SECTION("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, in_file = 0;
    char *prog;
    OPTION_CHOICE o;
    char file_read_buf[BUFSIZE] = { 0 };
    BIO *in = NULL;

    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;
        case OPT_IN_FILE:
            in_file = 1;
            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 bytes_read = 0;
            int valid_digits_length = 0;

            if (!in_file) {
                process_num(argv[0], hex);
            } else {
                in = bio_open_default_quiet(argv[0], 'r', 0);
                if (in == NULL) {
                    BIO_printf(bio_err, "Error opening file %s\n", argv[0]);
                    continue;
                }

                while ((bytes_read = BIO_get_line(in, file_read_buf, BUFSIZE)) > 0) {
                    /* Number is too long. Discard remainder of the line */
                    if (bytes_read == BUFSIZE - 1 && file_read_buf[BUFSIZE - 2] != '\n') {
                        BIO_printf(bio_err, "Value in %s is over the maximum size (%d digits)\n",
                                   argv[0], BUFSIZE - 2);
                        while (BIO_get_line(in, file_read_buf, BUFSIZE) == BUFSIZE - 1);
                        continue;
                    }

                    valid_digits_length = strspn(file_read_buf, "1234567890abcdefABCDEF");
                    file_read_buf[valid_digits_length] = '\0';

                    process_num(file_read_buf, hex);
                }

                if (bytes_read < 0)
                    BIO_printf(bio_err, "Read error in %s\n", argv[0]);

                if (in != NULL)
                    BIO_free(in);
                in = NULL;
            }
        }
    }

    ret = 0;
 end:
    BN_free(bn);
    return ret;
}
