summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSteffen Trumtrar <s.trumtrar@pengutronix.de>2016-02-17 11:54:09 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-04-12 11:58:39 +0200
commit6f91b9b1994fff3a627633b8883b9ea3fc3acef1 (patch)
tree4121e97842292edcd00823b9d7e4a8be36d25d52 /lib
parent4b4dc564f46d2179dbf7e40f6434ec0664ed7c53 (diff)
downloadbarebox-6f91b9b1994fff3a627633b8883b9ea3fc3acef1.tar.gz
barebox-6f91b9b1994fff3a627633b8883b9ea3fc3acef1.tar.xz
lib: add blobgen framework
This adds a framework for en/decrypting data blobs. Some SoCs have support for hardware crypto engines that can en/decrypt using keys that a tied to the SoC and are visible for the crypto hardware only. With this patch it's possible to encrypt confidential data using these keys and to decrypt it later for usage. Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile1
-rw-r--r--lib/blobgen.c223
3 files changed, 227 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 35f208cbc1..7cf6975bcc 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -158,4 +158,7 @@ config GENERIC_LIB_MULDI3
config NLS
bool "Native language support"
+config BLOBGEN
+ bool "include blob encode/decode support"
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 31e66de33f..161d3a756e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -18,6 +18,7 @@ obj-y += readkey.o
obj-y += kfifo.o
obj-y += libbb.o
obj-y += libgen.o
+obj-$(CONFIG_BLOBGEN) += blobgen.o
obj-y += stringlist.o
obj-y += cmdlinepart.o
obj-y += recursive_action.o
diff --git a/lib/blobgen.c b/lib/blobgen.c
new file mode 100644
index 0000000000..5a556a68ce
--- /dev/null
+++ b/lib/blobgen.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+#include <blobgen.h>
+#include <base64.h>
+#include <malloc.h>
+#include <crypto.h>
+#include <dma.h>
+#include <environment.h>
+
+static LIST_HEAD(blobs);
+static struct blobgen *bg_default;
+
+/**
+ * blob_gen_register - register a blob device
+ * @dev: The parent device
+ * @bg: The blobgen device
+ *
+ * This registers a blob device. Returns 0 for success or a negative error
+ * code otherwise.
+ */
+int blob_gen_register(struct device_d *dev, struct blobgen *bg)
+{
+ int ret;
+
+ dev_set_name(&bg->dev, "blob");
+ bg->dev.parent = dev;
+
+ ret = register_device(&bg->dev);
+ if (ret)
+ return ret;
+
+ list_add_tail(&bg->list, &blobs);
+
+ if (!bg_default)
+ bg_default = bg;
+
+ return 0;
+}
+
+/**
+ * blobgen_get - get a blob generator of given name
+ * @name: The name of the blob generator to look for
+ *
+ * Finds a blob generator by name and returns it. Returns NULL if none is found.
+ */
+struct blobgen *blobgen_get(const char *name)
+{
+ struct device_d *dev;
+ struct blobgen *bg;
+
+ if (!name)
+ return bg_default;
+
+ dev = get_device_by_name(name);
+ if (!dev)
+ return NULL;
+
+ list_for_each_entry(bg, &blobs, list) {
+ if (dev == &bg->dev)
+ return bg;
+ }
+
+ return NULL;
+}
+
+/**
+ * blob_encrypt - encrypt a data blob
+ * @bg: The blob generator to use
+ * @modifier: Modifier string
+ * @plain: The plaintext input
+ * @plainsize: Length of the plain data in bytes
+ * @retblob: The encrypted blob is returned here
+ * @blobsize: The returned length of the encrypted blob
+ *
+ * This encrypts a blob passed in @plain to an allocated buffer returned in
+ * @retblob. Returns 0 for success or a negative error code otherwise. @retblob
+ * is valid when the function returns successfully. The caller must free the
+ * buffer after use.
+ */
+int blob_encrypt(struct blobgen *bg, const char *modifier, const void *plain,
+ int plainsize, void **retblob, int *blobsize)
+{
+ void *blob;
+ int ret;
+
+ if (plainsize > bg->max_payload_size)
+ return -EINVAL;
+
+ pr_debug("%s plain:\n", __func__);
+ pr_memory_display(MSG_DEBUG, plain, 0, plainsize, 1, 0);
+
+ blob = dma_alloc(MAX_BLOB_LEN);
+ if (!blob)
+ return -ENOMEM;
+
+ ret = bg->encrypt(bg, modifier, plain, plainsize, blob, blobsize);
+
+ if (ret) {
+ free(blob);
+ } else {
+ pr_debug("%s encrypted:\n", __func__);
+ pr_memory_display(MSG_DEBUG, blob, 0, *blobsize, 1, 0);
+ *retblob = blob;
+ }
+
+ return ret;
+}
+
+/**
+ * blob_encrypt_to_env - encrypt blob to environment variable
+ * @bg: The blob generator to use
+ * @modifier: Modifier string
+ * @plain: The plaintext input
+ * @plainsize: Length of the plain data in bytes
+ * @varname: Name of the variable to set with the output blob
+ *
+ * This uses blob_encrypt to encrypt a blob. The result is base64 encoded and
+ * written to the environment variable @varname. Returns 0 for success or a
+ * negative error code otherwise.
+ */
+int blob_encrypt_to_env(struct blobgen *bg, const char *modifier,
+ const void *plain, int plainsize, const char *varname)
+{
+ int ret;
+ int blobsize;
+ void *blob;
+ char *value;
+
+ ret = blob_encrypt(bg, modifier, plain, plainsize, &blob, &blobsize);
+ if (ret)
+ return ret;
+
+ value = malloc(BASE64_LENGTH(blobsize) + 1);
+ if (!value)
+ return -ENOMEM;
+
+ uuencode(value, blob, blobsize);
+
+ pr_debug("%s encrypted base64: \"%s\"\n", __func__, value);
+
+ ret = setenv(varname, value);
+
+ free(value);
+ free(blob);
+
+ return ret;
+}
+
+/**
+ * blob_decrypt - decrypt a blob
+ * @bg: The blob generator to use
+ * @modifier: Modifier string
+ * @blob: The encrypted blob
+ * @blobsize: Size of the encrypted blob
+ * @plain: Plaintext is returned here
+ * @plainsize: Size of the data returned in bytes
+ *
+ * This function decrypts a blob generated with blob_encrypt. @modifier must match
+ * the modifier used to encrypt the data. Returns 0 when the data could be
+ * decrypted successfully or a negative error code otherwise.
+ */
+int blob_decrypt(struct blobgen *bg, const char *modifier, const void *blob,
+ int blobsize, void **plain, int *plainsize)
+{
+ int ret;
+
+ pr_debug("%s encrypted:\n", __func__);
+ pr_memory_display(MSG_DEBUG, blob, 0, blobsize, 1, 0);
+
+ ret = bg->decrypt(bg, modifier, blob, blobsize, plain, plainsize);
+
+ if (!ret) {
+ pr_debug("%s decrypted:\n", __func__);
+ pr_memory_display(MSG_DEBUG, *plain, 0, *plainsize, 1, 0);
+ }
+
+ return ret;
+}
+
+/**
+ * blob_decrypt_from_base64 - decrypt a base64 encoded blob
+ * @bg: The blob generator to use
+ * @modifier: Modifier string
+ * @encrypted: base64 encoded encrypted data
+ * @plain: Plaintext is returned here
+ * @plainsize: Size of the data returned in bytes
+ *
+ * like blob_decrypt, but takes the encrypted data as a base64 encoded string.
+ * Returns 0 when the data could be decrypted successfully or a negative error
+ * code otherwise.
+ */
+int blob_decrypt_from_base64(struct blobgen *bg, const char *modifier,
+ const char *encrypted, void **plain,
+ int *plainsize)
+{
+ char *data;
+ int ret, len;
+
+ data = dma_alloc(MAX_BLOB_LEN);
+ if (!data)
+ return -ENOMEM;
+
+ pr_debug("encrypted base64: \"%s\"\n", encrypted);
+
+ len = decode_base64(data, MAX_BLOB_LEN, encrypted);
+
+ ret = blob_decrypt(bg, modifier, data, len, plain, plainsize);
+
+ free(data);
+
+ return ret;
+}