diff options
author | Werner Koch <[email protected]> | 2006-04-19 11:26:11 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2006-04-19 11:26:11 +0000 |
commit | 29b23dea9731e8f258211bc6fd733d205c18e2a8 (patch) | |
tree | ff2a0f66bda0c1f050e8fa00cbf610e18b91c9f7 /g10/pubkey-enc.c | |
parent | 2006-04-14 Marcus Brinkmann <[email protected]> (diff) | |
download | gnupg-29b23dea9731e8f258211bc6fd733d205c18e2a8.tar.gz gnupg-29b23dea9731e8f258211bc6fd733d205c18e2a8.zip |
Merged with gpg 1.4.3 code.
The gpg part does not yet build.
Diffstat (limited to 'g10/pubkey-enc.c')
-rw-r--r-- | g10/pubkey-enc.c | 304 |
1 files changed, 158 insertions, 146 deletions
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 4b45b9f5c..5af0d5f1d 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -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; + /* 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( 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); + 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; } - 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"); + if ( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { + rc = GPG_ERR_WRONG_SECKEY; + goto leave; } - 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 ); + + /* 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 (!rc) { - KBNODE k; + 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; - } + 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) - 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 ( pk && pk->is_revoked ) { - log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_get_stream() ); - show_revocation_reason( pk, 1 ); - } + 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; } |