All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/7] key: Consistently return errno from syscall wrappers
@ 2016-07-29 18:11 Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 2/7] checksum: Add L_CHECKSUM_NONE, needed for key crypto Mat Martineau
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:11 UTC (permalink / raw)
  To: ell

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

---
 ell/key.c | 44 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 7 deletions(-)

diff --git a/ell/key.c b/ell/key.c
index 6117e31..a8d011a 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -29,6 +29,7 @@
 #include <stdint.h>
 #include <sys/syscall.h>
 #include <linux/keyctl.h>
+#include <errno.h>
 
 #include "private.h"
 #include "util.h"
@@ -64,43 +65,72 @@ static const char * const key_type_names[] = {
 static long kernel_add_key(const char *type, const char *description,
 				const void *payload, size_t len, int32_t keyring)
 {
-	return syscall(__NR_add_key, type, description, payload, len, keyring);
+	long result;
+
+	result = syscall(__NR_add_key, type, description, payload, len,
+				keyring);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_read_key(int32_t serial, const void *payload, size_t len)
 {
-	return syscall(__NR_keyctl, KEYCTL_READ, serial, payload, len);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_READ, serial, payload, len);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_update_key(int32_t serial, const void *payload, size_t len)
 {
-	return syscall(__NR_keyctl, KEYCTL_UPDATE, serial, payload, len);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_UPDATE, serial, payload, len);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_revoke_key(int32_t serial)
 {
-	return syscall(__NR_keyctl, KEYCTL_REVOKE, serial);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_REVOKE, serial);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_link_key(int32_t key_serial, int32_t ring_serial)
 {
-	return syscall(__NR_keyctl, KEYCTL_LINK, key_serial, ring_serial);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_LINK, key_serial, ring_serial);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_unlink_key(int32_t key_serial, int32_t ring_serial)
 {
-	return syscall(__NR_keyctl, KEYCTL_UNLINK, key_serial, ring_serial);
+	long result;
+
+	result = syscall(__NR_keyctl, KEYCTL_UNLINK, key_serial, ring_serial);
+
+	return result >= 0 ? result : -errno;
 }
 
 static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
 			      void *payload, size_t len)
 {
+	long result;
+
 	struct keyctl_dh_params params = { .private = private,
 					   .prime = prime,
 					   .base = base };
 
-	return syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, &params, payload, len,
+	result = syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, &params, payload, len,
 			NULL);
+
+	return result >= 0 ? result : -errno;
 }
 
 static bool setup_internal_keyring(void)
-- 
2.9.2


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

* [PATCH v2 2/7] checksum: Add L_CHECKSUM_NONE, needed for key crypto
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
@ 2016-07-29 18:11 ` Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose Mat Martineau
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:11 UTC (permalink / raw)
  To: ell

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

---
 ell/checksum.c | 8 ++++++--
 ell/checksum.h | 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/ell/checksum.c b/ell/checksum.c
index 7b0e3ee..68be73f 100644
--- a/ell/checksum.c
+++ b/ell/checksum.c
@@ -124,9 +124,9 @@ LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
 	if (!is_valid_type(type))
 		return NULL;
 
-	checksum = l_new(struct l_checksum, 1);
-
 	switch (type) {
+	case L_CHECKSUM_NONE:
+		return NULL;
 	case L_CHECKSUM_MD5:
 		name = "md5";
 		break;
@@ -144,6 +144,8 @@ LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
 		break;
 	}
 
+	checksum = l_new(struct l_checksum, 1);
+
 	fd = create_alg(name);
 	if (fd < 0)
 		goto error;
@@ -202,6 +204,8 @@ struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
 		return NULL;
 
 	switch (type) {
+	case L_CHECKSUM_NONE:
+		return NULL;
 	case L_CHECKSUM_MD5:
 		name = "hmac(md5)";
 		break;
diff --git a/ell/checksum.h b/ell/checksum.h
index 34401a6..e6eceb9 100644
--- a/ell/checksum.h
+++ b/ell/checksum.h
@@ -32,6 +32,7 @@ extern "C" {
 struct l_checksum;
 
 enum l_checksum_type {
+	L_CHECKSUM_NONE,
 	L_CHECKSUM_MD5,
 	L_CHECKSUM_SHA1,
 	L_CHECKSUM_SHA256,
-- 
2.9.2


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

* [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 2/7] checksum: Add L_CHECKSUM_NONE, needed for key crypto Mat Martineau
@ 2016-07-29 18:11 ` Mat Martineau
  2016-08-01 21:15   ` Denis Kenzior
  2016-07-29 18:11 ` [PATCH v2 4/7] unit: Adjust for renamed l_key_get_payload_size function Mat Martineau
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:11 UTC (permalink / raw)
  To: ell

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

The size returned is the number of bytes needed to store the payload.
---
 ell/key.c | 2 +-
 ell/key.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ell/key.c b/ell/key.c
index a8d011a..8e7b398 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -216,7 +216,7 @@ LIB_EXPORT bool l_key_extract(struct l_key *key, void *payload, size_t *len)
 	return true;
 }
 
-LIB_EXPORT ssize_t l_key_get_size(struct l_key *key)
+LIB_EXPORT ssize_t l_key_get_payload_size(struct l_key *key)
 {
 	return kernel_read_key(key->serial, NULL, 0);
 }
