diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/.gitignore | 2 | ||||
-rw-r--r-- | lib/libfdt/fdt_overlay.c | 7 | ||||
-rw-r--r-- | lib/net_utils.c | 8 | ||||
-rw-r--r-- | lib/rsa/rsa-sign.c | 244 | ||||
-rw-r--r-- | lib/time.c | 6 | ||||
-rw-r--r-- | lib/tiny-printf.c | 50 |
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; } @@ -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; |