1
0
Fork 0
grub2/grub-core/lib/libgcrypt-grub/cipher/dsa.c
Daniel Baumann 6a7a3b2a63
Adding upstream version 2.12.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 15:25:07 +02:00

292 lines
6.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This file was automatically imported with
import_gcry.py. Please don't modify it */
#include <grub/dl.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* dsa.c - DSA signature algorithm
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2006, 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/>.
*/
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
} DSA_public_key;
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
gcry_mpi_t x; /* secret exponent */
} DSA_secret_key;
/* A structure used to hold domain parameters. */
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
} dsa_domain_t;
/* A sample 1024 bit DSA key used for the selftests. */
/* A sample 1024 bit DSA key used for the selftests (public only). */
static int check_secret_key (DSA_secret_key *sk);
static int verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
DSA_public_key *pkey);
/*
* Generate a random secret exponent k less than q.
*/
/* Check that a freshly generated key actually works. Returns 0 on success. */
/*
Generate a DSA key pair with a key of size NBITS. If transient_key
is true the key is generated using the standard RNG and not the
very secure one.
Returns: 2 structures filled with all needed values
and an array with the n-1 factors of (p-1)
*/
/* Generate a DSA key pair with a key of size NBITS using the
algorithm given in FIPS-186-3. If USE_FIPS186_2 is true,
FIPS-186-2 is used and thus the length is restricted to 1024/160.
If DERIVEPARMS is not NULL it may contain a seed value. If domain
parameters are specified in DOMAIN, DERIVEPARMS may not be given
and NBITS and QBITS must match the specified domain parameters. */
/*
Test whether the secret key is valid.
Returns: if this is a valid key.
*/
static int
check_secret_key( DSA_secret_key *sk )
{
int rc;
gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) );
gcry_mpi_powm( y, sk->g, sk->x, sk->p );
rc = !mpi_cmp( y, sk->y );
mpi_free( y );
return rc;
}
/*
Make a DSA signature from HASH and put it into r and s.
*/
/*
Returns true if the signature composed from R and S is valid.
*/
static int
verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey )
{
int rc;
gcry_mpi_t w, u1, u2, v;
gcry_mpi_t base[3];
gcry_mpi_t ex[3];
if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
return 0; /* assertion 0 < r < q failed */
if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
return 0; /* assertion 0 < s < q failed */
w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
/* w = s^(-1) mod q */
mpi_invm( w, s, pkey->q );
/* u1 = (hash * w) mod q */
mpi_mulm( u1, hash, w, pkey->q );
/* u2 = r * w mod q */
mpi_mulm( u2, r, w, pkey->q );
/* v = g^u1 * y^u2 mod p mod q */
base[0] = pkey->g; ex[0] = u1;
base[1] = pkey->y; ex[1] = u2;
base[2] = NULL; ex[2] = NULL;
mpi_mulpowm( v, base, ex, pkey->p );
mpi_fdiv_r( v, v, pkey->q );
rc = !mpi_cmp( v, r );
mpi_free(w);
mpi_free(u1);
mpi_free(u2);
mpi_free(v);
return rc;
}
/*********************************************
************** interface ******************
*********************************************/
#define dsa_generate 0
#define dsa_generate 0
static gcry_err_code_t
dsa_check_secret_key (int algo, gcry_mpi_t *skey)
{
gcry_err_code_t err = GPG_ERR_NO_ERROR;
DSA_secret_key sk;
(void)algo;
if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4]))
err = GPG_ERR_BAD_MPI;
else
{
sk.p = skey[0];
sk.q = skey[1];
sk.g = skey[2];
sk.y = skey[3];
sk.x = skey[4];
if (! check_secret_key (&sk))
err = GPG_ERR_BAD_SECKEY;
}
return err;
}
#define dsa_sign 0
static gcry_err_code_t
dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
int (*cmp) (void *, gcry_mpi_t), void *opaquev)
{
gcry_err_code_t err = GPG_ERR_NO_ERROR;
DSA_public_key pk;
(void)algo;
(void)cmp;
(void)opaquev;
if ((! data[0]) || (! data[1]) || (! hash)
|| (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3]))
err = GPG_ERR_BAD_MPI;
else
{
pk.p = pkey[0];
pk.q = pkey[1];
pk.g = pkey[2];
pk.y = pkey[3];
if (! verify (data[0], data[1], hash, &pk))
err = GPG_ERR_BAD_SIGNATURE;
}
return err;
}
static unsigned int
dsa_get_nbits (int algo, gcry_mpi_t *pkey)
{
(void)algo;
return mpi_get_nbits (pkey[0]);
}
/*
Self-test section.
*/
/* Run a full self-test for ALGO and return 0 on success. */
static const char *dsa_names[] =
{
"dsa",
"openpgp-dsa",
NULL,
};
gcry_pk_spec_t _gcry_pubkey_spec_dsa =
{
"DSA", dsa_names,
"pqgy", "pqgyx", "", "rs", "pqgy",
GCRY_PK_USAGE_SIGN,
dsa_generate,
dsa_check_secret_key,
NULL,
NULL,
dsa_sign,
dsa_verify,
dsa_get_nbits
,
#ifdef GRUB_UTIL
.modname = "gcry_dsa",
#endif
};
GRUB_MOD_INIT(gcry_dsa)
{
grub_crypto_pk_dsa = &_gcry_pubkey_spec_dsa;
}
GRUB_MOD_FINI(gcry_dsa)
{
grub_crypto_pk_dsa = 0;
}