mirror of
git://git.gnupg.org/gnupg.git
synced 2025-05-14 08:13:25 +02:00
Make use of gcry_kdf_derive.
Factoring common code out is always a Good Thing. Also added a configure test to print an error if gcry_kdf_derive is missing in Libgcrypt.
This commit is contained in:
parent
35c731d889
commit
b9bcc77d6c
@ -1,3 +1,7 @@
|
|||||||
|
2011-03-10 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* protect.c (hash_passphrase): Use the new gcry_kdf_derive.
|
||||||
|
|
||||||
2011-03-08 Werner Koch <wk@g10code.com>
|
2011-03-08 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: Remove.
|
* cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: Remove.
|
||||||
|
@ -1023,70 +1023,13 @@ hash_passphrase (const char *passphrase, int hashalgo,
|
|||||||
unsigned long s2kcount,
|
unsigned long s2kcount,
|
||||||
unsigned char *key, size_t keylen)
|
unsigned char *key, size_t keylen)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
int pass, i;
|
|
||||||
int used = 0;
|
|
||||||
int pwlen = strlen (passphrase);
|
|
||||||
|
|
||||||
if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
|
return gcry_kdf_derive (passphrase, strlen (passphrase),
|
||||||
|| !hashalgo || !keylen || !key || !passphrase)
|
s2kmode == 3? GCRY_KDF_ITERSALTED_S2K :
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
s2kmode == 1? GCRY_KDF_SALTED_S2K :
|
||||||
if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
|
s2kmode == 0? GCRY_KDF_SIMPLE_S2K : GCRY_KDF_NONE,
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
hashalgo, s2ksalt, 8, s2kcount,
|
||||||
|
keylen, key);
|
||||||
rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
for (pass=0; used < keylen; pass++)
|
|
||||||
{
|
|
||||||
if (pass)
|
|
||||||
{
|
|
||||||
gcry_md_reset (md);
|
|
||||||
for (i=0; i < pass; i++) /* preset the hash context */
|
|
||||||
gcry_md_putc (md, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s2kmode == 1 || s2kmode == 3)
|
|
||||||
{
|
|
||||||
int len2 = pwlen + 8;
|
|
||||||
unsigned long count = len2;
|
|
||||||
|
|
||||||
if (s2kmode == 3)
|
|
||||||
{
|
|
||||||
count = s2kcount;
|
|
||||||
if (count < len2)
|
|
||||||
count = len2;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (count > len2)
|
|
||||||
{
|
|
||||||
gcry_md_write (md, s2ksalt, 8);
|
|
||||||
gcry_md_write (md, passphrase, pwlen);
|
|
||||||
count -= len2;
|
|
||||||
}
|
|
||||||
if (count < 8)
|
|
||||||
gcry_md_write (md, s2ksalt, count);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gcry_md_write (md, s2ksalt, 8);
|
|
||||||
count -= 8;
|
|
||||||
gcry_md_write (md, passphrase, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gcry_md_write (md, passphrase, pwlen);
|
|
||||||
|
|
||||||
gcry_md_final (md);
|
|
||||||
i = gcry_md_get_algo_dlen (hashalgo);
|
|
||||||
if (i > keylen - used)
|
|
||||||
i = keylen - used;
|
|
||||||
memcpy (key+used, gcry_md_read (md, hashalgo), i);
|
|
||||||
used += i;
|
|
||||||
}
|
|
||||||
gcry_md_close(md);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
25
configure.ac
25
configure.ac
@ -742,6 +742,22 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
|
|||||||
AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
|
AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
|
||||||
have_libgcrypt=yes,have_libgcrypt=no)
|
have_libgcrypt=yes,have_libgcrypt=no)
|
||||||
|
|
||||||
|
# FIxme: Remove this test after libgcrypt 1.5.0 has been released.
|
||||||
|
AC_CACHE_CHECK([whether Libgcrypt has gcry_kdf_derive],
|
||||||
|
gnupg_cv_gcry_kdf_derive,
|
||||||
|
[ _gnupg_gcry_save_cflags=$CFLAGS
|
||||||
|
_gnupg_gcry_save_libs=$LIBS
|
||||||
|
CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
|
||||||
|
LIBS="$LIBS $LIBGCRYPT_LIBS"
|
||||||
|
AC_TRY_LINK(
|
||||||
|
[#include <gcrypt.h>],
|
||||||
|
[ return gcry_kdf_derive (NULL,0,0,0,NULL,0,0,0,NULL); ],
|
||||||
|
gnupg_cv_gcry_kdf_derive=yes,
|
||||||
|
gnupg_cv_gcry_kdf_derive=no)
|
||||||
|
LIBS=$_gnupg_gcry_save_libs
|
||||||
|
CFLAGS=$_gnupg_gcry_save_cflags])
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# libassuan is used for IPC
|
# libassuan is used for IPC
|
||||||
#
|
#
|
||||||
@ -1605,6 +1621,15 @@ if test "$have_libgcrypt" = "no"; then
|
|||||||
*** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/
|
*** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/
|
||||||
*** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.)
|
*** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.)
|
||||||
***]])
|
***]])
|
||||||
|
elif test "$gnupg_cv_gcry_kdf_derive" = no; then
|
||||||
|
die=yes
|
||||||
|
AC_MSG_NOTICE([[
|
||||||
|
***
|
||||||
|
*** Libgcrypt 1.5.0 has not yet been released and thus the API
|
||||||
|
*** is a bit in a flux. Your version misses the function
|
||||||
|
*** gcry_kdf_derive
|
||||||
|
*** You need to install a newer Libgcrypt version.
|
||||||
|
***]])
|
||||||
fi
|
fi
|
||||||
if test "$have_libassuan" = "no"; then
|
if test "$have_libassuan" = "no"; then
|
||||||
die=yes
|
die=yes
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2011-03-10 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* passphrase.c (hash_passphrase): Remove.
|
||||||
|
(passphrase_to_dek_ext): Use gcry_kdf_derive.
|
||||||
|
|
||||||
2011-03-03 Werner Koch <wk@g10code.com>
|
2011-03-03 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* keylist.c (print_card_key_info): Re-implement using the agent.
|
* keylist.c (print_card_key_info): Re-implement using the agent.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* passphrase.c - Get a passphrase
|
/* passphrase.c - Get a passphrase
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||||
* 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
|
* 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -101,81 +101,6 @@ encode_s2k_iterations (int iterations)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Hash a passphrase using the supplied s2k.
|
|
||||||
Always needs: dek->algo, s2k->mode, s2k->hash_algo. */
|
|
||||||
static void
|
|
||||||
hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k)
|
|
||||||
{
|
|
||||||
gcry_md_hd_t md;
|
|
||||||
int pass, i;
|
|
||||||
int used = 0;
|
|
||||||
int pwlen = strlen(pw);
|
|
||||||
|
|
||||||
assert ( s2k->hash_algo );
|
|
||||||
dek->keylen = openpgp_cipher_get_algo_keylen (dek->algo);
|
|
||||||
if ( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) )
|
|
||||||
BUG();
|
|
||||||
|
|
||||||
if (gcry_md_open (&md, s2k->hash_algo, 1))
|
|
||||||
BUG ();
|
|
||||||
for (pass=0; used < dek->keylen ; pass++ )
|
|
||||||
{
|
|
||||||
if ( pass )
|
|
||||||
{
|
|
||||||
gcry_md_reset (md);
|
|
||||||
for (i=0; i < pass; i++ ) /* Preset the hash context. */
|
|
||||||
gcry_md_putc (md, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( s2k->mode == 1 || s2k->mode == 3 )
|
|
||||||
{
|
|
||||||
int len2 = pwlen + 8;
|
|
||||||
ulong count = len2;
|
|
||||||
|
|
||||||
if ( s2k->mode == 3 )
|
|
||||||
{
|
|
||||||
count = S2K_DECODE_COUNT(s2k->count);
|
|
||||||
if ( count < len2 )
|
|
||||||
count = len2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fixme: To avoid DoS attacks by sending an sym-encrypted
|
|
||||||
packet with a very high S2K count, we should either cap
|
|
||||||
the iteration count or CPU seconds based timeout. */
|
|
||||||
|
|
||||||
/* A little bit complicated because we need a ulong for count. */
|
|
||||||
while ( count > len2 ) /* maybe iterated+salted */
|
|
||||||
{
|
|
||||||
gcry_md_write ( md, s2k->salt, 8 );
|
|
||||||
gcry_md_write ( md, pw, pwlen );
|
|
||||||
count -= len2;
|
|
||||||
}
|
|
||||||
if ( count < 8 )
|
|
||||||
gcry_md_write ( md, s2k->salt, count );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gcry_md_write ( md, s2k->salt, 8 );
|
|
||||||
count -= 8;
|
|
||||||
gcry_md_write ( md, pw, count );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gcry_md_write ( md, pw, pwlen );
|
|
||||||
gcry_md_final( md );
|
|
||||||
|
|
||||||
i = gcry_md_get_algo_dlen ( s2k->hash_algo );
|
|
||||||
if ( i > dek->keylen - used )
|
|
||||||
i = dek->keylen - used;
|
|
||||||
|
|
||||||
memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i);
|
|
||||||
used += i;
|
|
||||||
}
|
|
||||||
gcry_md_close(md);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
have_static_passphrase()
|
have_static_passphrase()
|
||||||
{
|
{
|
||||||
@ -655,7 +580,24 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
|
|||||||
if ( (!pw || !*pw) && (mode == 2 || mode == 4))
|
if ( (!pw || !*pw) && (mode == 2 || mode == 4))
|
||||||
dek->keylen = 0;
|
dek->keylen = 0;
|
||||||
else
|
else
|
||||||
hash_passphrase (dek, pw, s2k);
|
{
|
||||||
|
dek->keylen = openpgp_cipher_get_algo_keylen (dek->algo);
|
||||||
|
if (!(dek->keylen > 0 && dek->keylen <= DIM(dek->key)))
|
||||||
|
BUG ();
|
||||||
|
if (gcry_kdf_derive (pw, strlen (pw),
|
||||||
|
s2k->mode == 3? GCRY_KDF_ITERSALTED_S2K :
|
||||||
|
s2k->mode == 1? GCRY_KDF_SALTED_S2K :
|
||||||
|
/* */ GCRY_KDF_SIMPLE_S2K,
|
||||||
|
s2k->hash_algo, s2k->salt, 8,
|
||||||
|
S2K_DECODE_COUNT(s2k->count),
|
||||||
|
dek->keylen, dek->key))
|
||||||
|
{
|
||||||
|
xfree (pw);
|
||||||
|
xfree (dek);
|
||||||
|
write_status( STATUS_MISSING_PASSPHRASE );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (s2k_cacheid)
|
if (s2k_cacheid)
|
||||||
memcpy (dek->s2k_cacheid, s2k_cacheid, sizeof dek->s2k_cacheid);
|
memcpy (dek->s2k_cacheid, s2k_cacheid, sizeof dek->s2k_cacheid);
|
||||||
xfree(last_pw);
|
xfree(last_pw);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user