diff options
author | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
---|---|---|
committer | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
commit | c60aed5432e9cda277b9351de51e82dfb8e02475 (patch) | |
tree | 97ccd1ea8e2544f6a9673ee7d04c18b714877a35 /plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c | |
parent | d2b26b1f86326362f56540b5185fa09ab5f2779c (diff) |
MirOTR: part one of many file/folder structure changes
git-svn-id: http://svn.miranda-ng.org/main/trunk@12402 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c')
-rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c | 1379 |
1 files changed, 0 insertions, 1379 deletions
diff --git a/plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c b/plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c deleted file mode 100644 index cf278c2532..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/cipher/rsa.c +++ /dev/null @@ -1,1379 +0,0 @@ -/* rsa.c - RSA implementation - * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) - * Copyright (C) 2000, 2001, 2002, 2003, 2008 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/>. - */ - -/* This code uses an algorithm protected by U.S. Patent #4,405,829 - which expired on September 20, 2000. The patent holder placed that - patent into the public domain on Sep 6th, 2000. -*/ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "g10lib.h" -#include "mpi.h" -#include "cipher.h" - - -typedef struct -{ - gcry_mpi_t n; /* modulus */ - gcry_mpi_t e; /* exponent */ -} RSA_public_key; - - -typedef struct -{ - gcry_mpi_t n; /* public modulus */ - gcry_mpi_t e; /* public exponent */ - gcry_mpi_t d; /* exponent */ - gcry_mpi_t p; /* prime p. */ - gcry_mpi_t q; /* prime q. */ - gcry_mpi_t u; /* inverse of p mod q. */ -} RSA_secret_key; - - -/* A sample 1024 bit RSA key used for the selftests. */ -static const char sample_secret_key[] = -"(private-key" -" (rsa" -" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" -" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" -" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" -" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" -" (e #010001#)" -" (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11" -" 7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd" -" c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21" -" c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)" -" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" -" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)" -" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" -" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)" -" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" -" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))"; -/* A sample 1024 bit RSA key used for the selftests (public only). */ -static const char sample_public_key[] = -"(public-key" -" (rsa" -" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" -" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" -" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" -" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" -" (e #010001#)))"; - - - - -static int test_keys (RSA_secret_key *sk, unsigned nbits); -static int check_secret_key (RSA_secret_key *sk); -static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey); -static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey); - - -/* Check that a freshly generated key actually works. Returns 0 on success. */ -static int -test_keys (RSA_secret_key *sk, unsigned int nbits) -{ - int result = -1; /* Default to failure. */ - RSA_public_key pk; - gcry_mpi_t plaintext = gcry_mpi_new (nbits); - gcry_mpi_t ciphertext = gcry_mpi_new (nbits); - gcry_mpi_t decr_plaintext = gcry_mpi_new (nbits); - gcry_mpi_t signature = gcry_mpi_new (nbits); - - /* Put the relevant parameters into a public key structure. */ - pk.n = sk->n; - pk.e = sk->e; - - /* Create a random plaintext. */ - gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); - - /* Encrypt using the public key. */ - public (ciphertext, plaintext, &pk); - - /* Check that the cipher text does not match the plaintext. */ - if (!gcry_mpi_cmp (ciphertext, plaintext)) - goto leave; /* Ciphertext is identical to the plaintext. */ - - /* Decrypt using the secret key. */ - secret (decr_plaintext, ciphertext, sk); - - /* Check that the decrypted plaintext matches the original plaintext. */ - if (gcry_mpi_cmp (decr_plaintext, plaintext)) - goto leave; /* Plaintext does not match. */ - - /* Create another random plaintext as data for signature checking. */ - gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); - - /* Use the RSA secret function to create a signature of the plaintext. */ - secret (signature, plaintext, sk); - - /* Use the RSA public function to verify this signature. */ - public (decr_plaintext, signature, &pk); - if (gcry_mpi_cmp (decr_plaintext, plaintext)) - goto leave; /* Signature does not match. */ - - /* Modify the signature and check that the signing fails. */ - gcry_mpi_add_ui (signature, signature, 1); - public (decr_plaintext, signature, &pk); - if (!gcry_mpi_cmp (decr_plaintext, plaintext)) - goto leave; /* Signature matches but should not. */ - - result = 0; /* All tests succeeded. */ - - leave: - gcry_mpi_release (signature); - gcry_mpi_release (decr_plaintext); - gcry_mpi_release (ciphertext); - gcry_mpi_release (plaintext); - return result; -} - - -/* Callback used by the prime generation to test whether the exponent - is suitable. Returns 0 if the test has been passed. */ -static int -check_exponent (void *arg, gcry_mpi_t a) -{ - gcry_mpi_t e = arg; - gcry_mpi_t tmp; - int result; - - mpi_sub_ui (a, a, 1); - tmp = _gcry_mpi_alloc_like (a); - result = !gcry_mpi_gcd(tmp, e, a); /* GCD is not 1. */ - gcry_mpi_release (tmp); - mpi_add_ui (a, a, 1); - return result; -} - -/**************** - * Generate a key pair with a key of size NBITS. - * USE_E = 0 let Libcgrypt decide what exponent to use. - * = 1 request the use of a "secure" exponent; this is required by some - * specification to be 65537. - * > 2 Use this public exponent. If the given exponent - * is not odd one is internally added to it. - * TRANSIENT_KEY: If true, generate the primes using the standard RNG. - * Returns: 2 structures filled with all needed values - */ -static gpg_err_code_t -generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, - int transient_key) -{ - gcry_mpi_t p, q; /* the two primes */ - gcry_mpi_t d; /* the private key */ - gcry_mpi_t u; - gcry_mpi_t t1, t2; - gcry_mpi_t n; /* the public key */ - gcry_mpi_t e; /* the exponent */ - gcry_mpi_t phi; /* helper: (p-1)(q-1) */ - gcry_mpi_t g; - gcry_mpi_t f; - gcry_random_level_t random_level; - - if (fips_mode ()) - { - if (nbits < 1024) - return GPG_ERR_INV_VALUE; - if (transient_key) - return GPG_ERR_INV_VALUE; - } - - /* The random quality depends on the transient_key flag. */ - random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; - - /* Make sure that nbits is even so that we generate p, q of equal size. */ - if ( (nbits&1) ) - nbits++; - - if (use_e == 1) /* Alias for a secure value */ - use_e = 65537; /* as demanded by Sphinx. */ - - /* Public exponent: - In general we use 41 as this is quite fast and more secure than the - commonly used 17. Benchmarking the RSA verify function - with a 1024 bit key yields (2001-11-08): - e=17 0.54 ms - e=41 0.75 ms - e=257 0.95 ms - e=65537 1.80 ms - */ - e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - if (!use_e) - mpi_set_ui (e, 41); /* This is a reasonable secure and fast value */ - else - { - use_e |= 1; /* make sure this is odd */ - mpi_set_ui (e, use_e); - } - - n = gcry_mpi_new (nbits); - - p = q = NULL; - do - { - /* select two (very secret) primes */ - if (p) - gcry_mpi_release (p); - if (q) - gcry_mpi_release (q); - if (use_e) - { /* Do an extra test to ensure that the given exponent is - suitable. */ - p = _gcry_generate_secret_prime (nbits/2, random_level, - check_exponent, e); - q = _gcry_generate_secret_prime (nbits/2, random_level, - check_exponent, e); - } - else - { /* We check the exponent later. */ - p = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL); - q = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL); - } - if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/ - mpi_swap(p,q); - /* calculate the modulus */ - mpi_mul( n, p, q ); - } - while ( mpi_get_nbits(n) != nbits ); - - /* calculate Euler totient: phi = (p-1)(q-1) */ - t1 = mpi_alloc_secure( mpi_get_nlimbs(p) ); - t2 = mpi_alloc_secure( mpi_get_nlimbs(p) ); - phi = gcry_mpi_snew ( nbits ); - g = gcry_mpi_snew ( nbits ); - f = gcry_mpi_snew ( nbits ); - mpi_sub_ui( t1, p, 1 ); - mpi_sub_ui( t2, q, 1 ); - mpi_mul( phi, t1, t2 ); - gcry_mpi_gcd(g, t1, t2); - mpi_fdiv_q(f, phi, g); - - while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */ - { - if (use_e) - BUG (); /* The prime generator already made sure that we - never can get to here. */ - mpi_add_ui (e, e, 2); - } - - /* calculate the secret key d = e^1 mod phi */ - d = gcry_mpi_snew ( nbits ); - mpi_invm(d, e, f ); - /* calculate the inverse of p and q (used for chinese remainder theorem)*/ - u = gcry_mpi_snew ( nbits ); - mpi_invm(u, p, q ); - - if( DBG_CIPHER ) - { - log_mpidump(" p= ", p ); - log_mpidump(" q= ", q ); - log_mpidump("phi= ", phi ); - log_mpidump(" g= ", g ); - log_mpidump(" f= ", f ); - log_mpidump(" n= ", n ); - log_mpidump(" e= ", e ); - log_mpidump(" d= ", d ); - log_mpidump(" u= ", u ); - } - - gcry_mpi_release (t1); - gcry_mpi_release (t2); - gcry_mpi_release (phi); - gcry_mpi_release (f); - gcry_mpi_release (g); - - sk->n = n; - sk->e = e; - sk->p = p; - sk->q = q; - sk->d = d; - sk->u = u; - - /* Now we can test our keys. */ - if (test_keys (sk, nbits - 64)) - { - gcry_mpi_release (sk->n); sk->n = NULL; - gcry_mpi_release (sk->e); sk->e = NULL; - gcry_mpi_release (sk->p); sk->p = NULL; - gcry_mpi_release (sk->q); sk->q = NULL; - gcry_mpi_release (sk->d); sk->d = NULL; - gcry_mpi_release (sk->u); sk->u = NULL; - fips_signal_error ("self-test after key generation failed"); - return GPG_ERR_SELFTEST_FAILED; - } - - return 0; -} - - -/* Helper for generate_x931. */ -static gcry_mpi_t -gen_x931_parm_xp (unsigned int nbits) -{ - gcry_mpi_t xp; - - xp = gcry_mpi_snew (nbits); - gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM); - - /* The requirement for Xp is: - - sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1 - - We set the two high order bits to 1 to satisfy the lower bound. - By using mpi_set_highbit we make sure that the upper bound is - satisfied as well. */ - mpi_set_highbit (xp, nbits-1); - mpi_set_bit (xp, nbits-2); - gcry_assert ( mpi_get_nbits (xp) == nbits ); - - return xp; -} - - -/* Helper for generate_x931. */ -static gcry_mpi_t -gen_x931_parm_xi (void) -{ - gcry_mpi_t xi; - - xi = gcry_mpi_snew (101); - gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM); - mpi_set_highbit (xi, 100); - gcry_assert ( mpi_get_nbits (xi) == 101 ); - - return xi; -} - - - -/* Variant of the standard key generation code using the algorithm - from X9.31. Using this algorithm has the advantage that the - generation can be made deterministic which is required for CAVS - testing. */ -static gpg_err_code_t -generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value, - gcry_sexp_t deriveparms, int *swapped) -{ - gcry_mpi_t p, q; /* The two primes. */ - gcry_mpi_t e; /* The public exponent. */ - gcry_mpi_t n; /* The public key. */ - gcry_mpi_t d; /* The private key */ - gcry_mpi_t u; /* The inverse of p and q. */ - gcry_mpi_t pm1; /* p - 1 */ - gcry_mpi_t qm1; /* q - 1 */ - gcry_mpi_t phi; /* Euler totient. */ - gcry_mpi_t f, g; /* Helper. */ - - *swapped = 0; - - if (e_value == 1) /* Alias for a secure value. */ - e_value = 65537; - - /* Point 1 of section 4.1: k = 1024 + 256s with S >= 0 */ - if (nbits < 1024 || (nbits % 256)) - return GPG_ERR_INV_VALUE; - - /* Point 2: 2 <= bitlength(e) < 2^{k-2} - Note that we do not need to check the upper bound because we use - an unsigned long for E and thus there is no way for E to reach - that limit. */ - if (e_value < 3) - return GPG_ERR_INV_VALUE; - - /* Our implementaion requires E to be odd. */ - if (!(e_value & 1)) - return GPG_ERR_INV_VALUE; - - /* Point 3: e > 0 or e 0 if it is to be randomly generated. - We support only a fixed E and thus there is no need for an extra test. */ - - - /* Compute or extract the derive parameters. */ - { - gcry_mpi_t xp1 = NULL; - gcry_mpi_t xp2 = NULL; - gcry_mpi_t xp = NULL; - gcry_mpi_t xq1 = NULL; - gcry_mpi_t xq2 = NULL; - gcry_mpi_t xq = NULL; - gcry_mpi_t tmpval; - - if (!deriveparms) - { - /* Not given: Generate them. */ - xp = gen_x931_parm_xp (nbits/2); - /* Make sure that |xp - xq| > 2^{nbits - 100} holds. */ - tmpval = gcry_mpi_snew (nbits/2); - do - { - gcry_mpi_release (xq); - xq = gen_x931_parm_xp (nbits/2); - mpi_sub (tmpval, xp, xq); - } - while (mpi_get_nbits (tmpval) <= (nbits/2 - 100)); - gcry_mpi_release (tmpval); - - xp1 = gen_x931_parm_xi (); - xp2 = gen_x931_parm_xi (); - xq1 = gen_x931_parm_xi (); - xq2 = gen_x931_parm_xi (); - - } - else - { - /* Parameters to derive the key are given. */ - struct { const char *name; gcry_mpi_t *value; } tbl[] = { - { "Xp1", &xp1 }, - { "Xp2", &xp2 }, - { "Xp", &xp }, - { "Xq1", &xq1 }, - { "Xq2", &xq2 }, - { "Xq", &xq }, - { NULL, NULL } - }; - int idx; - gcry_sexp_t oneparm; - - for (idx=0; tbl[idx].name; idx++) - { - oneparm = gcry_sexp_find_token (deriveparms, tbl[idx].name, 0); - if (oneparm) - { - *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1, - GCRYMPI_FMT_USG); - gcry_sexp_release (oneparm); - } - } - for (idx=0; tbl[idx].name; idx++) - if (!*tbl[idx].value) - break; - if (tbl[idx].name) - { - /* At least one parameter is missing. */ - for (idx=0; tbl[idx].name; idx++) - gcry_mpi_release (*tbl[idx].value); - return GPG_ERR_MISSING_VALUE; - } - } - - e = mpi_alloc_set_ui (e_value); - - /* Find two prime numbers. */ - p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL); - q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL); - gcry_mpi_release (xp); xp = NULL; - gcry_mpi_release (xp1); xp1 = NULL; - gcry_mpi_release (xp2); xp2 = NULL; - gcry_mpi_release (xq); xq = NULL; - gcry_mpi_release (xq1); xq1 = NULL; - gcry_mpi_release (xq2); xq2 = NULL; - if (!p || !q) - { - gcry_mpi_release (p); - gcry_mpi_release (q); - gcry_mpi_release (e); - return GPG_ERR_NO_PRIME; - } - } - - - /* Compute the public modulus. We make sure that p is smaller than - q to allow the use of the CRT. */ - if (mpi_cmp (p, q) > 0 ) - { - mpi_swap (p, q); - *swapped = 1; - } - n = gcry_mpi_new (nbits); - mpi_mul (n, p, q); - - /* Compute the Euler totient: phi = (p-1)(q-1) */ - pm1 = gcry_mpi_snew (nbits/2); - qm1 = gcry_mpi_snew (nbits/2); - phi = gcry_mpi_snew (nbits); - mpi_sub_ui (pm1, p, 1); - mpi_sub_ui (qm1, q, 1); - mpi_mul (phi, pm1, qm1); - - g = gcry_mpi_snew (nbits); - gcry_assert (gcry_mpi_gcd (g, e, phi)); - - /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */ - gcry_mpi_gcd (g, pm1, qm1); - f = pm1; pm1 = NULL; - gcry_mpi_release (qm1); qm1 = NULL; - mpi_fdiv_q (f, phi, g); - gcry_mpi_release (phi); phi = NULL; - d = g; g = NULL; - /* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */ - mpi_invm (d, e, f); - - /* Compute the inverse of p and q. */ - u = f; f = NULL; - mpi_invm (u, p, q ); - - if( DBG_CIPHER ) - { - if (*swapped) - log_debug ("p and q are swapped\n"); - log_mpidump(" p", p ); - log_mpidump(" q", q ); - log_mpidump(" n", n ); - log_mpidump(" e", e ); - log_mpidump(" d", d ); - log_mpidump(" u", u ); - } - - - sk->n = n; - sk->e = e; - sk->p = p; - sk->q = q; - sk->d = d; - sk->u = u; - - /* Now we can test our keys. */ - if (test_keys (sk, nbits - 64)) - { - gcry_mpi_release (sk->n); sk->n = NULL; - gcry_mpi_release (sk->e); sk->e = NULL; - gcry_mpi_release (sk->p); sk->p = NULL; - gcry_mpi_release (sk->q); sk->q = NULL; - gcry_mpi_release (sk->d); sk->d = NULL; - gcry_mpi_release (sk->u); sk->u = NULL; - fips_signal_error ("self-test after key generation failed"); - return GPG_ERR_SELFTEST_FAILED; - } - - return 0; -} - - -/**************** - * Test wether the secret key is valid. - * Returns: true if this is a valid key. - */ -static int -check_secret_key( RSA_secret_key *sk ) -{ - int rc; - gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 ); - - mpi_mul(temp, sk->p, sk->q ); - rc = mpi_cmp( temp, sk->n ); - mpi_free(temp); - return !rc; -} - - - -/**************** - * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT. - * - * c = m^e mod n - * - * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY. - */ -static void -public(gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *pkey ) -{ - if( output == input ) /* powm doesn't like output and input the same */ - { - gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs(input)*2 ); - mpi_powm( x, input, pkey->e, pkey->n ); - mpi_set(output, x); - mpi_free(x); - } - else - mpi_powm( output, input, pkey->e, pkey->n ); -} - -#if 0 -static void -stronger_key_check ( RSA_secret_key *skey ) -{ - gcry_mpi_t t = mpi_alloc_secure ( 0 ); - gcry_mpi_t t1 = mpi_alloc_secure ( 0 ); - gcry_mpi_t t2 = mpi_alloc_secure ( 0 ); - gcry_mpi_t phi = mpi_alloc_secure ( 0 ); - - /* check that n == p * q */ - mpi_mul( t, skey->p, skey->q); - if (mpi_cmp( t, skey->n) ) - log_info ( "RSA Oops: n != p * q\n" ); - - /* check that p is less than q */ - if( mpi_cmp( skey->p, skey->q ) > 0 ) - { - log_info ("RSA Oops: p >= q - fixed\n"); - _gcry_mpi_swap ( skey->p, skey->q); - } - - /* check that e divides neither p-1 nor q-1 */ - mpi_sub_ui(t, skey->p, 1 ); - mpi_fdiv_r(t, t, skey->e ); - if ( !mpi_cmp_ui( t, 0) ) - log_info ( "RSA Oops: e divides p-1\n" ); - mpi_sub_ui(t, skey->q, 1 ); - mpi_fdiv_r(t, t, skey->e ); - if ( !mpi_cmp_ui( t, 0) ) - log_info ( "RSA Oops: e divides q-1\n" ); - - /* check that d is correct */ - mpi_sub_ui( t1, skey->p, 1 ); - mpi_sub_ui( t2, skey->q, 1 ); - mpi_mul( phi, t1, t2 ); - gcry_mpi_gcd(t, t1, t2); - mpi_fdiv_q(t, phi, t); - mpi_invm(t, skey->e, t ); - if ( mpi_cmp(t, skey->d ) ) - { - log_info ( "RSA Oops: d is wrong - fixed\n"); - mpi_set (skey->d, t); - _gcry_log_mpidump (" fixed d", skey->d); - } - - /* check for correctness of u */ - mpi_invm(t, skey->p, skey->q ); - if ( mpi_cmp(t, skey->u ) ) - { - log_info ( "RSA Oops: u is wrong - fixed\n"); - mpi_set (skey->u, t); - _gcry_log_mpidump (" fixed u", skey->u); - } - - log_info ( "RSA secret key check finished\n"); - - mpi_free (t); - mpi_free (t1); - mpi_free (t2); - mpi_free (phi); -} -#endif - - - -/**************** - * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT. - * - * m = c^d mod n - * - * Or faster: - * - * m1 = c ^ (d mod (p-1)) mod p - * m2 = c ^ (d mod (q-1)) mod q - * h = u * (m2 - m1) mod q - * m = m1 + h * p - * - * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY. - */ -static void -secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey ) -{ - if (!skey->p || !skey->q || !skey->u) - { - mpi_powm (output, input, skey->d, skey->n); - } - else - { - gcry_mpi_t m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - gcry_mpi_t m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - gcry_mpi_t h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - - /* m1 = c ^ (d mod (p-1)) mod p */ - mpi_sub_ui( h, skey->p, 1 ); - mpi_fdiv_r( h, skey->d, h ); - mpi_powm( m1, input, h, skey->p ); - /* m2 = c ^ (d mod (q-1)) mod q */ - mpi_sub_ui( h, skey->q, 1 ); - mpi_fdiv_r( h, skey->d, h ); - mpi_powm( m2, input, h, skey->q ); - /* h = u * ( m2 - m1 ) mod q */ - mpi_sub( h, m2, m1 ); - if ( mpi_is_neg( h ) ) - mpi_add ( h, h, skey->q ); - mpi_mulm( h, skey->u, h, skey->q ); - /* m = m2 + h * p */ - mpi_mul ( h, h, skey->p ); - mpi_add ( output, m1, h ); - - mpi_free ( h ); - mpi_free ( m1 ); - mpi_free ( m2 ); - } -} - - - -/* Perform RSA blinding. */ -static gcry_mpi_t -rsa_blind (gcry_mpi_t x, gcry_mpi_t r, gcry_mpi_t e, gcry_mpi_t n) -{ - /* A helper. */ - gcry_mpi_t a; - - /* Result. */ - gcry_mpi_t y; - - a = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - - /* Now we calculate: y = (x * r^e) mod n, where r is the random - number, e is the public exponent, x is the non-blinded data and n - is the RSA modulus. */ - gcry_mpi_powm (a, r, e, n); - gcry_mpi_mulm (y, a, x, n); - - gcry_mpi_release (a); - - return y; -} - -/* Undo RSA blinding. */ -static gcry_mpi_t -rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n) -{ - gcry_mpi_t y; - - y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); - - /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded - decrypted data, ri is the modular multiplicative inverse of r and - n is the RSA modulus. */ - - gcry_mpi_mulm (y, ri, x, n); - - return y; -} - -/********************************************* - ************** interface ****************** - *********************************************/ - -static gcry_err_code_t -rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, - const gcry_sexp_t genparms, - gcry_mpi_t *skey, gcry_mpi_t **retfactors, - gcry_sexp_t *r_extrainfo) -{ - RSA_secret_key sk; - gpg_err_code_t ec; - gcry_sexp_t deriveparms; - int transient_key = 0; - int use_x931 = 0; - gcry_sexp_t l1; - - (void)algo; - - *retfactors = NULL; /* We don't return them. */ - - deriveparms = (genparms? - gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL); - if (!deriveparms) - { - /* Parse the optional "use-x931" flag. */ - l1 = gcry_sexp_find_token (genparms, "use-x931", 0); - if (l1) - { - use_x931 = 1; - gcry_sexp_release (l1); - } - } - - if (deriveparms || use_x931 || fips_mode ()) - { - int swapped; - ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped); - gcry_sexp_release (deriveparms); - if (!ec && r_extrainfo && swapped) - { - ec = gcry_sexp_new (r_extrainfo, - "(misc-key-info(p-q-swapped))", 0, 1); - if (ec) - { - gcry_mpi_release (sk.n); sk.n = NULL; - gcry_mpi_release (sk.e); sk.e = NULL; - gcry_mpi_release (sk.p); sk.p = NULL; - gcry_mpi_release (sk.q); sk.q = NULL; - gcry_mpi_release (sk.d); sk.d = NULL; - gcry_mpi_release (sk.u); sk.u = NULL; - } - } - } - else - { - /* Parse the optional "transient-key" flag. */ - l1 = gcry_sexp_find_token (genparms, "transient-key", 0); - if (l1) - { - transient_key = 1; - gcry_sexp_release (l1); - } - /* Generate. */ - ec = generate_std (&sk, nbits, evalue, transient_key); - } - - if (!ec) - { - skey[0] = sk.n; - skey[1] = sk.e; - skey[2] = sk.d; - skey[3] = sk.p; - skey[4] = sk.q; - skey[5] = sk.u; - } - - return ec; -} - - -static gcry_err_code_t -rsa_generate (int algo, unsigned int nbits, unsigned long evalue, - gcry_mpi_t *skey, gcry_mpi_t **retfactors) -{ - return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors, NULL); -} - - -static gcry_err_code_t -rsa_check_secret_key (int algo, gcry_mpi_t *skey) -{ - gcry_err_code_t err = GPG_ERR_NO_ERROR; - RSA_secret_key sk; - - (void)algo; - - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - - if (!sk.p || !sk.q || !sk.u) - err = GPG_ERR_NO_OBJ; /* To check the key we need the optional - parameters. */ - else if (!check_secret_key (&sk)) - err = GPG_ERR_PUBKEY_ALGO; - - return err; -} - - -static gcry_err_code_t -rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, - gcry_mpi_t *pkey, int flags) -{ - RSA_public_key pk; - - (void)algo; - (void)flags; - - pk.n = pkey[0]; - pk.e = pkey[1]; - resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n)); - public (resarr[0], data, &pk); - - return GPG_ERR_NO_ERROR; -} - - -static gcry_err_code_t -rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, - gcry_mpi_t *skey, int flags) -{ - RSA_secret_key sk; - gcry_mpi_t r = MPI_NULL; /* Random number needed for blinding. */ - gcry_mpi_t ri = MPI_NULL; /* Modular multiplicative inverse of - r. */ - gcry_mpi_t x = MPI_NULL; /* Data to decrypt. */ - gcry_mpi_t y; /* Result. */ - - (void)algo; - - /* Extract private key. */ - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; /* Optional. */ - sk.q = skey[4]; /* Optional. */ - sk.u = skey[5]; /* Optional. */ - - y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); - - /* We use blinding by default to mitigate timing attacks which can - be practically mounted over the network as shown by Brumley and - Boney in 2003. */ - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - { - /* Initialize blinding. */ - - /* First, we need a random number r between 0 and n - 1, which - is relatively prime to n (i.e. it is neither p nor q). The - random number needs to be only unpredictable, thus we employ - the gcry_create_nonce function by using GCRY_WEAK_RANDOM with - gcry_mpi_randomize. */ - r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); - ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); - - gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), GCRY_WEAK_RANDOM); - gcry_mpi_mod (r, r, sk.n); - - /* Calculate inverse of r. It practically impossible that the - follwing test fails, thus we do not add code to release - allocated resources. */ - if (!gcry_mpi_invm (ri, r, sk.n)) - return GPG_ERR_INTERNAL; - } - - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - x = rsa_blind (data[0], r, sk.e, sk.n); - else - x = data[0]; - - /* Do the encryption. */ - secret (y, x, &sk); - - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - { - /* Undo blinding. */ - gcry_mpi_t a = gcry_mpi_copy (y); - - gcry_mpi_release (y); - y = rsa_unblind (a, ri, sk.n); - - gcry_mpi_release (a); - } - - if (! (flags & PUBKEY_FLAG_NO_BLINDING)) - { - /* Deallocate resources needed for blinding. */ - gcry_mpi_release (x); - gcry_mpi_release (r); - gcry_mpi_release (ri); - } - - /* Copy out result. */ - *result = y; - - return GPG_ERR_NO_ERROR; -} - - -static gcry_err_code_t -rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) -{ - RSA_secret_key sk; - - (void)algo; - - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - resarr[0] = mpi_alloc( mpi_get_nlimbs (sk.n)); - secret (resarr[0], data, &sk); - - return GPG_ERR_NO_ERROR; -} - - -static gcry_err_code_t -rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, - int (*cmp) (void *opaque, gcry_mpi_t tmp), - void *opaquev) -{ - RSA_public_key pk; - gcry_mpi_t result; - gcry_err_code_t rc; - - (void)algo; - (void)cmp; - (void)opaquev; - - pk.n = pkey[0]; - pk.e = pkey[1]; - result = gcry_mpi_new ( 160 ); - public( result, data[0], &pk ); -#ifdef IS_DEVELOPMENT_VERSION - if (DBG_CIPHER) - { - log_mpidump ("rsa verify result:", result ); - log_mpidump (" hash:", hash ); - } -#endif /*IS_DEVELOPMENT_VERSION*/ - /*rc = (*cmp)( opaquev, result );*/ - rc = mpi_cmp (result, hash) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; - gcry_mpi_release (result); - - return rc; -} - - -static unsigned int -rsa_get_nbits (int algo, gcry_mpi_t *pkey) -{ - (void)algo; - - return mpi_get_nbits (pkey[0]); -} - - -/* Compute a keygrip. MD is the hash context which we are going to - update. KEYPARAM is an S-expression with the key parameters, this - is usually a public key but may also be a secret key. An example - of such an S-expression is: - - (rsa - (n #00B...#) - (e #010001#)) - - PKCS-15 says that for RSA only the modulus should be hashed - - however, it is not clear wether this is meant to use the raw bytes - (assuming this is an unsigned integer) or whether the DER required - 0 should be prefixed. We hash the raw bytes. */ -static gpg_err_code_t -compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) -{ - gcry_sexp_t l1; - const char *data; - size_t datalen; - - l1 = gcry_sexp_find_token (keyparam, "n", 1); - if (!l1) - return GPG_ERR_NO_OBJ; - - data = gcry_sexp_nth_data (l1, 1, &datalen); - if (!data) - { - gcry_sexp_release (l1); - return GPG_ERR_NO_OBJ; - } - - gcry_md_write (md, data, datalen); - gcry_sexp_release (l1); - - return 0; -} - - - - -/* - Self-test section. - */ - -static const char * -selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) -{ - static const char sample_data[] = - "(data (flags pkcs1)" - " (hash sha1 #11223344556677889900aabbccddeeff10203040#))"; - static const char sample_data_bad[] = - "(data (flags pkcs1)" - " (hash sha1 #11223344556677889900aabbccddeeff80203040#))"; - - const char *errtxt = NULL; - gcry_error_t err; - gcry_sexp_t data = NULL; - gcry_sexp_t data_bad = NULL; - gcry_sexp_t sig = NULL; - - err = gcry_sexp_sscan (&data, NULL, - sample_data, strlen (sample_data)); - if (!err) - err = gcry_sexp_sscan (&data_bad, NULL, - sample_data_bad, strlen (sample_data_bad)); - if (err) - { - errtxt = "converting data failed"; - goto leave; - } - - err = gcry_pk_sign (&sig, data, skey); - if (err) - { - errtxt = "signing failed"; - goto leave; - } - err = gcry_pk_verify (sig, data, pkey); - if (err) - { - errtxt = "verify failed"; - goto leave; - } - err = gcry_pk_verify (sig, data_bad, pkey); - if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE) - { - errtxt = "bad signature not detected"; - goto leave; - } - - - leave: - gcry_sexp_release (sig); - gcry_sexp_release (data_bad); - gcry_sexp_release (data); - return errtxt; -} - - - -/* Given an S-expression ENCR_DATA of the form: - - (enc-val - (rsa - (a a-value))) - - as returned by gcry_pk_decrypt, return the the A-VALUE. On error, - return NULL. */ -static gcry_mpi_t -extract_a_from_sexp (gcry_sexp_t encr_data) -{ - gcry_sexp_t l1, l2, l3; - gcry_mpi_t a_value; - - l1 = gcry_sexp_find_token (encr_data, "enc-val", 0); - if (!l1) - return NULL; - l2 = gcry_sexp_find_token (l1, "rsa", 0); - gcry_sexp_release (l1); - if (!l2) - return NULL; - l3 = gcry_sexp_find_token (l2, "a", 0); - gcry_sexp_release (l2); - if (!l3) - return NULL; - a_value = gcry_sexp_nth_mpi (l3, 1, 0); - gcry_sexp_release (l3); - - return a_value; -} - - -static const char * -selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) -{ - const char *errtxt = NULL; - gcry_error_t err; - const unsigned int nbits = 1000; /* Encrypt 1000 random bits. */ - gcry_mpi_t plaintext = NULL; - gcry_sexp_t plain = NULL; - gcry_sexp_t encr = NULL; - gcry_mpi_t ciphertext = NULL; - gcry_sexp_t decr = NULL; - gcry_mpi_t decr_plaintext = NULL; - gcry_sexp_t tmplist = NULL; - - /* Create plaintext. The plaintext is actually a big integer number. */ - plaintext = gcry_mpi_new (nbits); - gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); - - /* Put the plaintext into an S-expression. */ - err = gcry_sexp_build (&plain, NULL, - "(data (flags raw) (value %m))", plaintext); - if (err) - { - errtxt = "converting data failed"; - goto leave; - } - - /* Encrypt. */ - err = gcry_pk_encrypt (&encr, plain, pkey); - if (err) - { - errtxt = "encrypt failed"; - goto leave; - } - - /* Extraxt the ciphertext from the returned S-expression. */ - /*gcry_sexp_dump (encr);*/ - ciphertext = extract_a_from_sexp (encr); - if (!ciphertext) - { - errtxt = "gcry_pk_decrypt returned garbage"; - goto leave; - } - - /* Check that the ciphertext does no match the plaintext. */ - /* _gcry_log_mpidump ("plaintext", plaintext); */ - /* _gcry_log_mpidump ("ciphertxt", ciphertext); */ - if (!gcry_mpi_cmp (plaintext, ciphertext)) - { - errtxt = "ciphertext matches plaintext"; - goto leave; - } - - /* Decrypt. */ - err = gcry_pk_decrypt (&decr, encr, skey); - if (err) - { - errtxt = "decrypt failed"; - goto leave; - } - - /* Extract the decrypted data from the S-expression. Note that the - output of gcry_pk_decrypt depends on whether a flags lists occurs - in its input data. Because we passed the output of - gcry_pk_encrypt directly to gcry_pk_decrypt, such a flag value - won't be there as of today. To be prepared for future changes we - take care of it anyway. */ - tmplist = gcry_sexp_find_token (decr, "value", 0); - if (tmplist) - decr_plaintext = gcry_sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG); - else - decr_plaintext = gcry_sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG); - if (!decr_plaintext) - { - errtxt = "decrypt returned no plaintext"; - goto leave; - } - - /* Check that the decrypted plaintext matches the original plaintext. */ - if (gcry_mpi_cmp (plaintext, decr_plaintext)) - { - errtxt = "mismatch"; - goto leave; - } - - leave: - gcry_sexp_release (tmplist); - gcry_mpi_release (decr_plaintext); - gcry_sexp_release (decr); - gcry_mpi_release (ciphertext); - gcry_sexp_release (encr); - gcry_sexp_release (plain); - gcry_mpi_release (plaintext); - return errtxt; -} - - -static gpg_err_code_t -selftests_rsa (selftest_report_func_t report) -{ - const char *what; - const char *errtxt; - gcry_error_t err; - gcry_sexp_t skey = NULL; - gcry_sexp_t pkey = NULL; - - /* Convert the S-expressions into the internal representation. */ - what = "convert"; - err = gcry_sexp_sscan (&skey, NULL, - sample_secret_key, strlen (sample_secret_key)); - if (!err) - err = gcry_sexp_sscan (&pkey, NULL, - sample_public_key, strlen (sample_public_key)); - if (err) - { - errtxt = gcry_strerror (err); - goto failed; - } - - what = "key consistency"; - err = gcry_pk_testkey (skey); - if (err) - { - errtxt = gcry_strerror (err); - goto failed; - } - - what = "sign"; - errtxt = selftest_sign_1024 (pkey, skey); - if (errtxt) - goto failed; - - what = "encrypt"; - errtxt = selftest_encr_1024 (pkey, skey); - if (errtxt) - goto failed; - - gcry_sexp_release (pkey); - gcry_sexp_release (skey); - return 0; /* Succeeded. */ - - failed: - gcry_sexp_release (pkey); - gcry_sexp_release (skey); - if (report) - report ("pubkey", GCRY_PK_RSA, what, errtxt); - return GPG_ERR_SELFTEST_FAILED; -} - - -/* Run a full self-test for ALGO and return 0 on success. */ -static gpg_err_code_t -run_selftests (int algo, int extended, selftest_report_func_t report) -{ - gpg_err_code_t ec; - - (void)extended; - - switch (algo) - { - case GCRY_PK_RSA: - ec = selftests_rsa (report); - break; - default: - ec = GPG_ERR_PUBKEY_ALGO; - break; - - } - return ec; -} - - - - -static const char *rsa_names[] = - { - "rsa", - "openpgp-rsa", - "oid.1.2.840.113549.1.1.1", - NULL, - }; - -gcry_pk_spec_t _gcry_pubkey_spec_rsa = - { - "RSA", rsa_names, - "ne", "nedpqu", "a", "s", "n", - GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, - rsa_generate, - rsa_check_secret_key, - rsa_encrypt, - rsa_decrypt, - rsa_sign, - rsa_verify, - rsa_get_nbits, - }; -pk_extra_spec_t _gcry_pubkey_extraspec_rsa = - { - run_selftests, - rsa_generate_ext, - compute_keygrip - }; - |