diff --git a/ell/key.h b/ell/key.h
index 5d981f1..4ec32a6 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -52,7 +52,7 @@ bool l_key_update(struct l_key *key, const void *payload, size_t len);
 
 bool l_key_extract(struct l_key *key, void *payload, size_t *len);
 
-ssize_t l_key_get_size(struct l_key *key);
+ssize_t l_key_get_payload_size(struct l_key *key);
 
 bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private,
 			     struct l_key *prime, void *payload, size_t *len);
-- 
2.9.2


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

* [PATCH v2 4/7] unit: Adjust for renamed l_key_get_payload_size function
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 2/7] checksum: Add L_CHECKSUM_NONE, needed for key crypto Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose Mat Martineau
@ 2016-07-29 18:11 ` Mat Martineau
  2016-07-29 18:11 ` [PATCH v2 5/7] key: Rename asymmetric key type to L_KEY_RSA Mat Martineau
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:11 UTC (permalink / raw)
  To: ell

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

---
 unit/test-key.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/unit/test-key.c b/unit/test-key.c
index df1e13b..d52ae1b 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -55,7 +55,7 @@ static void test_user(const void *data)
 	key = l_key_new(L_KEY_RAW, KEY1_STR, KEY1_LEN);
 	assert(key);
 
-	reported_len = l_key_get_size(key);
+	reported_len = l_key_get_payload_size(key);
 	assert(reported_len == KEY1_LEN);
 
 	len = KEY1_LEN - 1;
-- 
2.9.2


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

* [PATCH v2 5/7] key: Rename asymmetric key type to L_KEY_RSA
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
                   ` (2 preceding siblings ...)
  2016-07-29 18:11 ` [PATCH v2 4/7] unit: Adjust for renamed l_key_get_payload_size function Mat Martineau
@ 2016-07-29 18:11 ` Mat Martineau
  2016-07-29 18:12 ` [PATCH v2 6/7] key: Add key-based asymmetric crypto operations Mat Martineau
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:11 UTC (permalink / raw)
  To: ell

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

The kernel automatically determines the correct crypto algorithm using
an OID present in each X.509 key, but it's still important to know which
algorithm it is in userspace so the requested cipher can be matched
up.

RSA is the only asymmetric algorithm supported using the keyctl API as
of v4.8. The crypto algorithm for a key can be parsed out of /proc/keys,
but it may soon be accessible through the keyctl API.
---
 ell/key.c | 9 ++++++++-
 ell/key.h | 2 +-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/ell/key.c b/ell/key.c
