diff --git a/g10/build-packet.c b/g10/build-packet.c index fc64c9c9f..b4e03d007 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -617,11 +617,8 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) IOBUF a = iobuf_temp(); log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC); + log_assert (enc->version == 4 || enc->version == 5); - /* The only acceptable version. */ - log_assert( enc->version == 4 ); - - /* RFC 4880, Section 3.7. */ switch (enc->s2k.mode) { case 0: /* Simple S2K. */ @@ -632,23 +629,26 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) default: log_bug ("do_symkey_enc: s2k=%d\n", enc->s2k.mode); } - iobuf_put( a, enc->version ); - iobuf_put( a, enc->cipher_algo ); - iobuf_put( a, enc->s2k.mode ); - iobuf_put( a, enc->s2k.hash_algo ); - if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { - iobuf_write(a, enc->s2k.salt, 8 ); - if( enc->s2k.mode == 3 ) - iobuf_put(a, enc->s2k.count); + iobuf_put (a, enc->version); + iobuf_put (a, enc->cipher_algo); + if (enc->version == 5) + iobuf_put (a, enc->aead_algo); + iobuf_put (a, enc->s2k.mode); + iobuf_put (a, enc->s2k.hash_algo); + if (enc->s2k.mode == 1 || enc->s2k.mode == 3) + { + iobuf_write (a, enc->s2k.salt, 8); + if (enc->s2k.mode == 3) + iobuf_put (a, enc->s2k.count); } - if( enc->seskeylen ) - iobuf_write(a, enc->seskey, enc->seskeylen ); + if (enc->seskeylen) + iobuf_write (a, enc->seskey, enc->seskeylen); - write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp( out, a ); + write_header (out, ctb, iobuf_get_temp_length(a)); + rc = iobuf_write_temp (out, a); - iobuf_close(a); - return rc; + iobuf_close (a); + return rc; } diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c index 7ed0bf006..46650f269 100644 --- a/g10/decrypt-data.c +++ b/g10/decrypt-data.c @@ -212,8 +212,10 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) if ( opt.verbose && !dek->algo_info_printed ) { if (!openpgp_cipher_test_algo (dek->algo)) - log_info (_("%s encrypted data\n"), - openpgp_cipher_algo_name (dek->algo)); + log_info (_("%s.%s encrypted data\n"), + openpgp_cipher_algo_name (dek->algo), + ed->aead_algo? openpgp_aead_algo_name (ed->aead_algo) + /**/ : "CFB"); else log_info (_("encrypted with unknown algorithm %d\n"), dek->algo ); dek->algo_info_printed = 1; diff --git a/g10/encrypt.c b/g10/encrypt.c index 4cc4b1a29..c6c9e3a03 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -47,12 +47,12 @@ static int write_pubkey_enc_from_list (ctrl_t ctrl, /**************** * Encrypt FILENAME with only the symmetric cipher. Take input from - * stdin if FILENAME is NULL. + * stdin if FILENAME is NULL. If --force-aead is used we use an SKESK. */ int encrypt_symmetric (const char *filename) { - return encrypt_simple( filename, 1, 0 ); + return encrypt_simple( filename, 1, opt.force_aead); } @@ -70,14 +70,16 @@ encrypt_store (const char *filename) /* Encrypt a session key using DEK and store a pointer to the result * at R_ENCKEY and its length at R_ENCKEYLEN. * - * R_SESKEY points to the unencrypted session key (.KEY, >KEYLEN) and + * R_SESKEY points to the unencrypted session key (.KEY, .KEYLEN) and * the algorithm that will be used to encrypt the contents of the * SKESK packet (.ALGO). If R_SESKEY points to NULL, then a random * session key that is appropriate for DEK->ALGO is generated and - * stored at R_SESKEY. + * stored at R_SESKEY. If AEAD_ALGO is not 0 the given AEAD algorithm + * is used for encryption. */ gpg_error_t -encrypt_seskey (DEK *dek, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) +encrypt_seskey (DEK *dek, aead_algo_t aead_algo, + DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) { gpg_error_t err; gcry_cipher_hd_t hd = NULL; @@ -102,30 +104,84 @@ encrypt_seskey (DEK *dek, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) /*log_hexdump( "thekey", c->key, c->keylen );*/ } - buf = xtrymalloc_secure (1 + seskey->keylen); - if (!buf) + + if (aead_algo) { - err = gpg_error_from_syserror (); - goto leave; + unsigned int noncelen; + enum gcry_cipher_modes ciphermode; + byte ad[4]; + + err = openpgp_aead_algo_info (aead_algo, &ciphermode, &noncelen); + if (err) + goto leave; + + /* Allocate space for the nonce, the key, and the authentication + * tag (16). */ + buf = xtrymalloc_secure (noncelen + seskey->keylen + 16); + if (!buf) + { + err = gpg_error_from_syserror (); + goto leave; + } + + gcry_randomize (buf, noncelen, GCRY_STRONG_RANDOM); + + err = openpgp_cipher_open (&hd, dek->algo, + ciphermode, GCRY_CIPHER_SECURE); + if (!err) + err = gcry_cipher_setkey (hd, dek->key, dek->keylen); + if (!err) + err = gcry_cipher_setiv (hd, buf, noncelen); + if (err) + goto leave; + + ad[0] = (0xc0 | PKT_SYMKEY_ENC); + ad[1] = 5; + ad[2] = dek->algo; + ad[3] = aead_algo; + err = gcry_cipher_authenticate (hd, ad, 4); + if (err) + goto leave; + + memcpy (buf + noncelen, seskey->key, seskey->keylen); + gcry_cipher_final (hd); + err = gcry_cipher_encrypt (hd, buf + noncelen, seskey->keylen, NULL,0); + if (err) + goto leave; + err = gcry_cipher_gettag (hd, buf + noncelen + seskey->keylen, 16); + if (err) + goto leave; + *r_enckeylen = noncelen + seskey->keylen + 16; + *r_enckey = buf; + buf = NULL; + } + else + { + /* In the old version 4 SKESK the encrypted session key is + * prefixed with a one-octet algorithm id. */ + buf = xtrymalloc_secure (1 + seskey->keylen); + if (!buf) + { + err = gpg_error_from_syserror (); + goto leave; + } + buf[0] = seskey->algo; + memcpy (buf + 1, seskey->key, seskey->keylen); + + err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1); + if (!err) + err = gcry_cipher_setkey (hd, dek->key, dek->keylen); + if (!err) + err = gcry_cipher_setiv (hd, NULL, 0); + if (!err) + err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0); + if (err) + goto leave; + *r_enckeylen = seskey->keylen + 1; + *r_enckey = buf; + buf = NULL; } - /* The encrypted session key is prefixed with a one-octet algorithm id. */ - buf[0] = seskey->algo; - memcpy (buf + 1, seskey->key, seskey->keylen); - - err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1); - if (!err) - err = gcry_cipher_setkey (hd, dek->key, dek->keylen); - if (!err) - err = gcry_cipher_setiv (hd, NULL, 0); - if (!err) - err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0); - if (err) - goto leave; - - *r_enckey = buf; - buf = NULL; - *r_enckeylen = seskey->keylen + 1; /* Return the session key in case we allocated it. */ *r_seskey = seskey; seskey = NULL; @@ -332,7 +388,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey) { DEK *dek = NULL; - rc = encrypt_seskey (cfx.dek, &dek, &enckey, &enckeylen); + rc = encrypt_seskey (cfx.dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) { xfree (cfx.dek); @@ -346,14 +402,16 @@ encrypt_simple (const char *filename, int mode, int use_seskey) cfx.dek = dek; } - if (opt.verbose) - log_info(_("using cipher %s\n"), - openpgp_cipher_algo_name (cfx.dek->algo)); - if (aead_algo) cfx.dek->use_aead = aead_algo; else cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); + + if (opt.verbose) + log_info(_("using cipher %s.%s\n"), + openpgp_cipher_algo_name (cfx.dek->algo), + cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead) + /**/ : "CFB"); } if (do_compress @@ -385,8 +443,9 @@ encrypt_simple (const char *filename, int mode, int use_seskey) { /* Fixme: This is quite similar to write_symkey_enc. */ PKT_symkey_enc *enc = xmalloc_clear (sizeof *enc + enckeylen); - enc->version = 4; + enc->version = cfx.dek->use_aead ? 5 : 4; enc->cipher_algo = cfx.dek->algo; + enc->aead_algo = cfx.dek->use_aead; enc->s2k = *s2k; if (enckeylen) { @@ -535,8 +594,8 @@ setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek) static int -write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, - iobuf_t out) +write_symkey_enc (STRING2KEY *symkey_s2k, aead_algo_t aead_algo, + DEK *symkey_dek, DEK *dek, iobuf_t out) { int rc; void *enckey; @@ -544,7 +603,7 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, PKT_symkey_enc *enc; PACKET pkt; - rc = encrypt_seskey (symkey_dek, &dek, &enckey, &enckeylen); + rc = encrypt_seskey (symkey_dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) return rc; enc = xtrycalloc (1, sizeof (PKT_symkey_enc) + enckeylen); @@ -555,8 +614,9 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, return rc; } - enc->version = 4; + enc->version = aead_algo? 5 : 4; enc->cipher_algo = opt.s2k_cipher_algo; + enc->aead_algo = aead_algo; enc->s2k = *symkey_s2k; enc->seskeylen = enckeylen; memcpy (enc->seskey, enckey, enckeylen); @@ -813,10 +873,11 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, goto leave; /* We put the passphrase (if any) after any public keys as this - seems to be the most useful on the recipient side - there is no - point in prompting a user for a passphrase if they have the - secret key needed to decrypt. */ - if(use_symkey && (rc = write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out))) + * seems to be the most useful on the recipient side - there is no + * point in prompting a user for a passphrase if they have the + * secret key needed to decrypt. */ + if (use_symkey && (rc = write_symkey_enc (symkey_s2k, cfx.dek->use_aead, + symkey_dek, cfx.dek, out))) goto leave; if (!opt.no_literal) @@ -1014,9 +1075,9 @@ encrypt_filter (void *opaque, int control, if(efx->symkey_s2k && efx->symkey_dek) { - rc=write_symkey_enc(efx->symkey_s2k,efx->symkey_dek, - efx->cfx.dek,a); - if(rc) + rc = write_symkey_enc (efx->symkey_s2k, efx->cfx.dek->use_aead, + efx->symkey_dek, efx->cfx.dek, a); + if (rc) return rc; } @@ -1084,9 +1145,11 @@ write_pubkey_enc (ctrl_t ctrl, if ( opt.verbose ) { char *ustr = get_user_id_string_native (ctrl, enc->keyid); - log_info (_("%s/%s encrypted for: \"%s\"\n"), + log_info (_("%s/%s.%s encrypted for: \"%s\"\n"), openpgp_pk_algo_name (enc->pubkey_algo), openpgp_cipher_algo_name (dek->algo), + dek->use_aead? openpgp_aead_algo_name (dek->use_aead) + /**/ : "CFB", ustr ); xfree (ustr); } diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c index f22c7c202..094bc7614 100644 --- a/g10/gpgcompose.c +++ b/g10/gpgcompose.c @@ -2284,7 +2284,7 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie) /* Now encrypt the session key (or rather, the algorithm used to encrypt the SKESK plus the session key) using ENCKEY. */ - err = encrypt_seskey (&s2kdek, &sesdekp, + err = encrypt_seskey (&s2kdek, 0, &sesdekp, (void**)&ske->seskey, (size_t *)&ske->seskeylen); if (err) log_fatal ("encrypt_seskey failed: %s\n", gpg_strerror (err)); diff --git a/g10/import.c b/g10/import.c index 71e39557c..ed679d5c0 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1113,6 +1113,24 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock) problem=1; } } + else if(prefs->type==PREFTYPE_AEAD) + { + if (openpgp_aead_test_algo (prefs->value)) + { + /* FIXME: The test below is wrong. We should + * check if ...algo_name yields a "?" and + * only in that case use NUM. */ + const char *algo = + (openpgp_aead_test_algo (prefs->value) + ? num + : openpgp_aead_algo_name (prefs->value)); + if(!problem) + check_prefs_warning(pk); + log_info(_(" \"%s\": preference for AEAD" + " algorithm %s\n"), user, algo); + problem=1; + } + } else if(prefs->type==PREFTYPE_HASH) { if(openpgp_md_test_algo(prefs->value)) @@ -2255,6 +2273,7 @@ transfer_secret_keys (ctrl_t ctrl, struct import_stats_s *stats, { char countbuf[35]; + /* FIXME: Support AEAD */ /* Note that the IVLEN may be zero if we are working on a dummy key. We can't express that in an S-expression and thus we send dummy data for the IV. */ diff --git a/g10/keyedit.c b/g10/keyedit.c index 81344eb79..3ae96a3b2 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -3064,6 +3064,23 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose) tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES)); } tty_printf ("\n "); + tty_printf (_("AEAD: ")); + for (i = any = 0; prefs[i].type; i++) + { + if (prefs[i].type == PREFTYPE_AEAD) + { + if (any) + tty_printf (", "); + any = 1; + /* We don't want to display strings for experimental algos */ + if (!openpgp_aead_test_algo (prefs[i].value) + && prefs[i].value < 100) + tty_printf ("%s", openpgp_aead_algo_name (prefs[i].value)); + else + tty_printf ("[%d]", prefs[i].value); + } + } + tty_printf ("\n "); tty_printf (_("Digest: ")); for (i = any = 0; prefs[i].type; i++) { @@ -3172,6 +3189,7 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose) for (i = 0; prefs[i].type; i++) { tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' : + prefs[i].type == PREFTYPE_AEAD ? 'A' : prefs[i].type == PREFTYPE_HASH ? 'H' : prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?', prefs[i].value); diff --git a/g10/main.h b/g10/main.h index 96899acf5..a02c5740f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -235,7 +235,7 @@ void display_online_help( const char *keyword ); /*-- encode.c --*/ int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek); -gpg_error_t encrypt_seskey (DEK *dek, DEK **r_seskey, +gpg_error_t encrypt_seskey (DEK *dek, aead_algo_t aead_algo, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen); aead_algo_t use_aead (pk_list_t pk_list, int algo); int use_mdc (pk_list_t pk_list,int algo); diff --git a/g10/mainproc.c b/g10/mainproc.c index 92da98242..d1d44d774 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -245,46 +245,102 @@ add_signature (CTX c, PACKET *pkt) return 1; } -static int +static gpg_error_t symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen) { + gpg_error_t err; gcry_cipher_hd_t hd; + unsigned int noncelen, keylen; + enum gcry_cipher_modes ciphermode; + byte ad[4]; - if(slen < 17 || slen > 33) + if (dek->use_aead) + { + err = openpgp_aead_algo_info (dek->use_aead, &ciphermode, &noncelen); + if (err) + return err; + } + else + { + ciphermode = GCRY_CIPHER_MODE_CFB; + noncelen = 0; + } + + /* Check that the session key has a size of 16 to 32 bytes. */ + if ((dek->use_aead && (slen < (noncelen + 16 + 16) + || slen > (noncelen + 32 + 16))) + || (!dek->use_aead && (slen < 17 || slen > 33))) { log_error ( _("weird size for an encrypted session key (%d)\n"), (int)slen); - return GPG_ERR_BAD_KEY; + return gpg_error (GPG_ERR_BAD_KEY); } - if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1)) - BUG (); - if (gcry_cipher_setkey ( hd, dek->key, dek->keylen )) - BUG (); - gcry_cipher_setiv ( hd, NULL, 0 ); - gcry_cipher_decrypt ( hd, seskey, slen, NULL, 0 ); - gcry_cipher_close ( hd ); + err = openpgp_cipher_open (&hd, dek->algo, ciphermode, GCRY_CIPHER_SECURE); + if (!err) + err = gcry_cipher_setkey (hd, dek->key, dek->keylen); + if (!err) + err = gcry_cipher_setiv (hd, noncelen? seskey : NULL, noncelen); + if (err) + goto leave; - /* Now we replace the dek components with the real session key to - decrypt the contents of the sequencing packet. */ + if (dek->use_aead) + { + byte ad[4]; - dek->keylen=slen-1; - dek->algo=seskey[0]; - - if(dek->keylen > DIM(dek->key)) - BUG (); - - memcpy(dek->key, seskey + 1, dek->keylen); + ad[0] = (0xc0 | PKT_SYMKEY_ENC); + ad[1] = 5; + ad[2] = dek->algo; + ad[3] = dek->use_aead; + err = gcry_cipher_authenticate (hd, ad, 4); + if (err) + goto leave; + gcry_cipher_final (hd); + keylen = slen - noncelen - 16; + err = gcry_cipher_decrypt (hd, seskey+noncelen, keylen, NULL, 0); + if (err) + goto leave; + err = gcry_cipher_checktag (hd, seskey+noncelen+keylen, 16); + if (err) + goto leave; + /* Now we replace the dek components with the real session key to + * decrypt the contents of the sequencing packet. */ + if (keylen > DIM(dek->key)) + { + err = gpg_error (GPG_ERR_TOO_LARGE); + goto leave; + } + dek->keylen = keylen; + memcpy (dek->key, seskey + noncelen, dek->keylen); + } + else + { + gcry_cipher_decrypt (hd, seskey, slen, NULL, 0 ); + /* Now we replace the dek components with the real session key to + * decrypt the contents of the sequencing packet. */ + keylen = slen-1; + if (keylen > DIM(dek->key)) + { + err = gpg_error (GPG_ERR_TOO_LARGE); + goto leave; + } + dek->algo = seskey[0]; + dek->keylen = keylen; + memcpy (dek->key, seskey + 1, dek->keylen); + } /*log_hexdump( "thekey", dek->key, dek->keylen );*/ - return 0; + leave: + gcry_cipher_close (hd); + return err; } static void proc_symkey_enc (CTX c, PACKET *pkt) { + gpg_error_t err; PKT_symkey_enc *enc; enc = pkt->pkt.symkey_enc; @@ -294,19 +350,21 @@ proc_symkey_enc (CTX c, PACKET *pkt) { int algo = enc->cipher_algo; const char *s = openpgp_cipher_algo_name (algo); + const char *a = (enc->aead_algo ? openpgp_aead_algo_name (enc->aead_algo) + /**/ : "CFB"); if (!openpgp_cipher_test_algo (algo)) { if (!opt.quiet) { if (enc->seskeylen) - log_info (_("%s encrypted session key\n"), s ); + log_info (_("%s.%s encrypted session key\n"), s, a ); else - log_info (_("%s encrypted data\n"), s ); + log_info (_("%s.%s encrypted data\n"), s, a ); } } else - log_error (_("encrypted with unknown algorithm %d\n"), algo); + log_error (_("encrypted with unknown algorithm %d.%s\n"), algo, a); if (openpgp_md_test_algo (enc->s2k.hash_algo)) { @@ -334,6 +392,7 @@ proc_symkey_enc (CTX c, PACKET *pkt) if (c->dek) { c->dek->symmetric = 1; + c->dek->use_aead = enc->aead_algo; /* FIXME: This doesn't work perfectly if a symmetric key comes before a public key in the message - if the @@ -344,9 +403,16 @@ proc_symkey_enc (CTX c, PACKET *pkt) come later. */ if (enc->seskeylen) { - if (symkey_decrypt_seskey (c->dek, - enc->seskey, enc->seskeylen)) + err = symkey_decrypt_seskey (c->dek, + enc->seskey, enc->seskeylen); + if (err) { + log_info ("decryption of the symmetrically encrypted" + " session key failed: %s\n", + gpg_strerror (err)); + if (gpg_err_code (err) != GPG_ERR_BAD_KEY) + log_fatal ("process terminated to be bug compatible" + " with GnuPG <= 2.2\n"); xfree (c->dek); c->dek = NULL; } diff --git a/g10/packet.h b/g10/packet.h index 4d155746e..4f4569f66 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -94,12 +94,14 @@ typedef struct /* A symmetric-key encrypted session key packet as defined in RFC 4880, Section 5.3. All fields are serialized. */ typedef struct { - /* RFC 4880: this must be 4. */ + /* We support version 4 (rfc4880) and 5 (rfc4880bis). */ byte version; - /* The cipher algorithm used to encrypt the session key. (This may - be different from the algorithm that is used to encrypt the SED - packet.) */ + /* The cipher algorithm used to encrypt the session key. Note that + * this may be different from the algorithm that is used to encrypt + * bulk data. */ byte cipher_algo; + /* The AEAD algorithm or 0 for CFB encryption. */ + byte aead_algo; /* The string-to-key specifier. */ STRING2KEY s2k; /* The length of SESKEY in bytes or 0 if this packet does not @@ -107,7 +109,8 @@ typedef struct { S2K function on the password is the session key. See RFC 4880, Section 5.3.) */ byte seskeylen; - /* The session key as encrypted by the S2K specifier. */ + /* The session key as encrypted by the S2K specifier. For AEAD this + * includes the nonce and the authentication tag. */ byte seskey[1]; } PKT_symkey_enc; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index de51770af..5c6d364ee 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1105,7 +1105,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, { PKT_symkey_enc *k; int rc = 0; - int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen; + int i, version, s2kmode, cipher_algo, aead_algo, hash_algo, seskeylen, minlen; if (pktlen < 4) { @@ -1117,7 +1117,11 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, } version = iobuf_get_noeof (inp); pktlen--; - if (version != 4) + if (version == 4) + ; + else if (version == 5) + ; + else { log_error ("packet(%d) with unknown version %d\n", pkttype, version); if (list_mode) @@ -1135,6 +1139,13 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, } cipher_algo = iobuf_get_noeof (inp); pktlen--; + if (version == 5) + { + aead_algo = iobuf_get_noeof (inp); + pktlen--; + } + else + aead_algo = 0; s2kmode = iobuf_get_noeof (inp); pktlen--; hash_algo = iobuf_get_noeof (inp); @@ -1169,6 +1180,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, + seskeylen - 1); k->version = version; k->cipher_algo = cipher_algo; + k->aead_algo = aead_algo; k->s2k.mode = s2kmode; k->s2k.hash_algo = hash_algo; if (s2kmode == 1 || s2kmode == 3) @@ -1199,10 +1211,20 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, if (list_mode) { es_fprintf (listfp, - ":symkey enc packet: version %d, cipher %d, s2k %d, hash %d", - version, cipher_algo, s2kmode, hash_algo); + ":symkey enc packet: version %d, cipher %d, aead %d," + " s2k %d, hash %d", + version, cipher_algo, aead_algo, s2kmode, hash_algo); if (seskeylen) - es_fprintf (listfp, ", seskey %d bits", (seskeylen - 1) * 8); + { + /* To compute the size of the session key we need to know + * the size of the AEAD nonce which we may not know. Thus + * we show only the seize of the entire encrypted session + * key. */ + if (aead_algo) + es_fprintf (listfp, ", encrypted seskey %d bytes", seskeylen); + else + es_fprintf (listfp, ", seskey %d bits", (seskeylen - 1) * 8); + } es_fprintf (listfp, "\n"); if (s2kmode == 1 || s2kmode == 3) { diff --git a/g10/sign.c b/g10/sign.c index 7045e8cad..df71ccce1 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1326,9 +1326,6 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr) s2k->hash_algo = S2K_DIGEST_ALGO; algo = default_cipher_algo(); - if (!opt.quiet || !opt.batch) - log_info (_("%s encryption will be used\n"), - openpgp_cipher_algo_name (algo) ); cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled); if (!cfx.dek || !cfx.dek->keylen) { @@ -1341,6 +1338,12 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr) if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); + if (!opt.quiet || !opt.batch) + log_info (_("%s.%s encryption will be used\n"), + openpgp_cipher_algo_name (algo), + cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead) + /**/ : "CFB"); + /* now create the outfile */ rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out); if (rc)