diff options
author | David Shaw <[email protected]> | 2003-10-26 03:26:14 +0000 |
---|---|---|
committer | David Shaw <[email protected]> | 2003-10-26 03:26:14 +0000 |
commit | bb7986e9a6a43a8732797ecf72f6759b1c4feaa4 (patch) | |
tree | cc638268722b231d80fa97b9d22e87778b01e5dd /g10/mainproc.c | |
parent | Updated to 0.12.1 (diff) | |
download | gnupg-bb7986e9a6a43a8732797ecf72f6759b1c4feaa4.tar.gz gnupg-bb7986e9a6a43a8732797ecf72f6759b1c4feaa4.zip |
* g10.c (main): Add --symmetric --encrypt command. This generates a
message that can be decrypted via a passphrase or public key system.
* main.h, encode.c (encode_seskey): Allow passing in an already-created
session key dek. (encode_simple): Use the actual symmetric cipher when
encrypting a session key for a symmetric message. (encode_crypt): Add a
flag to trigger a hybrid mode that can be decrypted via a passphrase or a
pk. Change all callers.
* mainproc.c (symkey_decrypt_sesskey): There is no way to tell the
difference here between a bad passphrase and a cipher algorithm that we
don't have, so use a error message that makes that clear. Use the actual
list of ciphers when checking whether a cipher is invalid. Return error
if the decrypted cipher algorithm is invalid. (proc_symkey_enc): In a
mixed passphrase/pk message, if a valid dek already exists from decrypting
via pk, do not try to process the passphrase. (proc_symkey_enc): Indicate
when we're decrypting a session key as opposed to decrypting data. If a
passphrase is invalid, discard the dek so we'll keep trying.
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r-- | g10/mainproc.c | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c index e6522f1ed..aefaad6c3 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1,5 +1,6 @@ /* mainproc.c - handle packets - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -238,8 +239,8 @@ add_signature( CTX c, PACKET *pkt ) return 1; } -static void -symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) +static int +symkey_decrypt_seskey( DEK *dek, byte *seskey, size_t slen ) { CIPHER_HANDLE hd; int n; @@ -247,28 +248,35 @@ symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) if ( slen < 17 || slen > 33 ) { log_error ( _("weird size for an encrypted session key (%d)\n"), (int)slen); - return; + return G10ERR_BAD_KEY; } hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); cipher_setkey( hd, dek->key, dek->keylen ); cipher_setiv( hd, NULL, 0 ); - cipher_decrypt( hd, sesskey, sesskey, slen ); + cipher_decrypt( hd, seskey, seskey, slen ); cipher_close( hd ); /* check first byte (the cipher algo) */ - if ( sesskey[0] > 10 ) { - log_error ( _("invalid symkey algorithm detected (%d)\n"), - sesskey[0] ); - return; - } - n = cipher_get_keylen (sesskey[0]) / 8; + if(check_cipher_algo(seskey[0])) + { + /* There is no way to tell the difference here between a bad + passphrase and a cipher algorithm that we don't have. */ + log_error(_("bad passphrase or unknown cipher algorithm (%d)\n"), + seskey[0]); + if(seskey[0]==CIPHER_ALGO_IDEA) + idea_cipher_warn(0); + return G10ERR_PASSPHRASE; + } + n = cipher_get_keylen (seskey[0]) / 8; if (n > DIM(dek->key)) BUG (); /* now we replace the dek components with the real session key to decrypt the contents of the sequencing packet. */ - dek->keylen = cipher_get_keylen( sesskey[0] ) / 8; - dek->algo = sesskey[0]; - memcpy( dek->key, sesskey + 1, dek->keylen ); + dek->keylen = cipher_get_keylen( seskey[0] ) / 8; + dek->algo = seskey[0]; + memcpy( dek->key, seskey + 1, dek->keylen ); /*log_hexdump( "thekey", dek->key, dek->keylen );*/ + + return 0; } static void @@ -279,26 +287,47 @@ proc_symkey_enc( CTX c, PACKET *pkt ) enc = pkt->pkt.symkey_enc; if (!enc) log_error ("invalid symkey encrypted packet\n"); - else { + else if(!c->dek) + { int algo = enc->cipher_algo; - const char *s; + const char *s = cipher_algo_to_string (algo); - s = cipher_algo_to_string (algo); if( s ) - log_info(_("%s encrypted data\n"), s ); + { + if(enc->seskeylen) + log_info(_("%s encrypted session key\n"), s ); + else + log_info(_("%s encrypted data\n"), s ); + } else - log_info(_("encrypted with unknown algorithm %d\n"), algo ); + log_info(_("encrypted with unknown algorithm %d\n"), algo ); c->last_was_session_key = 2; if ( opt.list_only ) goto leave; c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL, NULL ); - if (c->dek) - c->dek->algo_info_printed = 1; - if ( c->dek && enc->seskeylen ) - symkey_decrypt_sesskey( c->dek, enc->seskey, enc->seskeylen ); - } -leave: + if(c->dek) + { + /* FIXME: This doesn't work perfectly if a symmetric key + comes before a public key in the message - if the user + doesn't know the passphrase, then there is a chance + that the "decrypted" algorithm will happen to be a + valid one, which will make the returned dek appear + valid, so we won't try any public keys that come + later. */ + if(enc->seskeylen) + { + if(symkey_decrypt_seskey(c->dek, enc->seskey, enc->seskeylen)) + { + m_free(c->dek); + c->dek=NULL; + } + } + else + c->dek->algo_info_printed = 1; + } + } + leave: free_packet(pkt); } |