All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/2] Cipher infrastructure
@ 2015-01-30 10:57 Tomasz Bursztyka
  2015-01-30 10:57 ` [PATCH 1/2] cipher: Add a basic infrastructure for kernel based cipher operations Tomasz Bursztyka
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Tomasz Bursztyka @ 2015-01-30 10:57 UTC (permalink / raw)
  To: ell

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

Hi,

Went quickly through the cipher proposal, to get a somehow working implementation.
Seems to work with aes, but not with arc4.

And now I wonder if we should not provide an initialization vector for some ciphers? (like arc4).

I thought I could set one IV per socket once, but it does not seems so. (thus there is
nothing related to IV in this RFC).

So, should I set iv elements in struct l_cipher, so I could set one one encrypting/decrypting?
It's just a bit annoying with cmsg handling, but I got nice example with libkapi (though this
one mandate the user to provide the iv. I tought we could handle randomly generated ones?)

libkapi is kind of nice as it uses vmsplice and so on. It's just a lot of code, I don't
think we want something that complex.

Tomasz Bursztyka (2):
  cipher: Add a basic infrastructure for kernel based cipher operations
  unit: Add unit test for the cipher infrastructure

 Makefile.am        |  11 ++-
 ell/cipher.c       | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/cipher.h       |  51 +++++++++++++
 ell/ell.h          |   1 +
 unit/test-cipher.c | 109 +++++++++++++++++++++++++++
 5 files changed, 384 insertions(+), 3 deletions(-)
 create mode 100644 ell/cipher.c
 create mode 100644 ell/cipher.h
 create mode 100644 unit/test-cipher.c

-- 
2.0.5


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

* [PATCH 1/2] cipher: Add a basic infrastructure for kernel based cipher operations
  2015-01-30 10:57 [RFC 0/2] Cipher infrastructure Tomasz Bursztyka
@ 2015-01-30 10:57 ` Tomasz Bursztyka
  2015-01-30 10:57 ` [PATCH 2/2] unit: Add unit test for the cipher infrastructure Tomasz Bursztyka
  2015-02-02 18:44 ` [RFC 0/2] Cipher infrastructure Denis Kenzior
  2 siblings, 0 replies; 5+ messages in thread
From: Tomasz Bursztyka @ 2015-01-30 10:57 UTC (permalink / raw)
  To: ell

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

This will let the possibility to use the crypto API provided by the
kernel in a simple manner. However, it's worth noticing such API might
not be relevant if a lot of big frames need to processed, where it will
be better to get non blocking sockets as well as lowering the memory
copies via vmsplice/splice.
---
 Makefile.am  |   6 +-
 ell/cipher.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/cipher.h |  51 ++++++++++++++
 ell/ell.h    |   1 +
 4 files changed, 271 insertions(+), 2 deletions(-)
 create mode 100644 ell/cipher.c
 create mode 100644 ell/cipher.h

diff --git a/Makefile.am b/Makefile.am
index 50f81eb..910d5e0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,7 +33,8 @@ pkginclude_HEADERS = ell/ell.h \
 			ell/genl.h \
 			ell/dbus.h \
 			ell/dbus-service.h \
-			ell/hwdb.h
+			ell/hwdb.h \
+			ell/cipher.h
 
 lib_LTLIBRARIES = ell/libell.la
 
@@ -67,7 +68,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
 			ell/gvariant-util.c \
 			ell/siphash-private.h \
 			ell/siphash.c \
-			ell/hwdb.c
+			ell/hwdb.c \
+			ell/cipher.c
 
 ell_libell_la_LDFLAGS = -no-undefined \
 			-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/cipher.c b/ell/cipher.c
