From f3d3584faf29e8901e00794f4e5f770b9f1eb7a6 Mon Sep 17 00:00:00 2001
From: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Date: Thu, 15 Dec 2016 14:54:30 +0100
Subject: [PATCH] s390/crypto: Check des3_ede keys for uniqueness in fips mode

Triple-DES implementations will soon be required to check
for uniqueness of keys with fips mode enabled. Add checks
to ensure none of the 3 keys match.

Signed-off-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
 arch/s390/crypto/des_s390.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index 8b83144206eb0..0d296662bbf0a 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 #include <linux/crypto.h>
+#include <linux/fips.h>
 #include <crypto/algapi.h>
 #include <crypto/des.h>
 #include <asm/cpacf.h>
@@ -221,6 +222,8 @@ static struct crypto_alg cbc_des_alg = {
  *   same as DES.  Implementers MUST reject keys that exhibit this
  *   property.
  *
+ *   In fips mode additinally check for all 3 keys are unique.
+ *
  */
 static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
 		       unsigned int key_len)
@@ -234,6 +237,17 @@ static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
 		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
 		return -EINVAL;
 	}
+
+	/* in fips mode, ensure k1 != k2 and k2 != k3 and k1 != k3 */
+	if (fips_enabled &&
+	    !(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
+	      crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
+			    DES_KEY_SIZE) &&
+	      crypto_memneq(key, &key[DES_KEY_SIZE * 2], DES_KEY_SIZE))) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
 	memcpy(ctx->key, key, key_len);
 	return 0;
 }
-- 
GitLab