From: Patrick Steuer Subject: fix aes-gcm to allow zero pt/ct length. Patch-mainline: v3.1.1 Git-commit: 089670367c8f645fcf5e4f8e59640877d2400ce4 References: LTC#158531 Description: libica: AES-GCM/CCM sometimes compute wrong tag values Symptom: When the tag values of (unmodified) data are wrong, it is (wrongly) indicated that the data has been modified. Problem: With AES-GCM in-place decryption, the tag is computed from the plaintext. With AES-CCM in-place encryption, the tag is computed from the ciphertext. Solution: AES-GCM decryption always computes the tag from the ciphertext. AES-CCM encryption always computes the tag from the plaintext. Reproduction: When used with the ibmca 1.4 openssl engine (which enables libica's AES-GCM for libcrypto): (1) A SSH connection fails using an AES-GCM based cipher-suite, (2) A connection of openssl's s_client and s_server using an AES-GCM based cipher-suite fails. Upstream-Description: fix aes-gcm to allow zero pt/ct length. In case of zero pt/ct lenght, only aad is processed (ghash). Signed-off-by: Patrick Steuer Signed-off-by: Patrick Steuer --- src/ica_api.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) --- a/src/ica_api.c +++ b/src/ica_api.c @@ -1750,9 +1750,16 @@ unsigned int ica_aes_gcm(unsigned char * return EACCES; #endif /* ICA_FIPS */ - if (check_aes_parms(MODE_GCM, plaintext_length, plaintext, iv, key_length, - key, ciphertext)) - return EINVAL; + if (plaintext_length != 0) { + if (check_aes_parms(MODE_GCM, plaintext_length, plaintext, iv, key_length, + key, ciphertext)) + return EINVAL; + } else { + /* If only aad is processed (ghash), pt/ct may be NULL. */ + if (check_aes_parms(MODE_GCM, plaintext_length, (unsigned char *)1, + iv, key_length, key, (unsigned char *)1)) + return EINVAL; + } if (check_gcm_parms(plaintext_length, aad, aad_length, tag, tag_length, iv_length)) return EINVAL; @@ -1825,9 +1832,16 @@ unsigned int ica_aes_gcm_intermediate(un return EACCES; #endif /* ICA_FIPS */ - if (check_aes_parms(MODE_GCM, plaintext_length, plaintext, cb, key_length, - key, ciphertext)) - return EINVAL; + if (plaintext_length != 0) { + if (check_aes_parms(MODE_GCM, plaintext_length, plaintext, cb, key_length, + key, ciphertext)) + return EINVAL; + } else { + /* If only aad is processed (ghash), pt/ct may be NULL. */ + if (check_aes_parms(MODE_GCM, plaintext_length, (unsigned char *)1, + cb, key_length, key, (unsigned char *)1)) + return EINVAL; + } if (check_gcm_parms(plaintext_length, aad, aad_length, tag, tag_length, iv_length_dummy)) return EINVAL;