* [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types.
@ 2015-07-24 3:26 Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 02/17] checksum: Add l_checksum_clone API Andrew Zaborowski
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2196 bytes --]
---
ell/checksum.c | 20 ++++++++++++++++++--
ell/checksum.h | 2 ++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/ell/checksum.c b/ell/checksum.c
index 243470f..882f5f6 100644
--- a/ell/checksum.c
+++ b/ell/checksum.c
@@ -73,7 +73,7 @@ struct sockaddr_alg {
* Checksum handling
*/
-#define is_valid_type(type) ((type) <= L_CHECKSUM_SHA256)
+#define is_valid_type(type) ((type) <= L_CHECKSUM_SHA512)
/**
* l_checksum:
@@ -136,6 +136,12 @@ LIB_EXPORT struct l_checksum *l_checksum_new(enum l_checksum_type type)
case L_CHECKSUM_SHA256:
name = "sha256";
break;
+ case L_CHECKSUM_SHA384:
+ name = "sha384";
+ break;
+ case L_CHECKSUM_SHA512:
+ name = "sha512";
+ break;
}
fd = create_alg(name);
@@ -205,6 +211,12 @@ struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
case L_CHECKSUM_SHA256:
name = "hmac(sha256)";
break;
+ case L_CHECKSUM_SHA384:
+ name = "hmac(sha384)";
+ break;
+ case L_CHECKSUM_SHA512:
+ name = "hmac(sha512)";
+ break;
}
fd = create_alg(name);
@@ -338,13 +350,17 @@ LIB_EXPORT char *l_checksum_get_string(struct l_checksum *checksum)
{ .name = "md5", .digest_len = 16 },
{ .name = "sha1", .digest_len = 20 },
{ .name = "sha256", .digest_len = 32 },
+ { .name = "sha384", .digest_len = 48 },
+ { .name = "sha512", .digest_len = 64 },
{ .name = "cmac(aes)", .digest_len = 16 },
{ .name = "hmac(md5)", .digest_len = 16 },
{ .name = "hmac(sha1)", .digest_len = 20 },
{ .name = "hmac(sha256)", .digest_len = 32 },
+ { .name = "hmac(sha384)", .digest_len = 48 },
+ { .name = "hmac(sha512)", .digest_len = 64 },
{ .name = NULL, .digest_len = 0 },
};
- unsigned char digest[32];
+ unsigned char digest[64];
unsigned int i;
if (unlikely(!checksum))
diff --git a/ell/checksum.h b/ell/checksum.h
index 8e163c4..c516580 100644
--- a/ell/checksum.h
+++ b/ell/checksum.h
@@ -35,6 +35,8 @@ enum l_checksum_type {
L_CHECKSUM_MD5,
L_CHECKSUM_SHA1,
L_CHECKSUM_SHA256,
+ L_CHECKSUM_SHA384,
+ L_CHECKSUM_SHA512,
};
struct l_checksum *l_checksum_new(enum l_checksum_type type);
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/17] checksum: Add l_checksum_clone API.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 15:55 ` Denis Kenzior
2015-07-24 3:26 ` [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types Andrew Zaborowski
` (7 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1964 bytes --]
In the kernel API we use and also in GLib's API the l_checksum_get_digest()
equivalents can only be called once on each object meaning that in a
situation when multiple digest values at different points of a
running stream are needed the API becomes impractical. The new _clone()
call returns a clone of the checksum's state at the current time, on
which get_digest() can be called.
---
ell/checksum.c | 24 ++++++++++++++++++++++++
ell/checksum.h | 1 +
2 files changed, 25 insertions(+)
diff --git a/ell/checksum.c b/ell/checksum.c
index 882f5f6..7604ee0 100644
--- a/ell/checksum.c
+++ b/ell/checksum.c
@@ -242,6 +242,30 @@ struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
}
/**
+ * l_checksum_clone:
+ * @checksum: parent checksum object
+ *
+ * Creates a new checksum with an independent copy of parent @checksum's
+ * state. l_checksum_get_digest can then be called on the parent or the
+ * clone without affecting the state of the other object.
+ **/
+LIB_EXPORT struct l_checksum *l_checksum_clone(struct l_checksum *checksum)
+{
+ struct l_checksum *clone;
+
+ clone = l_new(struct l_checksum, 1);
+ clone->sk = accept4(checksum->sk, NULL, 0, SOCK_CLOEXEC);
+
+ if (clone->sk < 0) {
+ l_free(clone);
+ return NULL;
+ }
+
+ strcpy(clone->alg_name, checksum->alg_name);
+ return clone;
+}
+
+/**
* l_checksum_free:
* @checksum: checksum object
*
diff --git a/ell/checksum.h b/ell/checksum.h
index c516580..34401a6 100644
--- a/ell/checksum.h
+++ b/ell/checksum.h
@@ -43,6 +43,7 @@ struct l_checksum *l_checksum_new(enum l_checksum_type type);
struct l_checksum *l_checksum_new_cmac_aes(const void *key, size_t key_len);
struct l_checksum *l_checksum_new_hmac(enum l_checksum_type type,
const void *key, size_t key_len);
+struct l_checksum *l_checksum_clone(struct l_checksum *checksum);
void l_checksum_free(struct l_checksum *checksum);
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 02/17] checksum: Add l_checksum_clone API Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 15:56 ` Denis Kenzior
2015-07-24 3:26 ` [PATCH 04/17] cipher: Add l_cipher_set_iv Andrew Zaborowski
` (6 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1394 bytes --]
This again only adds the definitions needed to use the kernel
implementations, no real code here.
---
ell/cipher.c | 8 +++++++-
ell/cipher.h | 2 ++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/ell/cipher.c b/ell/cipher.c
index 2c4fd90..b7577d5 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -76,7 +76,7 @@ struct af_alg_iv {
#define SOL_ALG 279
#endif
-#define is_valid_type(type) ((type) <= L_CIPHER_ARC4)
+#define is_valid_type(type) ((type) <= L_CIPHER_DES3_EDE_CBC)
struct l_cipher {
enum l_cipher_type type;
@@ -103,9 +103,15 @@ static int create_alg(enum l_cipher_type type,
case L_CIPHER_AES:
strcpy((char *) salg.salg_name, "ecb(aes)");
break;
+ case L_CIPHER_AES_CBC:
+ strcpy((char *) salg.salg_name, "cbc(aes)");
+ break;
case L_CIPHER_ARC4:
strcpy((char *) salg.salg_name, "ecb(arc4)");
break;
+ case L_CIPHER_DES3_EDE_CBC:
+ strcpy((char *) salg.salg_name, "cbc(des3_ede)");
+ break;
}
if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
diff --git a/ell/cipher.h b/ell/cipher.h
index efa1ad2..8e91884 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -31,7 +31,9 @@ struct l_cipher;
enum l_cipher_type {
L_CIPHER_AES = 0,
+ L_CIPHER_AES_CBC,
L_CIPHER_ARC4,
+ L_CIPHER_DES3_EDE_CBC,
};
struct l_cipher *l_cipher_new(enum l_cipher_type type,
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/17] cipher: Add l_cipher_set_iv.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 02/17] checksum: Add l_checksum_clone API Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 05/17] Add ASN.1 BER / DER decoding utilities as asn1-private.h Andrew Zaborowski
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1737 bytes --]
This allows setting the IV on block ciphers for either the encryption
or decryption operations. It will affect the outcome of any later
_encrypt or _decrypt calls.
---
ell/cipher.c | 28 ++++++++++++++++++++++++++++
ell/cipher.h | 3 +++
2 files changed, 31 insertions(+)
diff --git a/ell/cipher.c b/ell/cipher.c
index b7577d5..3619f2c 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -228,3 +228,31 @@ LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, len);
}
+
+LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
+ size_t iv_length, bool encrypt)
+{
+ char c_msg_buf[CMSG_SPACE(4 + iv_length)];
+ struct msghdr msg = {};
+ struct cmsghdr *c_msg;
+ uint32_t len = iv_length;
+
+ msg.msg_control = c_msg_buf;
+ msg.msg_controllen = sizeof(c_msg_buf);
+
+ c_msg = CMSG_FIRSTHDR(&msg);
+ c_msg->cmsg_level = SOL_ALG;
+ c_msg->cmsg_type = ALG_SET_IV;
+ c_msg->cmsg_len = CMSG_LEN(4 + iv_length);
+ memcpy(CMSG_DATA(c_msg) + 0, &len, 4);
+ memcpy(CMSG_DATA(c_msg) + 4, iv, iv_length);
+
+ msg.msg_iov = NULL;
+ msg.msg_iovlen = 0;
+
+ if (sendmsg(encrypt ? cipher->encrypt_sk : cipher->decrypt_sk,
+ &msg, 0) < 0)
+ return false;
+
+ return true;
+}
diff --git a/ell/cipher.h b/ell/cipher.h
index 8e91884..74b96a3 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -47,6 +47,9 @@ bool l_cipher_encrypt(struct l_cipher *cipher,
bool l_cipher_decrypt(struct l_cipher *cipher,
const void *in, void *out, size_t len);
+bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
+ size_t iv_length, bool encrypt);
+
#ifdef __cplusplus
}
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/17] Add ASN.1 BER / DER decoding utilities as asn1-private.h
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (2 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 04/17] cipher: Add l_cipher_set_iv Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 06/17] Add RSA PKCS#1 1.5 assymetric key encryption operations Andrew Zaborowski
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 4621 bytes --]
This is a minimal set of utilities to allow parsing digital
certificate and RSA encryption related structures. They work on
simple uint8_t arrays. The same operations could be implemented
on top of a cleaner iterator-based API once that is added but since
the required operations are so simple adding that API to ell
didn't seem justified at this point.
One property of the structures used in X509 certificates is that
they use many levels of nested SEQUENCE and SET substructures, hence
the find_der_elem_by_path utility.
---
Makefile.am | 3 +-
ell/asn1-private.h | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+), 1 deletion(-)
create mode 100644 ell/asn1-private.h
diff --git a/Makefile.am b/Makefile.am
index 0861cec..fb2a35c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -75,7 +75,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/hwdb.c \
ell/cipher.c \
ell/random.c \
- ell/uintset.c
+ ell/uintset.c \
+ ell/asn1-private.h
ell_libell_la_LDFLAGS = -no-undefined \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/asn1-private.h b/ell/asn1-private.h
new file mode 100644
index 0000000..e439fd7
--- /dev/null
+++ b/ell/asn1-private.h
@@ -0,0 +1,126 @@
+/*
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2014 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)
+
+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;
+}
+
+static inline void write_asn1_definite_length(uint8_t **buf, size_t len)
+{
+ int n;
+
+ if (len < 0x80) {
+ *(*buf)++ = len;
+
+ return;
+ }
+
+ for (n = 1; len >> (n * 8); n++);
+ *(*buf)++ = 0x80 | n;
+
+ while (n--)
+ *(*buf)++ = len >> (n * 8);
+}
+
+/* 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;
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/17] Add RSA PKCS#1 1.5 assymetric key encryption operations.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (3 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 05/17] Add ASN.1 BER / DER decoding utilities as asn1-private.h Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 07/17] Add cert.{c,h} for basic X509 certificate operations Andrew Zaborowski
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 11089 bytes --]
RSA support is required for different X509 digital certificate and TLS
operations and is since recently present in the kernel. Being an
asymetric key cipher the API is not the same as that used by the
current symmetric ciphers in cipher.c based on the algif_skcipher driver.
At this time there's no corresponding algif_akcipher for userspace to
asymmetric key ciphers in Linux mainline or the crypto tree so this code
works against a patch that applies on the mainline kernel
4a10a91756ef381bced7b88cfb9232f660b92d93. Another algif_akcipher
implementation has been posted this week to the linux-kernel-cryptapi
list but comments so far indicate that it will be a while before it is
finalised so temporarily acceping this implementation against a patched
kernel may be a better option than waiting for the mainline support.
There's another twist to RSA in that it is normally used with pre/post
processing step before/after applying actual RSA operations to the data,
called a padding scheme - usually one two standards. We implement the
PKCS#1 v1.5 padding scheme. This may also end up being implemented in
the kernel but this is unclear. I decided not to call the ell files
ell/akcipher.{c,h} but rather ell/rsa.c and ell/rsa-private.h until
that is clear because we can then decide the API based on that.
ell/rsa.c only implements the padding scheme, reusing ell/cipher.c for
access to the kernel socket API.
---
Makefile.am | 4 +-
ell/cipher.c | 6 +-
ell/cipher.h | 1 +
ell/rsa-private.h | 41 +++++++++
ell/rsa.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 304 insertions(+), 2 deletions(-)
create mode 100644 ell/rsa-private.h
create mode 100644 ell/rsa.c
diff --git a/Makefile.am b/Makefile.am
index fb2a35c..aab2f9e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -76,7 +76,9 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/cipher.c \
ell/random.c \
ell/uintset.c \
- ell/asn1-private.h
+ ell/asn1-private.h \
+ ell/rsa-private.h \
+ ell/rsa.c
ell_libell_la_LDFLAGS = -no-undefined \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
diff --git a/ell/cipher.c b/ell/cipher.c
index 3619f2c..b85ba6b 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -76,7 +76,7 @@ struct af_alg_iv {
#define SOL_ALG 279
#endif
-#define is_valid_type(type) ((type) <= L_CIPHER_DES3_EDE_CBC)
+#define is_valid_type(type) ((type) <= L_CIPHER_RSA)
struct l_cipher {
enum l_cipher_type type;
@@ -112,6 +112,10 @@ static int create_alg(enum l_cipher_type type,
case L_CIPHER_DES3_EDE_CBC:
strcpy((char *) salg.salg_name, "cbc(des3_ede)");
break;
+ case L_CIPHER_RSA:
+ strcpy((char *) salg.salg_name, "rsa");
+ strcpy((char *) salg.salg_type, "akcipher");
+ break;
}
if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
diff --git a/ell/cipher.h b/ell/cipher.h
index 74b96a3..a4db8c2 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_DES3_EDE_CBC,
+ L_CIPHER_RSA,
};
struct l_cipher *l_cipher_new(enum l_cipher_type type,
diff --git a/ell/rsa-private.h b/ell/rsa-private.h
new file mode 100644
index 0000000..1835a88
--- /dev/null
+++ b/ell/rsa-private.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+struct l_rsa;
+
+struct l_rsa *l_rsa_pkcs1_v1_5_new(const void *key, size_t key_length);
+
+void l_rsa_free(struct l_rsa *rsa);
+
+int l_rsa_get_key_size(struct l_rsa *rsa);
+
+bool l_rsa_encrypt(struct l_rsa *cipher, const void *in, void *out,
+ size_t len_in, size_t len_out);
+
+bool l_rsa_decrypt(struct l_rsa *cipher, const void *in, void *out,
+ size_t len_in, size_t len_out);
+
+bool l_rsa_sign(struct l_rsa *cipher, const void *in, void *out,
+ size_t len_in, size_t len_out);
+
+bool l_rsa_verify(struct l_rsa *cipher, const void *in, void *out,
+ size_t len_in, size_t len_out);
diff --git a/ell/rsa.c b/ell/rsa.c
new file mode 100644
index 0000000..62de136
--- /dev/null
+++ b/ell/rsa.c
@@ -0,0 +1,254 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include "private.h"
+#include "rsa-private.h"
+#include "cipher.h"
+#include "random.h"
+#include "asn1-private.h"
+
+struct l_rsa {
+ struct l_cipher *cipher;
+ int key_size;
+};
+
+static bool parse_rsa_key(struct l_rsa *cipher, const void *key,
+ size_t key_length)
+{
+ /*
+ * Parse the DER-encoded public or private RSA key to find
+ * and cache the size of the modulus n for later use.
+ * (RFC3279)
+ */
+ size_t n_length;
+ const uint8_t *der;
+
+ if (key_length < 8)
+ return false;
+
+ /* Unpack the outer&inner SEQUENCE, take first INTEGER as the modulus */
+ der = der_find_elem_by_path((uint8_t *) key, key_length,
+ ASN1_ID_INTEGER, &n_length, 0, 0, -1);
+ if (!der || n_length < 4)
+ return false;
+
+ /* Skip leading zeros */
+ while (n_length && der[0] == 0x00) {
+ der++;
+ n_length--;
+ }
+
+ cipher->key_size = n_length;
+
+ return true;
+}
+
+struct l_rsa *l_rsa_pkcs1_v1_5_new(const void *key, size_t key_length)
+{
+ struct l_rsa *rsa;
+
+ rsa = l_new(struct l_rsa, 1);
+ rsa->cipher = l_cipher_new(L_CIPHER_RSA, key, key_length);
+
+ if (!rsa->cipher)
+ goto error_free_rsa;
+
+ if (!parse_rsa_key(rsa, key, key_length))
+ goto error_free;
+
+ return rsa;
+
+error_free:
+ l_cipher_free(rsa->cipher);
+error_free_rsa:
+ l_free(rsa);
+ return NULL;
+}
+
+void l_rsa_free(struct l_rsa *rsa)
+{
+ if (unlikely(!rsa))
+ return;
+
+ l_cipher_free(rsa->cipher);
+ l_free(rsa);
+}
+
+int l_rsa_get_key_size(struct l_rsa *rsa)
+{
+ return rsa->key_size;
+}
+
+static void getrandom_nonzero(uint8_t *buf, int len)
+{
+ while (len--) {
+ l_getrandom(buf, 1);
+ while (buf[0] == 0)
+ l_getrandom(buf, 1);
+
+ buf++;
+ }
+}
+
+bool l_rsa_encrypt(struct l_rsa *cipher,
+ const void *in, void *out,
+ size_t len_in, size_t len_out)
+{
+ /* PKCS#1 v1.5 RSA padding according to RFC3447 */
+ while (len_in) {
+ int chunk_len =
+ (size_t) cipher->key_size - 11 < len_in ?
+ cipher->key_size - 11 : (int) len_in;
+ uint8_t buf[cipher->key_size];
+ int ps_len = cipher->key_size - chunk_len - 3;
+
+ buf[0] = 0x00;
+ buf[1] = 0x02;
+ getrandom_nonzero(buf + 2, ps_len);
+ buf[ps_len + 2] = 0x00;
+ memcpy(buf + ps_len + 3, in, chunk_len);
+
+ if (!l_cipher_encrypt(cipher->cipher, buf, out,
+ cipher->key_size))
+ return false;
+
+ in += chunk_len;
+ len_in -= chunk_len;
+ out += cipher->key_size;
+ len_out -= cipher->key_size;
+ }
+
+ return true;
+}
+
+bool l_rsa_decrypt(struct l_rsa *cipher,
+ const void *in, void *out,
+ size_t len_in, size_t len_out)
+{
+ /* PKCS#1 v1.5 RSA padding according to RFC3447 */
+ while (len_in) {
+ uint8_t buf[cipher->key_size];
+ int pos;
+
+ if (len_in < (size_t) cipher->key_size)
+ return false;
+
+ if (!l_cipher_decrypt(cipher->cipher, in, buf,
+ cipher->key_size))
+ return false;
+
+ if (buf[0] != 0x00)
+ return false;
+ if (buf[1] != 0x02)
+ return false;
+
+ for (pos = 2; pos < cipher->key_size; pos++)
+ if (buf[pos] == 0)
+ break;
+ if (pos < 10 || pos == cipher->key_size)
+ return false;
+
+ pos++;
+ if (len_out < (size_t) cipher->key_size - pos)
+ return false;
+
+ memcpy(out, buf + pos, cipher->key_size - pos);
+
+ in += cipher->key_size;
+ len_in -= cipher->key_size;
+ out += cipher->key_size - pos;
+ len_out -= cipher->key_size - pos;
+ }
+
+ return true;
+}
+
+bool l_rsa_sign(struct l_rsa *cipher,
+ const void *in, void *out,
+ size_t len_in, size_t len_out)
+{
+ /* PKCS#1 v1.5 RSA padding according to RFC3447 */
+ uint8_t buf[cipher->key_size];
+ int ps_len = cipher->key_size - len_in - 3;
+
+ if (len_in > (size_t) cipher->key_size - 11)
+ return false;
+
+ buf[0] = 0x00;
+ buf[1] = 0x01;
+ memset(buf + 2, 0xff, ps_len);
+ buf[ps_len + 2] = 0x00;
+ memcpy(buf + ps_len + 3, in, len_in);
+
+ /*
+ * The RSA signing operation uses the same primitive as
+ * decryption so just call decrypt.
+ */
+ if (!l_cipher_decrypt(cipher->cipher, buf, out, cipher->key_size))
+ return false;
+
+ return true;
+}
+
+bool l_rsa_verify(struct l_rsa *cipher,
+ const void *in, void *out,
+ size_t len_in, size_t len_out)
+{
+ /* PKCS#1 v1.5 RSA padding according to RFC3447 */
+ uint8_t buf[cipher->key_size];
+ int pos;
+
+ if (len_in != (size_t) cipher->key_size)
+ return false;
+
+ /*
+ * The RSA verify operation uses the same primitive as
+ * encryption so just call encrypt.
+ */
+ if (!l_cipher_encrypt(cipher->cipher, in, buf, cipher->key_size))
+ return false;
+
+ if (buf[0] != 0x00)
+ return false;
+ if (buf[1] != 0x01)
+ return false;
+
+ for (pos = 2; pos < cipher->key_size; pos++)
+ if (buf[pos] != 0xff)
+ break;
+ if (pos < 10 || pos == cipher->key_size || buf[pos] != 0)
+ return false;
+
+ pos++;
+ if (len_out != (size_t) cipher->key_size - pos)
+ return false;
+
+ memcpy(out, buf + pos, cipher->key_size - pos);
+
+ return true;
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/17] Add cert.{c,h} for basic X509 certificate operations.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (4 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 06/17] Add RSA PKCS#1 1.5 assymetric key encryption operations Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 08/17] cert: Add RSA private key utilities Andrew Zaborowski
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 22593 bytes --]
Loading, extracting specific information pieces (those used by TLS)
and cryptographic verification functions are implemented. Only RSA-based
PKCS#1 digital signatures are supported.
---
Makefile.am | 5 +-
ell/cert-private.h | 25 +++
ell/cert.c | 618 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/cert.h | 64 ++++++
ell/ell.h | 1 +
5 files changed, 712 insertions(+), 1 deletion(-)
create mode 100644 ell/cert-private.h
create mode 100644 ell/cert.c
create mode 100644 ell/cert.h
diff --git a/Makefile.am b/Makefile.am
index aab2f9e..576641f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,7 +36,8 @@ pkginclude_HEADERS = ell/ell.h \
ell/hwdb.h \
ell/cipher.h \
ell/random.h \
- ell/uintset.h
+ ell/uintset.h \
+ ell/cert.h
lib_LTLIBRARIES = ell/libell.la
@@ -77,6 +78,8 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/random.c \
ell/uintset.c \
ell/asn1-private.h \
+ ell/cert-private.h \
+ ell/cert.c \
ell/rsa-private.h \
ell/rsa.c
diff --git a/ell/cert-private.h b/ell/cert-private.h
new file mode 100644
index 0000000..e0e65e4
--- /dev/null
+++ b/ell/cert-private.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2011-2014 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
+ *
+ */
+
+void pkcs1_write_digest_info(enum l_checksum_type type,
+ uint8_t *out, size_t *out_len,
+ const uint8_t *hash, size_t hash_len);
diff --git a/ell/cert.c b/ell/cert.c
new file mode 100644
index 0000000..ff9bf66
--- /dev/null
+++ b/ell/cert.c
@@ -0,0 +1,618 @@
+/*
+ * Embedded Linux library
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "util.h"
+#include "private.h"
+#include "cipher.h"
+#include "checksum.h"
+#include "cert-private.h"
+#include "cert.h"
+#include "asn1-private.h"
+#include "rsa-private.h"
+
+#define PEM_CERT_START "-----BEGIN CERTIFICATE-----"
+#define PEM_CERT_END "-----END CERTIFICATE-----"
+
+/* PKCS#1 key headers (default in OpenSSL 1.0.1+) */
+/* TODO: also support PKCS#8 keys (OpenSSL <= 0.9.8 default) */
+#define PEM_PRIVKEY_START "-----BEGIN PRIVATE KEY-----"
+#define PEM_PRIVKEY_END "-----END PRIVATE KEY-----"
+
+#define PEM_RSA_PRIVKEY_START "-----BEGIN RSA PRIVATE KEY-----"
+#define PEM_RSA_PRIVKEY_END "-----END RSA PRIVATE KEY-----"
+
+#define PEM_ENC_PRIVKEY_START "-----BEGIN ENCRYPTED PRIVATE KEY-----"
+#define PEM_ENC_PRIVKEY_END "-----END ENCRYPTED PRIVATE KEY-----"
+
+static size_t pem_decode(const uint8_t *buf, size_t size, uint8_t *out)
+{
+ const uint8_t *ptr;
+ int offset = 0;
+ uint16_t reg = 0;
+ char *end_marker;
+ int end_marker_len;
+
+ if (!memcmp(buf, PEM_CERT_START, strlen(PEM_CERT_START))) {
+ end_marker = PEM_CERT_END;
+ end_marker_len = strlen(PEM_CERT_END);
+
+ buf += strlen(PEM_CERT_START);
+ size -= strlen(PEM_CERT_START);
+ } else if (!memcmp(buf, PEM_PRIVKEY_START, strlen(PEM_PRIVKEY_START))) {
+ end_marker = PEM_PRIVKEY_END;
+ end_marker_len = strlen(PEM_PRIVKEY_END);
+
+ buf += strlen(PEM_PRIVKEY_START);
+ size -= strlen(PEM_PRIVKEY_START);
+ } else if (!memcmp(buf, PEM_ENC_PRIVKEY_START,
+ strlen(PEM_ENC_PRIVKEY_START))) {
+ end_marker = PEM_ENC_PRIVKEY_END;
+ end_marker_len = strlen(PEM_ENC_PRIVKEY_END);
+
+ buf += strlen(PEM_ENC_PRIVKEY_START);
+ size -= strlen(PEM_ENC_PRIVKEY_START);
+ } else if (!memcmp(buf, PEM_RSA_PRIVKEY_START,
+ strlen(PEM_RSA_PRIVKEY_START))) {
+ end_marker = PEM_RSA_PRIVKEY_END;
+ end_marker_len = strlen(PEM_RSA_PRIVKEY_END);
+
+ buf += strlen(PEM_RSA_PRIVKEY_START);
+ size -= strlen(PEM_RSA_PRIVKEY_START);
+ } else
+ return 0;
+
+ /* Base64-decode everything up to a PEM_CERT_END */
+
+ for (ptr = buf; ptr < buf + size; ptr++)
+ if (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n')
+ /* Whitespace */
+ continue;
+ else if (*ptr == end_marker[0] &&
+ ptr + end_marker_len <= buf + size &&
+ !memcmp(ptr, end_marker, end_marker_len))
+ /* PEM end marker */
+ break;
+ else if (*ptr == '=')
+ /* Final padding */
+ break;
+ else if ((*ptr >= 'A' && *ptr <= 'Z') ||
+ (*ptr >= 'a' && *ptr <= 'z') ||
+ (*ptr >= '0' && *ptr <= '9') ||
+ *ptr == '+' || *ptr == '/') {
+ /* Base64 character */
+
+ if (out) {
+ reg <<= 6;
+ if (*ptr >= 'A' && *ptr <= 'Z')
+ reg |= *ptr - 'A' + 0;
+ else if (*ptr >= 'a' && *ptr <= 'z')
+ reg |= *ptr - 'a' + 26;
+ else if (*ptr >= '0' && *ptr <= '9')
+ reg |= *ptr - '0' + 52;
+ else if (*ptr == '+')
+ reg |= 62;
+ else if (*ptr == '/')
+ reg |= 63;
+
+ if ((offset & 3) == 1)
+ *out++ = reg >> 4;
+ else if ((offset & 3) == 2)
+ *out++ = reg >> 2;
+ else if ((offset & 3) == 3)
+ *out++ = reg >> 0;
+ }
+
+ offset++;
+ } else
+ /* Bad character */
+ return 0;
+
+ if (offset & 3)
+ if ((offset & 3) == 1 || ptr == buf + size || *ptr != '=')
+ /* Uneven number of bytes and no padding */
+ return 0;
+
+ return offset * 3 / 4;
+}
+
+LIB_EXPORT struct l_cert *l_cert_decode(const uint8_t *buf, size_t size)
+{
+ struct l_cert *cert;
+ size_t der_size;
+
+ /*
+ * Only check if certificate body starts with a PEM begin line,
+ * if so decode it as PEM (base64) otherwise assume it's in DER
+ * format already.
+ */
+ if (size > strlen(PEM_CERT_START) + strlen(PEM_CERT_END) &&
+ !memcmp(buf, PEM_CERT_START, strlen(PEM_CERT_START))) {
+ /* Find the size of the decoded DER body */
+ der_size = pem_decode(buf, size, NULL);
+ if (!der_size)
+ return NULL;
+
+ cert = l_malloc(sizeof(*cert) + der_size);
+ cert->size = der_size;
+ cert->asn1 = (void *) cert + sizeof(*cert);
+ cert->issuer = NULL;
+
+ pem_decode(buf, size, cert->asn1);
+
+ goto check;
+ }
+
+ cert = l_malloc(sizeof(*cert) + size);
+ cert->size = size;
+ cert->asn1 = (void *) cert + sizeof(*cert);
+ cert->issuer = NULL;
+
+ memcpy(cert->asn1, buf, size);
+
+check:
+ if (!cert->size || cert->asn1[0] != ASN1_ID_SEQUENCE) {
+ l_free(cert);
+ cert = NULL;
+ }
+
+ return cert;
+}
+
+LIB_EXPORT struct l_cert *l_cert_load_file(const char *filename)
+{
+ int fd;
+ struct stat st;
+ uint8_t *data;
+ struct l_cert *cert;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+
+ return NULL;
+ }
+
+ data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED) {
+ close(fd);
+
+ return NULL;
+ }
+
+ cert = l_cert_decode(data, st.st_size);
+
+ munmap(data, st.st_size);
+ close(fd);
+
+ return cert;
+}
+
+LIB_EXPORT bool l_cert_find_certchain(struct l_cert *cert,
+ const char *cacert_filename)
+{
+ /*
+ * TODO: Load the CA certificate and find a chain from cert up to
+ * that CA certificate, store that entire chain in a linked list using
+ * the .issuer fields in each certificate. We might also want to
+ * accept a directory of trusted CA certs (/etc/ssl/certs by default)
+ * and find a chain to any of those CAs.
+ *
+ * This is unimplemented which means that only certificates issued
+ * directly by given root CA will work as they're already complete
+ * certchains.
+ */
+
+ return true;
+}
+
+struct asn1_oid {
+ uint8_t asn1_len;
+ uint8_t asn1[10];
+};
+
+static const struct pkcs1_encryption_oid {
+ enum l_cert_key_type key_type;
+ struct asn1_oid oid;
+} pkcs1_encryption_oids[] = {
+ { /* rsaEncryption */
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 } },
+ },
+};
+
+static const struct rsadsi_encryption_algorithm_oid {
+ enum l_cipher_type cipher_type;
+ struct asn1_oid oid;
+} rsadsi_encryption_algorithm_oids[] = {
+ { /* des-EDE3-CBC */
+ L_CIPHER_DES3_EDE_CBC,
+ { 8, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07 } },
+ },
+};
+
+static const struct pkcs1_signature_algorithm_oid {
+ enum l_checksum_type hash_type;
+ int hash_len;
+ enum l_cert_key_type key_type;
+ struct asn1_oid oid;
+} pkcs1_signature_algorithm_oids[] = {
+ { /* md5WithRSAEncryption */
+ L_CHECKSUM_MD5, 16,
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 } },
+ },
+ { /* sha1WithRSAEncryption */
+ L_CHECKSUM_SHA1, 20,
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 } },
+ },
+ { /* sha256WithRSAEncryption */
+ L_CHECKSUM_SHA256, 32,
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b } },
+ },
+ { /* sha384WithRSAEncryption */
+ L_CHECKSUM_SHA384, 48,
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c } },
+ },
+ { /* sha512WithRSAEncryption */
+ L_CHECKSUM_SHA512, 64,
+ L_CERT_KEY_RSA,
+ { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d } },
+ },
+};
+
+static bool verify_single(struct l_cert *cert, struct l_cert *cacert)
+{
+ uint8_t *issuer, *ca_subject;
+ int issuer_len, ca_subject_len;
+ uint8_t *sig_type1, *sig_type2;
+ int i, ca_key_len;
+ size_t len1, len2;
+ uint8_t *certificate, *start, *ca_pubkey, *signature;
+ struct l_checksum *checksum;
+ struct l_rsa *rsa;
+ uint8_t hash[64];
+ bool result;
+ uint8_t digest_info[128], expected[128];
+ size_t digest_info_len;
+
+ /* First make sure the certificate claims to be issued by the CA */
+
+ issuer = l_cert_find_dn(cert, true, &issuer_len);
+ ca_subject = l_cert_find_dn(cacert, false, &ca_subject_len);
+
+ if (!issuer || !ca_subject || issuer_len != ca_subject_len ||
+ memcmp(issuer, ca_subject, issuer_len))
+ return false;
+
+ /* Find out the signature type */
+
+ sig_type1 = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_OID,
+ &len1, 0, 0, 2, 0, -1);
+ if (!sig_type1)
+ return false;
+
+ for (i = 0; i < (int) L_ARRAY_SIZE(pkcs1_signature_algorithm_oids); i++)
+ if (len1 == pkcs1_signature_algorithm_oids[i].oid.asn1_len &&
+ !memcmp(sig_type1,
+ pkcs1_signature_algorithm_oids[i].oid.
+ asn1, len1))
+ break;
+ if (i == L_ARRAY_SIZE(pkcs1_signature_algorithm_oids))
+ return false;
+
+ /*
+ * Check if the signature AlgorithmIdentifier in TBSCertificate is
+ * identical with the signatureAlgorithm in Certificate, and if
+ * it's consistent with the public key type in the CA certificate.
+ */
+ sig_type2 = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_OID,
+ &len2, 0, 1, 0, -1);
+ if (!sig_type2 || len1 != len2 || memcmp(sig_type1, sig_type2, len1))
+ return false;
+
+ if (pkcs1_signature_algorithm_oids[i].key_type !=
+ l_cert_get_pubkey_type(cacert))
+ return false;
+
+ /* Compute the hash of the TBSCertificate part */
+
+ start = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_SEQUENCE,
+ &len1, 0, -1);
+ certificate = der_find_elem_by_path(start, len1, ASN1_ID_SEQUENCE,
+ &len1, 0, -1);
+
+ checksum = l_checksum_new(pkcs1_signature_algorithm_oids[i].hash_type);
+ if (!checksum)
+ return false;
+
+ /* Hash the entire SEQUENCE TLV including the T and the L */
+ l_checksum_update(checksum, start, certificate + len1 - start);
+ l_checksum_get_digest(checksum, hash,
+ pkcs1_signature_algorithm_oids[i].hash_len);
+
+ l_checksum_free(checksum);
+
+ pkcs1_write_digest_info(pkcs1_signature_algorithm_oids[i].hash_type,
+ digest_info, &digest_info_len, hash,
+ pkcs1_signature_algorithm_oids[i].hash_len);
+
+ /* Verify the signature against the hash using the CA's public key */
+
+ ca_pubkey = l_cert_find_pubkey(cacert, &ca_key_len);
+ if (!ca_pubkey)
+ return false;
+
+ signature = der_find_elem_by_path(cert->asn1, cert->size,
+ ASN1_ID_BIT_STRING, &len1,
+ 0, 2, -1);
+ if (!signature || len1 < 10)
+ return false;
+
+ /* Skip the BIT STRING metadata byte */
+ signature += 1;
+ len1 -= 1;
+
+ rsa = l_rsa_pkcs1_v1_5_new(ca_pubkey, ca_key_len);
+ if (!rsa)
+ return false;
+
+ result = l_rsa_verify(rsa, signature, expected, len1, digest_info_len);
+
+ l_rsa_free(rsa);
+
+ if (!result || memcmp(digest_info, expected, digest_info_len))
+ return false;
+
+ /*
+ * A CRL / OCSP check would go here. Other checks we should have:
+ * start & expiration date, unknown X509v3 extensions, CA:TRUE
+ * presence in the CA cert.
+ */
+
+ return true;
+}
+
+/*
+ * Verify a certificate chain internal consistency and optionally against
+ * a CA certificate if not NULL.
+ */
+LIB_EXPORT bool l_cert_verify_certchain(struct l_cert *certchain,
+ struct l_cert *ca_cert)
+{
+ while (certchain) {
+ /*
+ * Every certificate except the last in the chain (which may
+ * be the root CA or not) must be trusted by its issuer.
+ */
+ if (certchain->issuer)
+ if (!verify_single(certchain, certchain->issuer))
+ return false;
+
+ /*
+ * At least one certificate in the chain must be trusted by
+ * our CA if known.
+ */
+ if (ca_cert)
+ if (verify_single(certchain, ca_cert))
+ ca_cert = NULL;
+
+ certchain = certchain->issuer;
+ }
+
+ return !ca_cert;
+}
+
+LIB_EXPORT void l_cert_free_certchain(struct l_cert *cert)
+{
+ struct l_cert *next;
+
+ while (cert) {
+ next = cert->issuer;
+ l_free(cert);
+ cert = next;
+ }
+}
+
+LIB_EXPORT uint8_t *l_cert_find_dn(struct l_cert *cert, bool issuer,
+ int *name_len)
+{
+ uint8_t *name;
+ size_t len;
+
+ name = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_SEQUENCE,
+ &len, 0, 0, issuer ? 3 : 5, -1);
+ if (name)
+ *name_len = len;
+
+ return name;
+}
+
+static bool der_oid_match(uint8_t *seq, size_t seq_len,
+ const struct asn1_oid *oid)
+{
+ uint8_t *ptr, tag;
+ size_t oid_len;
+
+ ptr = der_find_elem(seq, seq_len, 0, &tag, &oid_len);
+
+ return ptr && tag == ASN1_ID_OID && oid_len == oid->asn1_len &&
+ !memcmp(oid->asn1, ptr, oid_len);
+}
+
+static const struct asn1_oid dn_organization_name_oid = { 3,
+ { 0x55, 0x04, 0x0a } };
+static const struct asn1_oid dn_common_name_oid = { 3,
+ { 0x55, 0x04, 0x03 } };
+
+LIB_EXPORT uint8_t *l_cert_dn_find_printable_name(uint8_t *dn, int dn_len,
+ int *printable_name_len)
+{
+ uint8_t *end = dn + dn_len;
+ uint8_t *set, *seq, *name = NULL, tag, name_tag;
+ size_t len, name_len;
+
+ while (dn < end) {
+ set = der_find_elem(dn, end - dn, 0, &tag, &len);
+ if (!set)
+ break;
+
+ dn = set + len;
+ if (tag != ASN1_ID_SET)
+ continue;
+
+ /* TODO: iterate over the set? */
+ seq = der_find_elem(set, len, 0, &tag, &len);
+ if (!seq || tag != ASN1_ID_SEQUENCE)
+ continue;
+
+ if (der_oid_match(seq, len, &dn_organization_name_oid)) {
+ /*
+ * This our first priority so override any name found
+ * so far.
+ */
+ name = der_find_elem(seq, len, 1, &name_tag, &name_len);
+ break;
+ } else if (der_oid_match(seq, len, &dn_common_name_oid) &&
+ !name)
+ name = der_find_elem(seq, len, 1, &name_tag, &name_len);
+ }
+
+ if (!name || (name_tag != ASN1_ID_PRINTABLESTRING &&
+ name_tag != ASN1_ID_UTF8STRING))
+ return NULL;
+
+ *printable_name_len = name_len;
+ return name;
+}
+
+LIB_EXPORT uint8_t *l_cert_find_pubkey(struct l_cert *cert, int *pubkey_len)
+{
+ uint8_t *key;
+ size_t len;
+
+ key = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_BIT_STRING,
+ &len, 0, 0, 6, 1, -1);
+ if (!key || len < 10)
+ return NULL;
+
+ /* Skip the BIT STRING metadata byte */
+ key += 1;
+ len -= 1;
+
+ *pubkey_len = len;
+ return key;
+}
+
+LIB_EXPORT enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert)
+{
+ uint8_t *key_type;
+ size_t key_type_len;
+ int i;
+
+ key_type = der_find_elem_by_path(cert->asn1, cert->size, ASN1_ID_OID,
+ &key_type_len, 0, 0, 6, 0, 0, -1);
+ if (!key_type)
+ return L_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))
+ break;
+ if (i == L_ARRAY_SIZE(pkcs1_encryption_oids))
+ return L_CERT_KEY_UNKNOWN;
+
+ return pkcs1_encryption_oids[i].key_type;
+}
+
+static const uint8_t pkcs1_digest_info_md5_start[] = {
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00, 0x04, 0x10,
+};
+static const uint8_t pkcs1_digest_info_sha1_start[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14,
+};
+static const uint8_t pkcs1_digest_info_sha256_start[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
+};
+static const uint8_t pkcs1_digest_info_sha384_start[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30,
+};
+static const uint8_t pkcs1_digest_info_sha512_start[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40,
+};
+
+void pkcs1_write_digest_info(enum l_checksum_type type,
+ uint8_t *out, size_t *out_len,
+ const uint8_t *hash, size_t hash_len)
+{
+ switch (type) {
+ case L_CHECKSUM_MD5:
+ memcpy(out, pkcs1_digest_info_md5_start,
+ sizeof(pkcs1_digest_info_md5_start));
+ *out_len = sizeof(pkcs1_digest_info_md5_start);
+ break;
+ case L_CHECKSUM_SHA1:
+ memcpy(out, pkcs1_digest_info_sha1_start,
+ sizeof(pkcs1_digest_info_sha1_start));
+ *out_len = sizeof(pkcs1_digest_info_sha1_start);
+ break;
+ case L_CHECKSUM_SHA256:
+ memcpy(out, pkcs1_digest_info_sha256_start,
+ sizeof(pkcs1_digest_info_sha256_start));
+ *out_len = sizeof(pkcs1_digest_info_sha256_start);
+ break;
+ case L_CHECKSUM_SHA384:
+ memcpy(out, pkcs1_digest_info_sha384_start,
+ sizeof(pkcs1_digest_info_sha384_start));
+ *out_len = sizeof(pkcs1_digest_info_sha384_start);
+ break;
+ case L_CHECKSUM_SHA512:
+ memcpy(out, pkcs1_digest_info_sha512_start,
+ sizeof(pkcs1_digest_info_sha512_start));
+ *out_len = sizeof(pkcs1_digest_info_sha512_start);
+ break;
+ }
+
+ memcpy(out + *out_len, hash, hash_len);
+ *out_len += hash_len;
+}
diff --git a/ell/cert.h b/ell/cert.h
new file mode 100644
index 0000000..bbea5eb
--- /dev/null
+++ b/ell/cert.h
@@ -0,0 +1,64 @@
+/*
+ * Embedded Linux library
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __ELL_CERT_H
+#define __ELL_CERT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_cert {
+ size_t size;
+ uint8_t *asn1;
+ struct l_cert *issuer;
+};
+
+enum l_cert_key_type {
+ L_CERT_KEY_RSA,
+ L_CERT_KEY_UNKNOWN,
+};
+
+/* Certificate and certificate chain operations */
+
+struct l_cert *l_cert_decode(const uint8_t *buf, size_t size);
+
+struct l_cert *l_cert_load_file(const char *filename);
+
+bool l_cert_find_certchain(struct l_cert *cert, const char *cacert_filename);
+
+bool l_cert_verify_certchain(struct l_cert *certchain, struct l_cert *ca_cert);
+
+void l_cert_free_certchain(struct l_cert *cert);
+
+uint8_t *l_cert_find_dn(struct l_cert *cert, bool issuer, int *name_len);
+
+uint8_t *l_cert_dn_find_printable_name(uint8_t *dn, int dn_len,
+ int *printable_name_len);
+
+uint8_t *l_cert_find_pubkey(struct l_cert *cert, int *pubkey_len);
+
+enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_CERT_H */
diff --git a/ell/ell.h b/ell/ell.h
index a5baf0d..2c88216 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -38,6 +38,7 @@
#include <ell/cipher.h>
#include <ell/random.h>
#include <ell/uintset.h>
+#include <ell/cert.h>
#include <ell/netlink.h>
#include <ell/genl.h>
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/17] cert: Add RSA private key utilities.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (5 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 07/17] Add cert.{c,h} for basic X509 certificate operations Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 09/17] unit: Add an RSA encryption/decryption test Andrew Zaborowski
2015-07-24 15:50 ` [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Denis Kenzior
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 5393 bytes --]
---
ell/cert.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/cert.h | 10 ++++
2 files changed, 174 insertions(+)
diff --git a/ell/cert.c b/ell/cert.c
index ff9bf66..9c257de 100644
--- a/ell/cert.c
+++ b/ell/cert.c
@@ -560,6 +560,170 @@ LIB_EXPORT enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert)
return pkcs1_encryption_oids[i].key_type;
}
+static uint8_t *l_cert_decode_key(const uint8_t *buf_in, size_t size_in,
+ size_t *size_out,
+ const char *passphrase, bool *encrypted)
+{
+ uint8_t *bin;
+ size_t bin_size;
+
+ if (size_in > strlen(PEM_ENC_PRIVKEY_START) +
+ strlen(PEM_ENC_PRIVKEY_END) &&
+ !memcmp(buf_in, PEM_ENC_PRIVKEY_START,
+ strlen(PEM_ENC_PRIVKEY_START))) {
+ *encrypted = true;
+
+ if (!passphrase)
+ return NULL;
+ } else if (size_in > strlen(PEM_PRIVKEY_START) +
+ strlen(PEM_PRIVKEY_END) &&
+ !memcmp(buf_in, PEM_PRIVKEY_START,
+ strlen(PEM_PRIVKEY_START))) {
+ *encrypted = false;
+ } else if (size_in > strlen(PEM_RSA_PRIVKEY_START) +
+ strlen(PEM_RSA_PRIVKEY_END) &&
+ !memcmp(buf_in, PEM_RSA_PRIVKEY_START,
+ strlen(PEM_RSA_PRIVKEY_START))) {
+ *encrypted = false;
+ } else {
+ *encrypted = false;
+
+ return NULL;
+ }
+
+ /* Find the size of the decoded DER body */
+ bin_size = pem_decode(buf_in, size_in, NULL);
+ if (!bin_size)
+ return NULL;
+
+ bin = l_malloc(bin_size);
+ pem_decode(buf_in, size_in, bin);
+
+ if (!*encrypted) {
+ *size_out = bin_size;
+ return bin;
+ }
+
+ /*
+ * If encrypted we need to parse the AlgorithmIdentifier and its
+ * parameters, the key derivation function, its parameters, etc (TODO).
+ */
+ l_cert_free_key(bin, bin_size);
+
+ return NULL;
+}
+
+LIB_EXPORT uint8_t *l_cert_load_key_file(const char *filename,
+ const char *passphrase,
+ size_t *len,
+ bool *encrypted)
+{
+ int fd;
+ struct stat st;
+ uint8_t *data;
+ uint8_t *key;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+
+ return NULL;
+ }
+
+ data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED) {
+ close(fd);
+
+ return NULL;
+ }
+
+ key = l_cert_decode_key(data, st.st_size, len, passphrase, encrypted);
+
+ munmap(data, st.st_size);
+ close(fd);
+
+ return key;
+}
+
+LIB_EXPORT void l_cert_free_key(uint8_t *key, size_t len)
+{
+ if (key) {
+ memset(key, 0, len);
+ l_free(key);
+ }
+}
+
+/*
+ * Extract a ASN1 RsaKey-formatted public+private key structure in the
+ * form used in the kernel. It is simpler than the PKCS#1 form as it only
+ * contains the N, E and D integers and also correctly parses as a PKCS#1
+ * RSAPublicKey.
+ */
+LIB_EXPORT uint8_t *l_cert_extract_rsakey(uint8_t *pkcs1_key,
+ size_t pkcs1_key_len,
+ size_t *out_len)
+{
+ uint8_t *key, *ptr, *ver, *n, *e, *d;
+ uint8_t tag;
+ size_t ver_len, n_len, e_len, d_len;
+ int pos;
+
+ /* Unpack the outer SEQUENCE */
+ pkcs1_key = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag,
+ &pkcs1_key_len);
+ if (!pkcs1_key || tag != ASN1_ID_SEQUENCE)
+ return NULL;
+
+ /* Check if the version element if present */
+ ver = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag, &ver_len);
+ if (!ver || tag != ASN1_ID_INTEGER)
+ return NULL;
+
+ pos = (ver_len == 1 && ver[0] == 0x00) ? 1 : 0;
+
+ n = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 0, &tag, &n_len);
+ if (!n || tag != ASN1_ID_INTEGER)
+ return NULL;
+
+ e = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 1, &tag, &e_len);
+ if (!e || tag != ASN1_ID_INTEGER)
+ return NULL;
+
+ d = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 2, &tag, &d_len);
+ if (!d || tag != ASN1_ID_INTEGER)
+ return NULL;
+
+ /* New SEQUENCE length including tags and lengths */
+ *out_len = 1 + (n_len >= 0x80 ? n_len >= 0x100 ? 3 : 2 : 1) + n_len +
+ 1 + (e_len >= 0x80 ? e_len >= 0x100 ? 3 : 2 : 1) + e_len +
+ 1 + (d_len >= 0x80 ? d_len >= 0x100 ? 3 : 2 : 1) + d_len;
+ ptr = key = l_malloc(*out_len);
+
+ *ptr++ = ASN1_ID_SEQUENCE;
+ write_asn1_definite_length(&ptr, *out_len);
+
+ *ptr++ = ASN1_ID_INTEGER;
+ write_asn1_definite_length(&ptr, n_len);
+ memcpy(ptr, n, n_len);
+ ptr += n_len;
+
+ *ptr++ = ASN1_ID_INTEGER;
+ write_asn1_definite_length(&ptr, e_len);
+ memcpy(ptr, e, e_len);
+ ptr += e_len;
+
+ *ptr++ = ASN1_ID_INTEGER;
+ write_asn1_definite_length(&ptr, d_len);
+ memcpy(ptr, d, d_len);
+ ptr += d_len;
+
+ *out_len = ptr - key;
+ return key;
+}
+
static const uint8_t pkcs1_digest_info_md5_start[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x02, 0x05, 0x05, 0x00, 0x04, 0x10,
diff --git a/ell/cert.h b/ell/cert.h
index bbea5eb..b4d8b57 100644
--- a/ell/cert.h
+++ b/ell/cert.h
@@ -57,6 +57,16 @@ uint8_t *l_cert_find_pubkey(struct l_cert *cert, int *pubkey_len);
enum l_cert_key_type l_cert_get_pubkey_type(struct l_cert *cert);
+/* Private keys */
+
+uint8_t *l_cert_load_key_file(const char *filename, const char *passphrase,
+ size_t *len, bool *encrypted);
+
+void l_cert_free_key(uint8_t *key, size_t len);
+
+uint8_t *l_cert_extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
+ size_t *out_len);
+
#ifdef __cplusplus
}
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/17] unit: Add an RSA encryption/decryption test.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (6 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 08/17] cert: Add RSA private key utilities Andrew Zaborowski
@ 2015-07-24 3:26 ` Andrew Zaborowski
2015-07-24 15:50 ` [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Denis Kenzior
8 siblings, 0 replies; 12+ messages in thread
From: Andrew Zaborowski @ 2015-07-24 3:26 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 5629 bytes --]
---
unit/test-cipher.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/unit/test-cipher.c b/unit/test-cipher.c
index 2ee268c..044cb7d 100644
--- a/unit/test-cipher.c
+++ b/unit/test-cipher.c
@@ -27,6 +27,7 @@
#include <assert.h>
#include <ell/ell.h>
+#include <ell/cert.h>
#define FIXED_STR "The quick brown fox jumps over the lazy dog. " \
"Jackdaws love my big sphinx of quartz. " \
@@ -122,6 +123,102 @@ static void test_arc4(const void *data)
l_cipher_free(cipher);
}
+/*
+ * openssl genrsa 1024 | openssl rsa -outform DER | \
+ * hexdump -v -e '"0x" 1/1 "%02x" ", "'
+ */
+static uint8_t rsa_priv_key[] = {
+ 0x30, 0x82, 0x02, 0x5c, /* SEQUENCE */
+ 0x02, 0x01, /* INTEGER - version */
+ 0x00,
+ 0x02, 0x81, 0x81, /* INTEGER - n */
+ 0x00, 0xbe, 0x8c, 0xe7, 0x6c, 0x7d, 0x97, 0xbd, 0x63, 0xf6, 0x00, 0x65,
+ 0x34, 0x23, 0xd9, 0xc6, 0xce, 0x6d, 0x1b, 0x30, 0x8f, 0xfa, 0x9b, 0x8e,
+ 0xbe, 0x97, 0x01, 0x10, 0x5b, 0x49, 0x7c, 0xba, 0xd5, 0x47, 0x5e, 0xb0,
+ 0x62, 0x24, 0xd9, 0xb0, 0xe2, 0x35, 0x5b, 0x05, 0xeb, 0x0a, 0x69, 0xc9,
+ 0x5c, 0x02, 0x6d, 0xf2, 0x89, 0x6d, 0xab, 0xaa, 0x43, 0x53, 0x52, 0xaa,
+ 0xed, 0xc9, 0xb6, 0x98, 0x17, 0x8a, 0x38, 0x9a, 0x80, 0x5b, 0xd1, 0x70,
+ 0xc7, 0xc9, 0x16, 0x1f, 0x34, 0xb3, 0x27, 0x40, 0xa2, 0x39, 0xbe, 0xf8,
+ 0x01, 0xfa, 0x9e, 0x04, 0x9f, 0x58, 0xc1, 0xa1, 0x19, 0x78, 0xcf, 0xfe,
+ 0x9c, 0x76, 0x43, 0xba, 0x69, 0x05, 0x67, 0x9a, 0xfc, 0xc4, 0x56, 0xbb,
+ 0xc1, 0x7f, 0xdb, 0xf0, 0xb9, 0x31, 0x2c, 0x4f, 0xc2, 0xd9, 0x42, 0xf6,
+ 0x3d, 0x1b, 0x48, 0x31, 0x88, 0xc2, 0xb5, 0xb9, 0xa5,
+ 0x02, 0x03, /* INTEGER - e */
+ 0x01, 0x00, 0x01,
+ 0x02, 0x81, 0x80, /* INTEGER - d */
+ 0x0b, 0x34, 0xa2, 0x0f, 0x61, 0x3b, 0x61, 0x29, 0xd5, 0xb7, 0xa4, 0x3b,
+ 0xf2, 0xb7, 0xc5, 0xd7, 0x31, 0xd7, 0x5d, 0x7d, 0xba, 0x11, 0x17, 0xcd,
+ 0xe1, 0x77, 0x70, 0x8c, 0xcd, 0xbf, 0x86, 0x05, 0x30, 0xd3, 0x42, 0xb0,
+ 0x22, 0xd6, 0xa2, 0x6e, 0x4b, 0x10, 0xf5, 0x42, 0x23, 0x34, 0xa1, 0x60,
+ 0xc5, 0xcb, 0xcd, 0x6d, 0x83, 0x83, 0x8a, 0xd9, 0xb6, 0xb6, 0xaf, 0xd2,
+ 0x98, 0x00, 0x22, 0xe5, 0x75, 0x67, 0xbe, 0x0b, 0x95, 0xe7, 0x76, 0xee,
+ 0x22, 0x03, 0xdd, 0x49, 0x02, 0x86, 0xd7, 0x2b, 0x96, 0xee, 0xb1, 0x1e,
+ 0x49, 0x02, 0xdf, 0xa9, 0x2e, 0x0f, 0x71, 0x33, 0xb5, 0xc6, 0x37, 0xb5,
+ 0x6b, 0x58, 0xa1, 0xbb, 0x1c, 0xb9, 0xa2, 0x33, 0x70, 0x01, 0xca, 0xd4,
+ 0xae, 0x96, 0xc3, 0x7d, 0x36, 0xc2, 0xe7, 0x50, 0x33, 0x17, 0xcc, 0xdc,
+ 0x28, 0x7c, 0x7b, 0xdf, 0x25, 0x06, 0x57, 0xa9,
+ 0x02, 0x41, /* INTEGER - p */
+ 0x00, 0xf1, 0xec, 0x4f, 0xdf, 0xb7, 0x05, 0x2e, 0xdd, 0x1c, 0x85, 0x9d,
+ 0x99, 0xb7, 0x60, 0x8c, 0x9b, 0x47, 0x1c, 0x04, 0x2f, 0x6f, 0x8a, 0xd5,
+ 0x89, 0x1c, 0x2e, 0xe2, 0x0d, 0x68, 0x9c, 0xf6, 0xb0, 0x09, 0x32, 0x70,
+ 0x06, 0x9f, 0x52, 0x7e, 0xc5, 0x46, 0x93, 0x60, 0x57, 0x77, 0xa8, 0xd3,
+ 0x92, 0xbb, 0x24, 0x9c, 0x24, 0x35, 0x14, 0x99, 0x62, 0xe2, 0xce, 0xa2,
+ 0x9b, 0x62, 0xd3, 0xe0, 0x0f,
+ 0x02, 0x41, /* INTEGER - q */
+ 0x00, 0xc9, 0xa3, 0x58, 0x17, 0x03, 0xfb, 0x19, 0x06, 0xa4, 0x75, 0xfb,
+ 0xa2, 0xb3, 0x84, 0x2a, 0x7f, 0xf7, 0x66, 0x80, 0xb5, 0xd6, 0xda, 0xcf,
+ 0xb2, 0x9e, 0x4f, 0x0a, 0xd3, 0xcd, 0xa5, 0x94, 0xc4, 0x80, 0x53, 0xc6,
+ 0xbf, 0x7e, 0xe0, 0x2c, 0xc0, 0x71, 0xdb, 0x9c, 0xe0, 0x92, 0x66, 0x41,
+ 0x6b, 0x64, 0x9e, 0x7a, 0xf3, 0xe7, 0x45, 0x15, 0x3f, 0xe4, 0xbc, 0xc1,
+ 0x91, 0x40, 0x2a, 0x57, 0x0b,
+ 0x02, 0x41, /* INTEGER - d mod (p - 1) */
+ 0x00, 0x88, 0x9f, 0x4f, 0x00, 0x65, 0x68, 0x9c, 0xed, 0xac, 0x14, 0xdd,
+ 0x4b, 0x19, 0x1f, 0x82, 0x68, 0x92, 0xc1, 0x04, 0xb0, 0x11, 0x4b, 0x13,
+ 0x8a, 0xaa, 0x0a, 0xe4, 0x08, 0x74, 0x82, 0xe8, 0x61, 0xc3, 0xdf, 0xe3,
+ 0x1a, 0x2a, 0x51, 0xb9, 0x5c, 0x09, 0x9e, 0x63, 0x33, 0x22, 0x55, 0x8a,
+ 0x9e, 0x7b, 0xe7, 0x91, 0xf2, 0x74, 0xb3, 0x9c, 0x68, 0x16, 0xf4, 0x61,
+ 0x2a, 0x65, 0xa6, 0x88, 0x0b,
+ 0x02, 0x40, /* INTEGER - d mod (q - 1) */
+ 0x56, 0x3c, 0xab, 0x07, 0x24, 0xe7, 0xb6, 0x5b, 0x55, 0xe9, 0x33, 0xd6,
+ 0xf1, 0x09, 0xfc, 0x97, 0x40, 0x3b, 0x31, 0x9f, 0x13, 0xa5, 0xff, 0xa0,
+ 0x77, 0xfe, 0x7c, 0x35, 0xfb, 0xc4, 0xee, 0x6c, 0x60, 0x29, 0xf4, 0x5d,
+ 0xa0, 0x28, 0xc6, 0x5b, 0x04, 0x17, 0x15, 0xf0, 0x22, 0x0c, 0xe3, 0xbb,
+ 0xc7, 0x8b, 0xd4, 0x30, 0x0e, 0x60, 0x48, 0x67, 0x4c, 0x2f, 0xc2, 0x65,
+ 0x99, 0xd8, 0xc1, 0xe3,
+ 0x02, 0x40, /* INTEGER - inv q mod p */
+ 0x12, 0x89, 0x47, 0x76, 0xb6, 0xbb, 0x18, 0x64, 0xc3, 0x19, 0xe7, 0xa9,
+ 0x93, 0xce, 0xec, 0xd6, 0x4b, 0xaa, 0xad, 0x46, 0x4f, 0x24, 0x0d, 0xf3,
+ 0xbf, 0xc2, 0x7c, 0x95, 0x3e, 0xc9, 0x27, 0x8a, 0x4b, 0xbc, 0x9e, 0x56,
+ 0x2a, 0x8c, 0x07, 0x5f, 0xb6, 0x07, 0x21, 0xb7, 0xc9, 0xae, 0x8c, 0x58,
+ 0x04, 0x65, 0x02, 0xa2, 0x08, 0x03, 0x40, 0xf3, 0x71, 0x8c, 0x89, 0xf7,
+ 0xaa, 0xb0, 0x6a, 0x75,
+};
+
+static void test_rsa(const void *data)
+{
+ struct l_cipher *cipher;
+ char buf[128];
+ uint8_t *short_key;
+ size_t short_key_len;
+
+ short_key = l_cert_extract_rsakey(rsa_priv_key, sizeof(rsa_priv_key),
+ &short_key_len);
+
+ cipher = l_cipher_new(L_CIPHER_RSA, short_key, short_key_len);
+ l_free(short_key);
+
+ assert(cipher);
+ assert(l_cipher_encrypt(cipher, FIXED_STR, buf, 128));
+
+ assert(memcmp(FIXED_STR, buf, 128));
+
+ assert(l_cipher_decrypt(cipher, buf, buf, 128));
+
+ assert(!memcmp(FIXED_STR, buf, 128));
+
+ l_cipher_free(cipher);
+}
+
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@@ -132,5 +229,7 @@ int main(int argc, char *argv[])
l_test_add("arc4", test_arc4, NULL);
+ l_test_add("rsa", test_rsa, NULL);
+
return l_test_run();
}
--
2.1.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types.
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
` (7 preceding siblings ...)
2015-07-24 3:26 ` [PATCH 09/17] unit: Add an RSA encryption/decryption test Andrew Zaborowski
@ 2015-07-24 15:50 ` Denis Kenzior
8 siblings, 0 replies; 12+ messages in thread
From: Denis Kenzior @ 2015-07-24 15:50 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 260 bytes --]
Hi Andrew,
On 07/23/2015 10:26 PM, Andrew Zaborowski wrote:
> ---
> ell/checksum.c | 20 ++++++++++++++++++--
> ell/checksum.h | 2 ++
> 2 files changed, 20 insertions(+), 2 deletions(-)
>
Patch has been applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 02/17] checksum: Add l_checksum_clone API.
2015-07-24 3:26 ` [PATCH 02/17] checksum: Add l_checksum_clone API Andrew Zaborowski
@ 2015-07-24 15:55 ` Denis Kenzior
0 siblings, 0 replies; 12+ messages in thread
From: Denis Kenzior @ 2015-07-24 15:55 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 875 bytes --]
Hi Andrew,
On 07/23/2015 10:26 PM, Andrew Zaborowski wrote:
> In the kernel API we use and also in GLib's API the l_checksum_get_digest()
> equivalents can only be called once on each object meaning that in a
> situation when multiple digest values at different points of a
> running stream are needed the API becomes impractical. The new _clone()
> call returns a clone of the checksum's state at the current time, on
> which get_digest() can be called.
> ---
> ell/checksum.c | 24 ++++++++++++++++++++++++
> ell/checksum.h | 1 +
> 2 files changed, 25 insertions(+)
>
<snip>
> +LIB_EXPORT struct l_checksum *l_checksum_clone(struct l_checksum *checksum)
> +{
> + struct l_checksum *clone;
> +
Patch has been applied, but I also added a tiny sanity check here to
make sure that checksum != NULL in a follow-on commit.
Regards,
-Denis
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types.
2015-07-24 3:26 ` [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types Andrew Zaborowski
@ 2015-07-24 15:56 ` Denis Kenzior
0 siblings, 0 replies; 12+ messages in thread
From: Denis Kenzior @ 2015-07-24 15:56 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 331 bytes --]
Hi Andrew,
On 07/23/2015 10:26 PM, Andrew Zaborowski wrote:
> This again only adds the definitions needed to use the kernel
> implementations, no real code here.
> ---
> ell/cipher.c | 8 +++++++-
> ell/cipher.h | 2 ++
> 2 files changed, 9 insertions(+), 1 deletion(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-07-24 15:56 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-24 3:26 [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 02/17] checksum: Add l_checksum_clone API Andrew Zaborowski
2015-07-24 15:55 ` Denis Kenzior
2015-07-24 3:26 ` [PATCH 03/17] cipher: Add 3DES EDE and AES CBC-mode cipher types Andrew Zaborowski
2015-07-24 15:56 ` Denis Kenzior
2015-07-24 3:26 ` [PATCH 04/17] cipher: Add l_cipher_set_iv Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 05/17] Add ASN.1 BER / DER decoding utilities as asn1-private.h Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 06/17] Add RSA PKCS#1 1.5 assymetric key encryption operations Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 07/17] Add cert.{c,h} for basic X509 certificate operations Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 08/17] cert: Add RSA private key utilities Andrew Zaborowski
2015-07-24 3:26 ` [PATCH 09/17] unit: Add an RSA encryption/decryption test Andrew Zaborowski
2015-07-24 15:50 ` [PATCH 01/17] checksum: Add SHA384 and SHA512 hash & hmac types 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.