Michal Suchanek 024a44
From f67b2860c00d242223c83ebb9cf78a409d94173a Mon Sep 17 00:00:00 2001
Michal Suchanek 7803c1
From: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 7803c1
Date: Mon, 16 Dec 2019 19:05:35 +0100
Michal Suchanek 7803c1
Subject: [PATCH] kABI: add _q suffix to exports that take struct dh
Michal Suchanek 7803c1
Michal Suchanek 7803c1
References: bsc#1155331
Michal Suchanek 7803c1
Patch-mainline: never, kABI
Michal Suchanek 7803c1
Michal Suchanek 7803c1
Also provide the old API with exports without suffix.
Michal Suchanek 7803c1
Michal Suchanek 7803c1
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 024a44
---
Michal Suchanek 024a44
 crypto/dh_helper.c  | 105 ++++++++++++++++++++++++++++++++++++++------
Michal Suchanek 024a44
 include/crypto/dh.h |  25 +++++++++++
Michal Suchanek 024a44
 3 files changed, 123 insertions(+), 16 deletions(-)
Michal Suchanek 7803c1
Michal Suchanek 024a44
diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c
Michal Suchanek 024a44
index 8625cb0c2af9..50d3d0c8734f 100644
Michal Suchanek 7803c1
--- a/crypto/dh_helper.c
Michal Suchanek 7803c1
+++ b/crypto/dh_helper.c
Michal Suchanek 024a44
@@ -14,6 +14,32 @@
Michal Suchanek 024a44
 #include <crypto/dh.h>
Michal Suchanek 024a44
 #include <crypto/kpp.h>
Michal Suchanek 024a44
 
Michal Suchanek 7803c1
+#undef dh
Michal Suchanek 7803c1
+#undef crypto_dh_key_len
Michal Suchanek a30af0
+#define DH_KPP_SECRET_MIN_SIZE_NO_Q (sizeof(struct kpp_secret) + 3 * sizeof(int))
Michal Suchanek a30af0
+
Michal Suchanek 024a44
+static inline int dh_data_size(const struct dh *p)
Michal Suchanek 7803c1
+{
Michal Suchanek 7803c1
+	return p->key_size + p->p_size + p->g_size;
Michal Suchanek 7803c1
+}
Michal Suchanek 7803c1
+
Michal Suchanek 7803c1
+int crypto_dh_key_len(const struct dh *p)
Michal Suchanek 7803c1
+{
Michal Suchanek 024a44
+	return DH_KPP_SECRET_MIN_SIZE_NO_Q + dh_data_size(p);
Michal Suchanek 7803c1
+}
Michal Suchanek 7803c1
+EXPORT_SYMBOL_GPL(crypto_dh_key_len);
Michal Suchanek 7803c1
+
Michal Suchanek 024a44
+/* Old calculation with new structure */
Michal Suchanek 024a44
+static inline int dh_data_size_no_q(const struct dh_q *p)
Michal Suchanek 024a44
+{
Michal Suchanek 024a44
+	return p->key_size + p->p_size + p->g_size;
Michal Suchanek 024a44
+}
Michal Suchanek 024a44
+
Michal Suchanek 024a44
+int crypto_dh_key_len_no_q(const struct dh_q *p)
Michal Suchanek 024a44
+{
Michal Suchanek 024a44
+	return DH_KPP_SECRET_MIN_SIZE_NO_Q + dh_data_size_no_q(p);
Michal Suchanek 024a44
+}
Michal Suchanek 024a44
+
Michal Suchanek 024a44
 #define DH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 4 * sizeof(int))
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 static inline u8 *dh_pack_data(void *dst, const void *src, size_t size)
Michal Suchanek 024a44
@@ -28,20 +54,21 @@ static inline const u8 *dh_unpack_data(void *dst, const void *src, size_t size)
Michal Suchanek 024a44
 	return src + size;
Michal Suchanek 024a44
 }
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-static inline int dh_data_size(const struct dh *p)
Michal Suchanek 024a44
+static inline int dh_data_size_q(const struct dh_q *p)
Michal Suchanek 024a44
 {
Michal Suchanek 024a44
 	return p->key_size + p->p_size + p->q_size + p->g_size;
Michal Suchanek 024a44
 }
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-int crypto_dh_key_len(const struct dh *p)
Michal Suchanek 024a44
+int crypto_dh_key_len_q(const struct dh_q *p)
Michal Suchanek 024a44
 {
Michal Suchanek 024a44
-	return DH_KPP_SECRET_MIN_SIZE + dh_data_size(p);
Michal Suchanek 024a44
+	return DH_KPP_SECRET_MIN_SIZE + dh_data_size_q(p);
Michal Suchanek 024a44
 }
