Hi NIIBE, list,

This is my first message from my other email addres that has a yubikey-backed 
key. I'm working on getting it working with my neomutt.
Because I just subscribed, it cannot reply to the thread about set_iv(). --> 
/me looks in the mirror: Yah, it's really me :o) and I have a second patch.



Okay, I removed all the FIPS related patch content and reformulated the guard 
statement, this second patch.

I'm aware that there are other issues, and am just trying to help, so I'm just 
focusing on fixing this leak that is still there.

The issue:

In non-FIPS mode, _if_ the caller never invokes set_iv() before calling 
gcm_encrypt(), gcm_decrypt(), or gcm_authenticate(), the library does not 
return an error.
It silently calls _gcry_cipher_gcm_setiv_zero(), which initializes the IV to an 
all-zero static buffer and proceeds. The caller receives no indication that 
anything is wrong.

This is a real vulnerability. The triggering condition is straightforward:

Any caller that opens a GCM cipher handle, sets a key, and encrypts without 
setting an IV gets a zero nonce silently.
In a multi-message session this means nonce reuse under the same key — GCM 
authentication is broken and confidentiality is compromised.
My demo program demonstrates this: without set_iv(), gcry_cipher_encrypt() 
returns GCRY_ERR_NO_ERROR while using a zero IV, and the ciphertext is 
decryptable — confirming silent proceed, not a no-op.



Now my fix is basically in the three affected functions to write a guard:

  if (!c->marks.iv && c->aead.geniv_method == 0)
    return GPG_ERR_INV_STATE;

And as you say it's not recommended IV practice, but still, it's not completely 
weird API usage either...



I'm thankful for pointing out the relevant tickets for the FIPS related stuff.

Best regards,
--Bert

diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index a9c48551..08af44fa 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -977,6 +977,8 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
       || c->u_mode.gcm.ghash_data_finalized
       || !c->u_mode.gcm.ghash_fn)
     return GPG_ERR_INV_STATE;
+  if (!c->marks.iv && c->aead.geniv_method == 0)
+    return GPG_ERR_INV_STATE;
 
   if (!c->marks.iv)
     _gcry_cipher_gcm_setiv_zero (c);
@@ -1017,6 +1019,8 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
       || c->u_mode.gcm.ghash_data_finalized
       || !c->u_mode.gcm.ghash_fn)
     return GPG_ERR_INV_STATE;
+  if (!c->marks.iv && c->aead.geniv_method == 0)
+    return GPG_ERR_INV_STATE;
 
   if (!c->marks.iv)
     _gcry_cipher_gcm_setiv_zero (c);
@@ -1052,6 +1056,8 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
       || c->u_mode.gcm.ghash_data_finalized
       || !c->u_mode.gcm.ghash_fn)
     return GPG_ERR_INV_STATE;
+  if (!c->marks.iv && c->aead.geniv_method == 0)
+    return GPG_ERR_INV_STATE;
 
   if (!c->marks.iv)
     _gcry_cipher_gcm_setiv_zero (c);
_______________________________________________
Gcrypt-devel mailing list
[email protected]
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel

Reply via email to