All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/10] checksum: Add SHA224 checksum type
@ 2017-08-10 23:10 Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 02/10] cipher: Add DES-CBC cipher type Andrew Zaborowski
                   ` (9 more replies)
  0 siblings, 10 replies; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

---
 ell/checksum.c | 2 ++
 ell/checksum.h | 1 +
 ell/key.c      | 3 +++
 3 files changed, 6 insertions(+)

diff --git a/ell/checksum.c b/ell/checksum.c
index 54cddac..4045489 100644
--- a/ell/checksum.c
+++ b/ell/checksum.c
@@ -142,6 +142,8 @@ static const char *checksum_type_to_name(enum l_checksum_type type)
 		return "md5";
 	case L_CHECKSUM_SHA1:
 		return "sha1";
+	case L_CHECKSUM_SHA224:
+		return "sha224";
 	case L_CHECKSUM_SHA256:
 		return "sha256";
 	case L_CHECKSUM_SHA384:
diff --git a/ell/checksum.h b/ell/checksum.h
index 5e6c027..05927b6 100644
--- a/ell/checksum.h
+++ b/ell/checksum.h
@@ -38,6 +38,7 @@ enum l_checksum_type {
 	L_CHECKSUM_MD4,
 	L_CHECKSUM_MD5,
 	L_CHECKSUM_SHA1,
+	L_CHECKSUM_SHA224,
 	L_CHECKSUM_SHA256,
 	L_CHECKSUM_SHA384,
 	L_CHECKSUM_SHA512,
diff --git a/ell/key.c b/ell/key.c
index fba400f..5a73bbd 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -380,6 +380,9 @@ static const char *lookup_checksum(enum l_checksum_type checksum)
 	case L_CHECKSUM_SHA1:
 		ret = "sha1";
 		break;
+	case L_CHECKSUM_SHA224:
+		ret = "sha224";
+		break;
 	case L_CHECKSUM_SHA256:
 		ret = "sha256";
 		break;
-- 
2.11.0


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

* [PATCH 02/10] cipher: Add DES-CBC cipher type
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 16:08   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h Andrew Zaborowski
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

---
 ell/cipher.c | 2 ++
 ell/cipher.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/ell/cipher.c b/ell/cipher.c
index 8c9e1d0..e51f6e7 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -152,6 +152,8 @@ static const char *cipher_type_to_name(enum l_cipher_type type)
 		return "ecb(arc4)";
 	case L_CIPHER_DES:
 		return "ecb(des)";
+	case L_CIPHER_DES_CBC:
+		return "cbc(des)";
 	case L_CIPHER_DES3_EDE_CBC:
 		return "cbc(des3_ede)";
 	}
diff --git a/ell/cipher.h b/ell/cipher.h
index 9297eeb..d787f33 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -34,6 +34,7 @@ enum l_cipher_type {
 	L_CIPHER_AES_CBC,
 	L_CIPHER_ARC4,
 	L_CIPHER_DES,
+	L_CIPHER_DES_CBC,
 	L_CIPHER_DES3_EDE_CBC,
 };
 
-- 
2.11.0


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

* [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 02/10] cipher: Add DES-CBC cipher type Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 16:17   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 04/10] tls: Report error if private key loading fails Andrew Zaborowski
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

Extract those utilities that can be used by pem.c for decoding encrypted
certificates and possibly other mechanisms.  Introduce the asn1_oid_eq
macro for comparing OIDs.
---
 ell/asn1-private.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/tls.c          | 102 ++-------------------------------------------
 2 files changed, 121 insertions(+), 99 deletions(-)
 create mode 100644 ell/asn1-private.h

diff --git a/ell/asn1-private.h b/ell/asn1-private.h
new file mode 100644
index 0000000..c1f1c5d
--- /dev/null
+++ b/ell/asn1-private.h
@@ -0,0 +1,118 @@
+/*
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2017  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
+ */
+
+#define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
+
+#define ASN1_CLASS_UNIVERSAL	0
+
+#define ASN1_ID_SEQUENCE	ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
+#define ASN1_ID_SET		ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
+#define ASN1_ID_INTEGER		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
+#define ASN1_ID_BIT_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
+#define ASN1_ID_OCTET_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
+#define ASN1_ID_OID		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
+#define ASN1_ID_UTF8STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
+#define ASN1_ID_PRINTABLESTRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
+
+struct asn1_oid {
+	uint8_t asn1_len;
+	uint8_t asn1[10];
+};
+
+#define asn1_oid_eq(oid1, oid2_len, oid2_string) \
+	((oid1)->asn1_len == (oid2_len) && \
+	 !memcmp((oid1)->asn1, (oid2_string), (oid2_len)))
+
+static inline int parse_asn1_definite_length(const uint8_t **buf,
+						size_t *len)
+{
+	int n;
+	size_t result = 0;
+
+	(*len)--;
+
+	if (!(**buf & 0x80))
+		return *(*buf)++;
+
+	n = *(*buf)++ & 0x7f;
+	if ((size_t) n > *len)
+		return -1;
+
+	*len -= n;
+	while (n--)
+		result = (result << 8) | *(*buf)++;
+
+	return result;
+}
+
+/* Return index'th element in a DER SEQUENCE */
+static inline uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
+			uint8_t *tag, size_t *len_out)
+{
+	int tlv_len;
+
+	while (1) {
+		if (len_in < 2)
+			return NULL;
+
+		*tag = *buf++;
+		len_in--;
+
+		tlv_len = parse_asn1_definite_length((void *) &buf, &len_in);
+		if (tlv_len < 0 || (size_t) tlv_len > len_in)
+			return NULL;
+
+		if (index-- == 0) {
+			*len_out = tlv_len;
+			return buf;
+		}
+
+		buf += tlv_len;
+		len_in -= tlv_len;
+	}
+}
+
+/* Return an element in a DER SEQUENCE structure by path */
+static inline uint8_t *der_find_elem_by_path(uint8_t *buf, size_t len_in,
+						uint8_t tag, size_t *len_out,
+						...)
+{
+	uint8_t elem_tag;
+	int pos;
+	va_list vl;
+
+	va_start(vl, len_out);
+
+	pos = va_arg(vl, int);
+
+	while (pos != -1) {
+		buf = der_find_elem(buf, len_in, pos, &elem_tag, &len_in);
+
+		pos = va_arg(vl, int);
+
+		if (!buf || elem_tag != (pos == -1 ? tag : ASN1_ID_SEQUENCE))
+			return NULL;
+	}
+
+	va_end(vl);
+
+	*len_out = len_in;
+	return buf;
+}
diff --git a/ell/tls.c b/ell/tls.c
index 6636fbf..75e3739 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -36,6 +36,7 @@
 #include "pem.h"
 #include "tls-private.h"
 #include "key.h"
+#include "asn1-private.h"
 
 void tls10_prf(const uint8_t *secret, size_t secret_len,
 		const char *label,
@@ -2309,19 +2310,6 @@ LIB_EXPORT const char *l_tls_alert_to_str(enum l_tls_alert_desc desc)
 
 /* X509 Certificates and Certificate Chains */
 
-#define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
-
-#define ASN1_CLASS_UNIVERSAL	0
-
-#define ASN1_ID_SEQUENCE	ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
-#define ASN1_ID_SET		ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
-#define ASN1_ID_INTEGER		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
-#define ASN1_ID_BIT_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
-#define ASN1_ID_OCTET_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
-#define ASN1_ID_OID		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
-#define ASN1_ID_UTF8STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
-#define ASN1_ID_PRINTABLESTRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
-
 #define X509_CERTIFICATE_POS			0
 #define   X509_TBSCERTIFICATE_POS		  0
 #define     X509_TBSCERT_VERSION_POS		    0
@@ -2341,83 +2329,6 @@ LIB_EXPORT const char *l_tls_alert_to_str(enum l_tls_alert_desc desc)
 #define   X509_SIGNATURE_ALGORITHM_POS		  1
 #define   X509_SIGNATURE_VALUE_POS		  2
 
-static inline int parse_asn1_definite_length(const uint8_t **buf,
-						size_t *len)
-{
-	int n;
-	size_t result = 0;
-
-	(*len)--;
-
-	if (!(**buf & 0x80))
-		return *(*buf)++;
-
-	n = *(*buf)++ & 0x7f;
-	if ((size_t) n > *len)
-		return -1;
-
-	*len -= n;
-	while (n--)
-		result = (result << 8) | *(*buf)++;
-
-	return result;
-}
-
-/* Return index'th element in a DER SEQUENCE */
-static uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
-			uint8_t *tag, size_t *len_out)
-{
-	int tlv_len;
-
-	while (1) {
-		if (len_in < 2)
-			return NULL;
-
-		*tag = *buf++;
-		len_in--;
-
-		tlv_len = parse_asn1_definite_length((void *) &buf, &len_in);
-		if (tlv_len < 0 || (size_t) tlv_len > len_in)
-			return NULL;
-
-		if (index-- == 0) {
-			*len_out = tlv_len;
-			return buf;
-		}
-
-		buf += tlv_len;
-		len_in -= tlv_len;
-	}
-}
-
-/* Return an element in a DER SEQUENCE structure by path */
-static inline uint8_t *der_find_elem_by_path(uint8_t *buf, size_t len_in,
-						uint8_t tag, size_t *len_out,
-						...)
-{
-	uint8_t elem_tag;
-	int pos;
-	va_list vl;
-
-	va_start(vl, len_out);
-
-	pos = va_arg(vl, int);
-
-	while (pos != -1) {
-		buf = der_find_elem(buf, len_in, pos, &elem_tag, &len_in);
-
-		pos = va_arg(vl, int);
-
-		if (!buf || elem_tag != (pos == -1 ? tag : ASN1_ID_SEQUENCE))
-			return NULL;
-	}
-
-	va_end(vl);
-
-	*len_out = len_in;
-	return buf;
-}
-
 struct tls_cert *tls_cert_load_file(const char *filename)
 {
 	uint8_t *der;
@@ -2449,11 +2360,6 @@ bool tls_cert_find_certchain(struct tls_cert *cert,
 	return true;
 }
 
-struct asn1_oid {
-	uint8_t asn1_len;
-	uint8_t asn1[10];
-};
-
 static const struct pkcs1_encryption_oid {
 	enum tls_cert_key_type key_type;
 	struct asn1_oid oid;
@@ -2599,10 +2505,8 @@ enum tls_cert_key_type tls_cert_get_pubkey_type(struct tls_cert *cert)
 		return TLS_CERT_KEY_UNKNOWN;
 
 	for (i = 0; i < (int) L_ARRAY_SIZE(pkcs1_encryption_oids); i++)
-		if (key_type_len == pkcs1_encryption_oids[i].oid.asn1_len &&
-				!memcmp(key_type,
-					pkcs1_encryption_oids[i].oid.asn1,
-					key_type_len))
+		if (asn1_oid_eq(&pkcs1_encryption_oids[i].oid,
+					key_type_len, key_type))
 			break;
 
 	if (i == L_ARRAY_SIZE(pkcs1_encryption_oids))
-- 
2.11.0


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

* [PATCH 04/10] tls: Report error if private key loading fails
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 02/10] cipher: Add DES-CBC cipher type Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 16:18   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 05/10] asn1: Use const pointers in ASN1 parsing utilities Andrew Zaborowski
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

Cleanup: drop the unneeded priv_key initialization and don't wait for
the next l_key_get_info() to fail when a private key was set but can't
be loaded.
---
 ell/tls.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/ell/tls.c b/ell/tls.c
index 75e3739..aa6e487 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -2218,19 +2218,19 @@ LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls, const char *cert_path,
 	}
 
 	if (priv_key_path) {
-		uint8_t *priv_key = NULL;
+		uint8_t *priv_key;
 		bool is_public = true;
 
 		priv_key = l_pem_load_private_key(priv_key_path,
 							priv_key_passphrase,
 							&tls->priv_key_size);
+		if (!priv_key)
+			return false;
 
 		tls->priv_key = l_key_new(L_KEY_RSA, priv_key,
 						tls->priv_key_size);
-		if (priv_key) {
-			memset(priv_key, 0, tls->priv_key_size);
-			l_free(priv_key);
-		}
+		memset(priv_key, 0, tls->priv_key_size);
+		l_free(priv_key);
 
 		if (!l_key_get_info(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
 					L_CHECKSUM_NONE, &tls->priv_key_size,
-- 
2.11.0


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

* [PATCH 05/10] asn1: Use const pointers in ASN1 parsing utilities
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (2 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 04/10] tls: Report error if private key loading fails Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions Andrew Zaborowski
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

For convenience take const pointers as inputs to the ASN1 utilites,
we only use those functions for parsing.
---
 ell/asn1-private.h | 11 ++++++-----
 ell/tls.c          |  2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/ell/asn1-private.h b/ell/asn1-private.h
index c1f1c5d..b87d932 100644
--- a/ell/asn1-private.h
+++ b/ell/asn1-private.h
@@ -63,8 +63,9 @@ static inline int parse_asn1_definite_length(const uint8_t **buf,
 }
 
 /* Return index'th element in a DER SEQUENCE */
-static inline uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
-			uint8_t *tag, size_t *len_out)
+static inline const uint8_t *der_find_elem(const uint8_t *buf, size_t len_in,
+						int index, uint8_t *tag,
+						size_t *len_out)
 {
 	int tlv_len;
 
@@ -90,9 +91,9 @@ static inline uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
 }
 
 /* Return an element in a DER SEQUENCE structure by path */
-static inline uint8_t *der_find_elem_by_path(uint8_t *buf, size_t len_in,
-						uint8_t tag, size_t *len_out,
-						...)
+static inline const uint8_t *der_find_elem_by_path(const uint8_t *buf,
+						size_t len_in, uint8_t tag,
+						size_t *len_out, ...)
 {
 	uint8_t elem_tag;
 	int pos;
diff --git a/ell/tls.c b/ell/tls.c
index aa6e487..9b199ef 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -2489,7 +2489,7 @@ void tls_cert_free_certchain(struct tls_cert *cert)
 
 enum tls_cert_key_type tls_cert_get_pubkey_type(struct tls_cert *cert)
 {
-	uint8_t *key_type;
+	const uint8_t *key_type;
 	size_t key_type_len;
 	int i;
 
-- 
2.11.0


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

* [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (3 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 05/10] asn1: Use const pointers in ASN1 parsing utilities Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 16:28   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id Andrew Zaborowski
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

Implement the PBKDF1 and PBKDF2 functions from PKCS#4 - RFC8018.  This
is for now placed in cipher.c as a dependency for the
l_cipher_from_pkcs5_id patch but probably better fits in a separate file
called pkcs5.c or something else.

Note iwd already has a PBKDF2 implementation and unit tests, it can be
switched to use this ell version and the unit tests moved to ell.
---
 ell/cipher.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/ell/cipher.c b/ell/cipher.c
index e51f6e7..8e60d61 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -34,6 +34,7 @@
 #include "cipher.h"
 #include "private.h"
 #include "random.h"
+#include "checksum.h"
 
 #ifndef HAVE_LINUX_IF_ALG_H
 #ifndef HAVE_LINUX_TYPES_H
@@ -632,3 +633,129 @@ bool l_aead_cipher_is_supported(enum l_aead_cipher_type type)
 
 	return supported_aead_ciphers & (1 << type);
 }
+
+/* RFC8018 section 5.1 */
+static bool pkcs5_pbkdf1(enum l_checksum_type type, const char *password,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iter_count,
+				size_t dk_len, uint8_t *out_dk)
+{
+	size_t hash_len, t_len;
+	uint8_t t[20 + salt_len + strlen(password)];
+	struct l_checksum *checksum;
+
+	switch (type) {
+	case L_CHECKSUM_MD5:
+		hash_len = 16;
+		break;
+	case L_CHECKSUM_SHA1:
+		hash_len = 20;
+		break;
+	default:
+		return false;
+	}
+
+	if (dk_len > hash_len)
+		return false;
+
+	checksum = l_checksum_new(type);
+	if (!checksum)
+		return false;
+
+	memcpy(t, password, strlen(password));
+	memcpy(t + strlen(password), salt, salt_len);
+	t_len = strlen(password) + salt_len;
+
+	while (iter_count) {
+		l_checksum_reset(checksum);
+		if (!l_checksum_update(checksum, t, t_len))
+			break;
+		if (l_checksum_get_digest(checksum, t, hash_len) !=
+				(ssize_t) hash_len)
+			break;
+		t_len = hash_len;
+
+		iter_count--;
+	}
+
+	l_checksum_free(checksum);
+
+	if (iter_count)
+		return false;
+
+	memcpy(out_dk, t, dk_len);
+	return true;
+}
+
+/* RFC8018 section 5.2 */
+static bool pkcs5_pbkdf2(enum l_checksum_type type, const char *password,
+				const uint8_t *salt, size_t salt_len,
+				unsigned int iter_count,
+				size_t dk_len, uint8_t *out_dk)
+{
+	size_t h_len;
+	struct l_checksum *checksum;
+	unsigned int i;
+
+	switch (type) {
+	case L_CHECKSUM_SHA1:
+		h_len = 20;
+		break;
+	case L_CHECKSUM_SHA224:
+		h_len = 28;
+		break;
+	case L_CHECKSUM_SHA256:
+		h_len = 32;
+		break;
+	case L_CHECKSUM_SHA384:
+		h_len = 48;
+		break;
+	case L_CHECKSUM_SHA512:
+		h_len = 64;
+		break;
+	default:
+		return false;
+	}
+
+	checksum = l_checksum_new_hmac(type, password, strlen(password));
+	if (!checksum)
+		return false;
+
+	for (i = 1; dk_len; i++) {
+		unsigned int j, k;
+		uint8_t u[salt_len + 64];
+		size_t u_len;
+		size_t block_len = h_len;
+
+		if (block_len > dk_len)
+			block_len = dk_len;
+
+		memset(out_dk, 0, block_len);
+
+		memcpy(u, salt, salt_len);
+		l_put_be32(i, u + salt_len);
+		u_len = salt_len + 4;
+
+		for (j = 0; j < iter_count; j++) {
+			l_checksum_reset(checksum);
+			if (!l_checksum_update(checksum, u, u_len))
+				break;
+			if (l_checksum_get_digest(checksum, u, h_len) !=
+					(ssize_t) h_len)
+				break;
+			u_len = h_len;
+
+			for (k = 0; k < block_len; k++)
+				out_dk[k] ^= u[k];
+		}
+		if (j < iter_count)
+			break;
+
+		out_dk += block_len;
+		dk_len -= block_len;
+	}
+
+	l_checksum_free(checksum);
+
+	return !dk_len;
+}
-- 
2.11.0


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

* [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (4 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 16:55   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key Andrew Zaborowski
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

Add a utility to parse all of the PKCS#5 DER-encoded encryption scheme
information, use the right PBKDF function to calculate the key,
create the appropriate l_cipher object type (if we support that PKCS#5
cipher type) with that key and set the IV on the l_cipher object.

We don't support any of the RC2 or RC5 based encryption schemes or
those that use MD2, SHA512-224 or SHA512-256 for the hash, because
there's no kernel support for those algorithms.  OpenSSL can create
RSA private keys encrypted with some of these algorithms but MD5+DES
and DES3-EDE are the default and the popular algorithms.  OpenSSL also
supports camellia ciphers in those scenarios which we could add.

Note that the caller still needs to add or remove the padding from the
data encrypted or decrypted with the l_cipher object so technically this
doesn't implement 100% of PKCS#5 PBES1 or PBES2.
Thise code may be better moved to a separate file from cipher.c.  If we
do that then it could be wrapped in a separate object that would do the
padding after calling the l_cipher operation, too, though the padding
is really simple anway, may not be worth the overhead of another wrapper.
---
 ell/cipher.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/cipher.h |   4 +
 2 files changed, 294 insertions(+)

diff --git a/ell/cipher.c b/ell/cipher.c
index 8e60d61..f9efd2b 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -34,6 +34,7 @@
 #include "cipher.h"
 #include "private.h"
 #include "random.h"
+#include "asn1-private.h"
 #include "checksum.h"
 
 #ifndef HAVE_LINUX_IF_ALG_H
@@ -759,3 +760,292 @@ static bool pkcs5_pbkdf2(enum l_checksum_type type, const char *password,
 
 	return !dk_len;
 }
+
+static struct asn1_oid pkcs5_pbkdf2_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c }
+};
+
+static struct asn1_oid pkcs5_pbes2_oid = {
+	9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d }
+};
+
+static const struct pkcs5_pbes1_encryption_oid {
+	enum l_checksum_type checksum_type;
+	enum l_cipher_type cipher_type;
+	struct asn1_oid oid;
+} pkcs5_pbes1_encryption_oids[] = {
+	{ /* pbeWithMD5AndDES-CBC */
+		L_CHECKSUM_MD5, L_CIPHER_DES_CBC,
+		{ 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x03 } },
+	},
+	{ /* pbeWithSHA1AndDES-CBC */
+		L_CHECKSUM_SHA1, L_CIPHER_DES_CBC,
+		{ 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0a } },
+	},
+	/* MD2- and RC2-based schemes 1, 4, 6 and 11 not supported */
+};
+
+static const struct pkcs5_digest_alg_oid {
+	enum l_checksum_type type;
+	struct asn1_oid oid;
+} pkcs5_digest_alg_oids[] = {
+	{ /* hmacWithSHA1 */
+		L_CHECKSUM_SHA1,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07 } },
+	},
+	{ /* hmacWithSHA224 */
+		L_CHECKSUM_SHA224,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x08 } },
+	},
+	{ /* hmacWithSHA256 */
+		L_CHECKSUM_SHA256,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09 } },
+	},
+	{ /* hmacWithSHA384 */
+		L_CHECKSUM_SHA384,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0a } },
+	},
+	{ /* hmacWithSHA512 */
+		L_CHECKSUM_SHA512,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0b } },
+	},
+	/* hmacWithSHA512-224 and hmacWithSHA512-256 not supported */
+};
+
+static const struct pkcs5_enc_alg_oid {
+	enum l_cipher_type cipher_type;
+	uint8_t key_size, iv_size;
+	struct asn1_oid oid;
+} pkcs5_enc_alg_oids[] = {
+	{ /* desCBC */
+		L_CIPHER_DES_CBC, 8, 8,
+		{ 5, { 0x2b, 0x0e, 0x03, 0x02, 0x07 } },
+	},
+	{ /* des-EDE3-CBC */
+		L_CIPHER_DES3_EDE_CBC, 24, 8,
+		{ 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07 } },
+	},
+	/* RC2/RC5-based schemes 2 and 9 not supported */
+	{ /* aes128-CBC-PAD */
+		L_CIPHER_AES_CBC, 16, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02 } },
+	},
+	{ /* aes192-CBC-PAD */
+		L_CIPHER_AES_CBC, 24, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16 } },
+	},
+	{ /* aes256-CBC-PAD */
+		L_CIPHER_AES_CBC, 32, 16,
+		{ 9, { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a } },
+	},
+};
+
+static struct l_cipher *cipher_from_pkcs5_pbes2_params(
+						const uint8_t *pbes2_params,
+						size_t pbes2_params_len,
+						const char *password)
+{
+	uint8_t tag;
+	const uint8_t *kdf_sequence, *enc_sequence, *oid, *params,
+		*salt, *iter_count_buf, *key_len_buf, *prf_sequence;
+	size_t kdf_len, enc_len, params_len, salt_len, key_len, tmp_len;
+	unsigned int i, iter_count;
+	enum l_checksum_type prf_alg = L_CHECKSUM_NONE;
+	const struct pkcs5_enc_alg_oid *enc_scheme = NULL;
+	uint8_t derived_key[64];
+	struct l_cipher *cipher;
+
+	/* RFC8018 section A.4 */
+
+	kdf_sequence = der_find_elem(pbes2_params, pbes2_params_len, 0,
+					&tag, &kdf_len);
+	if (!kdf_sequence || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	enc_sequence = der_find_elem(pbes2_params, pbes2_params_len, 1,
+					&tag, &enc_len);
+	if (!enc_sequence || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (der_find_elem(pbes2_params, pbes2_params_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section A.2 */
+
+	oid = der_find_elem(kdf_sequence, kdf_len, 0, &tag, &tmp_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	if (!asn1_oid_eq(&pkcs5_pbkdf2_oid, tmp_len, oid))
+		return NULL;
+
+	params = der_find_elem(kdf_sequence, kdf_len, 1, &tag, &params_len);
+	if (!params || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (der_find_elem(kdf_sequence, kdf_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	salt = der_find_elem(params, params_len, 0, &tag, &salt_len);
+	if (!salt || tag != ASN1_ID_OCTET_STRING ||
+			salt_len < 1 || salt_len > 512)
+		return NULL;
+
+	iter_count_buf = der_find_elem(params, params_len, 1, &tag, &tmp_len);
+	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
+			tmp_len < 1 || tmp_len > 4)
+		return NULL;
+
+	iter_count = 0;
+	while (tmp_len--)
+		iter_count = (iter_count << 8) | *iter_count_buf++;
+
+	key_len_buf = der_find_elem(params, params_len, 2, &tag, &tmp_len);
+	if (key_len_buf) {
+		if (tag != ASN1_ID_INTEGER || tmp_len != 1)
+			return NULL;
+
+		key_len = 0;
+		while (tmp_len--)
+			key_len = (key_len << 8) | *key_len_buf++;
+	} else
+		key_len = 0;
+
+	prf_sequence = der_find_elem(params, params_len, 3, &tag, &tmp_len);
+	if (prf_sequence) {
+		if (tag != ASN1_ID_SEQUENCE)
+			return NULL;
+
+		oid = der_find_elem(prf_sequence, tmp_len, 0, &tag, &tmp_len);
+		if (!oid || tag != ASN1_ID_OID)
+			return NULL;
+
+		for (i = 0; i < L_ARRAY_SIZE(pkcs5_digest_alg_oids); i++)
+			if (!asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
+						tmp_len, oid))
+				prf_alg = pkcs5_digest_alg_oids[i].type;
+		if (prf_alg == L_CHECKSUM_NONE)
+			return NULL;
+	} else
+		prf_alg = L_CHECKSUM_SHA1;
+
+	oid = der_find_elem(enc_sequence, enc_len, 0, &tag, &tmp_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	for (i = 0; i < L_ARRAY_SIZE(pkcs5_enc_alg_oids); i++)
+		if (asn1_oid_eq(&pkcs5_enc_alg_oids[i].oid, tmp_len, oid)) {
+			enc_scheme = &pkcs5_enc_alg_oids[i];
+			break;
+		}
+	if (!enc_scheme)
+		return NULL;
+
+	params = der_find_elem(enc_sequence, enc_len, 1, &tag, &params_len);
+	if (!params)
+		return NULL;
+
+	/* RFC8018 section B.2 */
+
+	/*
+	 * Since we don't support RC2/RC5, all our PKCS#5 ciphers only
+	 * have an obligatory OCTET STRING IV parameter and a fixed key
+	 * length.
+	 */
+	if (tag != ASN1_ID_OCTET_STRING || params_len != enc_scheme->iv_size)
+		return NULL;
+
+	if (key_len && enc_scheme->key_size != key_len)
+		return NULL;
+	key_len = enc_scheme->key_size;
+
+	if (der_find_elem(enc_sequence, enc_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section 6.2 */
+
+	if (!pkcs5_pbkdf2(prf_alg, password, salt, salt_len, iter_count,
+				key_len, derived_key))
+		return NULL;
+
+	cipher = l_cipher_new(enc_scheme->cipher_type, derived_key, key_len);
+	if (!cipher)
+		return NULL;
+
+	if (l_cipher_set_iv(cipher, params, enc_scheme->iv_size))
+		return cipher;
+
+	l_cipher_free(cipher);
+	return NULL;
+}
+
+LIB_EXPORT struct l_cipher *l_cipher_from_pkcs5_id(const uint8_t *id_asn1,
+							size_t id_asn1_len,
+							const char *password)
+{
+	uint8_t tag;
+	const uint8_t *oid, *params, *salt, *iter_count_buf;
+	size_t oid_len, params_len, tmp_len;
+	unsigned int i, iter_count;
+	const struct pkcs5_pbes1_encryption_oid *pbes1_scheme = NULL;
+	uint8_t derived_key[16];
+	struct l_cipher *cipher;
+
+	oid = der_find_elem(id_asn1, id_asn1_len, 0, &tag, &oid_len);
+	if (!oid || tag != ASN1_ID_OID)
+		return NULL;
+
+	params = der_find_elem(id_asn1, id_asn1_len, 1, &tag, &params_len);
+	if (!params || tag != ASN1_ID_SEQUENCE)
+		return NULL;
+
+	if (der_find_elem(id_asn1, id_asn1_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	if (asn1_oid_eq(&pkcs5_pbes2_oid, oid_len, oid))
+		return cipher_from_pkcs5_pbes2_params(params, params_len,
+							password);
+
+	/* RFC8018 section A.3 */
+
+	for (i = 0; i < L_ARRAY_SIZE(pkcs5_pbes1_encryption_oids); i++)
+		if (asn1_oid_eq(&pkcs5_pbes1_encryption_oids[i].oid,
+					oid_len, oid)) {
+			pbes1_scheme = &pkcs5_pbes1_encryption_oids[i];
+			break;
+		}
+	if (!pbes1_scheme)
+		return NULL;
+
+	salt = der_find_elem(params, params_len, 0, &tag, &tmp_len);
+	if (!salt || tag != ASN1_ID_OCTET_STRING || tmp_len != 8)
+		return NULL;
+
+	iter_count_buf = der_find_elem(params, params_len, 1, &tag, &tmp_len);
+	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
+			tmp_len < 1 || tmp_len > 4)
+		return NULL;
+
+	iter_count = 0;
+	while (tmp_len--)
+		iter_count = (iter_count << 8) | *iter_count_buf++;
+
+	if (der_find_elem(params, params_len, 2, &tag, &tmp_len))
+		return NULL;
+
+	/* RFC8018 section 6.1 */
+
+	if (!pkcs5_pbkdf1(pbes1_scheme->checksum_type,
+				password, salt, 8, iter_count, 16, derived_key))
+		return NULL;
+
+	cipher = l_cipher_new(pbes1_scheme->cipher_type, derived_key + 0, 8);
+	if (!cipher)
+		return NULL;
+
+	if (l_cipher_set_iv(cipher, derived_key + 8, 8))
+		return cipher;
+
+	l_cipher_free(cipher);
+	return NULL;
+}
diff --git a/ell/cipher.h b/ell/cipher.h
index d787f33..3c79aee 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -41,6 +41,10 @@ enum l_cipher_type {
 struct l_cipher *l_cipher_new(enum l_cipher_type type,
 				const void *key, size_t key_length);
 
+struct l_cipher *l_cipher_from_pkcs5_id(const uint8_t *id_asn1,
+					size_t id_asn1_len,
+					const char *password);
+
 void l_cipher_free(struct l_cipher *cipher);
 
 bool l_cipher_encrypt(struct l_cipher *cipher,
-- 
2.11.0


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

* [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (5 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 20:23   ` Denis Kenzior
  2017-08-10 23:10 ` [PATCH 09/10] unit: Update for l_pem_load_private_key() parameter change Andrew Zaborowski
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

Add support for loading PKCS#8 encrypted private key files (those
generated with "openssl pkcs8 ..." or "openssl pkey ..." commands, not
"openssl rsa ..." commands).  The 'encrypted' parameter can be used to
check if a password is required to decode the key if the caller knows
nothing about the key other than the file path.
---
 ell/pem.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 ell/pem.h |  4 +--
 ell/tls.c |  1 +
 3 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/ell/pem.c b/ell/pem.c
index d1f180e..058b8b8 100644
--- a/ell/pem.c
+++ b/ell/pem.c
@@ -36,6 +36,8 @@
 #include "pem.h"
 #include "base64.h"
 #include "string.h"
+#include "asn1-private.h"
+#include "cipher.h"
 
 #define PEM_START_BOUNDARY	"-----BEGIN "
 #define PEM_END_BOUNDARY	"-----END "
@@ -232,11 +234,15 @@ LIB_EXPORT uint8_t *l_pem_load_certificate(const char *filename, size_t *len)
 
 LIB_EXPORT uint8_t *l_pem_load_private_key(const char *filename,
 						const char *passphrase,
+						bool *encrypted,
 						size_t *len)
 {
 	uint8_t *content;
 	char *label;
 
+	if (encrypted)
+		*encrypted = false;
+
 	content = l_pem_load_file(filename, 0, &label, len);
 
 	if (!content)
@@ -246,19 +252,89 @@ LIB_EXPORT uint8_t *l_pem_load_private_key(const char *filename,
 	 * RFC7469- and PKCS#8-compatible label (default in OpenSSL 1.0.1+)
 	 * and the older (OpenSSL <= 0.9.8 default) label.
 	 */
-	if (strcmp(label, "PRIVATE KEY") && strcmp(label, "RSA PRIVATE KEY")) {
+	if (!strcmp(label, "PRIVATE KEY") ||
+			!strcmp(label, "RSA PRIVATE KEY"))
+		goto done;
+
+	/* RFC5958 (PKCS#8) section 3 type encrypted key label */
+	if (!strcmp(label, "ENCRYPTED PRIVATE KEY")) {
+		const uint8_t *key_info, *alg_id, *data;
+		uint8_t tag;
+		size_t key_info_len, alg_id_len, data_len, tmp_len;
+		struct l_cipher *alg;
+		uint8_t *decrypted;
+		int i;
+
+		if (encrypted)
+			*encrypted = true;
+
+		if (!passphrase)
+			goto err;
+
+		/* Technically this is BER, not limited to DER */
+		key_info = der_find_elem(content, *len, 0, &tag, &key_info_len);
+		if (!key_info || tag != ASN1_ID_SEQUENCE)
+			goto err;
+
+		alg_id = der_find_elem(key_info, key_info_len, 0, &tag,
+					&alg_id_len);
+		if (!alg_id || tag != ASN1_ID_SEQUENCE)
+			goto err;
+
+		data = der_find_elem(key_info, key_info_len, 1, &tag,
+					&data_len);
+		if (!data || tag != ASN1_ID_OCTET_STRING || data_len < 8 ||
+				(data_len & 7) != 0)
+			goto err;
+
+		if (der_find_elem(content, *len, 2, &tag, &tmp_len))
+			goto err;
+
+		alg = l_cipher_from_pkcs5_id(alg_id, alg_id_len, passphrase);
+		if (!alg)
+			goto err;
+
+		decrypted = l_malloc(data_len);
+
+		if (!l_cipher_decrypt(alg, data, decrypted, data_len)) {
+			l_cipher_free(alg);
+			l_free(decrypted);
+			goto err;
+		}
+
+		l_cipher_free(alg);
 		l_free(content);
-		content = NULL;
+		content = decrypted;
+
+		/*
+		 * Strip padding as defined in RFC8018 (for PKCS#5 v1) or
+		 * RFC1423 / RFC5652 (for v2).
+		 */
+
+		if (content[data_len - 1] >= data_len ||
+				content[data_len - 1] > 16)
+			goto err;
+		for (i = 1; i < content[data_len - 1]; i++)
+			if (content[data_len - 1 - i] != content[data_len - 1])
+				goto err;
+		*len = data_len - content[data_len - 1];
+
+		goto done;
 	}
 
 	/*
-	 * TODO: handle ENCRYPTED PRIVATE KEY - RFC5958 section 3.
-	 *
-	 * TODO: handle RSA PRIVATE KEY encrypted keys (OpenSSL <= 0.9.8),
-	 * incompatible with RFC7468 parsing because of the headers present
-	 * before base64 encoded data.
+	 * TODO: handle RSA PRIVATE KEY format encrypted keys
+	 * (as produced by "openssl rsa" commands), incompatible with
+	 * RFC7468 parsing because of the headers present before
+	 * base64-encoded data.
 	 */
 
+	/* Label not known */
+err:
+	l_free(content);
+	content = NULL;
+
+done:
 	l_free(label);
 
 	return content;
diff --git a/ell/pem.h b/ell/pem.h
index c220fd4..93282a3 100644
--- a/ell/pem.h
+++ b/ell/pem.h
@@ -34,8 +34,8 @@ uint8_t *l_pem_load_file(const char *filename, int index,
 
 uint8_t *l_pem_load_certificate(const char *filename, size_t *len);
 
-uint8_t *l_pem_load_private_key(const char *filename,
-				const char *passphrase, size_t *len);
+uint8_t *l_pem_load_private_key(const char *filename, const char *passphrase,
+				bool *encrypted, size_t *len);
 
 #ifdef __cplusplus
 }
diff --git a/ell/tls.c b/ell/tls.c
index 9b199ef..0ca3d6e 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -2223,6 +2223,7 @@ LIB_EXPORT bool l_tls_set_auth_data(struct l_tls *tls, const char *cert_path,
 
 		priv_key = l_pem_load_private_key(priv_key_path,
 							priv_key_passphrase,
+							NULL,
 							&tls->priv_key_size);
 		if (!priv_key)
 			return false;
-- 
2.11.0


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

* [PATCH 09/10] unit: Update for l_pem_load_private_key() parameter change
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (6 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-10 23:10 ` [PATCH 10/10] unit: Test loading encrypted private key PEM files Andrew Zaborowski
  2017-08-11 16:07 ` [PATCH 01/10] checksum: Add SHA224 checksum type Denis Kenzior
  9 siblings, 0 replies; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 561 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 7513b38..9e87fed 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -575,7 +575,7 @@ static void test_key_crypto(const void *data)
 	int rsa = L_KEY_RSA_PKCS1_V1_5;
 
 	cert = l_pem_load_private_key(TESTDATADIR "/cert-client-key-pkcs8.pem",
-					NULL, &certlen);
+					NULL, NULL, &certlen);
 	assert(cert);
 	pubcert = l_pem_load_certificate(TESTDATADIR "/cert-client.pem",
 						&pubcertlen);
-- 
2.11.0


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

* [PATCH 10/10] unit: Test loading encrypted private key PEM files
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (7 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 09/10] unit: Update for l_pem_load_private_key() parameter change Andrew Zaborowski
@ 2017-08-10 23:10 ` Andrew Zaborowski
  2017-08-11 20:26   ` Denis Kenzior
  2017-08-11 16:07 ` [PATCH 01/10] checksum: Add SHA224 checksum type Denis Kenzior
  9 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-10 23:10 UTC (permalink / raw)
  To: ell

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