index 8e7b398..7dad4a7 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -59,7 +59,7 @@ struct l_keyring {
 
 static const char * const key_type_names[] = {
 	[L_KEY_RAW] = "user",
-	[L_KEY_ASYMMETRIC] = "asymmetric",
+	[L_KEY_RSA] = "asymmetric",
 };
 
 static long kernel_add_key(const char *type, const char *description,
@@ -173,6 +173,13 @@ LIB_EXPORT struct l_key *l_key_new(enum l_key_type type, const void *payload,
 		key = NULL;
 	}
 
+	/*
+	 * TODO: Query asymmetric key algorithm from the kernel and
+	 * ensure that it matches the expected l_key_type. This can
+	 * currently be found by digging through /proc/keys, but a
+	 * keyctl() op makes more sense.
+	 */
+
 	return key;
 }
 
diff --git a/ell/key.h b/ell/key.h
index 4ec32a6..a0b4b64 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -35,7 +35,7 @@ struct l_keyring;
 
 enum l_key_type {
 	L_KEY_RAW = 0,
-	L_KEY_ASYMMETRIC
+	L_KEY_RSA,
 };
 
 enum l_keyring_type {
-- 
2.9.2


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

* [PATCH v2 6/7] key: Add key-based asymmetric crypto operations
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
                   ` (3 preceding siblings ...)
  2016-07-29 18:11 ` [PATCH v2 5/7] key: Rename asymmetric key type to L_KEY_RSA Mat Martineau
@ 2016-07-29 18:12 ` Mat Martineau
  2016-07-29 18:12 ` [PATCH v2 7/7] unit: Add tests for key-based asymmetric crypto Mat Martineau
  2016-08-01 21:16 ` [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Denis Kenzior
  6 siblings, 0 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:12 UTC (permalink / raw)
  To: ell

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

The kernel has asymmetric crypto methods available using the keyctl API
which make use of the kernel keyrings. The main advantage of this API
over AF_ALG is that typical asymmetric operations involve fewer system
calls.
---
 ell/key.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/key.h |  23 +++++++
 2 files changed, 239 insertions(+)

diff --git a/ell/key.c b/ell/key.c
index 7dad4a7..669d257 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -34,6 +34,7 @@
 #include "private.h"
 #include "util.h"
 #include "key.h"
+#include "string.h"
 
 #ifndef KEYCTL_DH_COMPUTE
 #define KEYCTL_DH_COMPUTE 23
@@ -45,6 +46,40 @@ struct keyctl_dh_params {
 };
 #endif
 
+#ifndef KEYCTL_PKEY_QUERY
+#define KEYCTL_PKEY_QUERY	24
+#define KEYCTL_PKEY_ENCRYPT	25
+#define KEYCTL_PKEY_DECRYPT	26
+#define KEYCTL_PKEY_SIGN	27
+#define KEYCTL_PKEY_VERIFY	28
+
+#define KEYCTL_SUPPORTS_ENCRYPT	0x01
+#define KEYCTL_SUPPORTS_DECRYPT	0x02
+#define KEYCTL_SUPPORTS_SIGN	0x04
+#define KEYCTL_SUPPORTS_VERIFY	0x08
+
+struct keyctl_pkey_query {
+	uint32_t supported_ops;
+	uint32_t key_size;
+	uint16_t max_data_size;
+	uint16_t max_sig_size;
+	uint16_t max_enc_size;
+	uint16_t max_dec_size;
+
+	uint32_t __spare[10];
+};
+
+struct keyctl_pkey_params {
+	int32_t key_id;
+	uint32_t in_len;
+	union {
+		uint32_t out_len;
+		uint32_t in2_len;
+	};
+	uint32_t __spare[7];
+};
+#endif
+
 static int32_t internal_keyring;
 
 struct l_key {
@@ -118,6 +153,43 @@ static long kernel_unlink_key(int32_t key_serial, int32_t ring_serial)
 	return result >= 0 ? result : -errno;
 }
 
+static char *format_key_info(const char *encoding, const char *hash)
+{
+	struct l_string *info;
+
+	if (!encoding && !hash)
+		return NULL;
+
+	info = l_string_new(0);
+
+	if (encoding)
+		l_string_append_printf(info, "enc=%s ", encoding);
+
+	if (hash)
+		l_string_append_printf(info, "hash=%s", hash);
+
+	return l_string_free(info, false);
+}
+
+static long kernel_query_key(int32_t key_serial, const char *encoding,
+				const char *hash, size_t *size, bool *public)
+{
+	long result;
+	struct keyctl_pkey_query query;
+	char *info = format_key_info(encoding, hash);
+
+	result = syscall(__NR_keyctl, KEYCTL_PKEY_QUERY, key_serial, 0,
+				info ?: "", &query);
+	if (result == 0) {
+		*size = query.key_size;
+		*public = ((query.supported_ops & KEYCTL_SUPPORTS_ENCRYPT) &&
+			!(query.supported_ops & KEYCTL_SUPPORTS_DECRYPT));
+	}
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
 static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
 			      void *payload, size_t len)
 {
@@ -133,6 +205,40 @@ static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
 	return result >= 0 ? result : -errno;
 }
 
+static long kernel_key_eds(int op, int32_t serial, const char *encoding,
+				const char *hash, const void *in, void *out,
+				size_t len_in, size_t len_out)
+{
+	long result;
+	struct keyctl_pkey_params params = { .key_id = serial,
+					     .in_len = len_in,
+					     .out_len = len_out };
+	char *info = format_key_info(encoding, hash);
+
+	result = syscall(__NR_keyctl, op, &params, info ?: "", in, out);
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
+static long kernel_key_verify(int32_t serial, const char *encoding,
+				const char *hash, const void *data,
+				const void *sig, size_t len_data,
+				size_t len_sig)
+{
+	long result;
+	struct keyctl_pkey_params params = { .key_id = serial,
+					     .in_len = len_data,
+					     .in2_len = len_sig };
+	char *info = format_key_info(encoding, hash);
+
+	result = syscall(__NR_keyctl, KEYCTL_PKEY_VERIFY, &params, info ?: "",
+				data, sig);
+	l_free(info);
+
+	return result >= 0 ? result : -errno;
+}
+
 static bool setup_internal_keyring(void)
 {
 	internal_keyring = kernel_add_key("keyring", "ell-internal", NULL, 0,
@@ -228,6 +334,54 @@ LIB_EXPORT ssize_t l_key_get_payload_size(struct l_key *key)
 	return kernel_read_key(key->serial, NULL, 0);
 }
 
+static const char *lookup_cipher(enum l_asymmetric_cipher_type cipher)
+{
+	const char* ret = NULL;
+
+	switch (cipher) {
+	case L_CIPHER_RSA_PKCS1_V1_5:
+		ret = "pkcs1";
+		break;
+	}
+
+	return ret;
+}
+
+static const char *lookup_checksum(enum l_checksum_type checksum)
+{
+	const char* ret = NULL;
+
+	switch (checksum) {
+	case L_CHECKSUM_NONE:
+		break;
+	case L_CHECKSUM_MD5:
+		ret = "md5";
+		break;
+	case L_CHECKSUM_SHA1:
+		ret = "sha1";
+		break;
+	case L_CHECKSUM_SHA256:
+		ret = "sha256";
+		break;
+	case L_CHECKSUM_SHA384:
+		ret = "sha384";
+		break;
+	case L_CHECKSUM_SHA512:
+		ret = "sha512";
+		break;
+	}
+
+	return ret;
+}
+
+bool l_key_get_info(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type hash, size_t *bits,
+			bool *public)
+{
+	return !kernel_query_key(key->serial, lookup_cipher(cipher),
+					lookup_checksum(hash), bits, public);
+}
+
 static bool compute_common(struct l_key *base,
 			   struct l_key *private,
 			   struct l_key *prime,
@@ -263,6 +417,68 @@ LIB_EXPORT bool l_key_compute_dh_secret(struct l_key *other_public,
 	return compute_common(other_public, private, prime, payload, len);
 }
 
+/* Common code for encrypt/decrypt/sign */
+static ssize_t eds_common(struct l_key *key,
+				enum l_asymmetric_cipher_type cipher,
+				enum l_checksum_type checksum, const void *in,
+				void *out, size_t len_in, size_t len_out,
+				int op)
+{
+	if (unlikely(!key))
+		return -EINVAL;
+
+	return kernel_key_eds(op, key->serial, lookup_cipher(cipher),
+				lookup_checksum(checksum), in, out, len_in,
+				len_out);
+}
+
+LIB_EXPORT ssize_t l_key_encrypt(struct l_key *key,
+					enum l_asymmetric_cipher_type cipher,
+					enum l_checksum_type checksum,
+					const void *in, void *out,
+					size_t len_in, size_t len_out)
+{
+	return eds_common(key, cipher, checksum, in, out, len_in, len_out,
+				KEYCTL_PKEY_ENCRYPT);
+}
+
+LIB_EXPORT ssize_t l_key_decrypt(struct l_key *key,
+					enum l_asymmetric_cipher_type cipher,
+					enum l_checksum_type checksum,
+					const void *in, void *out,
+					size_t len_in, size_t len_out)
+{
+	return eds_common(key, cipher, checksum, in, out, len_in, len_out,
+				KEYCTL_PKEY_DECRYPT);
+}
+
+LIB_EXPORT ssize_t l_key_sign(struct l_key *key,
+				enum l_asymmetric_cipher_type cipher,
+				enum l_checksum_type checksum, const void *in,
+				void *out, size_t len_in, size_t len_out)
+{
+	return eds_common(key, cipher, checksum, in, out, len_in, len_out,
+				KEYCTL_PKEY_SIGN);
+}
+
+LIB_EXPORT bool l_key_verify(struct l_key *key,
+				enum l_asymmetric_cipher_type cipher,
+				enum l_checksum_type checksum, const void *data,
+				const void *sig, size_t len_data,
+				size_t len_sig)
+{
+	long result;
+
+	if (unlikely(!key))
+		return false;
+
+	result = kernel_key_verify(key->serial, lookup_cipher(cipher),
+					lookup_checksum(checksum), data, sig,
+					len_data, len_sig);
+
+	return result == 0;
+}
+
 LIB_EXPORT struct l_keyring *l_keyring_new(enum l_keyring_type type,
 						const struct l_keyring *trusted)
 {
diff --git a/ell/key.h b/ell/key.h
index a0b4b64..9cc69ff 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -30,6 +30,9 @@ extern "C" {
 #include <stddef.h>
 #include <stdbool.h>
 
+#include <ell/checksum.h>
+#include <ell/cipher.h>
+
 struct l_key;
 struct l_keyring;
 
@@ -54,12 +57,32 @@ bool l_key_extract(struct l_key *key, void *payload, size_t *len);
 
 ssize_t l_key_get_payload_size(struct l_key *key);
 
+bool l_key_get_info(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type checksum, size_t *bits,
+			bool *public);
+
 bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private,
 			     struct l_key *prime, void *payload, size_t *len);
 
 bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private,
 			     struct l_key *prime, void *payload, size_t *len);
 
+ssize_t l_key_encrypt(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+ssize_t l_key_decrypt(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+ssize_t l_key_sign(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type checksum, const void *in,
+			void *out, size_t len_in, size_t len_out);
+
+bool l_key_verify(struct l_key *key, enum l_asymmetric_cipher_type cipher,
+			enum l_checksum_type checksum, const void *data,
+			const void *sig, size_t len_data, size_t len_sig);
+
 struct l_keyring *l_keyring_new(enum l_keyring_type type,
 				const struct l_keyring *trust);
 
-- 
2.9.2


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

* [PATCH v2 7/7] unit: Add tests for key-based asymmetric crypto
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
                   ` (4 preceding siblings ...)
  2016-07-29 18:12 ` [PATCH v2 6/7] key: Add key-based asymmetric crypto operations Mat Martineau
@ 2016-07-29 18:12 ` Mat Martineau
  2016-08-01 21:16 ` [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Denis Kenzior
  6 siblings, 0 replies; 9+ messages in thread
From: Mat Martineau @ 2016-07-29 18:12 UTC (permalink / raw)
  To: ell

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

---
 unit/cert-client-key-pkcs8.pem |  28 ++++++
 unit/gencerts.sh               |   1 +
 unit/test-key.c                | 198 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 225 insertions(+), 2 deletions(-)
 create mode 100644 unit/cert-client-key-pkcs8.pem

diff --git a/unit/cert-client-key-pkcs8.pem b/unit/cert-client-key-pkcs8.pem
new file mode 100644
index 0000000..738b825
--- /dev/null
+++ b/unit/cert-client-key-pkcs8.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhOQ/5VIWkwt8S
+9vNbbWT0VEV5Siai8HBxl0ErkJusMGFrQIS8jCxB668hNKAoSncN3lezZ/yDg8b5
+NUvLiLinx1rjXeal/8ruwowlr8optgkiRxduK0BZm/Xj6HXTmZwzDACM+zwt9uSV
+YW6/y0gS26oWdLJh8tRysq88xx8ylOGHEx/9/tx+DB2cJzWX23xuaoUWRjbrv/Lf
+gFlXBKHD0RmGac1iTaugAM6IwB0kjscYrHATIrkPgXaHz8PV4cKUvhbLZK7xfCfR
+X2Y+VNxTpvxIDkJ/Hn561C9t9T6gdUfTyCmL//d/Kd4gzCItBE4iouXHnVlfJtj3
+MpD3TTijAgMBAAECggEBAIbg9YAL7j1NtupUmkkWqm7oSPLqRVkvRSfBvXWplJD6
+KF1itht0lsyjqK3qJj/62HGlxj/a9o6MTIzSLiImLu/Lo9KmWYrwNUfnmqa3MArq
+yW2NxapknJUNoaRrgqTGSZUIiwvjKZcdVKdhQkH6K5+fja0FFg8yrahC+k8bsMNI
+5mw8NwRdR3SvHJWHCLfKCQ31tju7On/4C6jr0siUCc2//W+SO5c+FHDY1bma02cp
+jXTEiFpw91YcyKxiADIaH9/qfxWdefxqYg1WlUeXF3jYt5xYnYr34qKW1gOZ3jy1
+QJ3esn382ZTml3TFZWy+g9tkYyOSgmDwQZbLk/ppBAECgYEA8RzLBFwP018ieMBv
+khDtwcKk6ZihkWZxEPQPuUljWzzAHn/f3dXOcrfmflAKeoDEeYDimDYDizTLDPC4
+zmWkMJHNadcM5H065BbGVFQWXo47ltccfIlB/1vzG8aywfJ/yNfHvH87wbH2eg6N
+yOr+96ZjLJszQ+Rv189BbXDzTcMCgYEA7yEbUL/A1J0l2kLoYyS0vfVa7AyBVOFW
+vPgfkF7HdNpIiFWlukMr+DWOolaoZp5iHqQXFwJsL8qCcrbZuHbaNHAI/5vDE9xG
+fh8KzrfBrjIPIyNm6EWpsBo5unXK+wTeqIAGKdzDo5Q3zEE6G5DkkHItKA7yjPOM
+gz/b/MR3W6ECgYBBv3dA3hXWrreIs/j4nLMoxfoQVPWh34xvcg4jmXaFd6Bv8LDM
+HjRopestgIgK9bgd5d5kYT5AJIpGIhJS/fZy5B9egCzc1aVMc0Vr024yJJjtPgVf
+lFIx3xIA/gLazlS4INcveIaEABJVIEjbg/E4+N9MV5n4Jn+1GqgdvtIp3wKBgQC0
+C3lFkxrc+nVFoJrYCwsK+3E5yTCXeBKWtTsOuE307WUvQU1GsMyqVajPEfA5U4cN
+Cv9Xk7thQFh3hrTm7pXcZX5g9iYrDe8FhtncSv7I6Wf8TOtudwUMUrKkcYwi88ex
+lrMNUer7ft2ELJhTqQRuvYjCYH6/IaDqMWqxJju4AQKBgQDPjOh75ykQc93SsYpt
+Tb4gQKLeqOb57pofT8D44DccatfEgk31D4fBIIQu6XKopQmCtQyX9DUDjOWFTxuo
+IMPysN6Fh1quCbC6Xt5xfKoaJG5yQYKeKtLhknwEW9SUifU2xVrOcPikLs7Iwmmp
+BkDLsu/YKwRFSfrbYZXbTlU8tQ==
+-----END PRIVATE KEY-----
diff --git a/unit/gencerts.sh b/unit/gencerts.sh
index fb305d7..cfa6486 100755
--- a/unit/gencerts.sh
+++ b/unit/gencerts.sh
@@ -12,6 +12,7 @@ openssl verify -CAfile cert-ca.pem cert-server.pem
 
 echo -e "\n*** Client Certificate ***"
 openssl genrsa -out cert-client-key.pem
+openssl pkcs8 -topk8 -nocrypt -in cert-client-key.pem -out cert-client-key-pkcs8.pem
 openssl req -new -extensions cert_ext -config ./gencerts.cnf -subj '/O=Bar Example Organization/CN=Bar Example Organization/emailAddress=bar(a)mail.example' -key cert-client-key.pem -out cert-client.csr
 openssl x509 -req -extensions cert_ext -extfile ./gencerts.cnf -in cert-client.csr -CA cert-ca.pem -CAkey cert-ca-key.pem -CAcreateserial -sha256 -days 10000 -out cert-client.pem
 openssl verify -CAfile cert-ca.pem cert-client.pem
diff --git a/unit/test-key.c b/unit/test-key.c
index d52ae1b..df75df9 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -33,6 +33,12 @@
 #define KEY2_STR "This key is longer than 32 bytes, just to be different."
 #define KEY2_LEN (strlen(KEY2_STR))
 
+static const char *plaintext =
+	"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!";
+
 static void test_unsupported(const void *data)
 {
 	struct l_key *key;
@@ -375,9 +381,9 @@ static void test_trusted_keyring(const void *data)
 					&certlen);
 	assert(cert);
 
-	cakey = l_key_new(L_KEY_ASYMMETRIC, cacert, cacertlen);
+	cakey = l_key_new(L_KEY_RSA, cacert, cacertlen);
 	assert(cakey);
-	key = l_key_new(L_KEY_ASYMMETRIC, cert, certlen);
+	key = l_key_new(L_KEY_RSA, cert, certlen);
 	assert(key);
 
 	trust = l_keyring_new(L_KEYRING_SIMPLE, NULL);
@@ -400,6 +406,192 @@ static void test_trusted_keyring(const void *data)
 	l_free(cert);
 }
 
+/* Reference ciphertext:
+ * $ openssl rsautl -in reference_plaintext -inkey cert-client.pem -encrypt \
+ * > -pkcs -out reference_ciphertext
+ * $ xxd -i reference_ciphertext
+ *
+ * where reference_plaintext is a file containing the 183 characters of
+ * plaintext[] (above).
+ */
+static uint8_t reference_ciphertext[256] = {
+	0x45, 0x1a, 0xa1, 0x49, 0x4f, 0x61, 0xf6, 0x96, 0x23, 0x77, 0x0c, 0x33,
+	0x56, 0x07, 0xe6, 0x0f, 0xd6, 0x7b, 0x90, 0xd0, 0x4f, 0xc7, 0x9f, 0x34,
+	0xd4, 0x99, 0x55, 0x74, 0xd9, 0x68, 0x35, 0x3f, 0xd5, 0xbd, 0x7a, 0xec,
+	0xd3, 0xd1, 0x7e, 0xe3, 0xf0, 0xd6, 0x72, 0x7f, 0xb7, 0x20, 0x10, 0x53,
+	0x1c, 0xaa, 0x2b, 0xf6, 0x82, 0x66, 0xdf, 0xfe, 0x71, 0x62, 0x4e, 0x97,
+	0xdb, 0x83, 0xff, 0xc2, 0xab, 0x79, 0x69, 0xc7, 0xde, 0x77, 0x18, 0x55,
+	0x0c, 0xea, 0x01, 0x4e, 0xeb, 0x8b, 0x13, 0xa3, 0xef, 0xc4, 0x29, 0xa6,
+	0x51, 0x16, 0x3f, 0xa5, 0xe9, 0x91, 0x91, 0x26, 0x45, 0x98, 0x1f, 0x0b,
+	0x34, 0x6e, 0x4a, 0x61, 0xc4, 0xf3, 0x85, 0x78, 0x6b, 0xdf, 0x38, 0x9b,
+	0xeb, 0x6d, 0xc2, 0xed, 0xdf, 0xa9, 0xe6, 0xbb, 0x81, 0x84, 0xd9, 0x4a,
+	0x42, 0xa6, 0x3b, 0xa9, 0x5b, 0xae, 0xee, 0xaa, 0x6a, 0x3a, 0xc0, 0xcb,
+	0x48, 0x5c, 0x61, 0xa0, 0xe2, 0x4c, 0x06, 0x15, 0x7a, 0x8e, 0xe7, 0x47,
+	0x9c, 0x03, 0x86, 0x70, 0x00, 0xa1, 0xa8, 0x68, 0x9e, 0x7e, 0xc7, 0x81,
+	0x38, 0xb3, 0x00, 0xd4, 0xa9, 0xc2, 0x56, 0xf7, 0xf4, 0x3b, 0x9b, 0xb1,
+	0x27, 0xcd, 0xed, 0x2e, 0xf3, 0xa8, 0x9b, 0x08, 0x5e, 0x8a, 0xf3, 0x29,
+	0x67, 0xa4, 0x93, 0xc5, 0x68, 0xa5, 0x26, 0x1b, 0x3b, 0x1d, 0xc7, 0x78,
+	0x32, 0xd9, 0x81, 0x65, 0x8e, 0x17, 0xb3, 0x17, 0x30, 0x12, 0xe3, 0x78,
+	0x23, 0xd9, 0x02, 0x3b, 0xf9, 0x7b, 0x8d, 0x12, 0x4c, 0xff, 0xa0, 0xd2,
+	0x0f, 0x59, 0xb9, 0x75, 0xbd, 0x7f, 0xbb, 0x13, 0x8c, 0x6f, 0xbd, 0x00,
+	0x67, 0xf3, 0xa0, 0x43, 0x05, 0x5d, 0xb7, 0x64, 0xe3, 0xae, 0x81, 0xe1,
+	0x78, 0x5e, 0x81, 0xc5, 0x20, 0xc0, 0xdb, 0xba, 0xd0, 0xbe, 0x1f, 0xc5,
+	0x6a, 0xe4, 0x31, 0x46
+};
+
+/* Reference signature:
+ * $ openssl dgst -sha256 -sign cert-client-key.pem -out reference_signature \
+ * > good_plaintext
+ * $ xxd -i reference_signature
+ *
+ * where reference_plaintext is a file containing the 183 characters of
+ * plaintext[] (above).
+ */
+
+uint8_t reference_signature[256] = {
+	0x39, 0xaf, 0x0d, 0x23, 0x33, 0xcc, 0x48, 0xed, 0xc3, 0x15, 0x9e, 0xb9,
+	0xd3, 0x53, 0xe0, 0x0c, 0xea, 0x45, 0x65, 0xa7, 0x82, 0x8f, 0x4b, 0xfc,
+	0x5e, 0xd3, 0xc9, 0x10, 0xf5, 0xc6, 0x56, 0x3a, 0x0e, 0x60, 0xde, 0x01,
+	0xac, 0xb6, 0xf8, 0xc7, 0xe3, 0x60, 0xd1, 0xec, 0x4f, 0x38, 0x36, 0x42,
+	0xab, 0xf5, 0x90, 0xd6, 0xd8, 0x8b, 0x8a, 0x1c, 0x1a, 0xda, 0xec, 0x10,
+	0xd2, 0xec, 0x8a, 0x77, 0x9f, 0xcf, 0x25, 0x48, 0x13, 0xdf, 0xd0, 0xb1,
+	0xaf, 0x12, 0x55, 0xa0, 0x1a, 0xda, 0x8a, 0x60, 0xbf, 0x10, 0xcf, 0x02,
+	0xae, 0x3e, 0x7c, 0x01, 0x3f, 0x9d, 0xf4, 0xfb, 0x4b, 0x2c, 0x99, 0x7d,
+	0x0e, 0x06, 0xd5, 0x1e, 0x94, 0x38, 0x08, 0x18, 0x62, 0xb1, 0x73, 0x49,
+	0xae, 0x9f, 0x0e, 0x3b, 0x40, 0x48, 0x7f, 0x73, 0x73, 0xe0, 0x5c, 0xdf,
+	0xed, 0xb0, 0xf5, 0x9a, 0xbe, 0xa0, 0xff, 0x3f, 0x70, 0xe6, 0xe4, 0xf4,
+	0x99, 0x1a, 0x79, 0x1d, 0x76, 0x38, 0x8a, 0xae, 0x04, 0xba, 0x9a, 0xf7,
+	0x5e, 0x58, 0x5f, 0x4f, 0x86, 0x4b, 0x89, 0x2f, 0x6c, 0xf7, 0xf0, 0x42,
+	0x5e, 0x2f, 0x01, 0x6f, 0xb4, 0x7e, 0x7e, 0xa8, 0xeb, 0xa4, 0x7b, 0x03,
+	0x63, 0x61, 0x26, 0x1d, 0xc1, 0xba, 0xfa, 0xf3, 0xa9, 0xa4, 0xb1, 0x7e,
+	0x0a, 0x2f, 0x22, 0x30, 0x48, 0x16, 0xfb, 0x25, 0x13, 0x67, 0x86, 0x98,
+	0x39, 0x88, 0x31, 0x78, 0xb4, 0xfb, 0xe3, 0xa0, 0x2e, 0x5c, 0x97, 0xdd,
+	0xfa, 0xe1, 0xd8, 0x3e, 0xd2, 0x9f, 0x33, 0xa4, 0x65, 0xc8, 0x34, 0xa5,
+	0xe7, 0x57, 0x9a, 0xae, 0x97, 0x93, 0x17, 0xa4, 0x72, 0x85, 0x83, 0xc9,
+	0x64, 0x62, 0x58, 0xbf, 0x3b, 0xb4, 0xb8, 0x1f, 0x5c, 0xd5, 0x9a, 0x3f,
+	0x3a, 0xf8, 0xe1, 0x2d, 0x6a, 0xf3, 0x0c, 0x20, 0x6e, 0x87, 0xa6, 0xc8,
+	0xf4, 0x8e, 0x18, 0x07
+};
+
+static void test_key_crypto(const void *data)
+{
+	uint8_t *cert;
+	size_t certlen;
+	uint8_t *pubcert;
+	size_t pubcertlen;
+	struct l_key *key;
+	struct l_key *pubkey;
+	bool is_public;
+	size_t keybits;
+	bool success;
+	uint8_t ciphertext[256];
+	uint8_t decrypted[256];
+	uint8_t msghash[32];
+	ssize_t len;
+	struct l_checksum *checksum;
+	int hash = L_CHECKSUM_SHA256;
+	int rsa = L_CIPHER_RSA_PKCS1_V1_5;
+
+	cert = l_pem_load_private_key(TESTDATADIR "/cert-client-key-pkcs8.pem",
+					NULL, &certlen);
+	assert(cert);
+	pubcert = l_pem_load_certificate(TESTDATADIR "/cert-client.pem",
+						&pubcertlen);
+	assert(pubcert);
+
+	key = l_key_new(L_KEY_RSA, cert, certlen);
+	assert(key);
+	pubkey = l_key_new(L_KEY_RSA, pubcert, pubcertlen);
+	assert(pubkey);
+
+	success = l_key_get_info(key, rsa, hash, &keybits, &is_public);
+	assert(success);
+	assert(keybits == 2048);
+	assert(!is_public);
+
+	success = l_key_get_info(key, rsa, L_CHECKSUM_NONE, &keybits,
+					&is_public);
+	assert(success);
+	assert(keybits == 2048);
+	assert(!is_public);
+
+	success = l_key_get_info(pubkey, rsa, hash, &keybits, &is_public);
+	assert(success);
+	assert(keybits == 2048);
+	assert(is_public);
+
+	memset(ciphertext, 0, sizeof(ciphertext));
+	memset(decrypted, 0, sizeof(decrypted));
+
+	len = l_key_encrypt(pubkey, rsa, hash, plaintext, ciphertext,
+				strlen(plaintext), sizeof(ciphertext));
+	assert(len == sizeof(ciphertext));
+
+	/* Can't decrypt with public key */
+	len = l_key_decrypt(pubkey, rsa, hash, ciphertext, decrypted,
+				sizeof(ciphertext), sizeof(decrypted));
+	assert(len < 0);
+
+	len = l_key_decrypt(key, rsa, hash, ciphertext, decrypted,
+				sizeof(ciphertext), sizeof(decrypted));
+	assert(len == (ssize_t)strlen(plaintext));
+	assert(strcmp(plaintext, (char *)decrypted) == 0);
+
+	/* Decrypt reference ciphertext */
+	memset(decrypted, 0, sizeof(decrypted));
+	len = l_key_decrypt(key, rsa, hash, reference_ciphertext, decrypted,
+				sizeof(reference_ciphertext),
+				sizeof(decrypted));
+	assert(len == (ssize_t)strlen(plaintext));
+	assert(strcmp(plaintext, (char *)decrypted) == 0);
+
+	/* Decrypt corrupted ciphertext */
+	memset(decrypted, 0, sizeof(decrypted));
+	reference_ciphertext[0] = reference_ciphertext[0] ^ (uint8_t)0xFF;
+	len = l_key_decrypt(key, rsa, hash, reference_ciphertext, decrypted,
+				sizeof(reference_ciphertext),
+				sizeof(decrypted));
+	assert(len < 0);
+
+	checksum = l_checksum_new(L_CHECKSUM_SHA256);
+	assert(checksum);
+	l_checksum_update(checksum, plaintext, strlen(plaintext));
+	l_checksum_get_digest(checksum, msghash, sizeof(msghash));
+	l_checksum_free(checksum);
+
+	/* Can't sign with public key */
+	len = l_key_sign(pubkey, rsa, hash, msghash, ciphertext,
+				sizeof(msghash), sizeof(ciphertext));
+	assert(len < 0);
+
+	len = l_key_sign(key, rsa, hash, msghash, ciphertext, sizeof(msghash),
+				sizeof(ciphertext));
+	assert(len == sizeof(ciphertext));
+
+	success = l_key_verify(pubkey, rsa, hash, msghash, ciphertext,
+				sizeof(msghash), sizeof(ciphertext));
+	assert(success);
+
+	success = l_key_verify(key, rsa, hash, msghash, ciphertext,
+				sizeof(msghash), sizeof(ciphertext));
+	assert(success);
+
+	success = l_key_verify(pubkey, rsa, hash, msghash, reference_signature,
+				sizeof(msghash), sizeof(reference_signature));
+	assert(success);
+
+	/* Corrupt signature */
+	msghash[10] = msghash[10] ^ (uint8_t)0xFF;
+	success = l_key_verify(key, rsa, hash, msghash, ciphertext,
+				sizeof(msghash), sizeof(ciphertext));
+	assert(!success);
+
+	l_key_free(key);
+	l_key_free(pubkey);
+	l_free(cert);
+	l_free(pubcert);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -414,5 +606,7 @@ int main(int argc, char *argv[])
 	l_test_add("simple keyring", test_simple_keyring, NULL);
 	l_test_add("trusted keyring", test_trusted_keyring, NULL);
 
+	l_test_add("key crypto", test_key_crypto, NULL);
+
 	return l_test_run();
 }
-- 
2.9.2


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

* Re: [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose
  2016-07-29 18:11 ` [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose Mat Martineau
@ 2016-08-01 21:15   ` Denis Kenzior
  0 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2016-08-01 21:15 UTC (permalink / raw)
  To: ell

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

Hi Mat,

On 07/29/2016 01:11 PM, Mat Martineau wrote:
> The size returned is the number of bytes needed to store the payload.
> ---
>   ell/key.c | 2 +-
>   ell/key.h | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
>

Patches 3 - 5 applied, thanks.

Regards,
-Denis


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

* Re: [PATCH v2 1/7] key: Consistently return errno from syscall wrappers
  2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
                   ` (5 preceding siblings ...)
  2016-07-29 18:12 ` [PATCH v2 7/7] unit: Add tests for key-based asymmetric crypto Mat Martineau
@ 2016-08-01 21:16 ` Denis Kenzior
  6 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2016-08-01 21:16 UTC (permalink / raw)
  To: ell

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

Hi Mat,

On 07/29/2016 01:11 PM, Mat Martineau wrote:
> ---
>   ell/key.c | 44 +++++++++++++++++++++++++++++++++++++-------
>   1 file changed, 37 insertions(+), 7 deletions(-)
>

Applied, thanks.

Regards,
-Denis


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

end of thread, other threads:[~2016-08-01 21:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-29 18:11 [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Mat Martineau
2016-07-29 18:11 ` [PATCH v2 2/7] checksum: Add L_CHECKSUM_NONE, needed for key crypto Mat Martineau
2016-07-29 18:11 ` [PATCH v2 3/7] key: Rename l_key_get_payload_size to clarify its purpose Mat Martineau
2016-08-01 21:15   ` Denis Kenzior
2016-07-29 18:11 ` [PATCH v2 4/7] unit: Adjust for renamed l_key_get_payload_size function Mat Martineau
2016-07-29 18:11 ` [PATCH v2 5/7] key: Rename asymmetric key type to L_KEY_RSA Mat Martineau
2016-07-29 18:12 ` [PATCH v2 6/7] key: Add key-based asymmetric crypto operations Mat Martineau
2016-07-29 18:12 ` [PATCH v2 7/7] unit: Add tests for key-based asymmetric crypto Mat Martineau
2016-08-01 21:16 ` [PATCH v2 1/7] key: Consistently return errno from syscall wrappers Denis Kenzior

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.