2N/A/* This file was automatically imported with
2N/A import_gcry.py. Please don't modify it */
2N/A#include <grub/dl.h>
2N/AGRUB_MOD_LICENSE ("GPLv3+");
2N/A/* dsa.c - DSA signature algorithm
2N/A * Copyright (C) 1998, 2000, 2001, 2002, 2003,
2N/A * 2006, 2008 Free Software Foundation, Inc.
2N/A *
2N/A * This file is part of Libgcrypt.
2N/A *
2N/A * Libgcrypt is free software; you can redistribute it and/or modify
2N/A * it under the terms of the GNU Lesser General Public License as
2N/A * published by the Free Software Foundation; either version 2.1 of
2N/A * the License, or (at your option) any later version.
2N/A *
2N/A * Libgcrypt is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU Lesser General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU Lesser General Public
2N/A * License along with this program; if not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A
2N/A#include "g10lib.h"
2N/A#include "mpi.h"
2N/A#include "cipher.h"
2N/A
2N/Atypedef struct
2N/A{
2N/A gcry_mpi_t p; /* prime */
2N/A gcry_mpi_t q; /* group order */
2N/A gcry_mpi_t g; /* group generator */
2N/A gcry_mpi_t y; /* g^x mod p */
2N/A} DSA_public_key;
2N/A
2N/A
2N/Atypedef struct
2N/A{
2N/A gcry_mpi_t p; /* prime */
2N/A gcry_mpi_t q; /* group order */
2N/A gcry_mpi_t g; /* group generator */
2N/A gcry_mpi_t y; /* g^x mod p */
2N/A gcry_mpi_t x; /* secret exponent */
2N/A} DSA_secret_key;
2N/A
2N/A
2N/A/* A structure used to hold domain parameters. */
2N/Atypedef struct
2N/A{
2N/A gcry_mpi_t p; /* prime */
2N/A gcry_mpi_t q; /* group order */
2N/A gcry_mpi_t g; /* group generator */
2N/A} dsa_domain_t;
2N/A
2N/A
2N/A/* A sample 1024 bit DSA key used for the selftests. */
2N/Astatic const char sample_secret_key[] =
2N/A"(private-key"
2N/A" (dsa"
2N/A" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
2N/A" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
2N/A" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
2N/A" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
2N/A" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
2N/A" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
2N/A" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
2N/A" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
2N/A" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
2N/A" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
2N/A" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
2N/A" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
2N/A" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)"
2N/A" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))";
2N/A/* A sample 1024 bit DSA key used for the selftests (public only). */
2N/Astatic const char sample_public_key[] =
2N/A"(public-key"
2N/A" (dsa"
2N/A" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
2N/A" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
2N/A" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
2N/A" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
2N/A" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
2N/A" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
2N/A" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
2N/A" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
2N/A" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
2N/A" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
2N/A" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
2N/A" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
2N/A" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))";
2N/A
2N/A
2N/A
2N/A
2N/Astatic gcry_mpi_t gen_k (gcry_mpi_t q);
2N/Astatic int test_keys (DSA_secret_key *sk, unsigned int qbits);
2N/Astatic int check_secret_key (DSA_secret_key *sk);
2N/Astatic gpg_err_code_t generate (DSA_secret_key *sk,
2N/A unsigned int nbits,
2N/A unsigned int qbits,
2N/A int transient_key,
2N/A dsa_domain_t *domain,
2N/A gcry_mpi_t **ret_factors);
2N/Astatic void sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
2N/A DSA_secret_key *skey);
2N/Astatic int verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
2N/A DSA_public_key *pkey);
2N/A
2N/Astatic void (*progress_cb) (void *,const char *, int, int, int );
2N/Astatic void *progress_cb_data;
2N/A
2N/A
2N/Avoid
2N/A_gcry_register_pk_dsa_progress (void (*cb) (void *, const char *,
2N/A int, int, int),
2N/A void *cb_data)
2N/A{
2N/A progress_cb = cb;
2N/A progress_cb_data = cb_data;
2N/A}
2N/A
2N/A
2N/Astatic void
2N/Aprogress (int c)
2N/A{
2N/A if (progress_cb)
2N/A progress_cb (progress_cb_data, "pk_dsa", c, 0, 0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Generate a random secret exponent k less than q.
2N/A */
2N/Astatic gcry_mpi_t
2N/Agen_k( gcry_mpi_t q )
2N/A{
2N/A gcry_mpi_t k = mpi_alloc_secure( mpi_get_nlimbs(q) );
2N/A unsigned int nbits = mpi_get_nbits(q);
2N/A unsigned int nbytes = (nbits+7)/8;
2N/A char *rndbuf = NULL;
2N/A
2N/A if ( DBG_CIPHER )
2N/A log_debug("choosing a random k ");
2N/A for (;;)
2N/A {
2N/A if( DBG_CIPHER )
2N/A progress('.');
2N/A
2N/A if ( !rndbuf || nbits < 32 )
2N/A {
2N/A gcry_free(rndbuf);
2N/A rndbuf = gcry_random_bytes_secure( (nbits+7)/8, GCRY_STRONG_RANDOM );
2N/A }
2N/A else
2N/A { /* Change only some of the higher bits. We could improve
2N/A this by directly requesting more memory at the first call
2N/A to get_random_bytes() and use this the here maybe it is
2N/A easier to do this directly in random.c. */
2N/A char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM );
2N/A memcpy( rndbuf,pp, 4 );
2N/A gcry_free(pp);
2N/A }
2N/A _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 );
2N/A if ( mpi_test_bit( k, nbits-1 ) )
2N/A mpi_set_highbit( k, nbits-1 );
2N/A else
2N/A {
2N/A mpi_set_highbit( k, nbits-1 );
2N/A mpi_clear_bit( k, nbits-1 );
2N/A }
2N/A
2N/A if( !(mpi_cmp( k, q ) < 0) ) /* check: k < q */
2N/A {
2N/A if( DBG_CIPHER )
2N/A progress('+');
2N/A continue; /* no */
2N/A }
2N/A if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */
2N/A {
2N/A if( DBG_CIPHER )
2N/A progress('-');
2N/A continue; /* no */
2N/A }
2N/A break; /* okay */
2N/A }
2N/A gcry_free(rndbuf);
2N/A if( DBG_CIPHER )
2N/A progress('\n');
2N/A
2N/A return k;
2N/A}
2N/A
2N/A
2N/A/* Check that a freshly generated key actually works. Returns 0 on success. */
2N/Astatic int
2N/Atest_keys (DSA_secret_key *sk, unsigned int qbits)
2N/A{
2N/A int result = -1; /* Default to failure. */
2N/A DSA_public_key pk;
2N/A gcry_mpi_t data = gcry_mpi_new (qbits);
2N/A gcry_mpi_t sig_a = gcry_mpi_new (qbits);
2N/A gcry_mpi_t sig_b = gcry_mpi_new (qbits);
2N/A
2N/A /* Put the relevant parameters into a public key structure. */
2N/A pk.p = sk->p;
2N/A pk.q = sk->q;
2N/A pk.g = sk->g;
2N/A pk.y = sk->y;
2N/A
2N/A /* Create a random plaintext. */
2N/A gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM);
2N/A
2N/A /* Sign DATA using the secret key. */
2N/A sign (sig_a, sig_b, data, sk);
2N/A
2N/A /* Verify the signature using the public key. */
2N/A if ( !verify (sig_a, sig_b, data, &pk) )
2N/A goto leave; /* Signature does not match. */
2N/A
2N/A /* Modify the data and check that the signing fails. */
2N/A gcry_mpi_add_ui (data, data, 1);
2N/A if ( verify (sig_a, sig_b, data, &pk) )
2N/A goto leave; /* Signature matches but should not. */
2N/A
2N/A result = 0; /* The test succeeded. */
2N/A
2N/A leave:
2N/A gcry_mpi_release (sig_b);
2N/A gcry_mpi_release (sig_a);
2N/A gcry_mpi_release (data);
2N/A return result;
2N/A}
2N/A
2N/A
2N/A
2N/A/*
2N/A Generate a DSA key pair with a key of size NBITS. If transient_key
2N/A is true the key is generated using the standard RNG and not the
2N/A very secure one.
2N/A
2N/A Returns: 2 structures filled with all needed values
2N/A and an array with the n-1 factors of (p-1)
2N/A */
2N/Astatic gpg_err_code_t
2N/Agenerate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
2N/A int transient_key, dsa_domain_t *domain, gcry_mpi_t **ret_factors )
2N/A{
2N/A gcry_mpi_t p; /* the prime */
2N/A gcry_mpi_t q; /* the 160 bit prime factor */
2N/A gcry_mpi_t g; /* the generator */
2N/A gcry_mpi_t y; /* g^x mod p */
2N/A gcry_mpi_t x; /* the secret exponent */
2N/A gcry_mpi_t h, e; /* helper */
2N/A unsigned char *rndbuf;
2N/A gcry_random_level_t random_level;
2N/A
2N/A if (qbits)
2N/A ; /* Caller supplied qbits. Use this value. */
2N/A else if ( nbits >= 512 && nbits <= 1024 )
2N/A qbits = 160;
2N/A else if ( nbits == 2048 )
2N/A qbits = 224;
2N/A else if ( nbits == 3072 )
2N/A qbits = 256;
2N/A else if ( nbits == 7680 )
2N/A qbits = 384;
2N/A else if ( nbits == 15360 )
2N/A qbits = 512;
2N/A else
2N/A return GPG_ERR_INV_VALUE;
2N/A
2N/A if (qbits < 160 || qbits > 512 || (qbits%8) )
2N/A return GPG_ERR_INV_VALUE;
2N/A if (nbits < 2*qbits || nbits > 15360)
2N/A return GPG_ERR_INV_VALUE;
2N/A
2N/A if (fips_mode ())
2N/A {
2N/A if (nbits < 1024)
2N/A return GPG_ERR_INV_VALUE;
2N/A if (transient_key)
2N/A return GPG_ERR_INV_VALUE;
2N/A }
2N/A
2N/A if (domain->p && domain->q && domain->g)
2N/A {
2N/A /* Domain parameters are given; use them. */
2N/A p = mpi_copy (domain->p);
2N/A q = mpi_copy (domain->q);
2N/A g = mpi_copy (domain->g);
2N/A gcry_assert (mpi_get_nbits (p) == nbits);
2N/A gcry_assert (mpi_get_nbits (q) == qbits);
2N/A h = mpi_alloc (0);
2N/A e = NULL;
2N/A }
2N/A else
2N/A {
2N/A /* Generate new domain parameters. */
2N/A p = _gcry_generate_elg_prime (1, nbits, qbits, NULL, ret_factors);
2N/A /* Get q out of factors. */
2N/A q = mpi_copy ((*ret_factors)[0]);
2N/A gcry_assert (mpi_get_nbits (q) == qbits);
2N/A
2N/A /* Find a generator g (h and e are helpers).
2N/A e = (p-1)/q */
2N/A e = mpi_alloc (mpi_get_nlimbs (p));
2N/A mpi_sub_ui (e, p, 1);
2N/A mpi_fdiv_q (e, e, q);
2N/A g = mpi_alloc (mpi_get_nlimbs (p));
2N/A h = mpi_alloc_set_ui (1); /* (We start with 2.) */
2N/A do
2N/A {
2N/A mpi_add_ui (h, h, 1);
2N/A /* g = h^e mod p */
2N/A gcry_mpi_powm (g, h, e, p);
2N/A }
2N/A while (!mpi_cmp_ui (g, 1)); /* Continue until g != 1. */
2N/A }
2N/A
2N/A /* Select a random number X with the property:
2N/A * 0 < x < q-1
2N/A * This must be a very good random number because this is the secret
2N/A * part. The random quality depends on the transient_key flag. */
2N/A random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
2N/A if (DBG_CIPHER)
2N/A log_debug("choosing a random x%s", transient_key? " (transient-key)":"");
2N/A gcry_assert( qbits >= 160 );
2N/A x = mpi_alloc_secure( mpi_get_nlimbs(q) );
2N/A mpi_sub_ui( h, q, 1 ); /* put q-1 into h */
2N/A rndbuf = NULL;
2N/A do
2N/A {
2N/A if( DBG_CIPHER )
2N/A progress('.');
2N/A if( !rndbuf )
2N/A rndbuf = gcry_random_bytes_secure ((qbits+7)/8, random_level);
2N/A else
2N/A { /* Change only some of the higher bits (= 2 bytes)*/
2N/A char *r = gcry_random_bytes_secure (2, random_level);
2N/A memcpy(rndbuf, r, 2 );
2N/A gcry_free(r);
2N/A }
2N/A
2N/A _gcry_mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
2N/A mpi_clear_highbit( x, qbits+1 );
2N/A }
2N/A while ( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
2N/A gcry_free(rndbuf);
2N/A mpi_free( e );
2N/A mpi_free( h );
2N/A
2N/A /* y = g^x mod p */
2N/A y = mpi_alloc( mpi_get_nlimbs(p) );
2N/A gcry_mpi_powm( y, g, x, p );
2N/A
2N/A if( DBG_CIPHER )
2N/A {
2N/A progress('\n');
2N/A log_mpidump("dsa p", p );
2N/A log_mpidump("dsa q", q );
2N/A log_mpidump("dsa g", g );
2N/A log_mpidump("dsa y", y );
2N/A log_mpidump("dsa x", x );
2N/A }
2N/A
2N/A /* Copy the stuff to the key structures. */
2N/A sk->p = p;
2N/A sk->q = q;
2N/A sk->g = g;
2N/A sk->y = y;
2N/A sk->x = x;
2N/A
2N/A /* Now we can test our keys (this should never fail!). */
2N/A if ( test_keys (sk, qbits) )
2N/A {
2N/A gcry_mpi_release (sk->p); sk->p = NULL;
2N/A gcry_mpi_release (sk->q); sk->q = NULL;
2N/A gcry_mpi_release (sk->g); sk->g = NULL;
2N/A gcry_mpi_release (sk->y); sk->y = NULL;
2N/A gcry_mpi_release (sk->x); sk->x = NULL;
2N/A fips_signal_error ("self-test after key generation failed");
2N/A return GPG_ERR_SELFTEST_FAILED;
2N/A }
2N/A return 0;
2N/A}
2N/A
2N/A
2N/A/* Generate a DSA key pair with a key of size NBITS using the
2N/A algorithm given in FIPS-186-3. If USE_FIPS186_2 is true,
2N/A FIPS-186-2 is used and thus the length is restricted to 1024/160.
2N/A If DERIVEPARMS is not NULL it may contain a seed value. If domain
2N/A parameters are specified in DOMAIN, DERIVEPARMS may not be given
2N/A and NBITS and QBITS must match the specified domain parameters. */
2N/Astatic gpg_err_code_t
2N/Agenerate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
2N/A gcry_sexp_t deriveparms, int use_fips186_2,
2N/A dsa_domain_t *domain,
2N/A int *r_counter, void **r_seed, size_t *r_seedlen,
2N/A gcry_mpi_t *r_h)
2N/A{
2N/A gpg_err_code_t ec;
2N/A struct {
2N/A gcry_sexp_t sexp;
2N/A const void *seed;
2N/A size_t seedlen;
2N/A } initial_seed = { NULL, NULL, 0 };
2N/A gcry_mpi_t prime_q = NULL;
2N/A gcry_mpi_t prime_p = NULL;
2N/A gcry_mpi_t value_g = NULL; /* The generator. */
2N/A gcry_mpi_t value_y = NULL; /* g^x mod p */
2N/A gcry_mpi_t value_x = NULL; /* The secret exponent. */
2N/A gcry_mpi_t value_h = NULL; /* Helper. */
2N/A gcry_mpi_t value_e = NULL; /* Helper. */
2N/A
2N/A /* Preset return values. */
2N/A *r_counter = 0;
2N/A *r_seed = NULL;
2N/A *r_seedlen = 0;
2N/A *r_h = NULL;
2N/A
2N/A /* Derive QBITS from NBITS if requested */
2N/A if (!qbits)
2N/A {
2N/A if (nbits == 1024)
2N/A qbits = 160;
2N/A else if (nbits == 2048)
2N/A qbits = 224;
2N/A else if (nbits == 3072)
2N/A qbits = 256;
2N/A }
2N/A
2N/A /* Check that QBITS and NBITS match the standard. Note that FIPS
2N/A 186-3 uses N for QBITS and L for NBITS. */
2N/A if (nbits == 1024 && qbits == 160)
2N/A ;
2N/A else if (nbits == 2048 && qbits == 224)
2N/A ;
2N/A else if (nbits == 2048 && qbits == 256)
2N/A ;
2N/A else if (nbits == 3072 && qbits == 256)
2N/A ;
2N/A else
2N/A return GPG_ERR_INV_VALUE;
2N/A
2N/A if (domain->p && domain->q && domain->g)
2N/A {
2N/A /* Domain parameters are given; use them. */
2N/A prime_p = mpi_copy (domain->p);
2N/A prime_q = mpi_copy (domain->q);
2N/A value_g = mpi_copy (domain->g);
2N/A gcry_assert (mpi_get_nbits (prime_p) == nbits);
2N/A gcry_assert (mpi_get_nbits (prime_q) == qbits);
2N/A gcry_assert (!deriveparms);
2N/A ec = 0;
2N/A }
2N/A else
2N/A {
2N/A /* Generate new domain parameters. */
2N/A
2N/A /* Get an initial seed value. */
2N/A if (deriveparms)
2N/A {
2N/A initial_seed.sexp = gcry_sexp_find_token (deriveparms, "seed", 0);
2N/A if (initial_seed.sexp)
2N/A initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1,
2N/A &initial_seed.seedlen);
2N/A }
2N/A
2N/A /* Fixme: Enable 186-3 after it has been approved and after fixing
2N/A the generation function. */
2N/A /* if (use_fips186_2) */
2N/A (void)use_fips186_2;
2N/A ec = _gcry_generate_fips186_2_prime (nbits, qbits,
2N/A initial_seed.seed,
2N/A initial_seed.seedlen,
2N/A &prime_q, &prime_p,
2N/A r_counter,
2N/A r_seed, r_seedlen);
2N/A /* else */
2N/A /* ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, */
2N/A /* &prime_q, &prime_p, */
2N/A /* r_counter, */
2N/A /* r_seed, r_seedlen, NULL); */
2N/A gcry_sexp_release (initial_seed.sexp);
2N/A if (ec)
2N/A goto leave;
2N/A
2N/A /* Find a generator g (h and e are helpers).
2N/A e = (p-1)/q */
2N/A value_e = mpi_alloc_like (prime_p);
2N/A mpi_sub_ui (value_e, prime_p, 1);
2N/A mpi_fdiv_q (value_e, value_e, prime_q );
2N/A value_g = mpi_alloc_like (prime_p);
2N/A value_h = mpi_alloc_set_ui (1);
2N/A do
2N/A {
2N/A mpi_add_ui (value_h, value_h, 1);
2N/A /* g = h^e mod p */
2N/A mpi_powm (value_g, value_h, value_e, prime_p);
2N/A }
2N/A while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */
2N/A }
2N/A
2N/A
2N/A /* Select a random number x with: 0 < x < q */
2N/A value_x = gcry_mpi_snew (qbits);
2N/A do
2N/A {
2N/A if( DBG_CIPHER )
2N/A progress('.');
2N/A gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM);
2N/A mpi_clear_highbit (value_x, qbits+1);
2N/A }
2N/A while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0));
2N/A
2N/A /* y = g^x mod p */
2N/A value_y = mpi_alloc_like (prime_p);
2N/A gcry_mpi_powm (value_y, value_g, value_x, prime_p);
2N/A
2N/A if (DBG_CIPHER)
2N/A {
2N/A progress('\n');
2N/A log_mpidump("dsa p", prime_p );
2N/A log_mpidump("dsa q", prime_q );
2N/A log_mpidump("dsa g", value_g );
2N/A log_mpidump("dsa y", value_y );
2N/A log_mpidump("dsa x", value_x );
2N/A log_mpidump("dsa h", value_h );
2N/A }
2N/A
2N/A /* Copy the stuff to the key structures. */
2N/A sk->p = prime_p; prime_p = NULL;
2N/A sk->q = prime_q; prime_q = NULL;
2N/A sk->g = value_g; value_g = NULL;
2N/A sk->y = value_y; value_y = NULL;
2N/A sk->x = value_x; value_x = NULL;
2N/A *r_h = value_h; value_h = NULL;
2N/A
2N/A leave:
2N/A gcry_mpi_release (prime_p);
2N/A gcry_mpi_release (prime_q);
2N/A gcry_mpi_release (value_g);
2N/A gcry_mpi_release (value_y);
2N/A gcry_mpi_release (value_x);
2N/A gcry_mpi_release (value_h);
2N/A gcry_mpi_release (value_e);
2N/A
2N/A /* As a last step test this keys (this should never fail of course). */
2N/A if (!ec && test_keys (sk, qbits) )
2N/A {
2N/A gcry_mpi_release (sk->p); sk->p = NULL;
2N/A gcry_mpi_release (sk->q); sk->q = NULL;
2N/A gcry_mpi_release (sk->g); sk->g = NULL;
2N/A gcry_mpi_release (sk->y); sk->y = NULL;
2N/A gcry_mpi_release (sk->x); sk->x = NULL;
2N/A fips_signal_error ("self-test after key generation failed");
2N/A ec = GPG_ERR_SELFTEST_FAILED;
2N/A }
2N/A
2N/A if (ec)
2N/A {
2N/A *r_counter = 0;
2N/A gcry_free (*r_seed); *r_seed = NULL;
2N/A *r_seedlen = 0;
2N/A gcry_mpi_release (*r_h); *r_h = NULL;
2N/A }
2N/A
2N/A return ec;
2N/A}
2N/A
2N/A
2N/A
2N/A/*
2N/A Test whether the secret key is valid.
2N/A Returns: if this is a valid key.
2N/A */
2N/Astatic int
2N/Acheck_secret_key( DSA_secret_key *sk )
2N/A{
2N/A int rc;
2N/A gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) );
2N/A
2N/A gcry_mpi_powm( y, sk->g, sk->x, sk->p );
2N/A rc = !mpi_cmp( y, sk->y );
2N/A mpi_free( y );
2N/A return rc;
2N/A}
2N/A
2N/A
2N/A
2N/A/*
2N/A Make a DSA signature from HASH and put it into r and s.
2N/A */
2N/Astatic void
2N/Asign(gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_secret_key *skey )
2N/A{
2N/A gcry_mpi_t k;
2N/A gcry_mpi_t kinv;
2N/A gcry_mpi_t tmp;
2N/A
2N/A /* Select a random k with 0 < k < q */
2N/A k = gen_k( skey->q );
2N/A
2N/A /* r = (a^k mod p) mod q */
2N/A gcry_mpi_powm( r, skey->g, k, skey->p );
2N/A mpi_fdiv_r( r, r, skey->q );
2N/A
2N/A /* kinv = k^(-1) mod q */
2N/A kinv = mpi_alloc( mpi_get_nlimbs(k) );
2N/A mpi_invm(kinv, k, skey->q );
2N/A
2N/A /* s = (kinv * ( hash + x * r)) mod q */
2N/A tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
2N/A mpi_mul( tmp, skey->x, r );
2N/A mpi_add( tmp, tmp, hash );
2N/A mpi_mulm( s , kinv, tmp, skey->q );
2N/A
2N/A mpi_free(k);
2N/A mpi_free(kinv);
2N/A mpi_free(tmp);
2N/A}
2N/A
2N/A
2N/A/*
2N/A Returns true if the signature composed from R and S is valid.
2N/A */
2N/Astatic int
2N/Averify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey )
2N/A{
2N/A int rc;
2N/A gcry_mpi_t w, u1, u2, v;
2N/A gcry_mpi_t base[3];
2N/A gcry_mpi_t ex[3];
2N/A
2N/A if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
2N/A return 0; /* assertion 0 < r < q failed */
2N/A if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
2N/A return 0; /* assertion 0 < s < q failed */
2N/A
2N/A w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
2N/A u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
2N/A u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
2N/A v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
2N/A
2N/A /* w = s^(-1) mod q */
2N/A mpi_invm( w, s, pkey->q );
2N/A
2N/A /* u1 = (hash * w) mod q */
2N/A mpi_mulm( u1, hash, w, pkey->q );
2N/A
2N/A /* u2 = r * w mod q */
2N/A mpi_mulm( u2, r, w, pkey->q );
2N/A
2N/A /* v = g^u1 * y^u2 mod p mod q */
2N/A base[0] = pkey->g; ex[0] = u1;
2N/A base[1] = pkey->y; ex[1] = u2;
2N/A base[2] = NULL; ex[2] = NULL;
2N/A mpi_mulpowm( v, base, ex, pkey->p );
2N/A mpi_fdiv_r( v, v, pkey->q );
2N/A
2N/A rc = !mpi_cmp( v, r );
2N/A
2N/A mpi_free(w);
2N/A mpi_free(u1);
2N/A mpi_free(u2);
2N/A mpi_free(v);
2N/A
2N/A return rc;
2N/A}
2N/A
2N/A
2N/A/*********************************************
2N/A ************** interface ******************
2N/A *********************************************/
2N/A
2N/Astatic gcry_err_code_t
2N/Adsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
2N/A const gcry_sexp_t genparms,
2N/A gcry_mpi_t *skey, gcry_mpi_t **retfactors,
2N/A gcry_sexp_t *r_extrainfo)
2N/A{
2N/A gpg_err_code_t ec;
2N/A DSA_secret_key sk;
2N/A gcry_sexp_t l1;
2N/A unsigned int qbits = 0;
2N/A gcry_sexp_t deriveparms = NULL;
2N/A gcry_sexp_t seedinfo = NULL;
2N/A int transient_key = 0;
2N/A int use_fips186_2 = 0;
2N/A int use_fips186 = 0;
2N/A dsa_domain_t domain;
2N/A
2N/A (void)algo; /* No need to check it. */
2N/A (void)evalue; /* Not required for DSA. */
2N/A
2N/A memset (&domain, 0, sizeof domain);
2N/A
2N/A if (genparms)
2N/A {
2N/A gcry_sexp_t domainsexp;
2N/A
2N/A /* Parse the optional qbits element. */
2N/A l1 = gcry_sexp_find_token (genparms, "qbits", 0);
2N/A if (l1)
2N/A {
2N/A char buf[50];
2N/A const char *s;
2N/A size_t n;
2N/A
2N/A s = gcry_sexp_nth_data (l1, 1, &n);
2N/A if (!s || n >= DIM (buf) - 1 )
2N/A {
2N/A gcry_sexp_release (l1);
2N/A return GPG_ERR_INV_OBJ; /* No value or value too large. */
2N/A }
2N/A memcpy (buf, s, n);
2N/A buf[n] = 0;
2N/A qbits = (unsigned int)strtoul (buf, NULL, 0);
2N/A gcry_sexp_release (l1);
2N/A }
2N/A
2N/A /* Parse the optional transient-key flag. */
2N/A l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
2N/A if (l1)
2N/A {
2N/A transient_key = 1;
2N/A gcry_sexp_release (l1);
2N/A }
2N/A
2N/A /* Get the optional derive parameters. */
2N/A deriveparms = gcry_sexp_find_token (genparms, "derive-parms", 0);
2N/A
2N/A /* Parse the optional "use-fips186" flags. */
2N/A l1 = gcry_sexp_find_token (genparms, "use-fips186", 0);
2N/A if (l1)
2N/A {
2N/A use_fips186 = 1;
2N/A gcry_sexp_release (l1);
2N/A }
2N/A l1 = gcry_sexp_find_token (genparms, "use-fips186-2", 0);
2N/A if (l1)
2N/A {
2N/A use_fips186_2 = 1;
2N/A gcry_sexp_release (l1);
2N/A }
2N/A
2N/A /* Check whether domain parameters are given. */
2N/A domainsexp = gcry_sexp_find_token (genparms, "domain", 0);
2N/A if (domainsexp)
2N/A {
2N/A /* DERIVEPARMS can't be used together with domain
2N/A parameters. NBITS abnd QBITS may not be specified
2N/A because there values are derived from the domain
2N/A parameters. */
2N/A if (deriveparms || qbits || nbits)
2N/A {
2N/A gcry_sexp_release (domainsexp);
2N/A gcry_sexp_release (deriveparms);
2N/A return GPG_ERR_INV_VALUE;
2N/A }
2N/A
2N/A /* Put all domain parameters into the domain object. */
2N/A l1 = gcry_sexp_find_token (domainsexp, "p", 0);
2N/A domain.p = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2N/A gcry_sexp_release (l1);
2N/A l1 = gcry_sexp_find_token (domainsexp, "q", 0);
2N/A domain.q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2N/A gcry_sexp_release (l1);
2N/A l1 = gcry_sexp_find_token (domainsexp, "g", 0);
2N/A domain.g = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2N/A gcry_sexp_release (l1);
2N/A gcry_sexp_release (domainsexp);
2N/A
2N/A /* Check that all domain parameters are available. */
2N/A if (!domain.p || !domain.q || !domain.g)
2N/A {
2N/A gcry_mpi_release (domain.p);
2N/A gcry_mpi_release (domain.q);
2N/A gcry_mpi_release (domain.g);
2N/A gcry_sexp_release (deriveparms);
2N/A return GPG_ERR_MISSING_VALUE;
2N/A }
2N/A
2N/A /* Get NBITS and QBITS from the domain parameters. */
2N/A nbits = mpi_get_nbits (domain.p);
2N/A qbits = mpi_get_nbits (domain.q);
2N/A }
2N/A }
2N/A
2N/A if (deriveparms || use_fips186 || use_fips186_2 || fips_mode ())
2N/A {
2N/A int counter;
2N/A void *seed;
2N/A size_t seedlen;
2N/A gcry_mpi_t h_value;
2N/A
2N/A ec = generate_fips186 (&sk, nbits, qbits, deriveparms, use_fips186_2,
2N/A &domain,
2N/A &counter, &seed, &seedlen, &h_value);
2N/A gcry_sexp_release (deriveparms);
2N/A if (!ec && h_value)
2N/A {
2N/A /* Format the seed-values unless domain parameters are used
2N/A for which a H_VALUE of NULL is an indication. */
2N/A ec = gpg_err_code (gcry_sexp_build
2N/A (&seedinfo, NULL,
2N/A "(seed-values(counter %d)(seed %b)(h %m))",
2N/A counter, (int)seedlen, seed, h_value));
2N/A if (ec)
2N/A {
2N/A gcry_mpi_release (sk.p); sk.p = NULL;
2N/A gcry_mpi_release (sk.q); sk.q = NULL;
2N/A gcry_mpi_release (sk.g); sk.g = NULL;
2N/A gcry_mpi_release (sk.y); sk.y = NULL;
2N/A gcry_mpi_release (sk.x); sk.x = NULL;
2N/A }
2N/A gcry_free (seed);
2N/A gcry_mpi_release (h_value);
2N/A }
2N/A }
2N/A else
2N/A {
2N/A ec = generate (&sk, nbits, qbits, transient_key, &domain, retfactors);
2N/A }
2N/A
2N/A gcry_mpi_release (domain.p);
2N/A gcry_mpi_release (domain.q);
2N/A gcry_mpi_release (domain.g);
2N/A
2N/A if (!ec)
2N/A {
2N/A skey[0] = sk.p;
2N/A skey[1] = sk.q;
2N/A skey[2] = sk.g;
2N/A skey[3] = sk.y;
2N/A skey[4] = sk.x;
2N/A
2N/A if (!r_extrainfo)
2N/A {
2N/A /* Old style interface - return the factors - if any - at
2N/A retfactors. */
2N/A }
2N/A else if (!*retfactors && !seedinfo)
2N/A {
2N/A /* No factors and no seedinfo, thus there is nothing to return. */
2N/A *r_extrainfo = NULL;
2N/A }
2N/A else
2N/A {
2N/A /* Put the factors into extrainfo and set retfactors to NULL
2N/A to make use of the new interface. Note that the factors
2N/A are not confidential thus we can store them in standard
2N/A memory. */
2N/A int nfactors, i, j;
2N/A char *p;
2N/A char *format = NULL;
2N/A void **arg_list = NULL;
2N/A
2N/A for (nfactors=0; *retfactors && (*retfactors)[nfactors]; nfactors++)
2N/A ;
2N/A /* Allocate space for the format string:
2N/A "(misc-key-info%S(pm1-factors%m))"
2N/A with one "%m" for each factor and construct it. */
2N/A format = gcry_malloc (50 + 2*nfactors);
2N/A if (!format)
2N/A ec = gpg_err_code_from_syserror ();
2N/A else
2N/A {
2N/A p = stpcpy (format, "(misc-key-info");
2N/A if (seedinfo)
2N/A p = stpcpy (p, "%S");
2N/A if (nfactors)
2N/A {
2N/A p = stpcpy (p, "(pm1-factors");
2N/A for (i=0; i < nfactors; i++)
2N/A p = stpcpy (p, "%m");
2N/A p = stpcpy (p, ")");
2N/A }
2N/A p = stpcpy (p, ")");
2N/A
2N/A /* Allocate space for the list of factors plus one for
2N/A an S-expression plus an extra NULL entry for safety
2N/A and fill it with the factors. */
2N/A arg_list = gcry_calloc (nfactors+1+1, sizeof *arg_list);
2N/A if (!arg_list)
2N/A ec = gpg_err_code_from_syserror ();
2N/A else
2N/A {
2N/A i = 0;
2N/A if (seedinfo)
2N/A arg_list[i++] = &seedinfo;
2N/A for (j=0; j < nfactors; j++)
2N/A arg_list[i++] = (*retfactors) + j;
2N/A arg_list[i] = NULL;
2N/A
2N/A ec = gpg_err_code (gcry_sexp_build_array
2N/A (r_extrainfo, NULL, format, arg_list));
2N/A }
2N/A }
2N/A
2N/A gcry_free (arg_list);
2N/A gcry_free (format);
2N/A for (i=0; i < nfactors; i++)
2N/A {
2N/A gcry_mpi_release ((*retfactors)[i]);
2N/A (*retfactors)[i] = NULL;
2N/A }
2N/A *retfactors = NULL;
2N/A if (ec)
2N/A {
2N/A for (i=0; i < 5; i++)
2N/A {
2N/A gcry_mpi_release (skey[i]);
2N/A skey[i] = NULL;
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A gcry_sexp_release (seedinfo);
2N/A return ec;
2N/A}
2N/A
2N/A
2N/Astatic gcry_err_code_t
2N/Adsa_generate (int algo, unsigned int nbits, unsigned long evalue,
2N/A gcry_mpi_t *skey, gcry_mpi_t **retfactors)
2N/A{
2N/A (void)evalue;
2N/A return dsa_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
2N/A}
2N/A
2N/A
2N/A
2N/Astatic gcry_err_code_t
2N/Adsa_check_secret_key (int algo, gcry_mpi_t *skey)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A DSA_secret_key sk;
2N/A
2N/A (void)algo;
2N/A
2N/A if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4]))
2N/A err = GPG_ERR_BAD_MPI;
2N/A else
2N/A {
2N/A sk.p = skey[0];
2N/A sk.q = skey[1];
2N/A sk.g = skey[2];
2N/A sk.y = skey[3];
2N/A sk.x = skey[4];
2N/A if (! check_secret_key (&sk))
2N/A err = GPG_ERR_BAD_SECKEY;
2N/A }
2N/A
2N/A return err;
2N/A}
2N/A
2N/A
2N/Astatic gcry_err_code_t
2N/Adsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A DSA_secret_key sk;
2N/A
2N/A (void)algo;
2N/A
2N/A if ((! data)
2N/A || (! skey[0]) || (! skey[1]) || (! skey[2])
2N/A || (! skey[3]) || (! skey[4]))
2N/A err = GPG_ERR_BAD_MPI;
2N/A else
2N/A {
2N/A sk.p = skey[0];
2N/A sk.q = skey[1];
2N/A sk.g = skey[2];
2N/A sk.y = skey[3];
2N/A sk.x = skey[4];
2N/A resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p));
2N/A resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p));
2N/A sign (resarr[0], resarr[1], data, &sk);
2N/A }
2N/A return err;
2N/A}
2N/A
2N/Astatic gcry_err_code_t
2N/Adsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
2N/A int (*cmp) (void *, gcry_mpi_t), void *opaquev)
2N/A{
2N/A gcry_err_code_t err = GPG_ERR_NO_ERROR;
2N/A DSA_public_key pk;
2N/A
2N/A (void)algo;
2N/A (void)cmp;
2N/A (void)opaquev;
2N/A
2N/A if ((! data[0]) || (! data[1]) || (! hash)
2N/A || (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3]))
2N/A err = GPG_ERR_BAD_MPI;
2N/A else
2N/A {
2N/A pk.p = pkey[0];
2N/A pk.q = pkey[1];
2N/A pk.g = pkey[2];
2N/A pk.y = pkey[3];
2N/A if (! verify (data[0], data[1], hash, &pk))
2N/A err = GPG_ERR_BAD_SIGNATURE;
2N/A }
2N/A return err;
2N/A}
2N/A
2N/A
2N/Astatic unsigned int
2N/Adsa_get_nbits (int algo, gcry_mpi_t *pkey)
2N/A{
2N/A (void)algo;
2N/A
2N/A return mpi_get_nbits (pkey[0]);
2N/A}
2N/A
2N/A
2N/A
2N/A/*
2N/A Self-test section.
2N/A */
2N/A
2N/A
2N/A
2N/A
2N/A
2N/A/* Run a full self-test for ALGO and return 0 on success. */
2N/A
2N/A
2N/A
2N/A
2N/Astatic const char *dsa_names[] =
2N/A {
2N/A "dsa",
2N/A "openpgp-dsa",
2N/A NULL,
2N/A };
2N/A
2N/Agcry_pk_spec_t _gcry_pubkey_spec_dsa =
2N/A {
2N/A "DSA", dsa_names,
2N/A "pqgy", "pqgyx", "", "rs", "pqgy",
2N/A GCRY_PK_USAGE_SIGN,
2N/A dsa_generate,
2N/A dsa_check_secret_key,
2N/A NULL,
2N/A NULL,
2N/A dsa_sign,
2N/A dsa_verify,
2N/A dsa_get_nbits
2N/A };
2N/Apk_extra_spec_t _gcry_pubkey_extraspec_dsa =
2N/A {
2N/A run_selftests,
2N/A dsa_generate_ext
2N/A };
2N/A