summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-08-18 11:25:47 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-08-18 11:25:47 +0900
commitb512121503ac8d31e7225e302e8cd857576d4147 (patch)
tree00d79f61290f07f0fe7d350ae3ab5a480ddfa6f0
parentc5480b4934bb0adecdfc29a47b5e123f995507e1 (diff)
downloadlibgcrypt-b512121503ac8d31e7225e302e8cd857576d4147.tar.gz
Adding gcry_cipher_setup_geniv and gcry_cipher_geniv.
... to allow use of GCM in FIPS mode. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--cipher/cipher-gcm.c7
-rw-r--r--cipher/cipher-internal.h8
-rw-r--r--cipher/cipher.c62
-rw-r--r--src/gcrypt-int.h6
-rw-r--r--src/gcrypt.h.in16
-rw-r--r--src/libgcrypt.def3
-rw-r--r--src/libgcrypt.vers3
-rw-r--r--src/visibility.c16
-rw-r--r--src/visibility.h4
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
@@ -246,6 +246,14 @@ struct gcry_cipher_handle
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. */
unsigned int tag:1; /* Set to 1 if a tag is finalized. */
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);
}
@@ -1251,6 +1262,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
@@ -774,6 +774,22 @@ gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t 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)
{
if (!fips_is_operational ())
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