/* This file was automatically imported with import_gcry.py. Please don't modify it */ #include 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 . */ #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. */ static const char sample_secret_key[] = "(private-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" " 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" " CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" " 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" " (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" " (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" " AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" " B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" " 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" " (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" " A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" " (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; /* A sample 1024 bit DSA key used for the selftests (public only). */ static const char sample_public_key[] = "(public-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" " 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" " CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" " 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" " (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" " (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" " AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" " B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" " 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" " (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" " A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" " 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))"; 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; }