@@ -28,6 +28,7 @@ before_install:
- sudo apt-get install -y graphviz
- sudo apt-get install -y autoconf-archive
- sudo apt-get install -y linux-headers-$(uname -r)
+ - sudo apt-get install -y libmbedtls-dev
script:
- sudo ln -sf /usr/lib/x86_64-linux-gnu/pkgconfig/lua5.2.pc /usr/lib/x86_64-linux-gnu/pkgconfig/lua.pc
@@ -69,6 +69,10 @@ config HAVE_LIBCRYPTO
bool
option env="HAVE_LIBCRYPTO"
+config HAVE_MBEDTLS
+ bool
+ option env="HAVE_MBEDTLS"
+
config HAVE_JSON_C
bool
option env="HAVE_JSON_C"
@@ -313,6 +317,25 @@ endmenu
source bootloader/Config.in
+choice
+ prompt "SSL implementation to use"
+ default SSL_IMPL_OPENSSL
+ help
+ Select SSL implementation for hashing, verifying and decrypting images.
+
+ config SSL_IMPL_NONE
+ bool "None"
+
+ config SSL_IMPL_OPENSSL
+ bool "OpenSSL"
+ depends on HAVE_LIBSSL
+
+ config SSL_IMPL_MBEDTLS
+ bool "mbedTLS"
+ depends on HAVE_MBEDTLS
+
+endchoice
+
config DOWNLOAD
bool "Enable image downloading"
default n
@@ -329,8 +352,7 @@ config DOWNLOAD_SSL
bool "Enable SSL support for image downloading"
default n
depends on DOWNLOAD
- depends on HAVE_LIBSSL
- depends on HAVE_LIBCRYPTO
+ depends on SSL_IMPL_OPENSSL || SSL_IMPL_MBEDTLS
select CHANNEL_CURL_SSL
help
Enable SSL and checksum verification support in channels
@@ -344,26 +366,25 @@ config CHANNEL_CURL
config CHANNEL_CURL_SSL
bool
depends on CHANNEL_CURL
- depends on HAVE_LIBSSL
- depends on HAVE_LIBCRYPTO
+ depends on SSL_IMPL_OPENSSL || SSL_IMPL_MBEDTLS
select CURL_SSL
config HASH_VERIFY
bool "Allow to add sha256 hash to each image"
- depends on HAVE_LIBSSL
+ depends on SSL_IMPL_OPENSSL || SSL_IMPL_MBEDTLS
help
Allow to add a sha256 hash to an artifact.
This is automatically set in case of Signed Image
-comment "Hash verification needs libssl"
- depends on !HAVE_LIBSSL
+comment "Hash checking needs an SSL implementation"
+ depends on !SSL_IMPL_OPENSSL && !SSL_IMPL_MBEDTLS
config SIGNED_IMAGES
bool "Enable verification of signed images"
- depends on HAVE_LIBSSL
+ depends on SSL_IMPL_OPENSSL || SSL_IMPL_MBEDTLS
select HASH_VERIFY
-comment "Image verification (signed images) needs libssl"
- depends on !HAVE_LIBSSL
+comment "Image signature verification needs an SSL implementation"
+ depends on !SSL_IMPL_OPENSSL && !SSL_IMPL_MBEDTLS
choice
prompt "Signature verification algorithm"
@@ -381,6 +402,7 @@ choice
config SIGALG_CMS
bool "Cryptographic Message Syntax (CMS)"
+ depends on SSL_IMPL_OPENSSL
endchoice
@@ -399,9 +421,9 @@ endmenu
config ENCRYPTED_IMAGES
bool "Images can be encrypted with a symmetric key"
- depends on HAVE_LIBSSL
-comment "Image encryption needs libssl"
- depends on !HAVE_LIBSSL
+ depends on SSL_IMPL_OPENSSL || SSL_IMPL_MBEDTLS
+comment "Image encryption needs an SSL implementation"
+ depends on !SSL_IMPL_OPENSSL && !SSL_IMPL_MBEDTLS
source suricatta/Config.in
@@ -54,6 +54,10 @@ ifeq ($(HAVE_LIBCRYPTO),)
export HAVE_LIBCRYPTO = y
endif
+ifeq ($(HAVE_MBEDTLS),)
+export HAVE_MBEDTLS = y
+endif
+
ifeq ($(HAVE_JSON_C),)
export HAVE_JSON_C = y
endif
@@ -145,23 +145,12 @@ ifeq ($(CONFIG_JSON),y)
LDLIBS += json-c
endif
-# signed images require openssl (digest)
-ifneq ($(CONFIG_HASH_VERIFY),)
+ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
LDLIBS += crypto ssl
endif
-# signed images require openssl (digest)
-ifneq ($(CONFIG_ENCRYPTED_IMAGES),)
-LDLIBS += crypto ssl
-endif
-
-# mongoose / webserver
-ifeq ($(CONFIG_WEBSERVER),y)
-ifeq ($(CONFIG_MONGOOSE),y)
-ifeq ($(CONFIG_MONGOOSESSL),y)
-LDLIBS += crypto ssl
-endif
-endif
+ifeq ($(CONFIG_SSL_IMPL_MBEDTLS),y)
+LDLIBS += mbedcrypto mbedtls
endif
# MTD
@@ -197,20 +186,8 @@ ifeq ($(CONFIG_BOOTLOADER_EBG),y)
LDLIBS += ebgenv z
endif
-# channel_curl
-ifneq ($(CONFIG_CHANNEL_CURL_SSL),)
-ifeq ($(strip $(findstring crypto,$(LDLIBS))),)
-LDLIBS += crypto ssl
-endif
-endif
-
# suricatta
ifneq ($(CONFIG_SURICATTA),)
-ifneq ($(CONFIG_SURICATTA_SSL),)
-ifeq ($(strip $(findstring crypto,$(LDLIBS))),)
-LDLIBS += crypto ssl
-endif
-endif
ifneq ($(CONFIG_SURICATTA_HAWKBIT),)
ifeq ($(strip $(findstring json-c,$(LDLIBS))),)
LDLIBS += json-c
new file mode 100644
@@ -0,0 +1,18 @@
+CONFIG_HW_COMPATIBILITY=y
+# CONFIG_MTD is not set
+CONFIG_LUAPKG="lua5.2"
+CONFIG_EXTRA_CFLAGS="-g"
+CONFIG_BOOTLOADER_NONE=y
+CONFIG_DOWNLOAD=y
+CONFIG_SSL_IMPL_MBEDTLS=y
+CONFIG_HASH_VERIFY=y
+CONFIG_SIGNED_IMAGES=y
+CONFIG_ENCRYPTED_IMAGES=y
+CONFIG_WEBSERVER=y
+CONFIG_LUAEXTERNAL=y
+CONFIG_RAW=y
+CONFIG_LUASCRIPTHANDLER=y
+CONFIG_SHELLSCRIPTHANDLER=y
+CONFIG_HANDLER_IN_LUA=y
+CONFIG_ARCHIVE=y
+CONFIG_REMOTE_HANDLER=y
@@ -12,13 +12,19 @@ lib-y += installer.o \
lib-$(CONFIG_DOWNLOAD) += downloader.o
lib-$(CONFIG_MTD) += mtd-interface.o
lib-$(CONFIG_LUA) += lua_interface.o lua_compat.o
+ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
lib-$(CONFIG_HASH_VERIFY) += verify_signature.o
lib-$(CONFIG_ENCRYPTED_IMAGES) += swupdate_decrypt.o
+lib-$(CONFIG_SIGALG_RAWRSA) += swupdate_rsa_verify.o
+lib-$(CONFIG_SIGALG_RSAPSS) += swupdate_rsa_verify.o
+lib-$(CONFIG_SIGALG_CMS) += swupdate_cms_verify.o
+endif
+ifeq ($(CONFIG_SSL_IMPL_MBEDTLS),y)
+lib-$(CONFIG_HASH_VERIFY) += verify_signature_mbedtls.o
+lib-$(CONFIG_ENCRYPTED_IMAGES) += swupdate_decrypt_mbedtls.o
+lib-$(CONFIG_SIGALG_RAWRSA) += swupdate_rsa_verify_mbedtls.o
+endif
lib-$(CONFIG_LIBCONFIG) += swupdate_settings.o \
parsing_library_libconfig.o
lib-$(CONFIG_JSON) += parsing_library_libjson.o
lib-$(CONFIG_CHANNEL_CURL) += channel_curl.o
-lib-$(CONFIG_SIGALG_RAWRSA) += swupdate_rsa_verify.o
-lib-$(CONFIG_SIGALG_RSAPSS) += swupdate_rsa_verify.o
-lib-$(CONFIG_SIGALG_CMS) += swupdate_cms_verify.o
-
@@ -67,7 +67,7 @@ struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char
}
int swupdate_DECRYPT_update(struct swupdate_digest *dgst, unsigned char *buf,
- int *outlen, unsigned char *cryptbuf, int inlen)
+ int *outlen, const unsigned char *cryptbuf, int inlen)
{
if (EVP_DecryptUpdate(SSL_GET_CTXDEC(dgst), buf, outlen, cryptbuf, inlen) != 1) {
const char *reason = ERR_reason_error_string(ERR_peek_error());
new file mode 100644
@@ -0,0 +1,100 @@
+#include <errno.h>
+
+#include "sslapi.h"
+#include "util.h"
+
+struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv)
+{
+ struct swupdate_digest *dgst;
+ const mbedtls_cipher_info_t *cipher_info;
+ int error;
+
+ if ((key == NULL) || (iv == NULL)) {
+ ERROR("no key provided for decryption!");
+ return NULL;
+ }
+
+ cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC);
+ if (!cipher_info) {
+ ERROR("mbedtls_cipher_info_from_type");
+ return NULL;
+ }
+
+ dgst = calloc(1, sizeof(*dgst));
+ if (!dgst) {
+ return NULL;
+ }
+
+ mbedtls_cipher_init(&dgst->mbedtls_cipher_context);
+
+ error = mbedtls_cipher_setup(&dgst->mbedtls_cipher_context, cipher_info);
+ if (error) {
+ ERROR("mbedtls_cipher_setup: %d", error);
+ goto fail;
+ }
+
+ error = mbedtls_cipher_setkey(&dgst->mbedtls_cipher_context, key, 256, MBEDTLS_DECRYPT);
+ if (error) {
+ ERROR("mbedtls_cipher_setkey: %d", error);
+ goto fail;
+ }
+
+ error = mbedtls_cipher_set_iv(&dgst->mbedtls_cipher_context, iv, 16);
+ if (error) {
+ ERROR("mbedtls_cipher_set_iv: %d", error);
+ goto fail;
+ }
+
+ return dgst;
+
+fail:
+ free(dgst);
+ return NULL;
+}
+
+int swupdate_DECRYPT_update(struct swupdate_digest *dgst, unsigned char *buf,
+ int *outlen, const unsigned char *cryptbuf, int inlen)
+{
+ int error;
+ size_t olen = *outlen;
+
+ error = mbedtls_cipher_update(&dgst->mbedtls_cipher_context, cryptbuf, inlen, buf, &olen);
+ if (error) {
+ ERROR("mbedtls_cipher_update: %d", error);
+ return -EFAULT;
+ }
+ *outlen = olen;
+
+ return 0;
+}
+
+int swupdate_DECRYPT_final(struct swupdate_digest *dgst, unsigned char *buf,
+ int *outlen)
+{
+ int error;
+ size_t olen = *outlen;
+
+ if (!dgst) {
+ return -EINVAL;
+ }
+
+ error = mbedtls_cipher_finish(&dgst->mbedtls_cipher_context, buf, &olen);
+ if (error) {
+ ERROR("mbedtls_cipher_finish: %d", error);
+ return -EFAULT;
+ }
+ *outlen = olen;
+
+ return 0;
+
+}
+
+void swupdate_DECRYPT_cleanup(struct swupdate_digest *dgst)
+{
+ if (!dgst) {
+ return;
+ }
+
+ mbedtls_cipher_free(&dgst->mbedtls_cipher_context);
+ free(dgst);
+}
new file mode 100644
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2019
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sslapi.h"
+#include "util.h"
+
+int swupdate_dgst_init(struct swupdate_cfg *sw, const char *keyfile)
+{
+ struct swupdate_digest *dgst;
+ int error;
+
+ dgst = calloc(1, sizeof(*dgst));
+ if (!dgst) {
+ return -ENOMEM;
+ }
+
+ mbedtls_pk_init(&dgst->mbedtls_pk_context);
+
+ error = mbedtls_pk_parse_public_keyfile(&dgst->mbedtls_pk_context, keyfile);
+ if (error) {
+ ERROR("mbedtls_pk_parse_public_keyfile: %d", error);
+ goto fail;
+ }
+
+ sw->dgst = dgst;
+ return 0;
+
+fail:
+ free(dgst);
+ return -EIO;
+}
+
+static int read_file_into_buffer(uint8_t *buffer, int size, const char *filename)
+{
+ int fd;
+ ssize_t rd;
+ int result = -1;
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ ERROR("Failed to open file \"%s\"", filename);
+ return -errno;
+ }
+
+ rd = read(fd, buffer, size);
+ if (rd != size) {
+ ERROR("Failed to read %d bytes from file \"%s\"", size, filename);
+ result = -EMSGSIZE;
+ goto exit;
+ }
+
+ result = 0;
+
+exit:
+ return result;
+}
+
+int swupdate_verify_file(struct swupdate_digest *dgst, const char *sigfile,
+ const char *file, const char *signer_name)
+{
+ int error;
+ uint8_t hash_computed[32];
+ const mbedtls_md_info_t *md_info;
+ uint8_t signature[256];
+
+ (void)signer_name;
+
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ if (!md_info) {
+ ERROR("mbedtls_md_info_from_type");
+ return -ENOENT;
+ }
+
+ assert(mbedtls_md_get_size(md_info) == sizeof(hash_computed));
+
+ error = mbedtls_md_file(md_info, file, hash_computed);
+ if (error) {
+ ERROR("mbedtls_md_file: %d", error);
+ return error;
+ }
+
+ error = read_file_into_buffer(signature, sizeof(signature), sigfile);
+ if (error) {
+ return error;
+ }
+
+ return mbedtls_pk_verify(
+ &dgst->mbedtls_pk_context, mbedtls_md_get_type(md_info),
+ hash_computed, sizeof(hash_computed),
+ signature, sizeof(signature)
+ );
+}
@@ -51,7 +51,7 @@ static void do_crypt(struct cryptdata *crypt, unsigned char *CRYPTTEXT, unsigned
assert_true(ret >= 0);
assert_true(len == 0);
- ret = swupdate_DECRYPT_final(dcrypt, crypt->crypttext, &len);
+ ret = swupdate_DECRYPT_final(dcrypt, buffer, &len);
assert_true(ret == 0);
assert_true(len == (int)strlen((const char *)PLAINTEXT));
assert_true(strncmp((const char *)buffer, (const char *)PLAINTEXT, len) == 0);
@@ -119,7 +119,7 @@ static void test_crypt_failure(void **state)
unsigned char *buffer = calloc(1, strlen((const char *)CRYPTTEXT) + EVP_MAX_BLOCK_LENGTH);
int ret = swupdate_DECRYPT_update(dcrypt, buffer, &len, crypt.crypttext, strlen((const char *)CRYPTTEXT) / 2);
- ret = swupdate_DECRYPT_final(dcrypt, crypt.crypttext, &len);
+ ret = swupdate_DECRYPT_final(dcrypt, buffer, &len);
assert_true(ret != 0);
free(buffer);
@@ -63,7 +63,7 @@ struct swupdate_digest *swupdate_HASH_init(const char *SHAlength)
return dgst;
}
-int swupdate_HASH_update(struct swupdate_digest *dgst, unsigned char *buf,
+int swupdate_HASH_update(struct swupdate_digest *dgst, const unsigned char *buf,
size_t len)
{
if (!dgst)
@@ -97,7 +97,7 @@ void swupdate_HASH_cleanup(struct swupdate_digest *dgst)
/*
* Just a wrap function to memcmp
*/
-int swupdate_HASH_compare(unsigned char *hash1, unsigned char *hash2)
+int swupdate_HASH_compare(const unsigned char *hash1, const unsigned char *hash2)
{
int i;
new file mode 100644
@@ -0,0 +1,106 @@
+#include <ctype.h>
+#include <errno.h>
+
+#include "sslapi.h"
+#include "util.h"
+
+static char *algo_upper(const char *algo)
+{
+ static char result[16];
+ unsigned i;
+
+ for (i = 0; algo[i] && (i < sizeof(result) - 1); ++i) {
+ result[i] = toupper(algo[i]);
+ }
+ result[i] = '\0';
+ return result;
+}
+
+struct swupdate_digest *swupdate_HASH_init(const char *algo)
+{
+ struct swupdate_digest *dgst;
+ int error;
+
+ const mbedtls_md_info_t *info = mbedtls_md_info_from_string(algo_upper(algo));
+ if (!info) {
+ ERROR("mbedtls_md_info_from_string(\"%s\")", algo);
+ return NULL;
+ }
+
+ dgst = calloc(1, sizeof(*dgst));
+ if (!dgst) {
+ return NULL;
+ }
+
+ mbedtls_md_init(&dgst->mbedtls_md_context);
+
+ error = mbedtls_md_setup(&dgst->mbedtls_md_context, info, 0);
+ if (error) {
+ ERROR("mbedtls_md_setup: %d", error);
+ goto fail;
+ }
+
+ error = mbedtls_md_starts(&dgst->mbedtls_md_context);
+ if (error) {
+ ERROR("mbedtls_md_starts: %d", error);
+ goto fail;
+ }
+
+ return dgst;
+
+fail:
+ free(dgst);
+ return 0;
+}
+
+int swupdate_HASH_update(struct swupdate_digest *dgst, const unsigned char *buf,
+ size_t len)
+{
+ if (!dgst) {
+ return -EFAULT;
+ }
+
+ const int error = mbedtls_md_update(&dgst->mbedtls_md_context, buf, len);
+ if (error) {
+ ERROR("mbedtls_md_update: %d", error);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int swupdate_HASH_final(struct swupdate_digest *dgst, unsigned char *md_value,
+ unsigned int *md_len)
+{
+ if (!dgst) {
+ return -EFAULT;
+ }
+
+ int error = mbedtls_md_finish(&dgst->mbedtls_md_context, md_value);
+ if (error) {
+ return -EINVAL;
+ }
+ if (md_len) {
+ *md_len = mbedtls_md_get_size(dgst->mbedtls_md_context.md_info);
+ }
+ return 1;
+
+}
+
+void swupdate_HASH_cleanup(struct swupdate_digest *dgst)
+{
+ if (!dgst) {
+ return;
+ }
+
+ mbedtls_md_free(&dgst->mbedtls_md_context);
+ free(dgst);
+}
+
+/*
+ * Just a wrap function to memcmp
+ */
+int swupdate_HASH_compare(const unsigned char *hash1, const unsigned char *hash2)
+{
+ return memcmp(hash1, hash2, SHA256_HASH_LENGTH) ? -1 : 0;
+}
@@ -18,6 +18,7 @@
*/
#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_ENCRYPTED_IMAGES) || \
defined(CONFIG_SURICATTA_SSL) || defined(CONFIG_CHANNEL_CURL_SSL)
+#if defined(CONFIG_SSL_IMPL_OPENSSL)
#include <openssl/bio.h>
#include <openssl/objects.h>
#include <openssl/err.h>
@@ -96,22 +97,47 @@ static inline uint32_t SSL_X509_get_extended_key_usage(X509 *x)
#endif
}
+#elif defined(CONFIG_SSL_IMPL_MBEDTLS)
+#include <mbedtls/md.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/cipher.h>
+
+#define EVP_MAX_BLOCK_LENGTH (16)
+#define swupdate_crypto_init()
+
+struct swupdate_digest {
+#ifdef CONFIG_HASH_VERIFY
+ mbedtls_md_context_t mbedtls_md_context;
+#endif /* CONFIG_HASH_VERIFY */
+#ifdef CONFIG_SIGNED_IMAGES
+ mbedtls_pk_context mbedtls_pk_context;
+#endif /* CONFIG_SIGNED_IMAGES */
+#ifdef CONFIG_ENCRYPTED_IMAGES
+ mbedtls_cipher_context_t mbedtls_cipher_context;
+#endif /* CONFIG_ENCRYPTED_IMAGES */
+};
+
+#else /* CONFIG_SSL_IMPL */
+#error unknown SSL implementation
+#endif /* CONFIG_SSL_IMPL */
#else
#define swupdate_crypto_init()
#define AES_BLOCK_SIZE 16
#endif
#if defined(CONFIG_HASH_VERIFY)
+struct swupdate_cfg;
+
int swupdate_dgst_init(struct swupdate_cfg *sw, const char *keyfile);
struct swupdate_digest *swupdate_HASH_init(const char *SHALength);
-int swupdate_HASH_update(struct swupdate_digest *dgst, unsigned char *buf,
+int swupdate_HASH_update(struct swupdate_digest *dgst, const unsigned char *buf,
size_t len);
int swupdate_HASH_final(struct swupdate_digest *dgst, unsigned char *md_value,
unsigned int *md_len);
void swupdate_HASH_cleanup(struct swupdate_digest *dgst);
int swupdate_verify_file(struct swupdate_digest *dgst, const char *sigfile,
const char *file, const char *signer_name);
-int swupdate_HASH_compare(unsigned char *hash1, unsigned char *hash2);
+int swupdate_HASH_compare(const unsigned char *hash1, const unsigned char *hash2);
#else
@@ -127,7 +153,7 @@ int swupdate_HASH_compare(unsigned char *hash1, unsigned char *hash2);
#ifdef CONFIG_ENCRYPTED_IMAGES
struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv);
int swupdate_DECRYPT_update(struct swupdate_digest *dgst, unsigned char *buf,
- int *outlen, unsigned char *cryptbuf, int inlen);
+ int *outlen, const unsigned char *cryptbuf, int inlen);
int swupdate_DECRYPT_final(struct swupdate_digest *dgst, unsigned char *buf,
int *outlen);
void swupdate_DECRYPT_cleanup(struct swupdate_digest *dgst);
This patch enables using mbedtls as an alternative implementation as opposed to openssl. CMS signatures are not supported. Signed-off-by: Laszlo Ashin <laszlo@ashin.hu> --- .travis.yml | 1 + Kconfig | 48 ++++++++---- Makefile.deps | 4 + Makefile.flags | 29 +------ configs/mbedtls_defconfig | 18 +++++ corelib/Makefile | 14 +++- corelib/swupdate_decrypt.c | 2 +- corelib/swupdate_decrypt_mbedtls.c | 100 ++++++++++++++++++++++++ corelib/swupdate_rsa_verify_mbedtls.c | 103 +++++++++++++++++++++++++ corelib/test/test_crypt.c | 4 +- corelib/verify_signature.c | 4 +- corelib/verify_signature_mbedtls.c | 106 ++++++++++++++++++++++++++ include/sslapi.h | 32 +++++++- 13 files changed, 414 insertions(+), 51 deletions(-) create mode 100644 configs/mbedtls_defconfig create mode 100644 corelib/swupdate_decrypt_mbedtls.c create mode 100644 corelib/swupdate_rsa_verify_mbedtls.c create mode 100644 corelib/verify_signature_mbedtls.c