| /* dsa-common.c - Common code for DSA |
| * Copyright (C) 1998, 1999 Free Software Foundation, Inc. |
| * Copyright (C) 2013 g10 Code GmbH |
| * |
| * 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 <config.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "g10lib.h" |
| #include "mpi.h" |
| #include "cipher.h" |
| #include "pubkey-internal.h" |
| |
| |
| /* |
| * Generate a random secret exponent K less than Q. |
| * Note that ECDSA uses this code also to generate D. |
| */ |
| gcry_mpi_t |
| _gcry_dsa_gen_k (gcry_mpi_t q, int security_level) |
| { |
| gcry_mpi_t k = mpi_alloc_secure (mpi_get_nlimbs (q)); |
| unsigned int nbits = mpi_get_nbits (q); |
| unsigned int nbytes = (nbits+7)/8; |
| char *rndbuf = NULL; |
| |
| /* To learn why we don't use mpi_mod to get the requested bit size, |
| read the paper: "The Insecurity of the Digital Signature |
| Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. |
| Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ |
| |
| if (DBG_CIPHER) |
| log_debug ("choosing a random k of %u bits at seclevel %d\n", |
| nbits, security_level); |
| for (;;) |
| { |
| if ( !rndbuf || nbits < 32 ) |
| { |
| xfree (rndbuf); |
| rndbuf = _gcry_random_bytes_secure (nbytes, security_level); |
| } |
| else |
| { /* Change only some of the higher bits. We could improve |
| this by directly requesting more memory at the first call |
| to get_random_bytes() and use these extra bytes here. |
| However the required management code is more complex and |
| thus we better use this simple method. */ |
| char *pp = _gcry_random_bytes_secure (4, security_level); |
| memcpy (rndbuf, pp, 4); |
| xfree (pp); |
| } |
| _gcry_mpi_set_buffer (k, rndbuf, nbytes, 0); |
| |
| /* Make sure we have the requested number of bits. This code |
| looks a bit funny but it is easy to understand if you |
| consider that mpi_set_highbit clears all higher bits. We |
| don't have a clear_highbit, thus we first set the high bit |
| and then clear it again. */ |
| if (mpi_test_bit (k, nbits-1)) |
| mpi_set_highbit (k, nbits-1); |
| else |
| { |
| mpi_set_highbit (k, nbits-1); |
| mpi_clear_bit (k, nbits-1); |
| } |
| |
| if (!(mpi_cmp (k, q) < 0)) /* check: k < q */ |
| { |
| if (DBG_CIPHER) |
| log_debug ("\tk too large - again\n"); |
| continue; /* no */ |
| } |
| if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */ |
| { |
| if (DBG_CIPHER) |
| log_debug ("\tk is zero - again\n"); |
| continue; /* no */ |
| } |
| break; /* okay */ |
| } |
| xfree (rndbuf); |
| |
| return k; |
| } |
| |
| |
| /* Turn VALUE into an octet string and store it in an allocated buffer |
| at R_FRAME. If the resulting octet string is shorter than NBYTES |
| the result will be left padded with zeroes. If VALUE does not fit |
| into NBYTES an error code is returned. */ |
| static gpg_err_code_t |
| int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes) |
| { |
| gpg_err_code_t rc; |
| size_t nframe, noff, n; |
| unsigned char *frame; |
| |
| rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value); |
| if (rc) |
| return rc; |
| if (nframe > nbytes) |
| return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ |
| |
| noff = (nframe < nbytes)? nbytes - nframe : 0; |
| n = nframe + noff; |
| frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n); |
| if (!frame) |
| return gpg_err_code_from_syserror (); |
| if (noff) |
| memset (frame, 0, noff); |
| nframe += noff; |
| rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value); |
| if (rc) |
| { |
| xfree (frame); |
| return rc; |
| } |
| |
| *r_frame = frame; |
| return 0; |
| } |
| |
| |
| /* Connert the bit string BITS of length NBITS into an octet string |
| with a length of (QBITS+7)/8 bytes. On success store the result at |
| R_FRAME. */ |
| static gpg_err_code_t |
| bits2octets (unsigned char **r_frame, |
| const void *bits, unsigned int nbits, |
| gcry_mpi_t q, unsigned int qbits) |
| { |
| gpg_err_code_t rc; |
| gcry_mpi_t z1; |
| |
| /* z1 = bits2int (b) */ |
| rc = _gcry_mpi_scan (&z1, GCRYMPI_FMT_USG, bits, (nbits+7)/8, NULL); |
| if (rc) |
| return rc; |
| if (nbits > qbits) |
| mpi_rshift (z1, z1, nbits - qbits); |
| |
| /* z2 - z1 mod q */ |
| if (mpi_cmp (z1, q) >= 0) |
| mpi_sub (z1, z1, q); |
| |
| /* Convert to an octet string. */ |
| rc = int2octets (r_frame, z1, (qbits+7)/8); |
| |
| mpi_free (z1); |
| return rc; |
| } |
| |
| |
| /* |
| * Generate a deterministic secret exponent K less than DSA_Q. H1 is |
| * the to be signed digest with a length of HLEN bytes. HALGO is the |
| * algorithm used to create the hash. On success the value for K is |
| * stored at R_K. |
| */ |
| gpg_err_code_t |
| _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k, |
| gcry_mpi_t dsa_q, gcry_mpi_t dsa_x, |
| const unsigned char *h1, unsigned int hlen, |
| int halgo, unsigned int extraloops) |
| { |
| gpg_err_code_t rc; |
| unsigned char *V = NULL; |
| unsigned char *K = NULL; |
| unsigned char *x_buf = NULL; |
| unsigned char *h1_buf = NULL; |
| gcry_md_hd_t hd = NULL; |
| unsigned char *t = NULL; |
| gcry_mpi_t k = NULL; |
| unsigned int tbits, qbits; |
| int i; |
| |
| qbits = mpi_get_nbits (dsa_q); |
| |
| if (!qbits || !h1 || !hlen) |
| return GPG_ERR_EINVAL; |
| |
| if (_gcry_md_get_algo_dlen (halgo) != hlen) |
| return GPG_ERR_DIGEST_ALGO; |
| |
| /* Step b: V = 0x01 0x01 0x01 ... 0x01 */ |
| V = xtrymalloc (hlen); |
| if (!V) |
| { |
| rc = gpg_err_code_from_syserror (); |
| goto leave; |
| } |
| for (i=0; i < hlen; i++) |
| V[i] = 1; |
| |
| /* Step c: K = 0x00 0x00 0x00 ... 0x00 */ |
| K = xtrycalloc (1, hlen); |
| if (!K) |
| { |
| rc = gpg_err_code_from_syserror (); |
| goto leave; |
| } |
| |
| rc = int2octets (&x_buf, dsa_x, (qbits+7)/8); |
| if (rc) |
| goto leave; |
| |
| rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits); |
| if (rc) |
| goto leave; |
| |
| /* Create a handle to compute the HMACs. */ |
| rc = _gcry_md_open (&hd, halgo, (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)); |
| if (rc) |
| goto leave; |
| |
| /* Step d: K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| _gcry_md_write (hd, "", 1); |
| _gcry_md_write (hd, x_buf, (qbits+7)/8); |
| _gcry_md_write (hd, h1_buf, (qbits+7)/8); |
| memcpy (K, _gcry_md_read (hd, 0), hlen); |
| |
| /* Step e: V = HMAC_K(V) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| memcpy (V, _gcry_md_read (hd, 0), hlen); |
| |
| /* Step f: K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| _gcry_md_write (hd, "\x01", 1); |
| _gcry_md_write (hd, x_buf, (qbits+7)/8); |
| _gcry_md_write (hd, h1_buf, (qbits+7)/8); |
| memcpy (K, _gcry_md_read (hd, 0), hlen); |
| |
| /* Step g: V = HMAC_K(V) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| memcpy (V, _gcry_md_read (hd, 0), hlen); |
| |
| /* Step h. */ |
| t = xtrymalloc ((qbits+7)/8+hlen); |
| if (!t) |
| { |
| rc = gpg_err_code_from_syserror (); |
| goto leave; |
| } |
| |
| again: |
| for (tbits = 0; tbits < qbits;) |
| { |
| /* V = HMAC_K(V) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| memcpy (V, _gcry_md_read (hd, 0), hlen); |
| |
| /* T = T || V */ |
| memcpy (t+(tbits+7)/8, V, hlen); |
| tbits += 8*hlen; |
| } |
| |
| /* k = bits2int (T) */ |
| mpi_free (k); |
| k = NULL; |
| rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL); |
| if (rc) |
| goto leave; |
| if (tbits > qbits) |
| mpi_rshift (k, k, tbits - qbits); |
| |
| /* Check: k < q and k > 1 */ |
| if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0)) |
| { |
| /* K = HMAC_K(V || 0x00) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| _gcry_md_write (hd, "", 1); |
| memcpy (K, _gcry_md_read (hd, 0), hlen); |
| |
| /* V = HMAC_K(V) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| memcpy (V, _gcry_md_read (hd, 0), hlen); |
| |
| goto again; |
| } |
| |
| /* The caller may have requested that we introduce some extra loops. |
| This is for example useful if the caller wants another value for |
| K because the last returned one yielded an R of 0. Becuase this |
| is very unlikely we implement it in a straightforward way. */ |
| if (extraloops) |
| { |
| extraloops--; |
| |
| /* K = HMAC_K(V || 0x00) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| _gcry_md_write (hd, "", 1); |
| memcpy (K, _gcry_md_read (hd, 0), hlen); |
| |
| /* V = HMAC_K(V) */ |
| rc = _gcry_md_setkey (hd, K, hlen); |
| if (rc) |
| goto leave; |
| _gcry_md_write (hd, V, hlen); |
| memcpy (V, _gcry_md_read (hd, 0), hlen); |
| |
| goto again; |
| } |
| |
| /* log_mpidump (" k", k); */ |
| |
| leave: |
| xfree (t); |
| _gcry_md_close (hd); |
| xfree (h1_buf); |
| xfree (x_buf); |
| xfree (K); |
| xfree (V); |
| |
| if (rc) |
| mpi_free (k); |
| else |
| *r_k = k; |
| return rc; |
| } |
| |
| /* |
| * Truncate opaque hash value to qbits for DSA. |
| * Non-opaque input is not truncated, in hope that user |
| * knows what is passed. It is not possible to correctly |
| * trucate non-opaque inputs. |
| */ |
| gpg_err_code_t |
| _gcry_dsa_normalize_hash (gcry_mpi_t input, |
| gcry_mpi_t *out, |
| unsigned int qbits) |
| { |
| gpg_err_code_t rc = 0; |
| const void *abuf; |
| unsigned int abits; |
| gcry_mpi_t hash; |
| |
| if (mpi_is_opaque (input)) |
| { |
| abuf = mpi_get_opaque (input, &abits); |
| rc = _gcry_mpi_scan (&hash, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL); |
| if (rc) |
| return rc; |
| if (abits > qbits) |
| mpi_rshift (hash, hash, abits - qbits); |
| } |
| else |
| hash = input; |
| |
| *out = hash; |
| |
| return rc; |
| } |