[PATCH 1/3] pkcs5: Fix pbes2 KDF parsing
by Andrew Zaborowski
Make the key length field optional -- skip if the tag doesn't match --
and fix the oid comparison.
---
ell/pkcs5.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/ell/pkcs5.c b/ell/pkcs5.c
index cf61a35..7cedf4d 100644
--- a/ell/pkcs5.c
+++ b/ell/pkcs5.c
@@ -254,7 +254,7 @@ static struct l_cipher *pkcs5_cipher_from_pbes2_params(
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;
+ unsigned int i, iter_count, pos;
enum l_checksum_type prf_alg = L_CHECKSUM_NONE;
const struct pkcs5_enc_alg_oid *enc_scheme = NULL;
uint8_t derived_key[64];
@@ -309,11 +309,14 @@ static struct l_cipher *pkcs5_cipher_from_pbes2_params(
while (tmp_len--)
iter_count = (iter_count << 8) | *iter_count_buf++;
- key_len_buf = asn1_der_find_elem(params, params_len, 2, &tag, &tmp_len);
- if (key_len_buf) {
- if (tag != ASN1_ID_INTEGER || tmp_len != 1)
+ pos = 2;
+ key_len_buf = asn1_der_find_elem(params, params_len, pos,
+ &tag, &tmp_len);
+ if (key_len_buf && tag == ASN1_ID_INTEGER) {
+ if (tmp_len != 1)
return NULL;
+ pos++;
key_len = 0;
while (tmp_len--)
@@ -321,11 +324,10 @@ static struct l_cipher *pkcs5_cipher_from_pbes2_params(
} else
key_len = 0;
- prf_sequence = asn1_der_find_elem(params, params_len, 3,
+ prf_sequence = asn1_der_find_elem(params, params_len, pos,
&tag, &tmp_len);
- if (prf_sequence) {
- if (tag != ASN1_ID_SEQUENCE)
- return NULL;
+ if (prf_sequence && tag == ASN1_ID_SEQUENCE) {
+ pos++;
oid = asn1_der_find_elem(prf_sequence, tmp_len, 0,
&tag, &tmp_len);
@@ -333,7 +335,7 @@ static struct l_cipher *pkcs5_cipher_from_pbes2_params(
return NULL;
for (i = 0; i < L_ARRAY_SIZE(pkcs5_digest_alg_oids); i++)
- if (!asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
+ if (asn1_oid_eq(&pkcs5_digest_alg_oids[i].oid,
tmp_len, oid))
prf_alg = pkcs5_digest_alg_oids[i].type;
--
2.11.0
4 years, 10 months
[PATCH 1/7] tls: Move DER / ASN.1 related definitions to asn1-private.h
by Andrew Zaborowski
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.
---
Makefile.am | 1 +
ell/asn1-private.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/tls.c | 106 +++--------------------------------------------
3 files changed, 124 insertions(+), 101 deletions(-)
create mode 100644 ell/asn1-private.h
diff --git a/Makefile.am b/Makefile.am
index 34ccd55..603b692 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -83,6 +83,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/random.c \
ell/uintset.c \
ell/base64.c \
+ ell/asn1-private.h \
ell/pem.c \
ell/tls-private.h \
ell/tls.c \
diff --git a/ell/asn1-private.h b/ell/asn1-private.h
new file mode 100644
index 0000000..d7c8b6b
--- /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 asn1_parse_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 *asn1_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 = asn1_parse_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 *asn1_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 = asn1_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 a8a143a..894389a 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;
@@ -2587,8 +2493,8 @@ enum tls_cert_key_type tls_cert_get_pubkey_type(struct tls_cert *cert)
size_t key_type_len;
int i;
- key_type = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_OID,
- &key_type_len,
+ key_type = asn1_der_find_elem_by_path(cert->asn1, cert->size,
+ ASN1_ID_OID, &key_type_len,
X509_CERTIFICATE_POS,
X509_TBSCERTIFICATE_POS,
X509_TBSCERT_SUBJECT_KEY_POS,
@@ -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
4 years, 10 months
[PATCH] unit: Make gencerts.sh work on more distros
by Mat Martineau
/bin/sh is more universally available than /usr/bin/sh
---
unit/gencerts.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/unit/gencerts.sh b/unit/gencerts.sh
index 790c715..b0249fb 100755
--- a/unit/gencerts.sh
+++ b/unit/gencerts.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/sh
+#!/bin/sh
echo "*** CA Certificate ***"
openssl genrsa -out cert-ca-key.pem 2048
--
2.14.1
4 years, 10 months
[PATCH] unit: Generate encrypted keys in gencerts.sh
by Andrew Zaborowski
---
unit/gencerts.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/unit/gencerts.sh b/unit/gencerts.sh
index 790c715..419afa8 100755
--- a/unit/gencerts.sh
+++ b/unit/gencerts.sh
@@ -17,6 +17,11 @@ openssl pkcs8 -topk8 -nocrypt -in cert-client-key.pem -out cert-client-key-pkcs8
openssl req -new -extensions cert_ext -config ./gencerts.cnf -subj '/O=Bar Example Organization/CN=Bar Example Organization/emailAddress=bar(a)mail.example' -key cert-client-key.pem -out cert-client.csr
openssl x509 -req -extensions cert_ext -extfile ./gencerts.cnf -in cert-client.csr -CA cert-ca.pem -CAkey cert-ca-key.pem -CAcreateserial -sha256 -days 10000 -out cert-client.pem
openssl verify -CAfile cert-ca.pem cert-client.pem
+openssl pkcs8 -in cert-client-key-pkcs8.pem -out cert-client-key-md5-des.pem -topk8 -passout pass:abc
+openssl pkcs8 -in cert-client-key-pkcs8.pem -out cert-client-key-v2-des.pem -topk8 -v2 des-cbc -passout pass:abc
+openssl pkcs8 -in cert-client-key-pkcs8.pem -out cert-client-key-v2-des-ede3.pem -topk8 -v2 des-ede3-cbc -passout pass:abc
+openssl pkcs8 -in cert-client-key-pkcs8.pem -out cert-client-key-v2-aes128.pem -topk8 -v2 aes128 -passout pass:abc
+openssl pkcs8 -in cert-client-key-pkcs8.pem -out cert-client-key-v2-aes256.pem -topk8 -v2 aes256 -passout pass:abc
echo -e "\n*** Intermediate Certificate ***"
openssl genrsa -out cert-intca-key.pem
--
2.11.0
4 years, 10 months
[PATCH 01/10] checksum: Add SHA224 checksum type
by Andrew Zaborowski
---
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
4 years, 10 months