From da3015e3c05030fe709c8f922486e73d06d1d16a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 22 Jan 2018 16:23:02 +0100 Subject: [PATCH] gpg: Unify AEAD parameter retrieval. * g10/pkclist.c (select_aead_from_pklist): Return the AEAD_algo. * g10/encrypt.c (use_aead): Return the AEAD algo. (encrypt_simple): Adjust for this change. (encrypt_crypt): Ditto. (encrypt_filter): Ditto. * g10/sign.c (sign_symencrypt_file): Ditto. * g10/misc.c (MY_GCRY_CIPHER_MODE_EAX): New. (openpgp_aead_algo_info): New. * g10/cipher-aead.c (MY_GCRY_CIPHER_MODE_EAX): Remove. (write_header): Use new fucntion. * g10/decrypt-data.c (MY_GCRY_CIPHER_MODE_EAX): Remove. (decrypt_data): Use new function. Also allow for chunkbytes other than 10. -- Note that other chunk bytes than 10 and in particular 0 (64 byte chunks) have not yet been tested. Signed-off-by: Werner Koch --- g10/cipher-aead.c | 24 +++--------------------- g10/decrypt-data.c | 29 ++++++----------------------- g10/encrypt.c | 24 ++++++++++-------------- g10/keydb.h | 2 +- g10/main.h | 5 ++++- g10/misc.c | 33 +++++++++++++++++++++++++++++++++ g10/pkclist.c | 7 ++++--- g10/sign.c | 5 ++--- 8 files changed, 63 insertions(+), 66 deletions(-) diff --git a/g10/cipher-aead.c b/g10/cipher-aead.c index 1d7263419..637bd71a7 100644 --- a/g10/cipher-aead.c +++ b/g10/cipher-aead.c @@ -33,10 +33,6 @@ #include "options.h" #include "main.h" -/* FIXME: Libgcrypt 1.9 will support EAX. Until we kame this a - * requirement we hardwire the enum used for EAX. */ -#define MY_GCRY_CIPHER_MODE_EAX 14 - /* The size of the buffer we allocate to encrypt the data. This must * be a multiple of the OCB blocksize (16 byte). */ @@ -149,23 +145,9 @@ write_header (cipher_filter_context_t *cfx, iobuf_t a) if (blocksize != 16 ) log_fatal ("unsupported blocksize %u for AEAD\n", blocksize); - switch (cfx->dek->use_aead) - { - case AEAD_ALGO_OCB: - ciphermode = GCRY_CIPHER_MODE_OCB; - startivlen = 15; - break; - - case AEAD_ALGO_EAX: - ciphermode = MY_GCRY_CIPHER_MODE_EAX; - startivlen = 16; - break; - - default: - log_error ("unsupported AEAD algo %d\n", cfx->dek->use_aead); - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); - goto leave; - } + err = openpgp_aead_algo_info (cfx->dek->use_aead, &ciphermode, &startivlen); + if (err) + goto leave; cfx->chunkbyte = 10; cfx->chunksize = (uint64_t)1 << (cfx->chunkbyte + 6); diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c index 79e255480..7ed0bf006 100644 --- a/g10/decrypt-data.c +++ b/g10/decrypt-data.c @@ -31,10 +31,6 @@ #include "../common/status.h" #include "../common/compliance.h" -/* FIXME: Libgcrypt 1.9 will support EAX. Until we kame this a - * requirement we hardwire the enum used for EAX. */ -#define MY_GCRY_CIPHER_MODE_EAX 14 - static int aead_decode_filter (void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len); @@ -274,28 +270,15 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) goto leave; } - switch (ed->aead_algo) - { - case AEAD_ALGO_OCB: - startivlen = 15; - ciphermode = GCRY_CIPHER_MODE_OCB; - break; - case AEAD_ALGO_EAX: - startivlen = 16; - ciphermode = MY_GCRY_CIPHER_MODE_EAX; - break; - default: - log_error ("unknown AEAD algo %d\n", ed->aead_algo); - rc = gpg_error (GPG_ERR_INV_CIPHER_MODE); - goto leave; - } + rc = openpgp_aead_algo_info (ed->aead_algo, &ciphermode, &startivlen); + if (rc) + goto leave; log_assert (startivlen <= sizeof dfx->startiv); - if (ed->chunkbyte != 10) + if (ed->chunkbyte > 56) { - /* FIXME */ - log_error ("unsupported chunkbyte %u\n", ed->chunkbyte); - rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + log_error ("invalid AEAD chunkbyte %u\n", ed->chunkbyte); + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } diff --git a/g10/encrypt.c b/g10/encrypt.c index ab745cee8..4cc4b1a29 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -139,8 +139,9 @@ encrypt_seskey (DEK *dek, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) } -/* Return true if we shall use AEAD mode. */ -int +/* Return the AEAD algo if we shall use AEAD mode. Returns 0 if AEAD + * shall not be used. */ +aead_algo_t use_aead (pk_list_t pk_list, int algo) { int can_use; @@ -168,7 +169,7 @@ use_aead (pk_list_t pk_list, int algo) openpgp_cipher_algo_name (algo)); return 0; } - return 1; + return default_aead_algo (); } /* AEAD does only work with 128 bit cipher blocklength. */ @@ -176,10 +177,7 @@ use_aead (pk_list_t pk_list, int algo) return 0; /* If all keys support AEAD we can use it. */ - if (select_aead_from_pklist (pk_list)) - return 1; - - return 0; /* No AEAD. */ + return select_aead_from_pklist (pk_list); } @@ -328,7 +326,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey) } /* See whether we want to use AEAD. */ - aead_algo = use_aead (NULL, cfx.dek->algo)? default_aead_algo () : 0; + aead_algo = use_aead (NULL, cfx.dek->algo); if ( use_seskey ) { @@ -784,9 +782,8 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, gnupg_status_compliance_flag (CO_DE_VS), NULL); - if (use_aead (pk_list, cfx.dek->algo)) - cfx.dek->use_aead = 1; - else + cfx.dek->use_aead = use_aead (pk_list, cfx.dek->algo); + if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo); /* Only do the is-file-already-compressed check if we are using a @@ -1002,9 +999,8 @@ encrypt_filter (void *opaque, int control, efx->cfx.dek->algo = opt.def_cipher_algo; } - if (use_aead (efx->pk_list, efx->cfx.dek->algo)) - efx->cfx.dek->use_aead = 1; - else + efx->cfx.dek->use_aead = use_aead (efx->pk_list, efx->cfx.dek->algo); + if (!efx->cfx.dek->use_aead) efx->cfx.dek->use_mdc = !!use_mdc (efx->pk_list,efx->cfx.dek->algo); make_session_key ( efx->cfx.dek ); diff --git a/g10/keydb.h b/g10/keydb.h index 9f6064b41..f2ea8a7d2 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -232,7 +232,7 @@ int algo_available( preftype_t preftype, int algo, int select_algo_from_prefs( PK_LIST pk_list, int preftype, int request, const union pref_hint *hint); int select_mdc_from_pklist (PK_LIST pk_list); -int select_aead_from_pklist (pk_list_t pk_list); +aead_algo_t select_aead_from_pklist (pk_list_t pk_list); void warn_missing_mdc_from_pklist (PK_LIST pk_list); void warn_missing_aes_from_pklist (PK_LIST pk_list); diff --git a/g10/main.h b/g10/main.h index 509126c65..96899acf5 100644 --- a/g10/main.h +++ b/g10/main.h @@ -127,6 +127,9 @@ const char *openpgp_cipher_algo_name (cipher_algo_t algo); gpg_error_t openpgp_aead_test_algo (aead_algo_t algo); const char *openpgp_aead_algo_name (aead_algo_t algo); +gpg_error_t openpgp_aead_algo_info (aead_algo_t algo, + enum gcry_cipher_modes *r_mode, + unsigned int *r_noncelen); pubkey_algo_t map_pk_gcry_to_openpgp (enum gcry_pk_algos algo); int openpgp_pk_test_algo (pubkey_algo_t algo); @@ -234,7 +237,7 @@ void display_online_help( const char *keyword ); int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek); gpg_error_t encrypt_seskey (DEK *dek, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen); -int use_aead (pk_list_t pk_list, int algo); +aead_algo_t use_aead (pk_list_t pk_list, int algo); int use_mdc (pk_list_t pk_list,int algo); int encrypt_symmetric (const char *filename ); int encrypt_store (const char *filename ); diff --git a/g10/misc.c b/g10/misc.c index f7ac3c708..36d3bdc36 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -70,6 +70,11 @@ #include "../common/zb32.h" +/* FIXME: Libgcrypt 1.9 will support EAX. Until we kame this a + * requirement we hardwire the enum used for EAX. */ +#define MY_GCRY_CIPHER_MODE_EAX 14 + + #ifdef ENABLE_SELINUX_HACKS /* A object and a global variable to keep track of files marked as secured. */ @@ -616,6 +621,34 @@ openpgp_aead_algo_name (aead_algo_t algo) } +/* Return information for the AEAD algorithm ALGO. The corresponding + * Libgcrypt ciphermode is stored at R_MODE and the required number of + * octets for the nonce at R_NONCELEN. On error and error code is + * returned. Note that the taglen is always 128 bits. */ +gpg_error_t +openpgp_aead_algo_info (aead_algo_t algo, enum gcry_cipher_modes *r_mode, + unsigned int *r_noncelen) +{ + switch (algo) + { + case AEAD_ALGO_OCB: + *r_mode = GCRY_CIPHER_MODE_OCB; + *r_noncelen = 15; + break; + + case AEAD_ALGO_EAX: + *r_mode = MY_GCRY_CIPHER_MODE_EAX; + *r_noncelen = 16; + break; + + default: + log_error ("unsupported AEAD algo %d\n", algo); + return gpg_error (GPG_ERR_INV_CIPHER_MODE); + } + return 0; +} + + /* Return 0 if ALGO is a supported OpenPGP public key algorithm. */ int openpgp_pk_test_algo (pubkey_algo_t algo) diff --git a/g10/pkclist.c b/g10/pkclist.c index b85efa4cd..6ec5537f5 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1652,8 +1652,9 @@ select_mdc_from_pklist (PK_LIST pk_list) /* Select the AEAD flag from the pk_list. We can only use AEAD if all - * recipients support this feature. Returns true if AEAD can be used. */ -int + * recipients support this feature. Returns the AEAD to be used or 0 + * if AEAD shall not be used. */ +aead_algo_t select_aead_from_pklist (PK_LIST pk_list) { pk_list_t pkr; @@ -1672,7 +1673,7 @@ select_aead_from_pklist (PK_LIST pk_list) return 0; /* At least one recipient does not support it. */ } - return 1; /* Can be used. */ + return default_aead_algo (); /* Yes, AEAD can be used. */ } diff --git a/g10/sign.c b/g10/sign.c index 051ab594d..7045e8cad 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1337,9 +1337,8 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr) goto leave; } - if (use_aead (NULL, cfx.dek->algo)) - cfx.dek->use_aead = 1; - else + cfx.dek->use_aead = use_aead (NULL, cfx.dek->algo); + if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); /* now create the outfile */