mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Fixed regression in OpenPGP secret key export.
The protection used in the exported key used a different iteration count than given in the S2K field. Thus all OpenPGP keys exported from GnuPG 2.1-beta can't be imported again. Given that the actual secret key material is kept in private-keys-v1.d/ the can be re-exported with this fixed version.
This commit is contained in:
parent
5da12674ea
commit
817f07173c
2
NEWS
2
NEWS
@ -1,6 +1,8 @@
|
|||||||
Noteworthy changes in version 2.1.0beta3
|
Noteworthy changes in version 2.1.0beta3
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
* Fixed regression in GPG'S secret key export function.
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.1.0beta2 (2011-03-08)
|
Noteworthy changes in version 2.1.0beta2 (2011-03-08)
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2011-04-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* cvt-openpgp.c (convert_to_openpgp): Use rfc4880 encoded S2K count.
|
||||||
|
* protect.c (get_standard_s2k_count_rfc4880): New.
|
||||||
|
(S2K_DECODE_COUNT): New.
|
||||||
|
(s2k_hash_passphrase): Use the new macro.
|
||||||
|
|
||||||
2011-04-21 Werner Koch <wk@g10code.com>
|
2011-04-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* agent.h (server_control_s): Add field cache_ttl_opt_preset.
|
* agent.h (server_control_s): Add field cache_ttl_opt_preset.
|
||||||
|
@ -330,6 +330,7 @@ gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey,
|
|||||||
|
|
||||||
/*-- protect.c --*/
|
/*-- protect.c --*/
|
||||||
unsigned long get_standard_s2k_count (void);
|
unsigned long get_standard_s2k_count (void);
|
||||||
|
unsigned char get_standard_s2k_count_rfc4880 (void);
|
||||||
int agent_protect (const unsigned char *plainkey, const char *passphrase,
|
int agent_protect (const unsigned char *plainkey, const char *passphrase,
|
||||||
unsigned char **result, size_t *resultlen);
|
unsigned char **result, size_t *resultlen);
|
||||||
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
|
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
|
||||||
|
@ -1046,7 +1046,10 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
|
|||||||
|
|
||||||
gcry_create_nonce (protect_iv, sizeof protect_iv);
|
gcry_create_nonce (protect_iv, sizeof protect_iv);
|
||||||
gcry_create_nonce (salt, sizeof salt);
|
gcry_create_nonce (salt, sizeof salt);
|
||||||
s2k_count = get_standard_s2k_count ();
|
/* We need to use the encoded S2k count. It is not possible to
|
||||||
|
encode it after it has been used because the encoding procedure
|
||||||
|
may round the value up. */
|
||||||
|
s2k_count = get_standard_s2k_count_rfc4880 ();
|
||||||
err = apply_protection (array, npkey, nskey, passphrase,
|
err = apply_protection (array, npkey, nskey, passphrase,
|
||||||
GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
|
GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
|
||||||
3, GCRY_MD_SHA1, salt, s2k_count);
|
3, GCRY_MD_SHA1, salt, s2k_count);
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
#define PROT_CIPHER_STRING "aes"
|
#define PROT_CIPHER_STRING "aes"
|
||||||
#define PROT_CIPHER_KEYLEN (128/8)
|
#define PROT_CIPHER_KEYLEN (128/8)
|
||||||
|
|
||||||
|
/* Decode an rfc4880 encoded S2K count. */
|
||||||
|
#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
|
||||||
|
|
||||||
|
|
||||||
/* A table containing the information needed to create a protected
|
/* A table containing the information needed to create a protected
|
||||||
private key. */
|
private key. */
|
||||||
@ -192,6 +195,33 @@ get_standard_s2k_count (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same as get_standard_s2k_count but return the count in the encoding
|
||||||
|
as described by rfc4880. */
|
||||||
|
unsigned char
|
||||||
|
get_standard_s2k_count_rfc4880 (void)
|
||||||
|
{
|
||||||
|
unsigned long iterations;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned char result;
|
||||||
|
unsigned char c=0;
|
||||||
|
|
||||||
|
iterations = get_standard_s2k_count ();
|
||||||
|
if (iterations >= 65011712)
|
||||||
|
return 255;
|
||||||
|
|
||||||
|
/* Need count to be in the range 16-31 */
|
||||||
|
for (count=iterations>>6; count>=32; count>>=1)
|
||||||
|
c++;
|
||||||
|
|
||||||
|
result = (c<<4)|(count-16);
|
||||||
|
|
||||||
|
if (S2K_DECODE_COUNT(result) < iterations)
|
||||||
|
result++;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Calculate the MIC for a private key or shared secret S-expression.
|
/* Calculate the MIC for a private key or shared secret S-expression.
|
||||||
@ -1041,7 +1071,7 @@ s2k_hash_passphrase (const char *passphrase, int hashalgo,
|
|||||||
unsigned char *key, size_t keylen)
|
unsigned char *key, size_t keylen)
|
||||||
{
|
{
|
||||||
return hash_passphrase (passphrase, hashalgo, s2kmode, s2ksalt,
|
return hash_passphrase (passphrase, hashalgo, s2kmode, s2ksalt,
|
||||||
(16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6),
|
S2K_DECODE_COUNT (s2kcount),
|
||||||
key, keylen);
|
key, keylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2011-04-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* export.c (transfer_format_to_openpgp): Do not apply
|
||||||
|
encode_s2k_iterations to S2K_COUNT.
|
||||||
|
|
||||||
2011-04-25 Werner Koch <wk@g10code.com>
|
2011-04-25 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* delkey.c (do_delete_key): Mark classify_user_id for use with
|
* delkey.c (do_delete_key): Mark classify_user_id for use with
|
||||||
|
@ -626,10 +626,9 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do some sanity checks. */
|
/* Do some sanity checks. */
|
||||||
if (s2k_count <= 1024)
|
if (s2k_count > 255)
|
||||||
{
|
{
|
||||||
/* The count must be larger so that encode_s2k_iterations does
|
/* We expect an already encoded S2K count. */
|
||||||
not fall into a backward compatibility mode. */
|
|
||||||
err = gpg_error (GPG_ERR_INV_DATA);
|
err = gpg_error (GPG_ERR_INV_DATA);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -682,7 +681,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
|
|||||||
ski->s2k.hash_algo = s2k_algo;
|
ski->s2k.hash_algo = s2k_algo;
|
||||||
assert (sizeof ski->s2k.salt == sizeof s2k_salt);
|
assert (sizeof ski->s2k.salt == sizeof s2k_salt);
|
||||||
memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
|
memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
|
||||||
ski->s2k.count = encode_s2k_iterations (s2k_count);
|
ski->s2k.count = s2k_count;
|
||||||
assert (ivlen <= sizeof ski->iv);
|
assert (ivlen <= sizeof ski->iv);
|
||||||
memcpy (ski->iv, iv, ivlen);
|
memcpy (ski->iv, iv, ivlen);
|
||||||
ski->ivlen = ivlen;
|
ski->ivlen = ivlen;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user