Michal Suchanek 024a44
-EXPORT_SYMBOL_GPL(crypto_dh_key_len);
Michal Suchanek 024a44
+EXPORT_SYMBOL_GPL(crypto_dh_key_len_q);
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *params)
Michal Suchanek 024a44
+int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh_q *params)
Michal Suchanek 024a44
 {
Michal Suchanek 024a44
 	u8 *ptr = buf;
Michal Suchanek 024a44
+	bool do_q = true;
Michal Suchanek 024a44
 	struct kpp_secret secret = {
Michal Suchanek 024a44
 		.type = CRYPTO_KPP_SECRET_TYPE_DH,
Michal Suchanek 024a44
 		.len = len
Michal Suchanek 024a44
@@ -50,29 +77,33 @@ int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *params)
Michal Suchanek 024a44
 	if (unlikely(!buf))
Michal Suchanek 024a44
 		return -EINVAL;
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-	if (len != crypto_dh_key_len(params))
Michal Suchanek 024a44
+	if (len == crypto_dh_key_len_no_q(params) && !params->q_size)
Michal Suchanek 024a44
+		do_q = false;
Michal Suchanek 024a44
+	else if (len != crypto_dh_key_len_q(params))
Michal Suchanek 024a44
 		return -EINVAL;
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, &secret, sizeof(secret));
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, &params->key_size, sizeof(params->key_size));
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, &params->p_size, sizeof(params->p_size));
Michal Suchanek 024a44
-	ptr = dh_pack_data(ptr, &params->q_size, sizeof(params->q_size));
Michal Suchanek 024a44
+	if (do_q)
Michal Suchanek 024a44
+		ptr = dh_pack_data(ptr, &params->q_size, sizeof(params->q_size));
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, &params->g_size, sizeof(params->g_size));
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, params->key, params->key_size);
Michal Suchanek 024a44
 	ptr = dh_pack_data(ptr, params->p, params->p_size);
Michal Suchanek 024a44
-	ptr = dh_pack_data(ptr, params->q, params->q_size);
Michal Suchanek 024a44
+	if (do_q)
Michal Suchanek 024a44
+		ptr = dh_pack_data(ptr, params->q, params->q_size);
Michal Suchanek 024a44
 	dh_pack_data(ptr, params->g, params->g_size);
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 	return 0;
Michal Suchanek 024a44
 }
