From b512121503ac8d31e7225e302e8cd857576d4147 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 18 Aug 2022 11:25:47 +0900 Subject: Adding gcry_cipher_setup_geniv and gcry_cipher_geniv. ... to allow use of GCM in FIPS mode. Signed-off-by: NIIBE Yutaka --- cipher/cipher-gcm.c | 7 ------ cipher/cipher-internal.h | 8 +++++++ cipher/cipher.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++-- src/gcrypt-int.h | 6 +++++ src/gcrypt.h.in | 16 +++++++++++++ src/libgcrypt.def | 3 +++ src/libgcrypt.vers | 3 +++ src/visibility.c | 16 +++++++++++++ src/visibility.h | 4 ++++ 9 files changed, 116 insertions(+), 9 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 683f07b0..8652967d 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -1105,13 +1105,6 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { c->marks.iv = 0; c->marks.tag = 0; - c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0; - - if (fips_mode ()) - { - /* Direct invocation of GCM setiv in FIPS mode disables encryption. */ - c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1; - } return _gcry_cipher_gcm_initiv (c, iv, ivlen); } diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index e1ff0437..66b75955 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -245,6 +245,14 @@ struct gcry_cipher_handle int mode; unsigned int flags; + struct { + int geniv_method; + unsigned char fixed[MAX_BLOCKSIZE]; + unsigned char dynamic[MAX_BLOCKSIZE]; + size_t fixed_iv_len; + size_t dynamic_iv_len; + } aead; + struct { unsigned int key:1; /* Set to 1 if a key has been set. */ unsigned int iv:1; /* Set to 1 if a IV has been set. */ diff --git a/cipher/cipher.c b/cipher/cipher.c index d1443a62..2f0be964 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -1210,9 +1210,20 @@ _gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen) gcry_err_code_t -_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) +_gcry_cipher_setiv (gcry_cipher_hd_t c, const void *iv, size_t ivlen) { - return hd->mode_ops.setiv (hd, iv, ivlen); + if (c->mode == GCRY_CIPHER_MODE_GCM) + { + c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0; + + if (fips_mode ()) + { + /* Direct invocation of GCM setiv in FIPS mode disables encryption. */ + c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1; + } + } + + return c->mode_ops.setiv (c, iv, ivlen); } @@ -1250,6 +1261,53 @@ _gcry_cipher_getctr (gcry_cipher_hd_t hd, void *ctr, size_t ctrlen) } +gcry_err_code_t +_gcry_cipher_setup_geniv (gcry_cipher_hd_t hd, int method, + const void *fixed_iv, size_t fixed_iv_len, + const void *dyn_iv, size_t dyn_iv_len) +{ + gcry_err_code_t rc = 0; + + if (method != GCRY_CIPHER_GENIV_METHOD_CONCAT) + return GPG_ERR_INV_ARG; + + hd->aead.geniv_method = GCRY_CIPHER_GENIV_METHOD_CONCAT; + hd->aead.fixed_iv_len = fixed_iv_len; + hd->aead.dynamic_iv_len = dyn_iv_len; + memset (hd->aead.fixed, 0, MAX_BLOCKSIZE); + memset (hd->aead.dynamic, 0, MAX_BLOCKSIZE); + memcpy (hd->aead.fixed, fixed_iv, fixed_iv_len); + memcpy (hd->aead.dynamic, dyn_iv, dyn_iv_len); + + return rc; +} + + +gcry_err_code_t +_gcry_cipher_geniv (gcry_cipher_hd_t hd, void *iv, size_t iv_len) +{ + gcry_err_code_t rc = 0; + int i; + + if (hd->aead.geniv_method != GCRY_CIPHER_GENIV_METHOD_CONCAT) + return GPG_ERR_INV_ARG; + + if (iv_len != hd->aead.fixed_iv_len + hd->aead.dynamic_iv_len) + return GPG_ERR_INV_ARG; + + memcpy (iv, hd->aead.fixed, hd->aead.fixed_iv_len); + memcpy ((byte *)iv+hd->aead.fixed_iv_len, + hd->aead.dynamic, hd->aead.dynamic_iv_len); + rc = hd->mode_ops.setiv (hd, iv, iv_len); + + for (i = hd->aead.dynamic_iv_len; i > 0; i--) + if (++hd->aead.dynamic[i - 1] != 0) + break; + + return rc; +} + + gcry_err_code_t _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen) diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index 04953ffc..c3ca5d71 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -69,6 +69,12 @@ gcry_err_code_t _gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen); gcry_err_code_t _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen); +gcry_err_code_t _gcry_cipher_setup_geniv (gcry_cipher_hd_t hd, int method, + const void *fixed_iv, + size_t fixed_ivlen, + const void *dyn_iv, size_t dyn_ivlen); +gcry_err_code_t _gcry_cipher_geniv (gcry_cipher_hd_t hd, + void *iv, size_t ivlen); gpg_err_code_t _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen); gpg_err_code_t _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 299261db..7f901f8b 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -985,6 +985,13 @@ enum gcry_cipher_flags GCRY_CIPHER_EXTENDED = 16 /* Enable extended AES-WRAP. */ }; +/* Methods used for AEAD IV generation. */ +enum gcry_cipher_geniv_methods + { + GCRY_CIPHER_GENIV_METHOD_CONCAT = 1, + GCRY_CIPHER_GENIV_METHOD_XOR = 2 + }; + /* GCM works only with blocks of 128 bits */ #define GCRY_GCM_BLOCK_LEN (128 / 8) @@ -1056,6 +1063,15 @@ gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd, gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen); +/* Initialization vector generation setup for AEAD modes/ciphers. */ +gcry_error_t gcry_cipher_setup_geniv (gcry_cipher_hd_t hd, int method, + const void *fixed_iv, size_t fixed_ivlen, + const void *dyn_iv, size_t dyn_ivlen); + +/* Initialization vector generation for AEAD modes/ciphers. */ +gcry_error_t gcry_cipher_geniv (gcry_cipher_hd_t hd, + void *iv, size_t ivlen); + /* Provide additional authentication data for AEAD modes/ciphers. */ gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen); diff --git a/src/libgcrypt.def b/src/libgcrypt.def index d6de731f..a66511c8 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -298,4 +298,7 @@ EXPORTS gcry_kdf_final @260 gcry_kdf_close @261 + gcry_cipher_setup_geniv @262 + gcry_cipher_geniv @263 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 2e274f60..62b0e4ee 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -125,6 +125,9 @@ GCRYPT_1.6 { gcry_pk_hash_sign; gcry_pk_hash_verify; gcry_pk_random_override_new; gcry_kdf_open; gcry_kdf_compute; gcry_kdf_final; gcry_kdf_close; + + gcry_cipher_setup_geniv; gcry_cipher_geniv; + local: *; diff --git a/src/visibility.c b/src/visibility.c index aee5bffb..0ed5c463 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -773,6 +773,22 @@ gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) return gcry_error (_gcry_cipher_setctr (hd, ctr, ctrlen)); } +gcry_error_t +gcry_cipher_setup_geniv (gcry_cipher_hd_t hd, int method, + const void *fixed_iv, size_t fixed_iv_len, + const void *dyn_iv, size_t dyn_iv_len) +{ + return gcry_error (_gcry_cipher_setup_geniv (hd, method, + fixed_iv, fixed_iv_len, + dyn_iv, dyn_iv_len)); +} + +gcry_error_t +gcry_cipher_geniv (gcry_cipher_hd_t hd, void *iv, size_t iv_len) +{ + return gcry_error (_gcry_cipher_geniv (hd, iv, iv_len)); +} + gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen) { diff --git a/src/visibility.h b/src/visibility.h index 14bf6248..6aef3278 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -122,6 +122,8 @@ MARK_VISIBLEX (gcry_cipher_close) MARK_VISIBLEX (gcry_cipher_setkey) MARK_VISIBLEX (gcry_cipher_setiv) MARK_VISIBLEX (gcry_cipher_setctr) +MARK_VISIBLEX (gcry_cipher_setup_geniv) +MARK_VISIBLEX (gcry_cipher_geniv) MARK_VISIBLEX (gcry_cipher_authenticate) MARK_VISIBLEX (gcry_cipher_checktag) MARK_VISIBLEX (gcry_cipher_gettag) @@ -344,6 +346,8 @@ MARK_VISIBLEX (_gcry_mpi_get_const) #define gcry_cipher_setctr _gcry_USE_THE_UNDERSCORED_FUNCTION #define gcry_cipher_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION #define gcry_cipher_algo_name _gcry_USE_THE_UNDERSCORED_FUNCTION +#define gcry_cipher_setup_geniv _gcry_USE_THE_UNDERSCORED_FUNCTION +#define gcry_cipher_geniv _gcry_USE_THE_UNDERSCORED_FUNCTION #define gcry_cipher_authenticate _gcry_USE_THE_UNDERSCORED_FUNCTION #define gcry_cipher_checktag _gcry_USE_THE_UNDERSCORED_FUNCTION #define gcry_cipher_gettag _gcry_USE_THE_UNDERSCORED_FUNCTION -- cgit v1.2.1