Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36623932
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
10 KB
Subscribers
None
View Options
diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 6f2c2f9e..8c0a6843 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -1,394 +1,394 @@
/* 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);
+ t = xtrymalloc_secure ((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. Because 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;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 26, 7:03 PM (13 h, 3 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
db/0e/7d9cd4331b41ca4903ef29fe3301
Attached To
rC libgcrypt
Event Timeline
Log In to Comment