Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34085870
dsa-common.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
10 KB
Subscribers
None
dsa-common.c
View Options
/* 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
(
"
\t
k too large - again
\n
"
);
continue
;
/* no */
}
if
(
!
(
mpi_cmp_ui
(
k
,
0
)
>
0
))
/* check: k > 0 */
{
if
(
DBG_CIPHER
)
log_debug
(
"
\t
k 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. 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-c
Expires
Wed, Dec 3, 3:43 AM (1 d, 17 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0a/6c/95aecb1565a708ac7e4d2143f0b3
Attached To
rC libgcrypt
Event Timeline
Log In to Comment