mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
b4d9f8dbc8
* g10/keygen.c (keygen_set_std_prefs): Include IDEA only in PGP2 compatibility mode. * g10/misc.c (idea_cipher_warn): Remove. Also remove all callers. * common/status.h (STATUS_RSA_OR_IDEA): Remove. Do not emit this status anymore. -- To keep the number of actually used algorithms low, we want to support IDEA only in a basically read-only way (unless --pgp2 is used during key generation). It does not make sense to suggest the use of this old 64 bit blocksize algorithm. However, there is old data available where it might be helpful to have IDEA available.
257 lines
8.5 KiB
C
257 lines
8.5 KiB
C
/* seckey-cert.c - Not anymore used
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
|
|
* 2006, 2009 Free Software Foundation, Inc.
|
|
*
|
|
* This file is part of GnuPG.
|
|
*
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GnuPG 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#error Not anymore used - only kept for reference in the repository.
|
|
|
|
#include <config.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "gpg.h"
|
|
#include "util.h"
|
|
#include "packet.h"
|
|
#include "keydb.h"
|
|
#include "cipher.h"
|
|
#include "main.h"
|
|
#include "options.h"
|
|
#include "i18n.h"
|
|
#include "status.h"
|
|
#include "pkglue.h"
|
|
|
|
static int
|
|
xxxx_do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
|
|
int *canceled )
|
|
{
|
|
gpg_error_t err;
|
|
byte *buffer;
|
|
u16 csum=0;
|
|
int i, res;
|
|
size_t nbytes;
|
|
|
|
if( sk->is_protected ) { /* remove the protection */
|
|
DEK *dek = NULL;
|
|
u32 keyid[4]; /* 4! because we need two of them */
|
|
gcry_cipher_hd_t cipher_hd=NULL;
|
|
PKT_secret_key *save_sk;
|
|
|
|
if( sk->protect.s2k.mode == 1001 ) {
|
|
log_info(_("secret key parts are not available\n"));
|
|
return G10ERR_UNU_SECKEY;
|
|
}
|
|
if( sk->protect.algo == CIPHER_ALGO_NONE )
|
|
BUG();
|
|
if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
|
|
log_info(_("protection algorithm %d%s is not supported\n"),
|
|
sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" );
|
|
return G10ERR_CIPHER_ALGO;
|
|
}
|
|
if(gcry_md_test_algo (sk->protect.s2k.hash_algo))
|
|
{
|
|
log_info(_("protection digest %d is not supported\n"),
|
|
sk->protect.s2k.hash_algo);
|
|
return G10ERR_DIGEST_ALGO;
|
|
}
|
|
keyid_from_sk( sk, keyid );
|
|
keyid[2] = keyid[3] = 0;
|
|
if (!sk->flags.primary)
|
|
{
|
|
keyid[2] = sk->main_keyid[0];
|
|
keyid[3] = sk->main_keyid[1];
|
|
}
|
|
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
|
|
&sk->protect.s2k, mode,
|
|
tryagain_text, canceled );
|
|
if (!dek && canceled && *canceled)
|
|
return GPG_ERR_CANCELED;
|
|
|
|
|
|
err = openpgp_cipher_open (&cipher_hd, sk->protect.algo,
|
|
GCRY_CIPHER_MODE_CFB,
|
|
(GCRY_CIPHER_SECURE
|
|
| (sk->protect.algo >= 100 ?
|
|
0 : GCRY_CIPHER_ENABLE_SYNC)));
|
|
if (err)
|
|
log_fatal ("cipher open failed: %s\n", gpg_strerror (err) );
|
|
|
|
err = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen);
|
|
if (err)
|
|
log_fatal ("set key failed: %s\n", gpg_strerror (err) );
|
|
|
|
xfree(dek);
|
|
save_sk = copy_secret_key( NULL, sk );
|
|
|
|
gcry_cipher_setiv ( cipher_hd, sk->protect.iv, sk->protect.ivlen );
|
|
|
|
csum = 0;
|
|
if( sk->version >= 4 ) {
|
|
int ndata;
|
|
unsigned int ndatabits;
|
|
byte *p, *data;
|
|
u16 csumc = 0;
|
|
|
|
i = pubkey_get_npkey(sk->pubkey_algo);
|
|
|
|
assert ( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE ));
|
|
p = gcry_mpi_get_opaque ( sk->skey[i], &ndatabits );
|
|
ndata = (ndatabits+7)/8;
|
|
|
|
if ( ndata > 1 )
|
|
csumc = p[ndata-2] << 8 | p[ndata-1];
|
|
data = xmalloc_secure ( ndata );
|
|
gcry_cipher_decrypt ( cipher_hd, data, ndata, p, ndata );
|
|
gcry_mpi_release (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 {
|
|
gcry_md_hd_t h;
|
|
|
|
if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1))
|
|
BUG(); /* Algo not available. */
|
|
gcry_md_write (h, data, ndata - 20);
|
|
gcry_md_final (h);
|
|
if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1),
|
|
data + ndata - 20, 20) )
|
|
{
|
|
/* Digest does match. We have to keep the old
|
|
style checksum in sk->csum, so that the
|
|
test used for unprotected keys does work.
|
|
This test gets used when we are adding new
|
|
keys. */
|
|
sk->csum = csum = checksum (data, ndata-20);
|
|
}
|
|
gcry_md_close (h);
|
|
}
|
|
}
|
|
else {
|
|
if( ndata < 2 ) {
|
|
log_error("not enough bytes for checksum\n");
|
|
sk->csum = 0;
|
|
csum = 1;
|
|
}
|
|
else {
|
|
csum = checksum( data, ndata-2);
|
|
sk->csum = data[ndata-2] << 8 | data[ndata-1];
|
|
if ( sk->csum != csum ) {
|
|
/* This is a PGP 7.0.0 workaround */
|
|
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 */
|
|
if( sk->csum == csum ) {
|
|
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
|
if ( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
|
|
p, ndata, &nbytes))
|
|
{
|
|
/* Checksum was okay, but not correctly
|
|
decrypted. */
|
|
sk->csum = 0;
|
|
csum = 1;
|
|
break;
|
|
}
|
|
ndata -= nbytes;
|
|
p += nbytes;
|
|
}
|
|
/* Note: at this point ndata should be 2 for a simple
|
|
checksum or 20 for the sha1 digest */
|
|
}
|
|
xfree(data);
|
|
}
|
|
else {
|
|
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
|
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
|
byte *p;
|
|
size_t ndata;
|
|
unsigned int ndatabits;
|
|
|
|
assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
|
|
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
|
|
ndata = (ndatabits+7)/8;
|
|
assert (ndata >= 2);
|
|
assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2);
|
|
buffer = xmalloc_secure (ndata);
|
|
gcry_cipher_sync (cipher_hd);
|
|
buffer[0] = p[0];
|
|
buffer[1] = p[1];
|
|
gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2,
|
|
p+2, ndata-2);
|
|
csum += checksum (buffer, ndata);
|
|
gcry_mpi_release (sk->skey[i]);
|
|
|
|
err = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
|
|
buffer, ndata, &ndata );
|
|
xfree (buffer);
|
|
if (err)
|
|
{
|
|
/* Checksum was okay, but not correctly
|
|
decrypted. */
|
|
sk->csum = 0;
|
|
csum = 1;
|
|
break;
|
|
}
|
|
/* csum += checksum_mpi (sk->skey[i]); */
|
|
}
|
|
}
|
|
gcry_cipher_close ( cipher_hd );
|
|
|
|
/* Now let's see whether we have used the correct passphrase. */
|
|
if( csum != sk->csum ) {
|
|
copy_secret_key( sk, save_sk );
|
|
passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
|
|
free_secret_key( save_sk );
|
|
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
|
|
}
|
|
|
|
/* The checksum may fail, so we also check the key itself. */
|
|
res = pk_check_secret_key ( sk->pubkey_algo, sk->skey );
|
|
if( res ) {
|
|
copy_secret_key( sk, save_sk );
|
|
passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
|
|
free_secret_key( save_sk );
|
|
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
|
|
}
|
|
free_secret_key( save_sk );
|
|
sk->is_protected = 0;
|
|
}
|
|
else { /* not protected, assume it is okay if the checksum is okay */
|
|
csum = 0;
|
|
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
|
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
|
csum += checksum_mpi( sk->skey[i] );
|
|
}
|
|
if( csum != sk->csum )
|
|
return G10ERR_CHECKSUM;
|
|
}
|
|
|
|
return 0;
|
|
}
|