summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/.gitignore2
-rw-r--r--lib/libfdt/fdt_overlay.c7
-rw-r--r--lib/net_utils.c8
-rw-r--r--lib/rsa/rsa-sign.c244
-rw-r--r--lib/time.c6
-rw-r--r--lib/tiny-printf.c50
6 files changed, 288 insertions, 29 deletions
diff --git a/lib/efi_loader/.gitignore b/lib/efi_loader/.gitignore
new file mode 100644
index 0000000..634a600
--- /dev/null
+++ b/lib/efi_loader/.gitignore
@@ -0,0 +1,2 @@
+*.efi
+*.so
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index bb41404..56cb70e 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -359,6 +359,9 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
int symbol_off, fixup_off;
int prop_len;
+ if (symbols_off < 0)
+ return symbols_off;
+
symbol_path = fdt_getprop(fdt, symbols_off, label,
&prop_len);
if (!symbol_path)
@@ -492,7 +495,9 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
/* We can have overlays without any fixups */
fixups_off = fdt_path_offset(fdto, "/__fixups__");
- if ((fixups_off < 0 && (fixups_off != -FDT_ERR_NOTFOUND)))
+ if (fixups_off == -FDT_ERR_NOTFOUND)
+ return 0; /* nothing to do */
+ if (fixups_off < 0)
return fixups_off;
/* And base DTs without symbols */
diff --git a/lib/net_utils.c b/lib/net_utils.c
index cfae842..d06be22 100644
--- a/lib/net_utils.c
+++ b/lib/net_utils.c
@@ -24,6 +24,14 @@ struct in_addr string_to_ip(const char *s)
for (addr.s_addr = 0, i = 0; i < 4; ++i) {
ulong val = s ? simple_strtoul(s, &e, 10) : 0;
+ if (val > 255) {
+ addr.s_addr = 0;
+ return addr;
+ }
+ if (i != 3 && *e != '.') {
+ addr.s_addr = 0;
+ return addr;
+ }
addr.s_addr <<= 8;
addr.s_addr |= (val & 0xFF);
if (s) {
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 9a09280..8c6637e 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -14,6 +14,7 @@
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
+#include <openssl/engine.h>
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#define HAVE_ERR_REMOVE_THREAD_STATE
@@ -31,14 +32,14 @@ static int rsa_err(const char *msg)
}
/**
- * rsa_get_pub_key() - read a public key from a .crt file
+ * rsa_pem_get_pub_key() - read a public key from a .crt file
*
* @keydir: Directory containins the key
* @name Name of key file (will have a .crt extension)
* @rsap Returns RSA object, or NULL on failure
* @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
*/
-static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
{
char path[1024];
EVP_PKEY *key;
@@ -96,14 +97,90 @@ err_cert:
}
/**
- * rsa_get_priv_key() - read a private key from a .key file
+ * rsa_engine_get_pub_key() - read a public key from given engine
*
- * @keydir: Directory containins the key
+ * @keydir: Key prefix
+ * @name Name of key
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_pub_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ const char *engine_id;
+ char key_id[1024];
+ EVP_PKEY *key;
+ RSA *rsa;
+ int ret;
+
+ *rsap = NULL;
+
+ engine_id = ENGINE_get_id(engine);
+
+ if (engine_id && !strcmp(engine_id, "pkcs11")) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:%s;object=%s;type=public",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:object=%s;type=public",
+ name);
+ } else {
+ fprintf(stderr, "Engine not supported\n");
+ return -ENOTSUP;
+ }
+
+ key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
+ if (!key)
+ return rsa_err("Failure loading public key from engine");
+
+ /* Convert to a RSA_style key. */
+ rsa = EVP_PKEY_get1_RSA(key);
+ if (!rsa) {
+ rsa_err("Couldn't convert to a RSA style key");
+ ret = -EINVAL;
+ goto err_rsa;
+ }
+
+ EVP_PKEY_free(key);
+ *rsap = rsa;
+
+ return 0;
+
+err_rsa:
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key
+ *
+ * @keydir: Directory containing the key (PEM file) or key prefix (engine)
+ * @name Name of key file (will have a .crt extension)
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ if (engine)
+ return rsa_engine_get_pub_key(keydir, name, engine, rsap);
+ return rsa_pem_get_pub_key(keydir, name, rsap);
+}
+
+/**
+ * rsa_pem_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir: Directory containing the key
* @name Name of key file (will have a .key extension)
* @rsap Returns RSA object, or NULL on failure
* @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
*/
-static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
+static int rsa_pem_get_priv_key(const char *keydir, const char *name,
+ RSA **rsap)
{
char path[1024];
RSA *rsa;
@@ -130,6 +207,81 @@ static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
return 0;
}
+/**
+ * rsa_engine_get_priv_key() - read a private key from given engine
+ *
+ * @keydir: Key prefix
+ * @name Name of key
+ * @engine Engine to use
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_priv_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ const char *engine_id;
+ char key_id[1024];
+ EVP_PKEY *key;
+ RSA *rsa;
+ int ret;
+
+ *rsap = NULL;
+
+ engine_id = ENGINE_get_id(engine);
+
+ if (engine_id && !strcmp(engine_id, "pkcs11")) {
+ if (keydir)
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:%s;object=%s;type=private",
+ keydir, name);
+ else
+ snprintf(key_id, sizeof(key_id),
+ "pkcs11:object=%s;type=private",
+ name);
+ } else {
+ fprintf(stderr, "Engine not supported\n");
+ return -ENOTSUP;
+ }
+
+ key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
+ if (!key)
+ return rsa_err("Failure loading private key from engine");
+
+ /* Convert to a RSA_style key. */
+ rsa = EVP_PKEY_get1_RSA(key);
+ if (!rsa) {
+ rsa_err("Couldn't convert to a RSA style key");
+ ret = -EINVAL;
+ goto err_rsa;
+ }
+
+ EVP_PKEY_free(key);
+ *rsap = rsa;
+
+ return 0;
+
+err_rsa:
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key
+ *
+ * @keydir: Directory containing the key (PEM file) or key prefix (engine)
+ * @name Name of key
+ * @engine Engine to use for signing
+ * @rsap Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name,
+ ENGINE *engine, RSA **rsap)
+{
+ if (engine)
+ return rsa_engine_get_priv_key(keydir, name, engine, rsap);
+ return rsa_pem_get_priv_key(keydir, name, rsap);
+}
+
static int rsa_init(void)
{
int ret;
@@ -148,6 +300,45 @@ static int rsa_init(void)
return 0;
}
+static int rsa_engine_init(const char *engine_id, ENGINE **pe)
+{
+ ENGINE *e;
+ int ret;
+
+ ENGINE_load_builtin_engines();
+
+ e = ENGINE_by_id(engine_id);
+ if (!e) {
+ fprintf(stderr, "Engine isn't available\n");
+ ret = -1;
+ goto err_engine_by_id;
+ }
+
+ if (!ENGINE_init(e)) {
+ fprintf(stderr, "Couldn't initialize engine\n");
+ ret = -1;
+ goto err_engine_init;
+ }
+
+ if (!ENGINE_set_default_RSA(e)) {
+ fprintf(stderr, "Couldn't set engine as default for RSA\n");
+ ret = -1;
+ goto err_set_rsa;
+ }
+
+ *pe = e;
+
+ return 0;
+
+err_set_rsa:
+ ENGINE_finish(e);
+err_engine_init:
+ ENGINE_free(e);
+err_engine_by_id:
+ ENGINE_cleanup();
+ return ret;
+}
+
static void rsa_remove(void)
{
CRYPTO_cleanup_all_ex_data();
@@ -160,6 +351,14 @@ static void rsa_remove(void)
EVP_cleanup();
}
+static void rsa_engine_remove(ENGINE *e)
+{
+ if (e) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ }
+}
+
static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
const struct image_region region[], int region_count,
uint8_t **sigp, uint *sig_size)
@@ -235,13 +434,20 @@ int rsa_sign(struct image_sign_info *info,
uint8_t **sigp, uint *sig_len)
{
RSA *rsa;
+ ENGINE *e = NULL;
int ret;
ret = rsa_init();
if (ret)
return ret;
- ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
+ if (info->engine_id) {
+ ret = rsa_engine_init(info->engine_id, &e);
+ if (ret)
+ goto err_engine;
+ }
+
+ ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
if (ret)
goto err_priv;
ret = rsa_sign_with_key(rsa, info->checksum, region,
@@ -250,6 +456,8 @@ int rsa_sign(struct image_sign_info *info,
goto err_sign;
RSA_free(rsa);
+ if (info->engine_id)
+ rsa_engine_remove(e);
rsa_remove();
return ret;
@@ -257,6 +465,9 @@ int rsa_sign(struct image_sign_info *info,
err_sign:
RSA_free(rsa);
err_priv:
+ if (info->engine_id)
+ rsa_engine_remove(e);
+err_engine:
rsa_remove();
return ret;
}
@@ -446,14 +657,20 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
int ret;
int bits;
RSA *rsa;
+ ENGINE *e = NULL;
debug("%s: Getting verification data\n", __func__);
- ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
+ if (info->engine_id) {
+ ret = rsa_engine_init(info->engine_id, &e);
+ if (ret)
+ return ret;
+ }
+ ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
if (ret)
- return ret;
+ goto err_get_pub_key;
ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
if (ret)
- return ret;
+ goto err_get_params;
bits = BN_num_bits(modulus);
parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
if (parent == -FDT_ERR_NOTFOUND) {
@@ -518,7 +735,12 @@ done:
BN_free(modulus);
BN_free(r_squared);
if (ret)
- return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+ ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+err_get_params:
+ RSA_free(rsa);
+err_get_pub_key:
+ if (info->engine_id)
+ rsa_engine_remove(e);
- return 0;
+ return ret;
}
diff --git a/lib/time.c b/lib/time.c
index f37150f..3c49243 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -154,9 +154,3 @@ void udelay(unsigned long usec)
usec -= kv;
} while(usec);
}
-
-void mdelay(unsigned long msec)
-{
- while (msec--)
- udelay(1000);
-}
diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c
index 30ac759..dfa8432 100644
--- a/lib/tiny-printf.c
+++ b/lib/tiny-printf.c
@@ -38,8 +38,8 @@ static void out_dgt(struct printf_info *info, char dgt)
info->zs = 1;
}
-static void div_out(struct printf_info *info, unsigned int *num,
- unsigned int div)
+static void div_out(struct printf_info *info, unsigned long *num,
+ unsigned long div)
{
unsigned char dgt = 0;
@@ -56,9 +56,9 @@ int _vprintf(struct printf_info *info, const char *fmt, va_list va)
{
char ch;
char *p;
- unsigned int num;
+ unsigned long num;
char buf[12];
- unsigned int div;
+ unsigned long div;
while ((ch = *(fmt++))) {
if (ch != '%') {
@@ -66,8 +66,12 @@ int _vprintf(struct printf_info *info, const char *fmt, va_list va)
} else {
bool lz = false;
int width = 0;
+ bool islong = false;
ch = *(fmt++);
+ if (ch == '-')
+ ch = *(fmt++);
+
if (ch == '0') {
ch = *(fmt++);
lz = 1;
@@ -80,6 +84,11 @@ int _vprintf(struct printf_info *info, const char *fmt, va_list va)
ch = *fmt++;
}
}
+ if (ch == 'l') {
+ ch = *(fmt++);
+ islong = true;
+ }
+
info->bf = buf;
p = info->bf;
info->zs = 0;
@@ -89,24 +98,43 @@ int _vprintf(struct printf_info *info, const char *fmt, va_list va)
goto abort;
case 'u':
case 'd':
- num = va_arg(va, unsigned int);
- if (ch == 'd' && (int)num < 0) {
- num = -(int)num;
- out(info, '-');
+ div = 1000000000;
+ if (islong) {
+ num = va_arg(va, unsigned long);
+ if (sizeof(long) > 4)
+ div *= div * 10;
+ } else {
+ num = va_arg(va, unsigned int);
+ }
+
+ if (ch == 'd') {
+ if (islong && (long)num < 0) {
+ num = -(long)num;
+ out(info, '-');
+ } else if (!islong && (int)num < 0) {
+ num = -(int)num;
+ out(info, '-');
+ }
}
if (!num) {
out_dgt(info, 0);
} else {
- for (div = 1000000000; div; div /= 10)
+ for (; div; div /= 10)
div_out(info, &num, div);
}
break;
case 'x':
- num = va_arg(va, unsigned int);
+ if (islong) {
+ num = va_arg(va, unsigned long);
+ div = 1UL << (sizeof(long) * 8 - 4);
+ } else {
+ num = va_arg(va, unsigned int);
+ div = 0x10000000;
+ }
if (!num) {
out_dgt(info, 0);
} else {
- for (div = 0x10000000; div; div /= 0x10)
+ for (; div; div /= 0x10)
div_out(info, &num, div);
}
break;