---
 unit/cert-client-key-md5-des.pem     | 29 ++++++++++++++++++++++
 unit/cert-client-key-v2-aes128.pem   | 30 ++++++++++++++++++++++
 unit/cert-client-key-v2-aes256.pem   | 30 ++++++++++++++++++++++
 unit/cert-client-key-v2-des-ede3.pem | 30 ++++++++++++++++++++++
 unit/cert-client-key-v2-des.pem      | 29 ++++++++++++++++++++++
 unit/test-pem.c                      | 48 ++++++++++++++++++++++++++++++++++++
 6 files changed, 196 insertions(+)
 create mode 100644 unit/cert-client-key-md5-des.pem
 create mode 100644 unit/cert-client-key-v2-aes128.pem
 create mode 100644 unit/cert-client-key-v2-aes256.pem
 create mode 100644 unit/cert-client-key-v2-des-ede3.pem
 create mode 100644 unit/cert-client-key-v2-des.pem

diff --git a/unit/cert-client-key-md5-des.pem b/unit/cert-client-key-md5-des.pem
new file mode 100644
index 0000000..e3edfc5
--- /dev/null
+++ b/unit/cert-client-key-md5-des.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQMwDgQI4Jws4ZHp7oQCAggABIIEyGImScBCorOX2u/F
+ISGvMBLavYPfA1f349fcfPfjbMeTLtrubuFfSYJDrB1KaP4oWsK3RA8AjuNtP49N
+fWjaAD6E9YTcNPVODgqNaoeslatqszPEqsqfx+vz1inTc+dyZ8ZYTWDlWAFSC33B
+k6z5CX68YdujTI9hBtkwAJuCoSSIKJNM7duSXzlxM3IfCfzRn4BuO+8usdxqrc5A
+p1R+LvDehIeOrQxkpJE3oHPq1xcCG4/WOnHWwRlmHmQIc2Z+ZLdgFjXYLvmNG58B
+PcBAxWjppmZZMXiMqIoZxqQ7hBhwqI2wxCFYAihf4cgn6bT37sv0CeNPjRHfftpr
+3tWgSeqLbov7Sfm5f1tq3AhJ3om8aaHEL8vUexs0j9mKhJyM0gyel+d1pHSi9/Ka
+U/qNk2KzhZl4+/p7ngjkK8or7IDgbRQWzRXac6uxnvhDRuCZWWAjgzq7A9KdjMCf
+T0+OX9USpOl2/cQSeKdRY5xKLBudQGilMvKZwd+rxBMkDBCwl+fj5HX1Tcj085kv
+CSEOpA90HvqI9VvdxPw0KKWTc/d3FgWKVVzEqtVUCbtDGXZnv3Kt9F05zoX/wL2k
+PkCd7yQouCYxPevVVz1kus5mwWHaZbEUW6S9GUSeZXs/Itb9Jwl9X6m1G9e393U+
+FQb95dfDzP1zQzemLJ+Iu6rkmKNC6x1pC+hNG3jy5QRoQ9wB4WV4q3JRHFUECEgd
+CAN52Saz9f7qt1MmoNPM0fSS+ovh08KoABEI7mp8s9fFj0b7x9h/zlRgigNKp+JE
+N9/51OSopajlse0ly+1zb8I2iOGeA3U4cvZG5mEP+kstJvdD4PYgx9cWDm6EDKmN
+4nIL48aNoWFxa7MGJsmQo56QmGAxG7lZusVu4lYUvHQsmqDQWhqBz1k/f4GzioN0
+7wslyuElIrZyRugYdh+Epy7WbXRi9nBhwuWpOx8TnwOszWIfJT7NLWH+/SaVzuG4
+IsR1gnaQ5HLPyXxuaJkzcZs7EOG5S5MT7tDW9i72RZUiUPGztmhOLxkYrH/r3UCa
+8Agc1nYXs8VH9sV+LMMGdCVoY/RwJvZwf13fqnLcmIA4iI8cDf1beUVm1JvdgIL/
+5Pbxyh2sAzyk/DIFD6yCQUacBKkR3EAXPG9gm5jebjHOU+gxSt69e3jgA1BvuoS5
+S3xLePrZnGZuPjM2PQX6LW1wWBtNlhbqWAkyeL3YwEwv2FjluFqALB/He/MaNly3
+UXFULImo8C/2UF9y9hgoSuamFqlKtgaNBUlqNPxX0EQmyCuqBEGYaouZ2TzPfZ44
+Jf6p6sQZeEmklEIDkaC9DvAGU7DPRfxolLpYHvdHQTwnjKMbFkg7FSAzzdNiKKeR
+nEnCkaofA2FASfQaZvOkewACaZfqJ1FCSsoetYq2Ulf8o1f8j/QM+JIq4p0DIybz
+4gsBmg05xufNiZNqZrrFc0/HcZkT3ahgtY+TMzU8d0hAS7roFNlM2lpaE69HJeTZ
+rhRO7/VAU2Kb0bQI5UWe4yfvbPBmmaxw06lPahlBAEgqeULwfVWBPafjSyq8vPag
+9RzpwSASqL6dv89qdOPE0JioA9xZ3cemlVOgqzd04AkdnDf3flGCJa6O9BujGm72
+8t0TmXLstK7YNaxQYA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/unit/cert-client-key-v2-aes128.pem b/unit/cert-client-key-v2-aes128.pem
new file mode 100644
index 0000000..01cf80d
--- /dev/null
+++ b/unit/cert-client-key-v2-aes128.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIruvC4dfgwlMCAggA
+MB0GCWCGSAFlAwQBAgQQGE5EgJ6nZ5bHxZLAs90seQSCBNBZaeeYO7dFK8301zHn
+ESNjgFaiB11ipzPxjpdJ0+cuP3ljfO+6RD31zANbE7Cpn1NjlhdFVDe5zzK8/1fY
+FnWBbRF4+jYbIppjjwmGjzEEo2NO0kc022RkeIIX+EDWzi25+Vu6LFf5brCybElY
+ObT+kgRGE6mzCDGuUBWiiR+XinqOK9hcYmLo8RtyQ3bLq2aWRDSSQXcCY/Il52c7
+F0Ts6gx6NV5hNUYF5h2pEtS0Dl8Qa7zfFtnEYRuhbEj0WEK/MS+NdZZ30rV/6Qlb
+Voji1meigvXPgNp8/wZROlN6HSVmijE/PSejvhXbptd0VXlMUjloVKJwH3LK3nfo
+RoYKcVvHRslzWC5jXbsaM0TcOSE1JJJUG9ksnp0Ltv+tGw4OR1uCJGT6ZatTcIlt
++bYqvbbJ/t9849SDI3g87uipGqNxPOmH77T8Wikb9x3VE6DzOlXSYRNjbRIKA3XE
+eyD8ow1/95/gpUni0YewZCAuYUTn77Agq19RUa5AWHymMtj1YPZeBqh0SIVvz8nB
+FQafJr+XK9npT/adDHlQsJ129Fo0RvW+S73rgSOSb3qb4jQgGmRrmkyRsDqtufk5
+3EzUfn/uPdjkUu/m6X2nL6Y88sWPraK8bK4paKFOCwpb6/UN6DXVcgx7AS+EMzUv
+4MK7v1U140GKftH8qkFqG+iWgJfjZaWNhZX/k3KGYKANII1Fb35DgPjk3X1w+S6h
+QvQPjPHznlMTtzg8z7lSAXLZ0Ws66EiAVkBLK5+5ZKCz87hDjwwLXtGs4qbFIhTJ
+eZ5ohKvTlyiDfR1hmpcSu7L3jDzs/A62Y9Pc1yqCOhlXgRrefkqybPp1svXxR/Ja
+GKsWkWhSzq2qAzBJXrZ44eTxI79oDUoGdzFg9RLL5B+fsdh/q/OlJ0z079TwCS05
+ccyAmmlDANX8wHbmO4cDZ+0XU/wrsV3+N7DAokqTnBrMFnX0nohaBpgSiExnSxm7
+nOVk9tAoiuIxcabRAgtwW9tEEUDpoI+o44YuIYKsTX/ku3CILOzZhRuqS+oy1/na
+1PvFIuStDYwhWk92NZBsce6+9c5tpPsHgA4mUzokWH6kQ8EeFiq4x11Ooeb5ND4Q
+Z8unqZlJug4LHMWW2Mjsv1dA7qSg+4bbN6RQ+VS89cfcBZAjpKmMnGroWmcLJQQo
+l2CBTzKRw8r0UOnp/EUca7eOUdX7sQhN9Ozmd1HPh6araDAKBnA9IdTWdZKtgefp
+/gsZJ6rgBgqwhQxilCl4lzHN3QGtcg/6fU6VV68IrgU4lD5iKwWDcRBXaCgks/E3
+5useAMJAIJR0qJ2RBnNcfl9QX2qlDqeZKa2CqLHwc4BrEx+QHi8r2bJL1ChRNH9F
+dRaKXPWLWh9vx4d6Xw/xWBMQ3PIEM5JN3oZonFKMfYnRU4ncGQjxoR8PWwr1UEcA
+iT0JqgHX3PnWvSR5DfIJJHGlKTWZlMwtOdgB1Q1eSuIkkkU8JJCuIts4T9juLr0U
+Nng85ZA58JqHpLvPLAecRdMB652lBu4V63XyobnbkQH6rxvF5dh/wi/YyJ3EQgc/
+Lvh068Dheyegbg7B2tDbKvf7Xvjkzmd1T4KZcF0P7iuyq9tzWfQl+8bYmRW+VsR3
+g3GTgMVXQFVQz0+jFSM3Q/JWPA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/unit/cert-client-key-v2-aes256.pem b/unit/cert-client-key-v2-aes256.pem
new file mode 100644
index 0000000..cfca70c
--- /dev/null
+++ b/unit/cert-client-key-v2-aes256.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIpk7ueupozNMCAggA
+MB0GCWCGSAFlAwQBKgQQSlv6z6I4xJfloAEAyx3F7ASCBNDpL021QN2prL3hlTjK
+qea2QZu9xwAxQljKRL00T7i6VcDOJ//YwOgc83GHYjNf47bTIYmzuYvDta6zV82D
+huOMERS3Ep/bIWAf8Jd0bR1vbrvWcDI285083EFbh9PZqnUrFRPdJiqBu/VgyqiE
+2UNjK1s8l8SERVbOSTRNs1glHpUztuvrUxgDsvUqDrFDs8HIfRlOriI2NFIW5kPb
+ncSl5yrUlzerZWmXgF5KCKOh/ojyV56v4UUWaiFzAL7GBxLnYR4EaW3p8xKP/Adq
+vZMkAHX7YzMi9NEWVPmGVLPxkFC50d8XVOOaeI9nt6LAdsnba4xjLvih5dvtIUGc
+LrIgRrc+7l1r+/bZjpFOov4+jTX11cW0HCkm5G6ewuxp57t2XM3cZYk0gGsixGNd
+r3IdWIqCby2vbeI3bdoQpGQkheZmDZ9YUsaTm+qQVtP6bQgiuPLTroP4FISgXTAw
+9OAx9pCyqYMev4QQr9s/a/8kvjVlG6qx4PXLgt8pacW+1Sws7oa8PtfDfVqihqou
+jS91JxLh2xtWsaTepzpsyrMw9g3YjtnO0nkweFvG55Aie1uEkS0hzX7jJ1ITWxvN
+0g8lUNrG1oQeErD/V2bSgtK4r4eaF0RYM/DlR266fVQmKIydnuHzl7Yfdcq5doVg
+416FpzqHVPoPbeg8p9KgcveSGqkAHF0CtemipPu3pVoITvSgGmM6Q60hOk68Wsog
+WxqgT0/pq4W0A0nMwPnP5ecyCBxOZFcgHhgdoPELf1zwUiC6PrxrJaViKaD2tpHk
+IGugw/tBQKvDpQYg7eJyCtCS2bCsvh5FPPCm40Cre2AovidIhjHJ1J9FtlVBJZjG
+JHfF+dgiqKv4mdKyiTaUCiIdJeOvKh1wQTTY3fnyidPiVxL9/Yn/CmNsahrfE8Xe
+a8Le4g6eJk0PeuyhIv698JJFVcV5BVTkQL2YRIgEDrD/HSTm+XygAh+DTQiZrt3S
+i9CBWIU+ysE48soO7sD9iKGcQb3uJC6/l7dIaMW31erxpssXtfWeErtLFXnu7h8J
+SrP5Z5pYcC0ujimNGED1vFlFy5lQOWz3R6gWe44OJeqD3QKO4cthc9yafw/NmtZL
+WU+A7/NO86UK12+IErtDYgAkxZ0RkAb/H8lqWXseL+pnugw2ortLdhJ1PxosKGgq
+aPvfksyNKWKkspJ/9xpAgLoEjcClloExcymOCffpIE71UNhs09WUBIASxe5vIyaU
+61uklltTr2NNds7Sz1P6rwJNqQK2ExTWL3zQkm7xSdfwGBmPbducOjJXiQ1GJs5E
+IR3TJ3Z0fP18YqIMHXxJqt5iEozirtH2Z39xGLidOCNIK/oFiQIAwbRJX6GLDtBE
+QXnhrtzmnU1gzNzpLHpJkNys8v5uNqazlZYeTKCEXyF9xf75XhKpS5yObb5lUznT
+BQQ1SFct8/3JLdgke6lml/PdjL0T1Q98T8mKXAi0BMg0/41lbsuYMqEYpkgFQfYl
+7RsW7w7djVEOKpZOglBWVFUBOHYVyZru4ISzrp5KZxTvtLn8Avqi7gbNV7jZ0XqN
+C7uvJLPB3wyM17KAyW5iNldjXEpkwfle6txMxabmrAJiVBqs8VPagWtz2G5Sfhuc
+N7Om2aewyGHSTP+FVKJo5Zg94Q==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/unit/cert-client-key-v2-des-ede3.pem b/unit/cert-client-key-v2-des-ede3.pem
new file mode 100644
index 0000000..e94d345
--- /dev/null
+++ b/unit/cert-client-key-v2-des-ede3.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIVG6rLrQ+fVgCAggA
+MBQGCCqGSIb3DQMHBAizDQ76m4Q4ZQSCBMh50R/dRYR4agewBCpNNVYIHV/wotfZ
+PhhwcJQFZMmp50rCI9rh13w8TSr+KDreXTY+XzvqFS7fbB0JV3QWlv2wvqkAFXoJ
+CYlE40WXg5Qd2H849IyLEil8J5mvoZohDZYNk82zi+PSvkvxJ8d1RJIiHHhmReeC
+0+rDHd9C+Xr2MVBOMA+gimx/P3qtS4jI0qjmzyUiorHa9lvY5qzxbMibi4mEAjBy
+VWviWHszpCwKVapODFlG2r5R2wvmhp4GUGSigi7KtL7hijEbsh4CW2RqYLR733Nx
+WdsyIc4sD3908ttfQSmsSt6vchAMkelwFizGSEFLMsCne3MGjVsLpVitg6nswl6N
+pvngZu0zaggWFVPRIt+vIimeHrujzoiUuzDizjOVzCiyRkrFuJEMwN3l/AaSxUiG
+lOWga1Eb+McH3oJNU1WtrL7gDwfmKFc26D7xNMnGLcdYxfM1F98XfM3FVswaHdC7
+0uTmEmMdhpoNw4CWai37NpigW01cDnxMMpFuX0yTU8GUU/JkBgZ4NHE1sTZrFiOf
+mMr83waumMGwwChhZAd1qDRB35c1HLvVqBt3HkdcyCZP1JBxG4QLrw7IVzG+knlj
+QdrBC/lDNA15wG27v5hRUVEoeFRJkOllUlSqfh0PmJw2t32BP8dS6EsM8eTpnQ7R
+ysqO5CVZ3WTNFwIZ7wD8zmaBOamkZ1OzOluYFL5sBHGRM05pSEsYOivsi7tlp5Gj
+ZQjR+qSKLT34R4QxWhziWgNC/ynjVuWNWX67p1T/ngsM9kGa6cm84XbHQL7CqUyX
+H7vOWtWHGCclS1Ori5vjFP8/qdOVGMpiKnX8HvoBv6zxJvfMYNAz39MMewlfHdCa
+vEvBVwxLYRxbaL1IGNUebXVyn7JNRhuDm1SDNU1ADj8GW4AL5+22D9xArz8Lnkrj
++lvHm1NMIckciFYHraKmIPeJLiLIxDJ1SX+WgJGLo+P0W2TJLHAnQl5a1KzJOsIq
+/y35Q4mFLX0JE4mzAj2S1bsVate4FZpnKqVT0mfN5/UPSnQOpJKRSTYV9QJm1mGb
+gtdvwSvSniyjSSP/MAB+M7C0N4syC4N4sXYXJTKcM3CN/tN4ASycpkWRvXXLWRsj
+BuQq9z50ojdnx+twu2eG3eYRAGjEW7yOD3GHPQOtCx3IQDptmzYf2v4rk9x+IFfT
+L0ZfmyVevXgm9zjHI9s64Ok1g/6SL8lO+wszfjDs1zEgrMRfoVoKOBrWN7fYKiKi
+GBUeaZ9HgcM1ha/a63N1LPK9OPR2w4qh+DpCLpfvhzZN6IRv1oFddws8jwye1pJb
+1Po33NxHUfsOTX+lpc61NOEua7s3/Wu5gm0jBrX5c/aKCfXMsJHzW+0wl4SAXDog
+3Cl29/NAMSQDpQP9A91QSwHYkyzk4rBLcrbx6bQfFSHOqdl2dto+UJfiz+5PzD7s
+I7k72LGzrfIOq4brLbrLIGwj/ani/vvSZnXYzx3uUeP9w1EZSgNKC9HLBW7lyav3
+IlY7HAO2GMVlIdzynHPT3wMXtLqf/ykO+tkrEF4LjOu9r+cdhCxHum22vlgZKL7J
+J044ViKBro0CWL1wajpFQOvG/BG4VDJ/dfGee0iBr4R+CIkaUwVTCdRsibyZRM8E
+FL0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/unit/cert-client-key-v2-des.pem b/unit/cert-client-key-v2-des.pem
new file mode 100644
index 0000000..c34d7bd
--- /dev/null
+++ b/unit/cert-client-key-v2-des.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIzeF0Vz5uMq4CAggA
+MBEGBSsOAwIHBAiPr9VLgU0FCwSCBMiTCrQBvWrSvy78jVACd6Lc6eQwCdGiDzdK
+767UB+OTpwy7cbSUt94dcy9KVo2zoHfQFt/4U2c8XZWvmg03S2JtB61W0LPEqNTn
+4AWcYl4DZV7lV2YOzEawDsBz8fJDUcb9t00LKXX6mRZlJ8iXPs0HoYLv93sBf/Z1
+oj4M6Idr6ek1IlGwRZ3qJjHUqOPWj1dybY+LqMz5RHy4+BlH7v7f00sVUTJsCMlj
+fIyluMLQuCAi6y4zTQA+CgZt7BJcGWq3pAXD3AW0lSy+v7ODauPLwR3x8V9hwZ+D
+T/3+Eb7F5yy/7B48j4GgojhI1+Uqy4Jh/lAEKImxEiWM9q7cd9r0pf3hAO6eQLry
+S7aVzcEvvLyQLtCOOJX3C6bfIIkHVvn1OHeMV8beG0V+TcbH5LfIAJfffyqDeiSa
+xaPcHHISN9UqDM7PCTCABlzRO/zCJ8TfbroD2FUX5X6ryMfmPpVyTx2wJqb8Hagu
+2/Lt1kdIhMfBtqFFAfyUwOpcJ3bXDvuEV2qwb+e2wuYBdWgijON/9QH/mfq4dnwE
+drC+8Sx2FY2Tabq/UF13aWCiEU4A6bXKQuDZkwSHMQGAh0MMkzt2WDjv+a2k+Iew
+lTFqzmaIS6COWZx8VVaYbxZXqDqOPCD48BzSVp7oU8T/tplcDmwniNqS91zaU3GU
+AUoSaUaB2KjGCLfieKW7XaVbDIJ2zysU6kayfiYnUYUsGbFKDu8SuzT8VHGXA9Zy
+9EEJgabIOqecPmGSQQu3kpb9NF0KxNQC8WhnyGt6WEE9sG36US79tfMzCThBA6S5
+cP2P86NLEEyYlDSQYxmh46TqYiPtdmOZ7RKdAMnX50PRYroMMu91VCmkKlr1Twnj
+jIRzH6I8kRDNdYOcSit4HbIOzGy6unJhfVHhMBH7zIVWF1se8+Ri7M7veeiixbE/
+aWl0qZ1wMIZYKSHwgNl4LZwaxyvLR9n0rPkrJVOEmuKq2vyIjcus41YqKVm6zYWf
+gJSBXSYBEJq11wDCWJGVIi1VGS4PeA4t0u8af0PD9+Nyj2DfaQENaOyKsCAFqfZU
+rjk10dmpuAnEEE+uEqrpHeqaYSPZT08EkaZy9meUgtFeIqTzgXC9oHxTqJpj3+as
+ln7p28gMosEEK3At7kpMyD/gQmCeP+cyK7dFGP46D1qTtlSeWi+ZNa/W/ULvDcQw
+SWmT168M1aA5bHkHfK+xcFo776YGoP6tOaJeT684Tyj/35GTNldYdeQIFykQ5dRV
+TO/zO1WopBNVT+RQnOzJXvsiRJZ7c6Y2S1XyOj9t9LJndDD65leLWqKeepHmKMqD
+h78Kea72+3s+STj7D2pJFSeaPaBc9G0vZhDFqWyga9nHFNcF/k6jj22NDJyfgj1F
+1tEoMNn+Cu1xh1Krl6KHEFlcMm6j9XuU/BhDBMJhO8DfpQye/xNSYq+KFrQ1Emdl
+X/ynmsFsfmVv4P1YSg7/z87ZlBmcJUHePHpM1eiWygW8ujCsOybihAj3OxVpDF9R
+RGlsGvHXkNDVSQG5y/zron8IJjbixdAe1BUdYfI8V6f13fUbJVOg5oeICsEcna3v
+wnNE+gYCF3uEzoBx+N+tRHvJ0t2U9rHGXphefCE50mPCZ0nYps/OPSq0OCeGjgA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/unit/test-pem.c b/unit/test-pem.c
index 0a075dd..9090a24 100644
--- a/unit/test-pem.c
+++ b/unit/test-pem.c
@@ -87,6 +87,42 @@ static void test_pem(const void *data)
 	l_free(decoded);
 }
 
