From: Patrick Steuer <patrick.steuer@de.ibm.com>
Subject: fix aes-ccm encrypt code path.
Patch-mainline: v3.1.1
Git-commit: d901d1c06b1a5e3717907e3a8b32d4bb8f3cc03b
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-ccm encrypt code path.

    The aes-ccm encrypt code was like ct<-enc(pt), tag<-mac(pt). So in
    case of "in-place" encryption (pt=ct), the tag was computed from
    the ciphertext.

    Signed-off-by: Patrick Steuer <patrick.steuer@de.ibm.com>

Signed-off-by: Patrick Steuer <patrick.steuer@de.ibm.com>
---
 src/include/s390_ccm.h |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

--- a/src/include/s390_ccm.h
+++ b/src/include/s390_ccm.h
@@ -314,7 +314,26 @@ static inline unsigned int s390_ccm(unsi
 					  key, cipher_ctr, ccm_ctr_width);
 			if (rc)
 				return rc;
+			/* mac */
+			rc = s390_ccm_authenticate(UNDIRECTED_FC(function_code),
+						   payload, payload_length,
+						   assoc_data, assoc_data_length,
+						   nonce, nonce_length,
+						   tag, mac_length,
+						   key, fc_to_key_length(function_code));
+			if (rc)
+				return rc;
 		} else {
+			/* mac */
+			rc = s390_ccm_authenticate(UNDIRECTED_FC(function_code),
+						   payload, payload_length,
+						   assoc_data, assoc_data_length,
+						   nonce, nonce_length,
+						   tag, mac_length,
+						   key, fc_to_key_length(function_code));
+			if (rc)
+				return rc;
+
 			/*encrypt */
 			rc = s390_aes_ctr(UNDIRECTED_FC(function_code),
 					  payload, ciphertext, payload_length,
@@ -324,16 +343,6 @@ static inline unsigned int s390_ccm(unsi
 		}
 	}
 
-	/* generate tag */
-	rc = s390_ccm_authenticate(UNDIRECTED_FC(function_code),
-				   payload, payload_length,
-				   assoc_data, assoc_data_length,
-				   nonce, nonce_length,
-				   tag, mac_length,
-				   key, fc_to_key_length(function_code));
-	if (rc)
-		return rc;
-
 	/* encrypt tag into mac */
 	return s390_aes_ctr(UNDIRECTED_FC(function_code),
 			    tag, mac, mac_length,