mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-23 10:29:58 +01:00
* parse-packet.c (parse_key): Support a SHA1 checksum as per
draft-rfc2440-bis04. * packet.h (PKT_secret_key): Add field sha1chk. * seckey-cert.c (do_check): Check the SHA1 checksum (protect_secret_key): And create it. * build-packet.c (do_secret_key): Mark it as sha-1 protected. * g10.c, options.h: New option --simple-sk-checksum.
This commit is contained in:
parent
e906ef5f5b
commit
60e0b2ad92
15
doc/gpg.sgml
15
doc/gpg.sgml
@ -581,6 +581,9 @@ The second form of the command has the special property to
|
||||
render the secret part of the primary key useless; this is
|
||||
a GNU extension to OpenPGP and other implementations can
|
||||
not be expected to successfully import such a key.
|
||||
|
||||
See the option --simple-sk-checksum if you want to import such an
|
||||
exported key with an older OpenPGP implementation.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
|
||||
@ -1324,6 +1327,18 @@ for conventional encryption.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>--simple-sk-checksum</term>
|
||||
<listitem><para>
|
||||
Secret keys are integrity protected by using a SHA-1 checksum. This
|
||||
method will be part of an enhanced OpenPGP specification but GnuPG
|
||||
already uses it as a countermeasure against certain attacks. Old
|
||||
applications don't understand this new format, so this option may be
|
||||
used to switch back to the old behaviour. Using this this option
|
||||
bears a security risk.
|
||||
</para></listitem></varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term>--compress-algo &ParmN;</term>
|
||||
<listitem><para>
|
||||
|
@ -1,3 +1,16 @@
|
||||
2002-04-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
|
||||
2002-04-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* parse-packet.c (parse_key): Support a SHA1 checksum as per
|
||||
draft-rfc2440-bis04.
|
||||
* packet.h (PKT_secret_key): Add field sha1chk.
|
||||
* seckey-cert.c (do_check): Check the SHA1 checksum
|
||||
(protect_secret_key): And create it.
|
||||
* build-packet.c (do_secret_key): Mark it as sha-1 protected.
|
||||
* g10.c, options.h: New option --simple-sk-checksum.
|
||||
|
||||
2002-04-13 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* parse-packet.c (parse_signature): Minor fix - signatures should
|
||||
|
@ -389,7 +389,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
|
||||
}
|
||||
else {
|
||||
/* OpenPGP protection according to rfc2440 */
|
||||
iobuf_put(a, 0xff );
|
||||
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
|
||||
iobuf_put(a, sk->protect.algo );
|
||||
if( sk->protect.s2k.mode >= 1000 ) {
|
||||
/* These modes are not possible in OpenPGP, we use them
|
||||
|
@ -218,6 +218,7 @@ enum cmd_and_opt_values { aNull = 0,
|
||||
oS2KMode,
|
||||
oS2KDigest,
|
||||
oS2KCipher,
|
||||
oSimpleSKChecksum,
|
||||
oCharset,
|
||||
oNotDashEscaped,
|
||||
oEscapeFrom,
|
||||
@ -412,6 +413,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
N_("|NAME|use message digest algorithm NAME for passphrases")},
|
||||
{ oS2KCipher, "s2k-cipher-algo",2,
|
||||
N_("|NAME|use cipher algorithm NAME for passphrases")},
|
||||
{ oSimpleSKChecksum, "simple-sk-checksum", 0, "@"},
|
||||
{ oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
|
||||
{ oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
|
||||
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
|
||||
@ -1132,7 +1134,7 @@ main( int argc, char **argv )
|
||||
case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break;
|
||||
case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break;
|
||||
case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break;
|
||||
|
||||
case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break;
|
||||
case oNoEncryptTo: opt.no_encrypt_to = 1; break;
|
||||
case oEncryptTo: /* store the recipient in the second list */
|
||||
sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
|
||||
|
@ -94,6 +94,8 @@ struct {
|
||||
int s2k_mode;
|
||||
int s2k_digest_algo;
|
||||
int s2k_cipher_algo;
|
||||
int simple_sk_checksum; /* create the deprecated rfc2440 secret
|
||||
key protection*/
|
||||
int not_dash_escaped;
|
||||
int escape_from;
|
||||
int lock_once;
|
||||
|
@ -232,6 +232,7 @@ typedef struct {
|
||||
/* and should never be passed to a mpi_xxx() */
|
||||
struct {
|
||||
byte algo; /* cipher used to protect the secret information*/
|
||||
byte sha1chk; /* SHA1 is used instead of a 16 bit checksum */
|
||||
STRING2KEY s2k;
|
||||
byte ivlen; /* used length of the iv */
|
||||
byte iv[16]; /* initialization vector for CFB mode */
|
||||
|
@ -1494,14 +1494,16 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
if (rc) /* one of the MPIs were bad */
|
||||
goto leave;
|
||||
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
|
||||
sk->protect.sha1chk = 0;
|
||||
if( sk->protect.algo ) {
|
||||
sk->is_protected = 1;
|
||||
sk->protect.s2k.count = 0;
|
||||
if( sk->protect.algo == 255 ) {
|
||||
if( sk->protect.algo == 254 || sk->protect.algo == 255 ) {
|
||||
if( pktlen < 3 ) {
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
goto leave;
|
||||
}
|
||||
sk->protect.sha1chk = (sk->protect.algo == 254);
|
||||
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
|
||||
sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
|
||||
sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
|
||||
@ -1550,8 +1552,10 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
|
||||
if( list_mode ) {
|
||||
printf(", algo: %d, hash: %d",
|
||||
printf(", algo: %d,%s hash: %d",
|
||||
sk->protect.algo,
|
||||
sk->protect.sha1chk? ""
|
||||
:" simple checksum,",
|
||||
sk->protect.s2k.hash_algo );
|
||||
if( sk->protect.s2k.mode == 1
|
||||
|| sk->protect.s2k.mode == 3 ) {
|
||||
|
@ -90,6 +90,27 @@ do_check( PKT_secret_key *sk, const char *tryagain_text )
|
||||
cipher_decrypt( cipher_hd, data, p, ndata );
|
||||
mpi_free( sk->skey[i] ); sk->skey[i] = NULL ;
|
||||
p = data;
|
||||
if (sk->protect.sha1chk) {
|
||||
/* This is the new SHA1 checksum method to detect
|
||||
tampering with the key as used by the Klima/Rosa
|
||||
attack */
|
||||
sk->csum = 0;
|
||||
csum = 1;
|
||||
if( ndata < 20 )
|
||||
log_error("not enough bytes for SHA-1 checksum\n");
|
||||
else {
|
||||
MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1);
|
||||
if (!h)
|
||||
BUG(); /* algo not available */
|
||||
md_write (h, data, ndata - 20);
|
||||
md_final (h);
|
||||
if (!memcmp (md_read (h, DIGEST_ALGO_SHA1),
|
||||
data + ndata - 20, 20) )
|
||||
csum = 0; /* digest does match */
|
||||
md_close (h);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( ndata < 2 ) {
|
||||
log_error("not enough bytes for checksum\n");
|
||||
sk->csum = 0;
|
||||
@ -103,9 +124,10 @@ do_check( PKT_secret_key *sk, const char *tryagain_text )
|
||||
sk->csum = csumc; /* take the encrypted one */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* must check it here otherwise the mpi_read_xx would fail
|
||||
* because the length may have an arbitrary value */
|
||||
because the length may have an arbitrary value */
|
||||
if( sk->csum == csum ) {
|
||||
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
nbytes = ndata;
|
||||
@ -113,7 +135,8 @@ do_check( PKT_secret_key *sk, const char *tryagain_text )
|
||||
ndata -= nbytes;
|
||||
p += nbytes;
|
||||
}
|
||||
/* at this point ndata should be equal to 2 (the checksum) */
|
||||
/* Note: at this point ndata should be 2 for a simple
|
||||
checksum or 20 for the sha1 digest */
|
||||
}
|
||||
m_free(data);
|
||||
}
|
||||
@ -265,7 +288,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
||||
}
|
||||
for( ; j < PUBKEY_MAX_NSKEY; j++ )
|
||||
bufarr[j] = NULL;
|
||||
ndata += 2; /* for checksum */
|
||||
ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
|
||||
|
||||
data = m_alloc_secure( ndata );
|
||||
p = data;
|
||||
@ -277,11 +300,30 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
||||
p += narr[j];
|
||||
m_free(bufarr[j]);
|
||||
}
|
||||
|
||||
if (opt.simple_sk_checksum) {
|
||||
log_info (_("generating the deprecated 16-bit checksum"
|
||||
" for secret key protection\n"));
|
||||
csum = checksum( data, ndata-2);
|
||||
sk->csum = csum;
|
||||
*p++ = csum >> 8;
|
||||
*p++ = csum;
|
||||
sk->protect.sha1chk = 0;
|
||||
}
|
||||
else {
|
||||
MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1);
|
||||
if (!h)
|
||||
BUG(); /* algo not available */
|
||||
md_write (h, data, ndata - 20);
|
||||
md_final (h);
|
||||
memcpy (p, md_read (h, DIGEST_ALGO_SHA1), 20);
|
||||
p += 20;
|
||||
md_close (h);
|
||||
sk->csum = csum = 0;
|
||||
sk->protect.sha1chk = 1;
|
||||
}
|
||||
assert( p == data+ndata );
|
||||
|
||||
cipher_encrypt( cipher_hd, data, data, ndata );
|
||||
for(i = pubkey_get_npkey(sk->pubkey_algo);
|
||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user