All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cipher: add AES-CMAC hashing support
@ 2019-05-29  0:49 Brian Gix
  2019-05-29  1:32 ` Denis Kenzior
  0 siblings, 1 reply; 15+ messages in thread
From: Brian Gix @ 2019-05-29  0:49 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 7125 bytes --]

The algorythm is supported in the kernel, and it is used heavily by
Bluetooth Mesh, and is the one Mesh required algorythm missing from ELL.
---
 ell/cipher.c       | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/cipher.h       | 16 ++++++++++
 unit/test-cipher.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+)

diff --git a/ell/cipher.c b/ell/cipher.c
index 7b909df..2f2e482 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -90,6 +90,7 @@ struct af_alg_iv {
 
 static uint32_t supported_ciphers;
 static uint32_t supported_aead_ciphers;
+static uint32_t supported_hash_ciphers;
 
 struct l_cipher {
 	int type;
@@ -103,6 +104,11 @@ struct l_aead_cipher {
 	int decrypt_sk;
 };
 
+struct l_hash_cipher {
+	int type;
+	int encrypt_sk;
+};
+
 static int create_alg(const char *alg_type, const char *alg_name,
 			const void *key, size_t key_length, size_t tag_length)
 {
@@ -248,6 +254,42 @@ error_free:
 	return NULL;
 }
 
+static const char *hash_cipher_type_to_name(enum l_hash_cipher_type type)
+{
+	switch (type) {
+	case L_HASH_CIPHER_AES_CMAC:
+		return "cmac(aes)";
+	}
+
+	return NULL;
+}
+
+LIB_EXPORT struct l_hash_cipher *l_hash_cipher_new(enum l_hash_cipher_type type,
+							const void *key,
+							size_t key_length)
+{
+	struct l_hash_cipher *cipher;
+	const char *uninitialized_var(alg_name);
+
+	if (unlikely(!key))
+		return NULL;
+
+	if (type != L_HASH_CIPHER_AES_CMAC)
+		return NULL;
+
+	cipher = l_new(struct l_hash_cipher, 1);
+	cipher->type = type;
+	alg_name = hash_cipher_type_to_name(type);
+
+	cipher->encrypt_sk = create_alg("hash", alg_name, key, key_length,
+					0);
+	if (cipher->encrypt_sk >= 0)
+		return cipher;
+
+	l_free(cipher);
+	return NULL;
+}
+
 LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
 {
 	if (unlikely(!cipher))
@@ -270,6 +312,16 @@ LIB_EXPORT void l_aead_cipher_free(struct l_aead_cipher *cipher)
 	l_free(cipher);
 }
 
+LIB_EXPORT void l_hash_cipher_free(struct l_hash_cipher *cipher)
+{
+	if (unlikely(!cipher))
+		return;
+
+	close(cipher->encrypt_sk);
+
+	l_free(cipher);
+}
+
 static ssize_t operate_cipher(int sk, __u32 operation,
 				const void *in, size_t in_len,
 				const void *ad, size_t ad_len,
@@ -610,6 +662,20 @@ LIB_EXPORT bool l_aead_cipher_decrypt(struct l_aead_cipher *cipher,
 			(ssize_t)out_len;
 }
 
+LIB_EXPORT bool l_hash_cipher_encrypt(struct l_hash_cipher *cipher,
+					const void *in, size_t in_len,
+					void *out, size_t out_len)
+{
+	if (unlikely(!cipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, in_len,
+				NULL, 0, NULL, 0, out, out_len) >= 0;
+}
+
 static void init_supported()
 {
 	static bool initialized = false;
@@ -617,6 +683,7 @@ static void init_supported()
 	int sk;
 	enum l_cipher_type c;
 	enum l_aead_cipher_type a;
+	enum l_hash_cipher_type h;
 
 	if (likely(initialized))
 		return;
@@ -651,6 +718,17 @@ static void init_supported()
 		supported_aead_ciphers |= 1 << a;
 	}
 
+	strcpy((char *) salg.salg_type, "hash");
+
+	for (h = L_HASH_CIPHER_AES_CMAC; h <= L_HASH_CIPHER_AES_CMAC; h++) {
+		strcpy((char *) salg.salg_name, hash_cipher_type_to_name(h));
+
+		if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0)
+			continue;
+
+		supported_hash_ciphers |= 1 << h;
+	}
+
 	close(sk);
 }
 
@@ -673,3 +751,13 @@ LIB_EXPORT bool l_aead_cipher_is_supported(enum l_aead_cipher_type type)
 
 	return supported_aead_ciphers & (1 << type);
 }
+
+LIB_EXPORT bool l_hash_cipher_is_supported(enum l_hash_cipher_type type)
+{
+	if (type != L_HASH_CIPHER_AES_CMAC)
+		return false;
+
+	init_supported();
+
+	return supported_hash_ciphers & (1 << type);
+}
diff --git a/ell/cipher.h b/ell/cipher.h
index 84f2988..a18fbf0 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -84,8 +84,24 @@ bool l_aead_cipher_decrypt(struct l_aead_cipher *cipher,
 				const void *nonce, size_t nonce_len,
 				void *out, size_t out_len);
 
+struct l_hash_cipher;
+
+enum l_hash_cipher_type {
+	L_HASH_CIPHER_AES_CMAC = 0,
+};
+
+struct l_hash_cipher *l_hash_cipher_new(enum l_hash_cipher_type type,
+					const void *key, size_t key_length);
+
+void l_hash_cipher_free(struct l_hash_cipher *cipher);
+
+bool l_hash_cipher_encrypt(struct l_hash_cipher *cipher,
+					const void *in, size_t len,
+					void *out, size_t out_len);
+
 bool l_cipher_is_supported(enum l_cipher_type type);
 bool l_aead_cipher_is_supported(enum l_aead_cipher_type type);
+bool l_hash_cipher_is_supported(enum l_hash_cipher_type type);
 
 #ifdef __cplusplus
 }
diff --git a/unit/test-cipher.c b/unit/test-cipher.c
index 3bb7602..7d08f39 100644
--- a/unit/test-cipher.c
+++ b/unit/test-cipher.c
@@ -358,6 +358,75 @@ static void test_aead(const void *data)
 	l_free(tag);
 }
 
+struct hash_test_vector {
+	enum l_hash_cipher_type type;
+	char *plaintext;
+	char *key;
+	char *ciphertext;
+};
+
+/* Hash AES_CMAC tests based on Bluetooth Mesh published sample data */
+static const struct hash_test_vector hash_test1 = {
+	.type = L_HASH_CIPHER_AES_CMAC,
+	.plaintext = "74657374",
+	.key = "00000000000000000000000000000000",
+	.ciphertext = "b73cefbd641ef2ea598c2b6efb62f79c",
+};
+
+static const struct hash_test_vector hash_test2 = {
+	.type = L_HASH_CIPHER_AES_CMAC,
+	.plaintext = "f7a2a44f8e8a8029064f173ddc1e2b00",
+	.key = "4f90480c1871bfbffd16971f4d8d10b1",
+	.ciphertext = "2ea6467aa3378c4c545eda62935b9b86",
+};
+
+static void test_hash(const void *data)
+{
+	struct l_hash_cipher *cipher;
+	char *encbuf;
+	size_t encbuflen;
+	char *decbuf;
+	size_t decbuflen;
+	int r;
+	bool success;
+	const struct hash_test_vector *tv = data;
+
+	size_t ptlen;
+	uint8_t *pt = l_util_from_hexstring(tv->plaintext, &ptlen) ?:
+		(uint8_t[]) {};
+	size_t keylen;
+	uint8_t *key = l_util_from_hexstring(tv->key, &keylen);
+	size_t ctlen;
+	uint8_t *ct = l_util_from_hexstring(tv->ciphertext, &ctlen) ?:
+		(uint8_t[]) {};
+
+	encbuflen = ctlen;
+	encbuf = alloca(encbuflen);
+	memset(encbuf, 0, encbuflen);
+	decbuflen = ptlen;
+	decbuf = alloca(decbuflen);
+	memset(decbuf, 0, decbuflen);
+
+	cipher = l_hash_cipher_new(tv->type, key, keylen);
+	assert(cipher);
+
+	success = l_hash_cipher_encrypt(cipher, pt, ptlen, encbuf, encbuflen);
+	assert(success);
+
+	r = memcmp(encbuf, ct, ctlen);
+	assert(!r);
+
+	l_hash_cipher_free(cipher);
+
+	if (ptlen)
+		l_free(pt);
+
+	l_free(key);
+
+	if (ctlen)
+		l_free(ct);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -388,5 +457,10 @@ int main(int argc, char *argv[])
 		l_test_add("aes_gcm test 6", test_aead, &gcm_test6);
 	}
 
+	if (l_hash_cipher_is_supported(L_HASH_CIPHER_AES_CMAC)) {
+		l_test_add("hash_aes_cmac test 1", test_hash, &hash_test1);
+		l_test_add("hash_aes_cmac test 2", test_hash, &hash_test2);
+	}
+
 	return l_test_run();
 }
-- 
2.14.5


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-05-31 23:12 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-29  0:49 [PATCH] cipher: add AES-CMAC hashing support Brian Gix
2019-05-29  1:32 ` Denis Kenzior
2019-05-29  3:04   ` Gix, Brian
2019-05-29  3:25     ` Gix, Brian
2019-05-29 10:52       ` =?unknown-8bit?q?Micha=C5=82?= Lowas-Rzechonek
2019-05-29 15:29         ` Gix, Brian
2019-05-29 19:26           ` michal.lowas-rzechonek
2019-05-29 20:07             ` Gix, Brian
2019-05-29 16:14         ` Denis Kenzior
2019-05-31 17:28           ` ELL building broken for 32bit systems Gix, Brian
2019-05-31 17:41             ` Gix, Brian
2019-05-31 19:53             ` Denis Kenzior
2019-05-31 20:28               ` Gix, Brian
2019-05-31 20:44                 ` Denis Kenzior
2019-05-31 23:12                   ` Gix, Brian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.