Michal Suchanek 024a44
 EXPORT_SYMBOL_GPL(crypto_dh_encode_key);
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
Michal Suchanek 024a44
+int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh_q *params)
Michal Suchanek 024a44
 {
Michal Suchanek 024a44
 	const u8 *ptr = buf;
Michal Suchanek 024a44
 	struct kpp_secret secret;
Michal Suchanek 024a44
 
Michal Suchanek 024a44
-	if (unlikely(!buf || len < DH_KPP_SECRET_MIN_SIZE))
Michal Suchanek 024a44
+	if (unlikely(!buf || len < DH_KPP_SECRET_MIN_SIZE_NO_Q))
Michal Suchanek 024a44
 		return -EINVAL;
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 	ptr = dh_unpack_data(&secret, ptr, sizeof(secret));
Michal Suchanek 024a44
@@ -81,10 +112,21 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 	ptr = dh_unpack_data(&params->key_size, ptr, sizeof(params->key_size));
Michal Suchanek 024a44
 	ptr = dh_unpack_data(&params->p_size, ptr, sizeof(params->p_size));
Michal Suchanek 024a44
-	ptr = dh_unpack_data(&params->q_size, ptr, sizeof(params->q_size));
Michal Suchanek 024a44
 	ptr = dh_unpack_data(&params->g_size, ptr, sizeof(params->g_size));
Michal Suchanek 024a44
-	if (secret.len != crypto_dh_key_len(params))
Michal Suchanek 024a44
-		return -EINVAL;
Michal Suchanek 024a44
+	params->q_size = 0;
Michal Suchanek 024a44
+	/*
Michal Suchanek 024a44
+	 * G is not optional so if we assigned q_size to g_size here when
Michal Suchanek 024a44
+	 * decoding a new key with Q parameter the length will not match on
Michal Suchanek 024a44
+	 * well-formed key.
Michal Suchanek 024a44
+	 */
Michal Suchanek 024a44
+	if (secret.len != crypto_dh_key_len_no_q(params)) {
Michal Suchanek 024a44
+		if (len < DH_KPP_SECRET_MIN_SIZE)
Michal Suchanek 024a44
+			return -EINVAL;
Michal Suchanek 024a44
+		params->q_size = params->g_size;
Michal Suchanek 024a44
+		ptr = dh_unpack_data(&params->g_size, ptr, sizeof(params->g_size));
Michal Suchanek 024a44
+		if (secret.len != crypto_dh_key_len_q(params))
Michal Suchanek 024a44
+			return -EINVAL;
Michal Suchanek 024a44
+	}
Michal Suchanek 024a44
 
Michal Suchanek 024a44
 	/*
Michal Suchanek 024a44
 	 * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
Michal Suchanek 024a44
@@ -118,3 +160,40 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
Michal Suchanek 024a44
 	return 0;
Michal Suchanek 024a44
 }
Michal Suchanek 024a44
 EXPORT_SYMBOL_GPL(crypto_dh_decode_key);
Michal Suchanek 024a44
+
Michal Suchanek 024a44
+#undef crypto_dh_encode_key
Michal Suchanek 024a44
+#undef crypto_dh_decode_key
Michal Suchanek 024a44
+
Michal Suchanek 7803c1
+int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *old_params)
Michal Suchanek 7803c1
+{
Michal Suchanek 7803c1
+	struct dh_q params = {
Michal Suchanek 7803c1
+		.q_size = 0, .q = NULL,
Michal Suchanek 7803c1
+		.key_size = old_params->key_size,
Michal Suchanek 7803c1
+		.p_size = old_params->p_size,
Michal Suchanek 7803c1
+		.g_size = old_params->g_size,
Michal Suchanek 7803c1
+		.key = old_params->key,
Michal Suchanek 7803c1
+		.p = old_params->p,
Michal Suchanek 7803c1
+		.g = old_params->g,
Michal Suchanek 7803c1
+	};
Michal Suchanek 7803c1
+	return crypto_dh_encode_key_q(buf, len, &params);
Michal Suchanek 7803c1
+
Michal Suchanek 7803c1
+}
Michal Suchanek 7803c1
+EXPORT_SYMBOL_GPL(crypto_dh_encode_key);
Michal Suchanek 7803c1
+
Michal Suchanek 7803c1
+int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *old_params)
Michal Suchanek 7803c1
+{
Michal Suchanek 7803c1
+	struct dh_q params;
Michal Suchanek 7803c1
+	int ret = crypto_dh_decode_key_q(buf, len, &params);
Michal Suchanek 7803c1
+	if (ret)
Michal Suchanek 7803c1
+		return ret;
Michal Suchanek 7803c1
+	if (params.q_size)
Michal Suchanek 7803c1
+		return -EOPNOTSUPP;
Michal Suchanek 7803c1
+	old_params->key_size = params.key_size;
Michal Suchanek 7803c1
+	old_params->p_size = params.p_size;
Michal Suchanek 7803c1
+	old_params->g_size = params.g_size;
Michal Suchanek 7803c1
+	old_params->key = params.key;
Michal Suchanek 7803c1
+	old_params->p = params.p;
Michal Suchanek 7803c1
+	old_params->g = params.g;
Michal Suchanek 7803c1
+	return ret;
Michal Suchanek 7803c1
+}
Michal Suchanek 7803c1
+EXPORT_SYMBOL_GPL(crypto_dh_decode_key);
Michal Suchanek 024a44
diff --git a/include/crypto/dh.h b/include/crypto/dh.h
Michal Suchanek 024a44
index 6952b63f2957..b6b269878b57 100644
Michal Suchanek 7803c1
--- a/include/crypto/dh.h
Michal Suchanek 7803c1
+++ b/include/crypto/dh.h
Michal Suchanek 024a44
@@ -13,6 +13,31 @@
Michal Suchanek 024a44
 #ifndef _CRYPTO_DH_
Michal Suchanek 7803c1
 #define _CRYPTO_DH_
Michal Suchanek 7803c1
 
Michal Suchanek 024a44
+/**
Michal Suchanek 7803c1
+ * struct dh - define a DH private key for old API without Q parameter
Michal Suchanek 7803c1
+ *
Michal Suchanek 7803c1
+ * @key:	Private DH key
Michal Suchanek 7803c1
+ * @p:		Diffie-Hellman parameter P
Michal Suchanek 7803c1
+ * @g:		Diffie-Hellman generator G
Michal Suchanek 7803c1
+ * @key_size:	Size of the private DH key
Michal Suchanek 7803c1
+ * @p_size:	Size of DH parameter P
Michal Suchanek 7803c1
+ * @g_size:	Size of DH generator G
Michal Suchanek 7803c1
+ */
Michal Suchanek 7803c1
+struct dh {
Michal Suchanek 7803c1
+	void *key;
Michal Suchanek 7803c1
+	void *p;
Michal Suchanek 7803c1
+	void *g;
Michal Suchanek 7803c1
+	unsigned int key_size;
Michal Suchanek 7803c1
+	unsigned int p_size;
Michal Suchanek 7803c1
+	unsigned int g_size;
Michal Suchanek 7803c1
+};
Michal Suchanek 7803c1
+
Michal Suchanek 7803c1
+/* kABI we added the q parameter to struct dh so interface of these functions changed. */
Michal Suchanek a30af0
+#define dh dh_q
Michal Suchanek 7803c1
+#define crypto_dh_key_len crypto_dh_key_len_q
Michal Suchanek 7803c1
+#define crypto_dh_encode_key crypto_dh_encode_key_q
Michal Suchanek 7803c1
+#define crypto_dh_decode_key crypto_dh_decode_key_q
Michal Suchanek 7803c1
+
Michal Suchanek 024a44
 /**
Michal Suchanek 7803c1
  * DOC: DH Helper Functions
Michal Suchanek 7803c1
  *
Michal Suchanek 024a44
-- 
Michal Suchanek 024a44
2.23.0
Michal Suchanek 024a44