prime.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. #include <string.h>
  10. #include "apps.h"
  11. #include "progs.h"
  12. #include <openssl/bn.h>
  13. typedef enum OPTION_choice {
  14. OPT_COMMON,
  15. OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
  16. OPT_PROV_ENUM
  17. } OPTION_CHOICE;
  18. static int check_num(const char *s, const int is_hex)
  19. {
  20. int i;
  21. /*
  22. * It would make sense to use ossl_isxdigit and ossl_isdigit here,
  23. * but ossl_ctype_check is a local symbol in libcrypto.so.
  24. */
  25. if (is_hex) {
  26. for (i = 0; ('0' <= s[i] && s[i] <= '9')
  27. || ('A' <= s[i] && s[i] <= 'F')
  28. || ('a' <= s[i] && s[i] <= 'f'); i++);
  29. } else {
  30. for (i = 0; '0' <= s[i] && s[i] <= '9'; i++);
  31. }
  32. return s[i] == 0;
  33. }
  34. const OPTIONS prime_options[] = {
  35. {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"},
  36. OPT_SECTION("General"),
  37. {"help", OPT_HELP, '-', "Display this summary"},
  38. {"bits", OPT_BITS, 'p', "Size of number in bits"},
  39. {"checks", OPT_CHECKS, 'p', "Number of checks"},
  40. OPT_SECTION("Output"),
  41. {"hex", OPT_HEX, '-', "Hex output"},
  42. {"generate", OPT_GENERATE, '-', "Generate a prime"},
  43. {"safe", OPT_SAFE, '-',
  44. "When used with -generate, generate a safe prime"},
  45. OPT_PROV_OPTIONS,
  46. OPT_PARAMETERS(),
  47. {"number", 0, 0, "Number(s) to check for primality if not generating"},
  48. {NULL}
  49. };
  50. int prime_main(int argc, char **argv)
  51. {
  52. BIGNUM *bn = NULL;
  53. int hex = 0, generate = 0, bits = 0, safe = 0, ret = 1;
  54. char *prog;
  55. OPTION_CHOICE o;
  56. prog = opt_init(argc, argv, prime_options);
  57. while ((o = opt_next()) != OPT_EOF) {
  58. switch (o) {
  59. case OPT_EOF:
  60. case OPT_ERR:
  61. opthelp:
  62. BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
  63. goto end;
  64. case OPT_HELP:
  65. opt_help(prime_options);
  66. ret = 0;
  67. goto end;
  68. case OPT_HEX:
  69. hex = 1;
  70. break;
  71. case OPT_GENERATE:
  72. generate = 1;
  73. break;
  74. case OPT_BITS:
  75. bits = atoi(opt_arg());
  76. break;
  77. case OPT_SAFE:
  78. safe = 1;
  79. break;
  80. case OPT_CHECKS:
  81. /* ignore parameter and argument */
  82. opt_arg();
  83. break;
  84. case OPT_PROV_CASES:
  85. if (!opt_provider(o))
  86. goto end;
  87. break;
  88. }
  89. }
  90. /* Optional arguments are numbers to check. */
  91. if (generate && !opt_check_rest_arg(NULL))
  92. goto opthelp;
  93. argc = opt_num_rest();
  94. argv = opt_rest();
  95. if (!generate && argc == 0) {
  96. BIO_printf(bio_err, "Missing number (s) to check\n");
  97. goto opthelp;
  98. }
  99. if (generate) {
  100. char *s;
  101. if (!bits) {
  102. BIO_printf(bio_err, "Specify the number of bits.\n");
  103. goto end;
  104. }
  105. bn = BN_new();
  106. if (bn == NULL) {
  107. BIO_printf(bio_err, "Out of memory.\n");
  108. goto end;
  109. }
  110. if (!BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL)) {
  111. BIO_printf(bio_err, "Failed to generate prime.\n");
  112. goto end;
  113. }
  114. s = hex ? BN_bn2hex(bn) : BN_bn2dec(bn);
  115. if (s == NULL) {
  116. BIO_printf(bio_err, "Out of memory.\n");
  117. goto end;
  118. }
  119. BIO_printf(bio_out, "%s\n", s);
  120. OPENSSL_free(s);
  121. } else {
  122. for ( ; *argv; argv++) {
  123. int r = check_num(argv[0], hex);
  124. if (r)
  125. r = hex ? BN_hex2bn(&bn, argv[0]) : BN_dec2bn(&bn, argv[0]);
  126. if (!r) {
  127. BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]);
  128. goto end;
  129. }
  130. BN_print(bio_out, bn);
  131. BIO_printf(bio_out, " (%s) %s prime\n",
  132. argv[0],
  133. BN_check_prime(bn, NULL, NULL)
  134. ? "is" : "is not");
  135. }
  136. }
  137. ret = 0;
  138. end:
  139. BN_free(bn);
  140. return ret;
  141. }