new file mode 100644
index 0000000..230d1af
--- /dev/null
+++ b/ell/cipher.c
@@ -0,0 +1,215 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2015  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "util.h"
+#include "cipher.h"
+#include "private.h"
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+#ifndef AF_ALG
+#define AF_ALG	38
+#define PF_ALG	AF_ALG
+
+#include <linux/types.h>
+
+struct sockaddr_alg {
+	__u16	salg_family;
+	__u8	salg_type[14];
+	__u32	salg_feat;
+	__u32	salg_mask;
+	__u8	salg_name[64];
+};
+
+struct af_alg_iv {
+	__u32   ivlen;
+	__u8    iv[0];
+};
+
+/* Socket options */
+#define ALG_SET_KEY	1
+#define ALG_SET_IV	2
+#define ALG_SET_OP	3
+
+/* Operations */
+#define ALG_OP_DECRYPT	0
+#define ALG_OP_ENCRYPT	1
+
+#else
+#include <linux/if_alg.h>
+#endif
+
+#define is_valid_type(type)  ((type) <= L_CIPHER_ARC4)
+
+static struct {
+	int sk;
+	unsigned int count;
+} alg_list[L_CIPHER_ARC4 + 1];
+
+struct l_cipher {
+	enum l_cipher_type type;
+	int sk;
+};
+
+LIB_EXPORT struct l_cipher *l_cipher_new(enum l_cipher_type type,
+						const void *key,
+						size_t key_length)
+{
+	struct sockaddr_alg salg;
+	struct l_cipher *cipher;
+	int sk;
+
+	if (!is_valid_type(type))
+		return NULL;
+
+	cipher = l_new(struct l_cipher, 1);
+
+	cipher->type = type;
+
+	if (alg_list[type].sk > 0) {
+		sk = alg_list[type].sk;
+		goto accept;
+	}
+
+	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		goto error;
+
+	memset(&salg, 0, sizeof(salg));
+	salg.salg_family = AF_ALG;
+	strcpy((char *) salg.salg_type, "skcipher");
+
+	switch (type) {
+	case L_CIPHER_AES:
+		strcpy((char *) salg.salg_name, "ecb(aes)");
+		break;
+	case L_CIPHER_ARC4:
+		strcpy((char *) salg.salg_name, "ecb(arc4)");
+		break;
+	}
+
+	if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0)
+		goto error;
+accept:
+	if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, key_length) < 0)
+		goto error;
+
+	cipher->sk = accept4(sk, NULL, 0, SOCK_CLOEXEC);
+	if (cipher->sk < 0)
+		goto error;
+
+	if (alg_list[type].sk == 0) {
+		alg_list[type].sk = sk;
+		alg_list[type].count = 1;
+	} else
+		alg_list[type].count++;
+
+	return cipher;
+error:
+	if (sk > 0 && alg_list[type].sk == 0)
+		close(sk);
+
+	l_free(cipher);
+
+	return NULL;
+}
+
+LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
+{
+	if (unlikely(!cipher))
+		return;
+
+	alg_list[cipher->type].count--;
+
+	close(cipher->sk);
+
+	if (alg_list[cipher->type].count == 0) {
+		close(alg_list[cipher->type].sk);
+		alg_list[cipher->type].sk = 0;
+	}
+
+	l_free(cipher);
+}
+
+static void operate_cipher(int sk, __u32 operation,
+				const void *in, void *out, size_t len)
+{
+	char c_msg_buf[CMSG_SPACE(sizeof(operation))] = {};
+	struct msghdr msg = {};
+	struct cmsghdr *c_msg;
+	struct iovec iov;
+
+	msg.msg_control = c_msg_buf;
+	msg.msg_controllen = sizeof(c_msg_buf);
+
+	c_msg = CMSG_FIRSTHDR(&msg);
+	c_msg->cmsg_level = SOL_ALG;
+	c_msg->cmsg_type = ALG_SET_OP;
+	c_msg->cmsg_len = CMSG_LEN(sizeof(operation));
+	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
+
+	iov.iov_base = (void *) in;
+	iov.iov_len = len;
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+
+	if (sendmsg(sk, &msg, 0) < 0)
+		return;
+
+	if (read(sk, out, len) < 0)
+		return;
+}
+
+LIB_EXPORT void l_cipher_encrypt(struct l_cipher *cipher,
+					const void *in, void *out, size_t len)
+{
+	if (unlikely(!cipher))
+		return;
+
+	if (unlikely(!in) || unlikely(!out))
+		return;
+
+	operate_cipher(cipher->sk, ALG_OP_ENCRYPT, in, out, len);
+}
+
+LIB_EXPORT void l_cipher_decrypt(struct l_cipher *cipher,
+					const void *in, void *out, size_t len)
+{
+	if (unlikely(!cipher))
+		return;
+
+	if (unlikely(!in) || unlikely(!out))
+		return;
+
+	operate_cipher(cipher->sk, ALG_OP_DECRYPT, in, out, len);
+}
diff --git a/ell/cipher.h b/ell/cipher.h
new file mode 100644
index 0000000..644d350
--- /dev/null
+++ b/ell/cipher.h
@@ -0,0 +1,51 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2015  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __ELL_CIPHER_H
+#define __ELL_CIPHER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_cipher;
+
+enum l_cipher_type {
+	L_CIPHER_AES,
+	L_CIPHER_ARC4,
+};
+
+struct l_cipher *l_cipher_new(enum l_cipher_type type,
+				const void *key, size_t key_length);
+void l_cipher_free(struct l_cipher *cipher);
+
+void l_cipher_encrypt(struct l_cipher *cipher,
+			const void *in, void *out, size_t len);
+
+void l_cipher_decrypt(struct l_cipher *cipher,
+			const void *in, void *out, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_CIPHER_H */
diff --git a/ell/ell.h b/ell/ell.h
index c4dc1f2..4d9afa3 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -35,6 +35,7 @@
 #include <ell/checksum.h>
 #include <ell/settings.h>
 #include <ell/hwdb.h>
+#include <ell/cipher.h>
 
 #include <ell/netlink.h>
 #include <ell/genl.h>
-- 
2.0.5


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

* [PATCH 2/2] unit: Add unit test for the cipher infrastructure
  2015-01-30 10:57 [RFC 0/2] Cipher infrastructure Tomasz Bursztyka
  2015-01-30 10:57 ` [PATCH 1/2] cipher: Add a basic infrastructure for kernel based cipher operations Tomasz Bursztyka
@ 2015-01-30 10:57 ` Tomasz Bursztyka
  2015-02-02 18:44 ` [RFC 0/2] Cipher infrastructure Denis Kenzior
  2 siblings, 0 replies; 5+ messages in thread
From: Tomasz Bursztyka @ 2015-01-30 10:57 UTC (permalink / raw)
  To: ell

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

It quickly encrypt, verify that the buffer has different content, and
again decrypt and verify now it has the same content.
---
 Makefile.am        |   5 ++-
 unit/test-cipher.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+), 1 deletion(-)
 create mode 100644 unit/test-cipher.c

diff --git a/Makefile.am b/Makefile.am
index 910d5e0..e32054f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -107,7 +107,8 @@ unit_tests = unit/test-unit \
 			unit/test-gvariant-util \
 			unit/test-gvariant-message \
 			unit/test-siphash \
-			unit/test-hwdb
+			unit/test-hwdb \
+			unit/test-cipher
 
 if MAINTAINER_MODE
 noinst_PROGRAMS += $(unit_tests)
@@ -157,6 +158,8 @@ unit_test_siphash_LDADD = ell/libell-private.la
 
 unit_test_hwdb_LDADD = ell/libell-private.la
 
+unit_test_cipher_LDADD = ell/libell-private.la
+
 if MAINTAINER_MODE
 noinst_LTLIBRARIES += unit/example-plugin.la
 endif
diff --git a/unit/test-cipher.c b/unit/test-cipher.c
new file mode 100644
index 0000000..f52cac5
--- /dev/null
+++ b/unit/test-cipher.c
@@ -0,0 +1,109 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2015  Intel Corporation. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+
+#include <ell/ell.h>
+
+#define FIXED_STR  "The quick brown fox jumps over the lazy dog. " \
+		   "Jackdaws love my big sphinx of quartz. "       \
+		   "Pack my box with five dozen liquor jugs. "     \
+		   "How razorback-jumping frogs can level six piqued gymnasts!"
+#define FIXED_LEN  (strlen (FIXED_STR))
+
+#define KEY_STR "This key has exactly _32_ bytes!"
+#define KEY_LEN (strlen (KEY_STR))
+
+static void test_unsupported(const void *data)
+{
+	struct l_cipher *cipher;
+
+	cipher = l_cipher_new(42, KEY_STR, KEY_LEN);
+	assert(!cipher);
+}
+
+static void test_aes(const void *data)
+{
+	struct l_cipher *cipher;
+	char in[256] = {};
+	char out[256] = {};
+	int r;
+
+	cipher = l_cipher_new(L_CIPHER_AES, KEY_STR, KEY_LEN);
+	assert(cipher);
+
+	memcpy(in, FIXED_STR, FIXED_LEN);
+
+	l_cipher_encrypt(cipher, in, out, 256);
+
+	r = memcmp(out, FIXED_STR, FIXED_LEN);
+	assert(r);
+
+	l_cipher_decrypt(cipher, out, in, 256);
+
+	r = memcmp(in, FIXED_STR, FIXED_LEN);
+	assert(!r);
+
+	l_cipher_free(cipher);
+}
+
+static void test_arc4(const void *data)
+{
+	struct l_cipher *cipher;
+	char in[256] = {};
+	char out[256] = {};
+	int r;
+
+	cipher = l_cipher_new(L_CIPHER_ARC4, KEY_STR, KEY_LEN);
+	assert(cipher);
+
+	memcpy(in, FIXED_STR, FIXED_LEN);
+
+	l_cipher_encrypt(cipher, in, out, 256);
+
+	r = memcmp(out, FIXED_STR, FIXED_LEN);
+	assert(r);
+
+	l_cipher_decrypt(cipher, out, in, 256);
+
+	r = memcmp(in, FIXED_STR, FIXED_LEN);
+	assert(!r);
+
+	l_cipher_free(cipher);
+}
+
+int main(int argc, char *argv[])
+{
+	l_test_init(&argc, &argv);
+
+	l_test_add("unsupported", test_unsupported, NULL);
+
+	l_test_add("aes", test_aes, NULL);
+
+	l_test_add("arc4", test_arc4, NULL);
+
+	return l_test_run();
+}
-- 
2.0.5


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

* Re: [RFC 0/2] Cipher infrastructure
  2015-01-30 10:57 [RFC 0/2] Cipher infrastructure Tomasz Bursztyka
  2015-01-30 10:57 ` [PATCH 1/2] cipher: Add a basic infrastructure for kernel based cipher operations Tomasz Bursztyka
  2015-01-30 10:57 ` [PATCH 2/2] unit: Add unit test for the cipher infrastructure Tomasz Bursztyka
@ 2015-02-02 18:44 ` Denis Kenzior
  2015-02-03  8:07   ` Tomasz Bursztyka
  2 siblings, 1 reply; 5+ messages in thread
From: Denis Kenzior @ 2015-02-02 18:44 UTC (permalink / raw)
  To: ell

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

Hi Tomasz,

On 01/30/2015 04:57 AM, Tomasz Bursztyka wrote:
> Hi,
>
> Went quickly through the cipher proposal, to get a somehow working implementation.
> Seems to work with aes, but not with arc4.
>

ARC4 is a bit weird.  The same function is used for encryption and 
decryption, so the stream is not reset.  You will likely need to set the 
key prior to each encrypt/decrypt operation.

> And now I wonder if we should not provide an initialization vector for some ciphers? (like arc4).
>

I'm still not fully sure we need the IV.  EAPoL Key-IV is only used in 
certain situations.  Lets try to find an AP / trace that actually sets 
the IV field.

Regards,
-Denis

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

* Re: [RFC 0/2] Cipher infrastructure
  2015-02-02 18:44 ` [RFC 0/2] Cipher infrastructure Denis Kenzior
@ 2015-02-03  8:07   ` Tomasz Bursztyka
  0 siblings, 0 replies; 5+ messages in thread
From: Tomasz Bursztyka @ 2015-02-03  8:07 UTC (permalink / raw)
  To: ell

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

Hi Denis,

> Hi Tomasz,
>
> On 01/30/2015 04:57 AM, Tomasz Bursztyka wrote:
>> Hi,
>>
>> Went quickly through the cipher proposal, to get a somehow working 
>> implementation.
>> Seems to work with aes, but not with arc4.
>>
>
> ARC4 is a bit weird.  The same function is used for encryption and 
> decryption, so the stream is not reset.  You will likely need to set 
> the key prior to each encrypt/decrypt operation.

OK.

>
>> And now I wonder if we should not provide an initialization vector 
>> for some ciphers? (like arc4).
>>
>
> I'm still not fully sure we need the IV.  EAPoL Key-IV is only used in 
> certain situations.  Lets try to find an AP / trace that actually sets 
> the IV field.
>

Ok, then I think it's worth putting an iv/iv-len params to the 
l_cipher_new(). I might implement its support later though, let's see 
(but at least the API would be fixed).

Tomasz

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

end of thread, other threads:[~2015-02-03  8:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-30 10:57 [RFC 0/2] Cipher infrastructure Tomasz Bursztyka
2015-01-30 10:57 ` [PATCH 1/2] cipher: Add a basic infrastructure for kernel based cipher operations Tomasz Bursztyka
2015-01-30 10:57 ` [PATCH 2/2] unit: Add unit test for the cipher infrastructure Tomasz Bursztyka
2015-02-02 18:44 ` [RFC 0/2] Cipher infrastructure Denis Kenzior
2015-02-03  8:07   ` Tomasz Bursztyka

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.