+static void test_encrypted_pkey(const void *data)
+{
+	const char *encrypted_pem = data;
+	const char *plaintext_pem = "unit/cert-client-key-pkcs8.pem";
+	bool encrypted;
+	size_t size1, size2;
+	uint8_t *pkey1, *pkey2;
+
+	encrypted = false;
+	assert(!l_pem_load_private_key(encrypted_pem, NULL,
+					&encrypted, &size1));
+	assert(encrypted);
+
+	encrypted = false;
+	assert(!l_pem_load_private_key(encrypted_pem, "wrong-passwd",
+					&encrypted, &size1));
+	assert(encrypted);
+
+	encrypted = false;
+	pkey1 = l_pem_load_private_key(encrypted_pem, "abc",
+					&encrypted, &size1);
+	assert(pkey1);
+	assert(encrypted);
+
+	pkey2 = l_pem_load_private_key(plaintext_pem, NULL,
+					&encrypted, &size2);
+	assert(pkey2);
+	assert(!encrypted);
+
+	assert(size1 == size2);
+	assert(!memcmp(pkey1, pkey2, size1));
+
+	l_free(pkey1);
+	l_free(pkey2);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -98,5 +134,17 @@ int main(int argc, char *argv[])
 
 	l_test_add("pem/empty label", test_pem, &empty_label);
 
+	l_test_add("pem/v1 MD5AndDES encrypted Private Key",
+			test_encrypted_pkey,
+			"unit/cert-client-key-md5-des.pem");
+	l_test_add("pem/v2 DES encrypted Private Key", test_encrypted_pkey,
+			"unit/cert-client-key-v2-des.pem");
+	l_test_add("pem/v2 DES EDE3 encrypted Private Key", test_encrypted_pkey,
+			"unit/cert-client-key-v2-des-ede3.pem");
+	l_test_add("pem/v2 AES128 encrypted Private Key", test_encrypted_pkey,
+			"unit/cert-client-key-v2-aes128.pem");
+	l_test_add("pem/v2 AES256 encrypted Private Key", test_encrypted_pkey,
+			"unit/cert-client-key-v2-aes256.pem");
+
 	return l_test_run();
 }
