1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Merged with gpg 1.4.3 code.

The gpg part does not yet build.
This commit is contained in:
Werner Koch 2006-04-19 11:26:11 +00:00
parent 751a3aeea7
commit 29b23dea97
90 changed files with 18002 additions and 10564 deletions

View file

@ -1,6 +1,6 @@
/* pubkey-enc.c - public key encoded packet handling
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003 Free Software Foundation, Inc.
* 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -16,7 +16,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#include <config.h>
@ -27,9 +28,7 @@
#include "gpg.h"
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "mpi.h"
#include "keydb.h"
#include "trustdb.h"
#include "cipher.h"
@ -38,7 +37,7 @@
#include "main.h"
#include "i18n.h"
#include "pkglue.h"
#include "call-agent.h"
static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid );
@ -77,12 +76,12 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
PKT_secret_key *sk = NULL;
int rc;
rc = openpgp_pk_test_algo (k->pubkey_algo, PUBKEY_USAGE_ENC);
rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
if( rc )
goto leave;
if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
sk = xcalloc (1, sizeof *sk );
sk = xmalloc_clear( sizeof *sk );
sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
if( !(rc = get_seckey( sk, k->keyid )) )
rc = get_it( k, dek, sk, k->keyid );
@ -95,34 +94,49 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
for(;;) {
if( sk )
free_secret_key( sk );
sk = xcalloc (1, sizeof *sk );
sk = xmalloc_clear( sizeof *sk );
rc=enum_secret_keys( &enum_context, sk, 1, 0);
if( rc ) {
rc = GPG_ERR_NO_SECKEY;
rc = G10ERR_NO_SECKEY;
break;
}
if( sk->pubkey_algo != k->pubkey_algo )
continue;
keyid_from_sk( sk, keyid );
log_info(_("anonymous recipient; trying secret key %08lX ...\n"),
(ulong)keyid[1] );
log_info(_("anonymous recipient; trying secret key %s ...\n"),
keystr(keyid));
if(!opt.try_all_secrets && !is_status_enabled())
{
p=get_last_passphrase();
set_next_passphrase(p);
xfree (p);
xfree(p);
}
rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask
only
once */
if( !rc )
{
rc = get_it( k, dek, sk, keyid );
if( !rc ) {
/* Successfully checked the secret key (either it was
a card, had no passphrase, or had the right
passphrase) but couldn't decrypt the session key,
so thus that key is not the anonymous recipient.
Move the next passphrase into last for the next
round. We only do this if the secret key was
successfully checked as in the normal case,
check_secret_key handles this for us via
passphrase_to_dek */
if(rc)
next_to_last_passphrase();
}
if( !rc )
{
log_info(_("okay, we are the anonymous recipient.\n") );
break;
}
}
}
enum_secret_keys( &enum_context, NULL, 0, 0 ); /* free context */
}
@ -138,15 +152,17 @@ static int
get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
int rc;
gcry_mpi_t plain_dek = NULL;
gcry_mpi_t plain_dek = NULL;
byte *frame = NULL;
unsigned n, nframe;
u16 csum, csum2;
int card = 0;
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{ /* FIXME: Note that we do only support RSA for now. */
char *rbuf;
{ /* Note, that we only support RSA for now. */
#ifdef ENABLE_CARD_SUPPORT
unsigned char *rbuf;
size_t rbuflen;
char *snbuf;
unsigned char *indata = NULL;
@ -154,9 +170,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen,
enc->data[0]))
BUG();
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, enc->data[0]))
BUG ();
rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
xfree (snbuf);
@ -167,148 +182,145 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
frame = rbuf;
nframe = rbuflen;
card = 1;
#else
rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
#endif /*!ENABLE_CARD_SUPPORT*/
}
else
{
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey);
rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
if( rc )
goto leave;
goto leave;
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek))
BUG();
gcry_mpi_release (plain_dek); plain_dek = NULL;
}
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
*
* Later versions encode the DEK like this:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (mpi_get_buffer already removed the leading zero).
*
* RND are non-zero randow bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( DBG_CIPHER )
log_printhex ("DEK frame:", frame, nframe );
n=0;
if (!card)
{
if( n + 7 > nframe )
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
log_info(_("old encoding of the DEK is not supported\n"));
rc = GPG_ERR_CIPHER_ALGO;
goto leave;
}
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
}
if( n + 4 > nframe )
{ rc = GPG_ERR_WRONG_SECKEY; goto leave; }
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == CIPHER_ALGO_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo (dek->algo);
if( rc ) {
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) {
log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
if(dek->algo==CIPHER_ALGO_IDEA)
idea_cipher_warn(0);
}
dek->algo = 0;
goto leave;
}
if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
rc = GPG_ERR_WRONG_SECKEY;
goto leave;
}
/* copy the key to DEK and compare the checksum */
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
rc = GPG_ERR_WRONG_SECKEY;
goto leave;
}
if( DBG_CIPHER )
log_printhex ("DEK is:", dek->key, dek->keylen );
/* check that the algo is in the preferences and whether it has expired */
{
PKT_public_key *pk = NULL;
KBNODE pkb = get_pubkeyblock (keyid);
if( !pkb ) {
rc = -1;
log_error("oops: public key not found for preference check\n");
}
else if( pkb->pkt->pkt.public_key->selfsigversion > 3
&& dek->algo != CIPHER_ALGO_3DES
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
/* Don't print a note while we are not on verbose mode,
* the cipher is blowfish and the preferences have twofish
* listed */
if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
|| !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
log_info(_(
"NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo );
}
if (!rc) {
KBNODE k;
for (k=pkb; k; k = k->next) {
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
u32 aki[2];
keyid_from_pk(k->pkt->pkt.public_key, aki);
if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
pk = k->pkt->pkt.public_key;
break;
}
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
*
* Later versions encode the DEK like this:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (mpi_get_buffer already removed the leading zero).
*
* RND are non-zero randow bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
if (!card)
{
if( n + 7 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
log_info(_("old encoding of the DEK is not supported\n"));
rc = G10ERR_CIPHER_ALGO;
goto leave;
}
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
}
if (!pk)
BUG ();
if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
log_info(_("NOTE: secret key %08lX expired at %s\n"),
(ulong)keyid[1], asctimestamp( pk->expiredate) );
}
if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == CIPHER_ALGO_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_cipher_test_algo (dek->algo);
if( rc ) {
if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) {
log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
if(dek->algo==CIPHER_ALGO_IDEA)
idea_cipher_warn(0);
}
dek->algo = 0;
goto leave;
}
if ( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
rc = GPG_ERR_WRONG_SECKEY;
goto leave;
}
if ( pk && pk->is_revoked ) {
log_info( _("NOTE: key has been revoked") );
putc( '\n', log_get_stream() );
show_revocation_reason( pk, 1 );
/* copy the key to DEK and compare the checksum */
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
rc = G10ERR_WRONG_SECKEY;
goto leave;
}
if( DBG_CIPHER )
log_hexdump("DEK is:", dek->key, dek->keylen );
/* check that the algo is in the preferences and whether it has expired */
{
PKT_public_key *pk = NULL;
KBNODE pkb = get_pubkeyblock (keyid);
if( !pkb ) {
rc = -1;
log_error("oops: public key not found for preference check\n");
}
else if(pkb->pkt->pkt.public_key->selfsigversion > 3
&& dek->algo != CIPHER_ALGO_3DES
&& !opt.quiet
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
log_info (_("WARNING: cipher algorithm %s not found in recipient"
" preferences\n"), gcry_cipher_algo_name (dek->algo));
if (!rc) {
KBNODE k;
for (k=pkb; k; k = k->next) {
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
u32 aki[2];
keyid_from_pk(k->pkt->pkt.public_key, aki);
if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
pk = k->pkt->pkt.public_key;
break;
}
}
}
if (!pk)
BUG ();
if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
log_info(_("NOTE: secret key %s expired at %s\n"),
keystr(keyid), asctimestamp( pk->expiredate) );
}
}
if ( pk && pk->is_revoked ) {
log_info( _("NOTE: key has been revoked") );
putc( '\n', log_get_stream() );
show_revocation_reason( pk, 1 );
}
release_kbnode (pkb);
rc = 0;
}
release_kbnode (pkb);
rc = 0;
}
leave:
gcry_mpi_release (plain_dek);
xfree (frame);
return rc;
leave:
gcry_mpi_release (plain_dek);
xfree (frame);
return rc;
}
@ -324,21 +336,21 @@ get_override_session_key( DEK *dek, const char *string )
int i;
if ( !string )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->algo = atoi(string);
if ( dek->algo < 1 )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
if ( !(s = strchr ( string, ':' )) )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
s++;
for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) {
int c = hextobyte ( s );
if (c == -1)
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->key[i] = c;
}
if ( *s )
return GPG_ERR_BAD_KEY;
return G10ERR_BAD_KEY;
dek->keylen = i;
return 0;
}