diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/libgcrypt/tests/rsacvt.c | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/libgcrypt/tests/rsacvt.c')
-rw-r--r-- | comm/third_party/libgcrypt/tests/rsacvt.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/comm/third_party/libgcrypt/tests/rsacvt.c b/comm/third_party/libgcrypt/tests/rsacvt.c new file mode 100644 index 0000000000..3cc50d7993 --- /dev/null +++ b/comm/third_party/libgcrypt/tests/rsacvt.c @@ -0,0 +1,399 @@ +/* rsacvt.c - A debug tool to convert RSA formats. + Copyright (C) 2009 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* Input data format: + +======= +# A hash denotes a comment line +e861b700e17e8afe68[...]f1 +f7a7ca5367c661f8e6[...]61 +10001 + +# After an empty line another input block may follow. +7861b700e17e8afe68[...]f3 +e7a7ca5367c661f8e6[...]71 +3 +========= + +*/ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#include <ctype.h> +#ifdef HAVE_W32_SYSTEM +# include <fcntl.h> /* We need setmode(). */ +#else +# include <signal.h> +#endif +#include <assert.h> +#include <unistd.h> + +#ifdef _GCRYPT_IN_LIBGCRYPT +# include "../src/gcrypt-int.h" +#else +# include <gcrypt.h> +# define PACKAGE_BUGREPORT "devnull@example.org" +# define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]" +#endif + + +#define PGM "rsacvt" +#include "t-common.h" + + +/* Prefix output with labels. */ +static int with_labels; + +/* Do not suppress leading zeroes. */ +static int keep_lz; + +/* Create parameters as specified by OpenPGP (rfc4880). That is we + don't store dmp1 and dmp1 but d and make sure that p is less than q. */ +static int openpgp_mode; + + +static char * +read_textline (FILE *fp) +{ + char line[4096]; + char *p; + int any = 0; + + /* Read line but skip over initial empty lines. */ + do + { + do + { + if (!fgets (line, sizeof line, fp)) + { + if (feof (fp)) + return NULL; + die ("error reading input line: %s\n", strerror (errno)); + } + p = strchr (line, '\n'); + if (p) + *p = 0; + p = line + (*line? (strlen (line)-1):0); + for ( ;p > line; p--) + if (my_isascii (*p) && isspace (*p)) + *p = 0; + } + while (!any && !*line); + any = 1; + } + while (*line == '#'); /* Always skip comment lines. */ + if (verbose > 1) + fprintf (stderr, PGM ": received line: %s\n", line); + return gcry_xstrdup (line); +} + + +static gcry_mpi_t +read_hexmpi_line (FILE *fp, int *got_eof) +{ + gpg_error_t err; + gcry_mpi_t a; + char *line; + + *got_eof = 0; + line = read_textline (fp); + if (!line) + { + *got_eof = 1; + return NULL; + } + err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL); + gcry_free (line); + if (err) + a = NULL; + return a; +} + + +static int +skip_to_empty_line (FILE *fp) +{ + char line[256]; + char *p; + + do + { + if (!fgets (line, sizeof line, fp)) + { + if (feof (fp)) + return -1; + die ("error reading input line: %s\n", strerror (errno)); + } + p = strchr (line, '\n'); + if (p) + *p =0; + } + while (*line); + return 0; +} + + +/* Print an MPI on a line. */ +static void +print_mpi_line (const char *label, gcry_mpi_t a) +{ + unsigned char *buf, *p; + gcry_error_t err; + int writerr = 0; + + if (with_labels && label) + printf ("%s = ", label); + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a); + if (err) + die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err)); + + p = buf; + if (!keep_lz && p[0] == '0' && p[1] == '0' && p[2]) + p += 2; + + printf ("%s\n", p); + if (ferror (stdout)) + writerr++; + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + die ("writing output failed: %s\n", strerror (errno)); + gcry_free (buf); +} + + +/* Compute and print missing RSA parameters. */ +static void +compute_missing (gcry_mpi_t rsa_p, gcry_mpi_t rsa_q, gcry_mpi_t rsa_e) +{ + gcry_mpi_t rsa_n, rsa_d, rsa_pm1, rsa_qm1, rsa_u; + gcry_mpi_t phi, tmp_g, tmp_f; + + rsa_n = gcry_mpi_new (0); + rsa_d = gcry_mpi_new (0); + rsa_pm1 = gcry_mpi_new (0); + rsa_qm1 = gcry_mpi_new (0); + rsa_u = gcry_mpi_new (0); + + phi = gcry_mpi_new (0); + tmp_f = gcry_mpi_new (0); + tmp_g = gcry_mpi_new (0); + + /* Check that p < q; if not swap p and q. */ + if (openpgp_mode && gcry_mpi_cmp (rsa_p, rsa_q) > 0) + { + fprintf (stderr, PGM ": swapping p and q\n"); + gcry_mpi_swap (rsa_p, rsa_q); + } + + gcry_mpi_mul (rsa_n, rsa_p, rsa_q); + + + /* Compute the Euler totient: phi = (p-1)(q-1) */ + gcry_mpi_sub_ui (rsa_pm1, rsa_p, 1); + gcry_mpi_sub_ui (rsa_qm1, rsa_q, 1); + gcry_mpi_mul (phi, rsa_pm1, rsa_qm1); + + if (!gcry_mpi_gcd (tmp_g, rsa_e, phi)) + die ("parameter 'e' does match 'p' and 'q'\n"); + + /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */ + gcry_mpi_gcd (tmp_g, rsa_pm1, rsa_qm1); + gcry_mpi_div (tmp_f, NULL, phi, tmp_g, -1); + + /* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */ + gcry_mpi_invm (rsa_d, rsa_e, tmp_f); + + /* Compute the CRT helpers: d mod (p-1), d mod (q-1) */ + gcry_mpi_mod (rsa_pm1, rsa_d, rsa_pm1); + gcry_mpi_mod (rsa_qm1, rsa_d, rsa_qm1); + + /* Compute the CRT value: OpenPGP: u = p^{-1} mod q + Standard: iqmp = q^{-1} mod p */ + if (openpgp_mode) + gcry_mpi_invm (rsa_u, rsa_p, rsa_q); + else + gcry_mpi_invm (rsa_u, rsa_q, rsa_p); + + gcry_mpi_release (phi); + gcry_mpi_release (tmp_f); + gcry_mpi_release (tmp_g); + + /* Print everything. */ + print_mpi_line ("n", rsa_n); + print_mpi_line ("e", rsa_e); + if (openpgp_mode) + print_mpi_line ("d", rsa_d); + print_mpi_line ("p", rsa_p); + print_mpi_line ("q", rsa_q); + if (openpgp_mode) + print_mpi_line ("u", rsa_u); + else + { + print_mpi_line ("dmp1", rsa_pm1); + print_mpi_line ("dmq1", rsa_qm1); + print_mpi_line ("iqmp", rsa_u); + } + + gcry_mpi_release (rsa_n); + gcry_mpi_release (rsa_d); + gcry_mpi_release (rsa_pm1); + gcry_mpi_release (rsa_qm1); + gcry_mpi_release (rsa_u); +} + + + +static void +usage (int show_help) +{ + if (!show_help) + { + fputs ("usage: " PGM + " [OPTION] [FILE] (try --help for more information)\n", stderr); + exit (2); + } + fputs + ("Usage: " PGM " [OPTIONS] [FILE]\n" + "Take RSA parameters p, n, e and compute missing parameters.\n" + "OPTIONS:\n" + " --openpgp Compute as specified by RFC4880\n" + " --labels Prefix output with labels\n" + " --keep-lz Keep all leading zeroes in the output\n" + " --verbose Print additional information\n" + " --version Print version information\n" + " --help Print this text\n" + "With no FILE, or if FILE is -, read standard input.\n" + "Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout); + exit (0); +} + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + FILE *input; + gcry_mpi_t rsa_p, rsa_q, rsa_e; + int got_eof; + int any = 0; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + usage (1); + } + else if (!strcmp (*argv, "--version")) + { + fputs (PGM " (Libgcrypt) " PACKAGE_VERSION "\n", stdout); + printf ("libgcrypt %s\n", gcry_check_version (NULL)); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--labels")) + { + with_labels = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--keep-lz")) + { + keep_lz = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--openpgp")) + { + openpgp_mode = 1; + argc--; argv++; + } + } + + if (argc > 1) + usage (0); + +#if !defined (HAVE_W32_SYSTEM) && !defined (_WIN32) + signal (SIGPIPE, SIG_IGN); +#endif + + if (argc == 1 && strcmp (argv[0], "-")) + { + input = fopen (argv[0], "r"); + if (!input) + die ("can't open `%s': %s\n", argv[0], strerror (errno)); + } + else + input = stdin; + + xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose)); + if (!gcry_check_version ("1.4.0")) + die ("Libgcrypt is not sufficient enough\n"); + xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + + do + { + rsa_p = read_hexmpi_line (input, &got_eof); + if (!rsa_p && got_eof) + break; + if (!rsa_p) + die ("RSA parameter 'p' missing or not properly hex encoded\n"); + rsa_q = read_hexmpi_line (input, &got_eof); + if (!rsa_q) + die ("RSA parameter 'q' missing or not properly hex encoded\n"); + rsa_e = read_hexmpi_line (input, &got_eof); + if (!rsa_e) + die ("RSA parameter 'e' missing or not properly hex encoded\n"); + got_eof = skip_to_empty_line (input); + + if (any) + putchar ('\n'); + + compute_missing (rsa_p, rsa_q, rsa_e); + + gcry_mpi_release (rsa_p); + gcry_mpi_release (rsa_q); + gcry_mpi_release (rsa_e); + + any = 1; + } + while (!got_eof); + + return 0; +} |