-- 
2.11.0


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

* Re: [PATCH 01/10] checksum: Add SHA224 checksum type
  2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
                   ` (8 preceding siblings ...)
  2017-08-10 23:10 ` [PATCH 10/10] unit: Test loading encrypted private key PEM files Andrew Zaborowski
@ 2017-08-11 16:07 ` Denis Kenzior
  9 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:07 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> ---
>   ell/checksum.c | 2 ++
>   ell/checksum.h | 1 +
>   ell/key.c      | 3 +++
>   3 files changed, 6 insertions(+)
> 

Applied, thanks.

Regards,
-Denis


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

* Re: [PATCH 02/10] cipher: Add DES-CBC cipher type
  2017-08-10 23:10 ` [PATCH 02/10] cipher: Add DES-CBC cipher type Andrew Zaborowski
@ 2017-08-11 16:08   ` Denis Kenzior
  0 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:08 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> ---
>   ell/cipher.c | 2 ++
>   ell/cipher.h | 1 +
>   2 files changed, 3 insertions(+)
> 

Applied, thanks.

Regards,
-Denis


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

* Re: [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h
  2017-08-10 23:10 ` [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h Andrew Zaborowski
@ 2017-08-11 16:17   ` Denis Kenzior
  2017-08-12  0:08     ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:17 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> Extract those utilities that can be used by pem.c for decoding encrypted
> certificates and possibly other mechanisms.  Introduce the asn1_oid_eq
> macro for comparing OIDs.
> ---
>   ell/asn1-private.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>   ell/tls.c          | 102 ++-------------------------------------------
>   2 files changed, 121 insertions(+), 99 deletions(-)
>   create mode 100644 ell/asn1-private.h
> 

We also need the Makefile.am changes.

> diff --git a/ell/asn1-private.h b/ell/asn1-private.h
> new file mode 100644
> index 0000000..c1f1c5d
> --- /dev/null
> +++ b/ell/asn1-private.h
> @@ -0,0 +1,118 @@
> +/*
> + *  Embedded Linux library
> + *
> + *  Copyright (C) 2017  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
> + */
> +
> +#define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
> +
> +#define ASN1_CLASS_UNIVERSAL	0
> +
> +#define ASN1_ID_SEQUENCE	ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
> +#define ASN1_ID_SET		ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
> +#define ASN1_ID_INTEGER		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x02)
> +#define ASN1_ID_BIT_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
> +#define ASN1_ID_OCTET_STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
> +#define ASN1_ID_OID		ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
> +#define ASN1_ID_UTF8STRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
> +#define ASN1_ID_PRINTABLESTRING	ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x13)
> +
> +struct asn1_oid {
> +	uint8_t asn1_len;
> +	uint8_t asn1[10];
> +};
> +
> +#define asn1_oid_eq(oid1, oid2_len, oid2_string) \
> +	((oid1)->asn1_len == (oid2_len) && \
> +	 !memcmp((oid1)->asn1, (oid2_string), (oid2_len)))
> +
> +static inline int parse_asn1_definite_length(const uint8_t **buf, > +						size_t *len)

Since this is now a separate (albeit private) module, we should follow 
our usual naming conventions by prefixing with the module name.  So 
should this be asn1_parse_definite_length?

> +{
> +	int n;
> +	size_t result = 0;
> +
> +	(*len)--;
> +
> +	if (!(**buf & 0x80))
> +		return *(*buf)++;
> +
> +	n = *(*buf)++ & 0x7f;
> +	if ((size_t) n > *len)
> +		return -1;
> +
> +	*len -= n;
> +	while (n--)
> +		result = (result << 8) | *(*buf)++;
> +
> +	return result;
> +}
> +
> +/* Return index'th element in a DER SEQUENCE */
> +static inline uint8_t *der_find_elem(uint8_t *buf, size_t len_in, int index,
> +			uint8_t *tag, size_t *len_out)

asn1_der_find_elem?

> +{
> +	int tlv_len;
> +
> +	while (1) {
> +		if (len_in < 2)
> +			return NULL;
> +
> +		*tag = *buf++;
> +		len_in--;
> +
> +		tlv_len = parse_asn1_definite_length((void *) &buf, &len_in);
> +		if (tlv_len < 0 || (size_t) tlv_len > len_in)
> +			return NULL;
> +
> +		if (index-- == 0) {
> +			*len_out = tlv_len;
> +			return buf;
> +		}
> +
> +		buf += tlv_len;
> +		len_in -= tlv_len;
> +	}
> +}
> +
> +/* Return an element in a DER SEQUENCE structure by path */
> +static inline uint8_t *der_find_elem_by_path(uint8_t *buf, size_t len_in,
> +						uint8_t tag, size_t *len_out,
> +						...)

asn1_der_find_elem_by_path?

> +{
> +	uint8_t elem_tag;
> +	int pos;
> +	va_list vl;
> +
> +	va_start(vl, len_out);
> +
> +	pos = va_arg(vl, int);
> +
> +	while (pos != -1) {
> +		buf = der_find_elem(buf, len_in, pos, &elem_tag, &len_in);
> +
> +		pos = va_arg(vl, int);
> +
> +		if (!buf || elem_tag != (pos == -1 ? tag : ASN1_ID_SEQUENCE))
> +			return NULL;
> +	}
> +
> +	va_end(vl);
> +
> +	*len_out = len_in;
> +	return buf;
> +}

Otherwise this looks fine.

Regards,
-Denis

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

* Re: [PATCH 04/10] tls: Report error if private key loading fails
  2017-08-10 23:10 ` [PATCH 04/10] tls: Report error if private key loading fails Andrew Zaborowski
@ 2017-08-11 16:18   ` Denis Kenzior
  0 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:18 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> Cleanup: drop the unneeded priv_key initialization and don't wait for
> the next l_key_get_info() to fail when a private key was set but can't
> be loaded.
> ---
>   ell/tls.c | 10 +++++-----
>   1 file changed, 5 insertions(+), 5 deletions(-)
> 

Applied, thanks.

Regards,
-Denis


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

* Re: [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions
  2017-08-10 23:10 ` [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions Andrew Zaborowski
@ 2017-08-11 16:28   ` Denis Kenzior
  2017-08-12  0:12     ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:28 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> Implement the PBKDF1 and PBKDF2 functions from PKCS#4 - RFC8018.  This
> is for now placed in cipher.c as a dependency for the
> l_cipher_from_pkcs5_id patch but probably better fits in a separate file
> called pkcs5.c or something else.
> > Note iwd already has a PBKDF2 implementation and unit tests, it can be
> switched to use this ell version and the unit tests moved to ell.

We might as well export this from ell and use it in iwd.  There's no 
sense in both carrying the same code.

So maybe we should put this into ell/pkcs5.c and export l_pkcs5_pbkdf1 
and l_pkcs5_pbkdf2

> ---
>   ell/cipher.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 127 insertions(+)
> 
> diff --git a/ell/cipher.c b/ell/cipher.c
> index e51f6e7..8e60d61 100644
> --- a/ell/cipher.c
> +++ b/ell/cipher.c
> @@ -34,6 +34,7 @@
>   #include "cipher.h"
>   #include "private.h"
>   #include "random.h"
> +#include "checksum.h"
>   
>   #ifndef HAVE_LINUX_IF_ALG_H
>   #ifndef HAVE_LINUX_TYPES_H
> @@ -632,3 +633,129 @@ bool l_aead_cipher_is_supported(enum l_aead_cipher_type type)
>   
>   	return supported_aead_ciphers & (1 << type);
>   }
> +
> +/* RFC8018 section 5.1 */
> +static bool pkcs5_pbkdf1(enum l_checksum_type type, const char *password,
> +				const uint8_t *salt, size_t salt_len,
> +				unsigned int iter_count,
> +				size_t dk_len, uint8_t *out_dk)

I know RFC8018 uses this order, but should dk_len be after out_dk? 
That's generally how we order the parameters (e.g. in l_cipher_encrypt)

Same question for pbkdf2

> +{
> +	size_t hash_len, t_len;
> +	uint8_t t[20 + salt_len + strlen(password)];
> +	struct l_checksum *checksum;
> +
> +	switch (type) {
> +	case L_CHECKSUM_MD5:
> +		hash_len = 16;
> +		break;
> +	case L_CHECKSUM_SHA1:
> +		hash_len = 20;
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	if (dk_len > hash_len)
> +		return false;
> +
> +	checksum = l_checksum_new(type);
> +	if (!checksum)
> +		return false;
> +
> +	memcpy(t, password, strlen(password));
> +	memcpy(t + strlen(password), salt, salt_len);
> +	t_len = strlen(password) + salt_len;
> +
> +	while (iter_count) {
> +		l_checksum_reset(checksum);
> +		if (!l_checksum_update(checksum, t, t_len))
> +			break;

doc/coding-style.txt item M1

> +		if (l_checksum_get_digest(checksum, t, hash_len) !=
> +				(ssize_t) hash_len)
> +			break;

as above

> +		t_len = hash_len;
> +
> +		iter_count--;
> +	}
> +
> +	l_checksum_free(checksum);
> +
> +	if (iter_count)
> +		return false;
> +
> +	memcpy(out_dk, t, dk_len);
> +	return true;
> +}
> +
> +/* RFC8018 section 5.2 */
> +static bool pkcs5_pbkdf2(enum l_checksum_type type, const char *password,
> +				const uint8_t *salt, size_t salt_len,
> +				unsigned int iter_count,
> +				size_t dk_len, uint8_t *out_dk)
> +{
> +	size_t h_len;
> +	struct l_checksum *checksum;
> +	unsigned int i;
> +
> +	switch (type) {
> +	case L_CHECKSUM_SHA1:
> +		h_len = 20;
> +		break;
> +	case L_CHECKSUM_SHA224:
> +		h_len = 28;
> +		break;
> +	case L_CHECKSUM_SHA256:
> +		h_len = 32;
> +		break;
> +	case L_CHECKSUM_SHA384:
> +		h_len = 48;
> +		break;
> +	case L_CHECKSUM_SHA512:
> +		h_len = 64;
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	checksum = l_checksum_new_hmac(type, password, strlen(password));
> +	if (!checksum)
> +		return false;
> +
> +	for (i = 1; dk_len; i++) {
> +		unsigned int j, k;
> +		uint8_t u[salt_len + 64];
> +		size_t u_len;
> +		size_t block_len = h_len;
> +
> +		if (block_len > dk_len)
> +			block_len = dk_len;
> +
> +		memset(out_dk, 0, block_len);
> +
> +		memcpy(u, salt, salt_len);
> +		l_put_be32(i, u + salt_len);
> +		u_len = salt_len + 4;
> +
> +		for (j = 0; j < iter_count; j++) {
> +			l_checksum_reset(checksum);
> +			if (!l_checksum_update(checksum, u, u_len))
> +				break;

item M1

> +			if (l_checksum_get_digest(checksum, u, h_len) !=
> +					(ssize_t) h_len)
> +				break;

item M1
> +			u_len = h_len;
> +
> +			for (k = 0; k < block_len; k++)
> +				out_dk[k] ^= u[k];
> +		}

item M1

> +		if (j < iter_count)
> +			break;
> +
> +		out_dk += block_len;
> +		dk_len -= block_len;
> +	}
> +
> +	l_checksum_free(checksum);
> +
> +	return !dk_len;
> +}
> 

Regards,
-Denis

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

* Re: [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-10 23:10 ` [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id Andrew Zaborowski
@ 2017-08-11 16:55   ` Denis Kenzior
  2017-08-12  0:17     ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 16:55 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> Add a utility to parse all of the PKCS#5 DER-encoded encryption scheme
> information, use the right PBKDF function to calculate the key,
> create the appropriate l_cipher object type (if we support that PKCS#5
> cipher type) with that key and set the IV on the l_cipher object.
> 
> We don't support any of the RC2 or RC5 based encryption schemes or
> those that use MD2, SHA512-224 or SHA512-256 for the hash, because
> there's no kernel support for those algorithms.  OpenSSL can create
> RSA private keys encrypted with some of these algorithms but MD5+DES
> and DES3-EDE are the default and the popular algorithms.  OpenSSL also
> supports camellia ciphers in those scenarios which we could add.
> 
> Note that the caller still needs to add or remove the padding from the
> data encrypted or decrypted with the l_cipher object so technically this
> doesn't implement 100% of PKCS#5 PBES1 or PBES2.
> Thise code may be better moved to a separate file from cipher.c.  If we
> do that then it could be wrapped in a separate object that would do the
> padding after calling the l_cipher operation, too, though the padding
> is really simple anway, may not be worth the overhead of another wrapper.

Another reason to move this is that I don't really want to expose it in 
l_cipher.  The right way for us to enable encrypted certificates is via 
the keyctl API.  Until then, we should stuff this into some private 
file.  Can we put this into asn1-private.[ch]?

> ---
>   ell/cipher.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   ell/cipher.h |   4 +
>   2 files changed, 294 insertions(+)
> 

<snip>

> +static struct l_cipher *cipher_from_pkcs5_pbes2_params(
> +						const uint8_t *pbes2_params,
> +						size_t pbes2_params_len,
> +						const char *password)
> +{
> +	uint8_t tag;
> +	const uint8_t *kdf_sequence, *enc_sequence, *oid, *params,
> +		*salt, *iter_count_buf, *key_len_buf, *prf_sequence;
> +	size_t kdf_len, enc_len, params_len, salt_len, key_len, tmp_len;
> +	unsigned int i, iter_count;
> +	enum l_checksum_type prf_alg = L_CHECKSUM_NONE;
> +	const struct pkcs5_enc_alg_oid *enc_scheme = NULL;
> +	uint8_t derived_key[64];
> +	struct l_cipher *cipher;
> +
> +	/* RFC8018 section A.4 */
> +
> +	kdf_sequence = der_find_elem(pbes2_params, pbes2_params_len, 0,
> +					&tag, &kdf_len);
> +	if (!kdf_sequence || tag != ASN1_ID_SEQUENCE)
> +		return NULL;
> +
> +	enc_sequence = der_find_elem(pbes2_params, pbes2_params_len, 1,
> +					&tag, &enc_len);
> +	if (!enc_sequence || tag != ASN1_ID_SEQUENCE)
> +		return NULL;
> +
> +	if (der_find_elem(pbes2_params, pbes2_params_len, 2, &tag, &tmp_len))
> +		return NULL;
> +
> +	/* RFC8018 section A.2 */
> +
> +	oid = der_find_elem(kdf_sequence, kdf_len, 0, &tag, &tmp_len);
> +	if (!oid || tag != ASN1_ID_OID)
> +		return NULL;
> +
> +	if (!asn1_oid_eq(&pkcs5_pbkdf2_oid, tmp_len, oid))
> +		return NULL;
> +
> +	params = der_find_elem(kdf_sequence, kdf_len, 1, &tag, &params_len);
> +	if (!params || tag != ASN1_ID_SEQUENCE)
> +		return NULL;
> +
> +	if (der_find_elem(kdf_sequence, kdf_len, 2, &tag, &tmp_len))
> +		return NULL;
> +
> +	salt = der_find_elem(params, params_len, 0, &tag, &salt_len);
> +	if (!salt || tag != ASN1_ID_OCTET_STRING ||
> +			salt_len < 1 || salt_len > 512)
> +		return NULL;
> +
> +	iter_count_buf = der_find_elem(params, params_len, 1, &tag, &tmp_len);
> +	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
> +			tmp_len < 1 || tmp_len > 4)
> +		return NULL;
> +
> +	iter_count = 0;
> +	while (tmp_len--)
> +		iter_count = (iter_count << 8) | *iter_count_buf++;
> +
> +	key_len_buf = der_find_elem(params, params_len, 2, &tag, &tmp_len);
> +	if (key_len_buf) {
> +		if (tag != ASN1_ID_INTEGER || tmp_len != 1)
> +			return NULL;
> +
> +		key_len = 0;
> +		while (tmp_len--)
> +			key_len = (key_len << 8) | *key_len_buf++;
> +	} else
> +		key_len = 0;
> +
> +	prf_sequence = der_find_elem(params, params_len, 3, &tag, &tmp_len);
> +	if (prf_sequence) {
> +		if (tag != ASN1_ID_SEQUENCE)
> +			return NULL;
> +
> +		oid = der_find_elem(prf_sequence, tmp_len, 0, &tag, &tmp_len);
> +		if (!oid || tag != ASN1_ID_OID)
> +			return NULL;
> +
> +		for (i = 0; i < L_ARRAY_SIZE(pkcs5_digest_alg_oids); i++)
> +			if (!asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
> +						tmp_len, oid))
> +				prf_alg = pkcs5_digest_alg_oids[i].type;
> +		if (prf_alg == L_CHECKSUM_NONE)
> +			return NULL;
> +	} else
> +		prf_alg = L_CHECKSUM_SHA1;
> +
> +	oid = der_find_elem(enc_sequence, enc_len, 0, &tag, &tmp_len);
> +	if (!oid || tag != ASN1_ID_OID)
> +		return NULL;
> +
> +	for (i = 0; i < L_ARRAY_SIZE(pkcs5_enc_alg_oids); i++)
> +		if (asn1_oid_eq(&pkcs5_enc_alg_oids[i].oid, tmp_len, oid)) {
> +			enc_scheme = &pkcs5_enc_alg_oids[i];
> +			break;
> +		}

Our preference is to put {} around the enclosing for in this case.

item M1 here as well

> +	if (!enc_scheme)
> +		return NULL;
> +
> +	params = der_find_elem(enc_sequence, enc_len, 1, &tag, &params_len);
> +	if (!params)
> +		return NULL;
> +
> +	/* RFC8018 section B.2 */
> +
> +	/*
> +	 * Since we don't support RC2/RC5, all our PKCS#5 ciphers only
> +	 * have an obligatory OCTET STRING IV parameter and a fixed key
> +	 * length.
> +	 */
> +	if (tag != ASN1_ID_OCTET_STRING || params_len != enc_scheme->iv_size)
> +		return NULL;
> +
> +	if (key_len && enc_scheme->key_size != key_len)
> +		return NULL;
> +	key_len = enc_scheme->key_size;
> +
> +	if (der_find_elem(enc_sequence, enc_len, 2, &tag, &tmp_len))
> +		return NULL;
> +
> +	/* RFC8018 section 6.2 */
> +
> +	if (!pkcs5_pbkdf2(prf_alg, password, salt, salt_len, iter_count,
> +				key_len, derived_key))
> +		return NULL;
> +
> +	cipher = l_cipher_new(enc_scheme->cipher_type, derived_key, key_len);
> +	if (!cipher)
> +		return NULL;
> +
> +	if (l_cipher_set_iv(cipher, params, enc_scheme->iv_size))
> +		return cipher;
> +
> +	l_cipher_free(cipher);
> +	return NULL;
> +}
> +
> +LIB_EXPORT struct l_cipher *l_cipher_from_pkcs5_id(const uint8_t *id_asn1,
> +							size_t id_asn1_len,
> +							const char *password)
> +{
> +	uint8_t tag;
> +	const uint8_t *oid, *params, *salt, *iter_count_buf;
> +	size_t oid_len, params_len, tmp_len;
> +	unsigned int i, iter_count;
> +	const struct pkcs5_pbes1_encryption_oid *pbes1_scheme = NULL;
> +	uint8_t derived_key[16];
> +	struct l_cipher *cipher;
> +
> +	oid = der_find_elem(id_asn1, id_asn1_len, 0, &tag, &oid_len);
> +	if (!oid || tag != ASN1_ID_OID)
> +		return NULL;
> +
> +	params = der_find_elem(id_asn1, id_asn1_len, 1, &tag, &params_len);
> +	if (!params || tag != ASN1_ID_SEQUENCE)
> +		return NULL;
> +
> +	if (der_find_elem(id_asn1, id_asn1_len, 2, &tag, &tmp_len))
> +		return NULL;
> +
> +	if (asn1_oid_eq(&pkcs5_pbes2_oid, oid_len, oid))
> +		return cipher_from_pkcs5_pbes2_params(params, params_len,
> +							password);
> +
> +	/* RFC8018 section A.3 */
> +
> +	for (i = 0; i < L_ARRAY_SIZE(pkcs5_pbes1_encryption_oids); i++)
> +		if (asn1_oid_eq(&pkcs5_pbes1_encryption_oids[i].oid,
> +					oid_len, oid)) {
> +			pbes1_scheme = &pkcs5_pbes1_encryption_oids[i];
> +			break;
> +		}

{}s for the outer for here please.  Item M1...

> +	if (!pbes1_scheme)
> +		return NULL;
> +
> +	salt = der_find_elem(params, params_len, 0, &tag, &tmp_len);
> +	if (!salt || tag != ASN1_ID_OCTET_STRING || tmp_len != 8)
> +		return NULL;
> +
> +	iter_count_buf = der_find_elem(params, params_len, 1, &tag, &tmp_len);
> +	if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
> +			tmp_len < 1 || tmp_len > 4)
> +		return NULL;
> +
> +	iter_count = 0;
> +	while (tmp_len--)
> +		iter_count = (iter_count << 8) | *iter_count_buf++;
> +
> +	if (der_find_elem(params, params_len, 2, &tag, &tmp_len))
> +		return NULL;
> +
> +	/* RFC8018 section 6.1 */
> +
> +	if (!pkcs5_pbkdf1(pbes1_scheme->checksum_type,
> +				password, salt, 8, iter_count, 16, derived_key))
> +		return NULL;
> +
> +	cipher = l_cipher_new(pbes1_scheme->cipher_type, derived_key + 0, 8);
> +	if (!cipher)
> +		return NULL;
> +
> +	if (l_cipher_set_iv(cipher, derived_key + 8, 8))
> +		return cipher;
> +
> +	l_cipher_free(cipher);
> +	return NULL;
> +}
> diff --git a/ell/cipher.h b/ell/cipher.h
> index d787f33..3c79aee 100644
> --- a/ell/cipher.h
> +++ b/ell/cipher.h
> @@ -41,6 +41,10 @@ enum l_cipher_type {
>   struct l_cipher *l_cipher_new(enum l_cipher_type type,
>   				const void *key, size_t key_length);
>   
> +struct l_cipher *l_cipher_from_pkcs5_id(const uint8_t *id_asn1,
> +					size_t id_asn1_len,
> +					const char *password);
> +
>   void l_cipher_free(struct l_cipher *cipher);
>   
>   bool l_cipher_encrypt(struct l_cipher *cipher,
> 

Regards,
-Denis

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

* Re: [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-10 23:10 ` [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key Andrew Zaborowski
@ 2017-08-11 20:23   ` Denis Kenzior
  2017-08-12  0:30     ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 20:23 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> Add support for loading PKCS#8 encrypted private key files (those
> generated with "openssl pkcs8 ..." or "openssl pkey ..." commands, not
> "openssl rsa ..." commands).  The 'encrypted' parameter can be used to
> check if a password is required to decode the key if the caller knows
> nothing about the key other than the file path.
> ---
>   ell/pem.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>   ell/pem.h |  4 +--
>   ell/tls.c |  1 +
>   3 files changed, 86 insertions(+), 9 deletions(-)
> 
> diff --git a/ell/pem.c b/ell/pem.c
> index d1f180e..058b8b8 100644
> --- a/ell/pem.c
> +++ b/ell/pem.c
> @@ -36,6 +36,8 @@
>   #include "pem.h"
>   #include "base64.h"
>   #include "string.h"
> +#include "asn1-private.h"
> +#include "cipher.h"
>   
>   #define PEM_START_BOUNDARY	"-----BEGIN "
>   #define PEM_END_BOUNDARY	"-----END "
> @@ -232,11 +234,15 @@ LIB_EXPORT uint8_t *l_pem_load_certificate(const char *filename, size_t *len)
>   
>   LIB_EXPORT uint8_t *l_pem_load_private_key(const char *filename,
>   						const char *passphrase,
> +						bool *encrypted,
>   						size_t *len)
>   {
>   	uint8_t *content;
>   	char *label;
>   
> +	if (encrypted)
> +		*encrypted = false;
> +

So we set encrypted even if we fail?  Right now you're not even using 
this parameter, so I wonder if we should maybe introduce a new function, 
like l_pem_is_encrypted() instead?

>   	content = l_pem_load_file(filename, 0, &label, len);
>   
>   	if (!content)

Rest looks good.

Regards,
-Denis

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

* Re: [PATCH 10/10] unit: Test loading encrypted private key PEM files
  2017-08-10 23:10 ` [PATCH 10/10] unit: Test loading encrypted private key PEM files Andrew Zaborowski
@ 2017-08-11 20:26   ` Denis Kenzior
  0 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-11 20:26 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
> ---
>   unit/cert-client-key-md5-des.pem     | 29 ++++++++++++++++++++++
>   unit/cert-client-key-v2-aes128.pem   | 30 ++++++++++++++++++++++
>   unit/cert-client-key-v2-aes256.pem   | 30 ++++++++++++++++++++++
>   unit/cert-client-key-v2-des-ede3.pem | 30 ++++++++++++++++++++++
>   unit/cert-client-key-v2-des.pem      | 29 ++++++++++++++++++++++
>   unit/test-pem.c                      | 48 ++++++++++++++++++++++++++++++++++++
>   6 files changed, 196 insertions(+)
>   create mode 100644 unit/cert-client-key-md5-des.pem
>   create mode 100644 unit/cert-client-key-v2-aes128.pem
>   create mode 100644 unit/cert-client-key-v2-aes256.pem
>   create mode 100644 unit/cert-client-key-v2-des-ede3.pem
>   create mode 100644 unit/cert-client-key-v2-des.pem
> 

Makefile.am changes seem to be missing.  e.g. adding the new pem files 
to unit_test_data_files.

Regards,
-Denis


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

* Re: [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h
  2017-08-11 16:17   ` Denis Kenzior
@ 2017-08-12  0:08     ` Andrew Zaborowski
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:08 UTC (permalink / raw)
  To: ell

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

Hi Denis,

On 11 August 2017 at 18:17, Denis Kenzior <denkenz@gmail.com> wrote:
> On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
>>
>> Extract those utilities that can be used by pem.c for decoding encrypted
>> certificates and possibly other mechanisms.  Introduce the asn1_oid_eq
>> macro for comparing OIDs.
>> ---
>>   ell/asn1-private.h | 118
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   ell/tls.c          | 102 ++-------------------------------------------
>>   2 files changed, 121 insertions(+), 99 deletions(-)
>>   create mode 100644 ell/asn1-private.h
>>
>
> We also need the Makefile.am changes.

Good catch.

>
>
>> diff --git a/ell/asn1-private.h b/ell/asn1-private.h
>> new file mode 100644
>> index 0000000..c1f1c5d
>> --- /dev/null
>> +++ b/ell/asn1-private.h
>> @@ -0,0 +1,118 @@
>> +/*
>> + *  Embedded Linux library
>> + *
>> + *  Copyright (C) 2017  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
>> + */
>> +
>> +#define ASN1_ID(class, pc, tag)        (((class) << 6) | ((pc) << 5) |
>> (tag))
>> +
>> +#define ASN1_CLASS_UNIVERSAL   0
>> +
>> +#define ASN1_ID_SEQUENCE       ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x10)
>> +#define ASN1_ID_SET            ASN1_ID(ASN1_CLASS_UNIVERSAL, 1, 0x11)
>> +#define ASN1_ID_INTEGER                ASN1_ID(ASN1_CLASS_UNIVERSAL, 0,
>> 0x02)
>> +#define ASN1_ID_BIT_STRING     ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x03)
>> +#define ASN1_ID_OCTET_STRING   ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x04)
>> +#define ASN1_ID_OID            ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x06)
>> +#define ASN1_ID_UTF8STRING     ASN1_ID(ASN1_CLASS_UNIVERSAL, 0, 0x0c)
>> +#define ASN1_ID_PRINTABLESTRING        ASN1_ID(ASN1_CLASS_UNIVERSAL, 0,
>> 0x13)
>> +
>> +struct asn1_oid {
>> +       uint8_t asn1_len;
>> +       uint8_t asn1[10];
>> +};
>> +
>> +#define asn1_oid_eq(oid1, oid2_len, oid2_string) \
>> +       ((oid1)->asn1_len == (oid2_len) && \
>> +        !memcmp((oid1)->asn1, (oid2_string), (oid2_len)))
>> +
>> +static inline int parse_asn1_definite_length(const uint8_t **buf, > +
>> size_t *len)
>
>
> Since this is now a separate (albeit private) module, we should follow our
> usual naming conventions by prefixing with the module name.  So should this
> be asn1_parse_definite_length?

Right, I'll rename these functions.

Best regards

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

* Re: [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions
  2017-08-11 16:28   ` Denis Kenzior
@ 2017-08-12  0:12     ` Andrew Zaborowski
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:12 UTC (permalink / raw)
  To: ell

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

On 11 August 2017 at 18:28, Denis Kenzior <denkenz@gmail.com> wrote:
> Hi Andrew,
>
> On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
>>
>> Implement the PBKDF1 and PBKDF2 functions from PKCS#4 - RFC8018.  This
>> is for now placed in cipher.c as a dependency for the
>> l_cipher_from_pkcs5_id patch but probably better fits in a separate file
>> called pkcs5.c or something else.
>> > Note iwd already has a PBKDF2 implementation and unit tests, it can be
>> switched to use this ell version and the unit tests moved to ell.
>
>
> We might as well export this from ell and use it in iwd.  There's no sense
> in both carrying the same code.
>
> So maybe we should put this into ell/pkcs5.c and export l_pkcs5_pbkdf1 and
> l_pkcs5_pbkdf2

Sounds good, that's what I was thinking about.  The PBES1 and PBES2
functions would also fit there.

>
>> ---
>>   ell/cipher.c | 127
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 127 insertions(+)
>>
>> diff --git a/ell/cipher.c b/ell/cipher.c
>> index e51f6e7..8e60d61 100644
>> --- a/ell/cipher.c
>> +++ b/ell/cipher.c
>> @@ -34,6 +34,7 @@
>>   #include "cipher.h"
>>   #include "private.h"
>>   #include "random.h"
>> +#include "checksum.h"
>>     #ifndef HAVE_LINUX_IF_ALG_H
>>   #ifndef HAVE_LINUX_TYPES_H
>> @@ -632,3 +633,129 @@ bool l_aead_cipher_is_supported(enum
>> l_aead_cipher_type type)
>>         return supported_aead_ciphers & (1 << type);
>>   }
>> +
>> +/* RFC8018 section 5.1 */
>> +static bool pkcs5_pbkdf1(enum l_checksum_type type, const char *password,
>> +                               const uint8_t *salt, size_t salt_len,
>> +                               unsigned int iter_count,
>> +                               size_t dk_len, uint8_t *out_dk)
>
>
> I know RFC8018 uses this order, but should dk_len be after out_dk? That's
> generally how we order the parameters (e.g. in l_cipher_encrypt)
>
> Same question for pbkdf2

Ok.  Will also fix the style issues.

Best regards

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

* Re: [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-11 16:55   ` Denis Kenzior
@ 2017-08-12  0:17     ` Andrew Zaborowski
  2017-08-12  0:30       ` Denis Kenzior
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:17 UTC (permalink / raw)
  To: ell

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

Hi Denis,

On 11 August 2017 at 18:55, Denis Kenzior <denkenz@gmail.com> wrote:
> On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
>> Add a utility to parse all of the PKCS#5 DER-encoded encryption scheme
>> information, use the right PBKDF function to calculate the key,
>> create the appropriate l_cipher object type (if we support that PKCS#5
>> cipher type) with that key and set the IV on the l_cipher object.
>>
>> We don't support any of the RC2 or RC5 based encryption schemes or
>> those that use MD2, SHA512-224 or SHA512-256 for the hash, because
>> there's no kernel support for those algorithms.  OpenSSL can create
>> RSA private keys encrypted with some of these algorithms but MD5+DES
>> and DES3-EDE are the default and the popular algorithms.  OpenSSL also
>> supports camellia ciphers in those scenarios which we could add.
>>
>> Note that the caller still needs to add or remove the padding from the
>> data encrypted or decrypted with the l_cipher object so technically this
>> doesn't implement 100% of PKCS#5 PBES1 or PBES2.
>> Thise code may be better moved to a separate file from cipher.c.  If we
>> do that then it could be wrapped in a separate object that would do the
>> padding after calling the l_cipher operation, too, though the padding
>> is really simple anway, may not be worth the overhead of another wrapper.
>
>
> Another reason to move this is that I don't really want to expose it in
> l_cipher.  The right way for us to enable encrypted certificates is via the
> keyctl API.  Until then, we should stuff this into some private file.  Can
> we put this into asn1-private.[ch]?

If we're going to have pkcs5.c, perhaps let's put it there since all
of this is basically PKCS#5?  We would then also need pkcs5-private.h,
is that too many files?

>
>> ---
>>   ell/cipher.c | 290
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   ell/cipher.h |   4 +
>>   2 files changed, 294 insertions(+)
>>
>
> <snip>
>
>
>> +static struct l_cipher *cipher_from_pkcs5_pbes2_params(
>> +                                               const uint8_t
>> *pbes2_params,
>> +                                               size_t pbes2_params_len,
>> +                                               const char *password)
>> +{
>> +       uint8_t tag;
>> +       const uint8_t *kdf_sequence, *enc_sequence, *oid, *params,
>> +               *salt, *iter_count_buf, *key_len_buf, *prf_sequence;
>> +       size_t kdf_len, enc_len, params_len, salt_len, key_len, tmp_len;
>> +       unsigned int i, iter_count;
>> +       enum l_checksum_type prf_alg = L_CHECKSUM_NONE;
>> +       const struct pkcs5_enc_alg_oid *enc_scheme = NULL;
>> +       uint8_t derived_key[64];
>> +       struct l_cipher *cipher;
>> +
>> +       /* RFC8018 section A.4 */
>> +
>> +       kdf_sequence = der_find_elem(pbes2_params, pbes2_params_len, 0,
>> +                                       &tag, &kdf_len);
>> +       if (!kdf_sequence || tag != ASN1_ID_SEQUENCE)
>> +               return NULL;
>> +
>> +       enc_sequence = der_find_elem(pbes2_params, pbes2_params_len, 1,
>> +                                       &tag, &enc_len);
>> +       if (!enc_sequence || tag != ASN1_ID_SEQUENCE)
>> +               return NULL;
>> +
>> +       if (der_find_elem(pbes2_params, pbes2_params_len, 2, &tag,
>> &tmp_len))
>> +               return NULL;
>> +
>> +       /* RFC8018 section A.2 */
>> +
>> +       oid = der_find_elem(kdf_sequence, kdf_len, 0, &tag, &tmp_len);
>> +       if (!oid || tag != ASN1_ID_OID)
>> +               return NULL;
>> +
>> +       if (!asn1_oid_eq(&pkcs5_pbkdf2_oid, tmp_len, oid))
>> +               return NULL;
>> +
>> +       params = der_find_elem(kdf_sequence, kdf_len, 1, &tag,
>> &params_len);
>> +       if (!params || tag != ASN1_ID_SEQUENCE)
>> +               return NULL;
>> +
>> +       if (der_find_elem(kdf_sequence, kdf_len, 2, &tag, &tmp_len))
>> +               return NULL;
>> +
>> +       salt = der_find_elem(params, params_len, 0, &tag, &salt_len);
>> +       if (!salt || tag != ASN1_ID_OCTET_STRING ||
>> +                       salt_len < 1 || salt_len > 512)
>> +               return NULL;
>> +
>> +       iter_count_buf = der_find_elem(params, params_len, 1, &tag,
>> &tmp_len);
>> +       if (!iter_count_buf || tag != ASN1_ID_INTEGER ||
>> +                       tmp_len < 1 || tmp_len > 4)
>> +               return NULL;
>> +
>> +       iter_count = 0;
>> +       while (tmp_len--)
>> +               iter_count = (iter_count << 8) | *iter_count_buf++;
>> +
>> +       key_len_buf = der_find_elem(params, params_len, 2, &tag,
>> &tmp_len);
>> +       if (key_len_buf) {
>> +               if (tag != ASN1_ID_INTEGER || tmp_len != 1)
>> +                       return NULL;
>> +
>> +               key_len = 0;
>> +               while (tmp_len--)
>> +                       key_len = (key_len << 8) | *key_len_buf++;
>> +       } else
>> +               key_len = 0;
>> +
>> +       prf_sequence = der_find_elem(params, params_len, 3, &tag,
>> &tmp_len);
>> +       if (prf_sequence) {
>> +               if (tag != ASN1_ID_SEQUENCE)
>> +                       return NULL;
>> +
>> +               oid = der_find_elem(prf_sequence, tmp_len, 0, &tag,
>> &tmp_len);
>> +               if (!oid || tag != ASN1_ID_OID)
>> +                       return NULL;
>> +
>> +               for (i = 0; i < L_ARRAY_SIZE(pkcs5_digest_alg_oids); i++)
>> +                       if (!asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
>> +                                               tmp_len, oid))
>> +                               prf_alg = pkcs5_digest_alg_oids[i].type;
>> +               if (prf_alg == L_CHECKSUM_NONE)
>> +                       return NULL;
>> +       } else
>> +               prf_alg = L_CHECKSUM_SHA1;
>> +
>> +       oid = der_find_elem(enc_sequence, enc_len, 0, &tag, &tmp_len);
>> +       if (!oid || tag != ASN1_ID_OID)
>> +               return NULL;
>> +
>> +       for (i = 0; i < L_ARRAY_SIZE(pkcs5_enc_alg_oids); i++)
>> +               if (asn1_oid_eq(&pkcs5_enc_alg_oids[i].oid, tmp_len, oid))
>> {
>> +                       enc_scheme = &pkcs5_enc_alg_oids[i];
>> +                       break;
>> +               }
>
>
> Our preference is to put {} around the enclosing for in this case.
>
> item M1 here as well

Ok.

Best regards

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

* Re: [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-11 20:23   ` Denis Kenzior
@ 2017-08-12  0:30     ` Andrew Zaborowski
  2017-08-12  0:40       ` Denis Kenzior
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:30 UTC (permalink / raw)
  To: ell

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

Hi Denis,

On 11 August 2017 at 22:23, Denis Kenzior <denkenz@gmail.com> wrote:
> On 08/10/2017 06:10 PM, Andrew Zaborowski wrote:
>> Add support for loading PKCS#8 encrypted private key files (those
>> generated with "openssl pkcs8 ..." or "openssl pkey ..." commands, not
>> "openssl rsa ..." commands).  The 'encrypted' parameter can be used to
>> check if a password is required to decode the key if the caller knows
>> nothing about the key other than the file path.
>> ---
>>   ell/pem.c | 90
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>>   ell/pem.h |  4 +--
>>   ell/tls.c |  1 +
>>   3 files changed, 86 insertions(+), 9 deletions(-)
>>
>> diff --git a/ell/pem.c b/ell/pem.c
>> index d1f180e..058b8b8 100644
>> --- a/ell/pem.c
>> +++ b/ell/pem.c
>> @@ -36,6 +36,8 @@
>>   #include "pem.h"
>>   #include "base64.h"
>>   #include "string.h"
>> +#include "asn1-private.h"
>> +#include "cipher.h"
>>     #define PEM_START_BOUNDARY  "-----BEGIN "
>>   #define PEM_END_BOUNDARY      "-----END "
>> @@ -232,11 +234,15 @@ LIB_EXPORT uint8_t *l_pem_load_certificate(const
>> char *filename, size_t *len)
>>     LIB_EXPORT uint8_t *l_pem_load_private_key(const char *filename,
>>                                                 const char *passphrase,
>> +                                               bool *encrypted,
>>                                                 size_t *len)
>>   {
>>         uint8_t *content;
>>         char *label;
>>   +     if (encrypted)
>> +               *encrypted = false;
>> +
>
>
> So we set encrypted even if we fail?  Right now you're not even using this
> parameter, so I wonder if we should maybe introduce a new function, like
> l_pem_is_encrypted() instead?

I could do either thing, but the idea here was that whoever is setting
up TLS checks if a passphrase is required.  If it isn't, they get
feedback on whether the PEM file loads Ok in the same call.  If it is
they validate the passphrase and the encrypted PEM in one call.  With
a separate l_pem_is_encrypted the file will be loaded twice.

Best regards

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

* Re: [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-12  0:17     ` Andrew Zaborowski
@ 2017-08-12  0:30       ` Denis Kenzior
  2017-08-12  0:40         ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-12  0:30 UTC (permalink / raw)
  To: ell

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

>> Another reason to move this is that I don't really want to expose it in
>> l_cipher.  The right way for us to enable encrypted certificates is via the
>> keyctl API.  Until then, we should stuff this into some private file.  Can
>> we put this into asn1-private.[ch]?
> 
> If we're going to have pkcs5.c, perhaps let's put it there since all
> of this is basically PKCS#5?  We would then also need pkcs5-private.h,
> is that too many files?
> 

I'm not to worried about the number of files.  I am mostly worried about 
introducing something into the public API and then taking it out later. 
So if we want iwd to use whatever is inside pkcs5.[ch], then it probably 
should be public/exported API, which means it isn't a good candidate for 
l_cipher_from_pkcs5_id either.  That one should be private and hence I 
was thinking of having it in asn1-private.  If you think it belongs 
logically with pkcs5, then we could introduce pkcs5-private.h 
specifically for that purpose.

Hope that made sense.

Regards,
-Denis

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

* Re: [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-12  0:30     ` Andrew Zaborowski
@ 2017-08-12  0:40       ` Denis Kenzior
  2017-08-12  0:45         ` Andrew Zaborowski
  0 siblings, 1 reply; 28+ messages in thread
From: Denis Kenzior @ 2017-08-12  0:40 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

>> So we set encrypted even if we fail?  Right now you're not even using this
>> parameter, so I wonder if we should maybe introduce a new function, like
>> l_pem_is_encrypted() instead?
> 
> I could do either thing, but the idea here was that whoever is setting
> up TLS checks if a passphrase is required.  If it isn't, they get
> feedback on whether the PEM file loads Ok in the same call.  If it is
> they validate the passphrase and the encrypted PEM in one call.  With
> a separate l_pem_is_encrypted the file will be loaded twice.
> 

Do you have a need for this?  If we don't have any immediate need, I 
would just punt on this for now.

Regards,
-Denis

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

* Re: [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-12  0:30       ` Denis Kenzior
@ 2017-08-12  0:40         ` Andrew Zaborowski
  2017-08-12  0:42           ` Denis Kenzior
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:40 UTC (permalink / raw)
  To: ell

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

On 12 August 2017 at 02:30, Denis Kenzior <denkenz@gmail.com> wrote:
>>> Another reason to move this is that I don't really want to expose it in
>>> l_cipher.  The right way for us to enable encrypted certificates is via
>>> the
>>> keyctl API.  Until then, we should stuff this into some private file.
>>> Can
>>> we put this into asn1-private.[ch]?
>>
>>
>> If we're going to have pkcs5.c, perhaps let's put it there since all
>> of this is basically PKCS#5?  We would then also need pkcs5-private.h,
>> is that too many files?
>>
>
> I'm not to worried about the number of files.  I am mostly worried about
> introducing something into the public API and then taking it out later. So
> if we want iwd to use whatever is inside pkcs5.[ch], then it probably should
> be public/exported API, which means it isn't a good candidate for
> l_cipher_from_pkcs5_id either.  That one should be private and hence I was
> thinking of having it in asn1-private.  If you think it belongs logically
> with pkcs5, then we could introduce pkcs5-private.h specifically for that
> purpose.
>
> Hope that made sense.

Since you want l_cipher_from_pkcs5_if private I was thinking of all of
the implementation being in pkcs5.c since it's really all just the
text of the PKCS#5 RFC.  But the PBKDF functions would be exported in
pkcs5.h while the PBES function would only be declared in
pkcs5-private.h as something potentially useless after the kernel
implements this (unless we gain another use case for it in the
meantime)

Best regards

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

* Re: [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id
  2017-08-12  0:40         ` Andrew Zaborowski
@ 2017-08-12  0:42           ` Denis Kenzior
  0 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-12  0:42 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

> Since you want l_cipher_from_pkcs5_if private I was thinking of all of
> the implementation being in pkcs5.c since it's really all just the
> text of the PKCS#5 RFC.  But the PBKDF functions would be exported in
> pkcs5.h while the PBES function would only be declared in
> pkcs5-private.h as something potentially useless after the kernel
> implements this (unless we gain another use case for it in the
> meantime)

That sounds good to me.

Regards,
-Denis

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

* Re: [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-12  0:40       ` Denis Kenzior
@ 2017-08-12  0:45         ` Andrew Zaborowski
  2017-08-12  0:49           ` Denis Kenzior
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Zaborowski @ 2017-08-12  0:45 UTC (permalink / raw)
  To: ell

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

On 12 August 2017 at 02:40, Denis Kenzior <denkenz@gmail.com> wrote:
>>> So we set encrypted even if we fail?  Right now you're not even using
>>> this
>>> parameter, so I wonder if we should maybe introduce a new function, like
>>> l_pem_is_encrypted() instead?
>>
>>
>> I could do either thing, but the idea here was that whoever is setting
>> up TLS checks if a passphrase is required.  If it isn't, they get
>> feedback on whether the PEM file loads Ok in the same call.  If it is
>> they validate the passphrase and the encrypted PEM in one call.  With
>> a separate l_pem_is_encrypted the file will be loaded twice.
>>
>
> Do you have a need for this?  If we don't have any immediate need, I would
> just punt on this for now.

I have iwd code to actually enable encrypted EAP-TLS or EAP-TTLS
private keys.  But it could use a "l_pem_is_encrypted" too, only the
files would be loaded more times.

Best regards

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

* Re: [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key
  2017-08-12  0:45         ` Andrew Zaborowski
@ 2017-08-12  0:49           ` Denis Kenzior
  0 siblings, 0 replies; 28+ messages in thread
From: Denis Kenzior @ 2017-08-12  0:49 UTC (permalink / raw)
  To: ell

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

Hi Andrew,

> 
> I have iwd code to actually enable encrypted EAP-TLS or EAP-TTLS
> private keys.  But it could use a "l_pem_is_encrypted" too, only the
> files would be loaded more times.
> 

Ah I see, because you're asking the agent for the passphrase.

Go with the current proposal, but do me a favor and put in a doc block 
above that function and explain that 'encrypted' doesn't follow our 
typical out-argument semantics.  E.g. it is actually touched even if the 
function fails.

Regards,
-Denis

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

end of thread, other threads:[~2017-08-12  0:49 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-10 23:10 [PATCH 01/10] checksum: Add SHA224 checksum type Andrew Zaborowski
2017-08-10 23:10 ` [PATCH 02/10] cipher: Add DES-CBC cipher type Andrew Zaborowski
2017-08-11 16:08   ` Denis Kenzior
2017-08-10 23:10 ` [PATCH 03/10] tls: Move DER / ASN.1 related definitions to asn1-private.h Andrew Zaborowski
2017-08-11 16:17   ` Denis Kenzior
2017-08-12  0:08     ` Andrew Zaborowski
2017-08-10 23:10 ` [PATCH 04/10] tls: Report error if private key loading fails Andrew Zaborowski
2017-08-11 16:18   ` Denis Kenzior
2017-08-10 23:10 ` [PATCH 05/10] asn1: Use const pointers in ASN1 parsing utilities Andrew Zaborowski
2017-08-10 23:10 ` [PATCH 06/10][RFC] cipher: Implement PKCS#5 key derivation functions Andrew Zaborowski
2017-08-11 16:28   ` Denis Kenzior
2017-08-12  0:12     ` Andrew Zaborowski
2017-08-10 23:10 ` [PATCH 07/10] cipher: Add l_cipher_from_pkcs5_id Andrew Zaborowski
2017-08-11 16:55   ` Denis Kenzior
2017-08-12  0:17     ` Andrew Zaborowski
2017-08-12  0:30       ` Denis Kenzior
2017-08-12  0:40         ` Andrew Zaborowski
2017-08-12  0:42           ` Denis Kenzior
2017-08-10 23:10 ` [PATCH 08/10] pem: Support encrypted keys in l_pem_load_private_key Andrew Zaborowski
2017-08-11 20:23   ` Denis Kenzior
2017-08-12  0:30     ` Andrew Zaborowski
2017-08-12  0:40       ` Denis Kenzior
2017-08-12  0:45         ` Andrew Zaborowski
2017-08-12  0:49           ` Denis Kenzior
2017-08-10 23:10 ` [PATCH 09/10] unit: Update for l_pem_load_private_key() parameter change Andrew Zaborowski
2017-08-10 23:10 ` [PATCH 10/10] unit: Test loading encrypted private key PEM files Andrew Zaborowski
2017-08-11 20:26   ` Denis Kenzior
2017-08-11 16:07 ` [PATCH 01/10] checksum: Add SHA224 checksum type 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.