summaryrefslogtreecommitdiff
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/lib/host_key.c3
-rw-r--r--host/lib/host_signature.c2
-rw-r--r--host/lib/include/util_misc.h25
-rw-r--r--host/lib/signature_digest.c4
-rw-r--r--host/lib/util_misc.c133
-rw-r--r--host/lib21/host_key.c116
-rw-r--r--host/lib21/host_misc.c69
-rw-r--r--host/lib21/host_signature.c2
-rw-r--r--host/lib21/include/host_key2.h67
-rw-r--r--host/lib21/include/host_misc2.h36
10 files changed, 417 insertions, 40 deletions
diff --git a/host/lib/host_key.c b/host/lib/host_key.c
index c9efa85c..067a188e 100644
--- a/host/lib/host_key.c
+++ b/host/lib/host_key.c
@@ -8,10 +8,7 @@
/* TODO: change all 'return 0', 'return 1' into meaningful return codes */
#define OPENSSL_NO_SHA
-#include <openssl/engine.h>
#include <openssl/pem.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/host/lib/host_signature.c b/host/lib/host_signature.c
index 1ea6bc40..43766cfa 100644
--- a/host/lib/host_signature.c
+++ b/host/lib/host_signature.c
@@ -8,8 +8,6 @@
/* TODO: change all 'return 0', 'return 1' into meaningful return codes */
#define OPENSSL_NO_SHA
-#include <openssl/engine.h>
-#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <stdio.h>
diff --git a/host/lib/include/util_misc.h b/host/lib/include/util_misc.h
index 788929de..0a6ed4c4 100644
--- a/host/lib/include/util_misc.h
+++ b/host/lib/include/util_misc.h
@@ -9,8 +9,33 @@
#define VBOOT_REFERENCE_UTIL_MISC_H_
#include "vboot_struct.h"
+struct rsa_st;
/* Prints the sha1sum of the given VbPublicKey to stdout. */
void PrintPubKeySha1Sum(VbPublicKey* key);
+/*
+ * Our packed RSBPublicKey buffer (historically in files ending with ".keyb",
+ * but also the part of VbPublicKey and struct vb2_packed_key that is
+ * referenced by .key_offset) has this binary format:
+ *
+ * struct {
+ * uint32_t nwords; // size of RSA key in 32-bit words
+ * uint32_t N0inv; // -1 / N[0] mod 2^32
+ * uint32_t modulus[nwords]; // modulus as a little endian array
+ * uint32_t R2[nwords]; // R^2 as little endian array
+ * };
+ *
+ * This function allocates and extracts that binary structure directly
+ * from the RSA private key, rather than from a file.
+ *
+ * @param rsa_private_key RSA private key (duh)
+ * @param keyb_data Pointer to newly allocated binary blob
+ * @param keyb_size Size of newly allocated binary blob
+ *
+ * @return 0 on success, non-zero if unable to allocate enough memory.
+ */
+int vb_keyb_from_rsa(struct rsa_st *rsa_private_key,
+ uint8_t **keyb_data, uint32_t *keyb_size);
+
#endif /* VBOOT_REFERENCE_UTIL_MISC_H_ */
diff --git a/host/lib/signature_digest.c b/host/lib/signature_digest.c
index 81c666ea..c9e721e4 100644
--- a/host/lib/signature_digest.c
+++ b/host/lib/signature_digest.c
@@ -3,11 +3,8 @@
* found in the LICENSE file.
*/
-#include "signature_digest.h"
#define OPENSSL_NO_SHA
-#include <openssl/engine.h>
#include <openssl/pem.h>
-#include <openssl/rsa.h>
#include <stdio.h>
#include <stdlib.h>
@@ -15,6 +12,7 @@
#include "cryptolib.h"
#include "host_common.h"
+#include "signature_digest.h"
uint8_t* PrependDigestInfo(unsigned int algorithm, uint8_t* digest) {
diff --git a/host/lib/util_misc.c b/host/lib/util_misc.c
index 09df8eef..d2c21f52 100644
--- a/host/lib/util_misc.c
+++ b/host/lib/util_misc.c
@@ -5,6 +5,9 @@
* Miscellaneous functions for userspace vboot utilities.
*/
+#define OPENSSL_NO_SHA
+#include <openssl/rsa.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,12 +18,126 @@
#include "util_misc.h"
#include "vboot_common.h"
-void PrintPubKeySha1Sum(VbPublicKey* key) {
- uint8_t* buf = ((uint8_t *)key) + key->key_offset;
- uint64_t buflen = key->key_size;
- uint8_t* digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM);
- int i;
- for (i=0; i<SHA1_DIGEST_SIZE; i++)
- printf("%02x", digest[i]);
- free(digest);
+void PrintPubKeySha1Sum(VbPublicKey *key)
+{
+ uint8_t *buf = ((uint8_t *)key) + key->key_offset;
+ uint64_t buflen = key->key_size;
+ uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM);
+ int i;
+ for (i = 0; i < SHA1_DIGEST_SIZE; i++)
+ printf("%02x", digest[i]);
+ free(digest);
+}
+
+int vb_keyb_from_rsa(struct rsa_st *rsa_private_key,
+ uint8_t **keyb_data, uint32_t *keyb_size)
+{
+ uint32_t i, nwords;
+ BIGNUM *N = NULL;
+ BIGNUM *Big1 = NULL, *Big2 = NULL, *Big32 = NULL, *BigMinus1 = NULL;
+ BIGNUM *B = NULL;
+ BIGNUM *N0inv = NULL, *R = NULL, *RR = NULL;
+ BIGNUM *RRTemp = NULL, *NnumBits = NULL;
+ BIGNUM *n = NULL, *rr = NULL;
+ BN_CTX *bn_ctx = BN_CTX_new();
+ uint32_t n0invout;
+ uint32_t bufsize;
+ uint32_t *outbuf;
+ int retval = 1;
+
+ /* Size of RSA key in 32-bit words */
+ nwords = BN_num_bits(rsa_private_key->n) / 32;
+
+ bufsize = (2 + nwords + nwords) * sizeof(uint32_t);
+ outbuf = malloc(bufsize);
+ if (!outbuf)
+ goto done;
+
+ *keyb_data = (uint8_t *)outbuf;
+ *keyb_size = bufsize;
+
+ *outbuf++ = nwords;
+
+ /* Initialize BIGNUMs */
+#define NEW_BIGNUM(x) do { x = BN_new(); if (!x) goto done; } while (0)
+ NEW_BIGNUM(N);
+ NEW_BIGNUM(Big1);
+ NEW_BIGNUM(Big2);
+ NEW_BIGNUM(Big32);
+ NEW_BIGNUM(BigMinus1);
+ NEW_BIGNUM(N0inv);
+ NEW_BIGNUM(R);
+ NEW_BIGNUM(RR);
+ NEW_BIGNUM(RRTemp);
+ NEW_BIGNUM(NnumBits);
+ NEW_BIGNUM(n);
+ NEW_BIGNUM(rr);
+ NEW_BIGNUM(B);
+#undef NEW_BIGNUM
+
+ BN_copy(N, rsa_private_key->n);
+ BN_set_word(Big1, 1L);
+ BN_set_word(Big2, 2L);
+ BN_set_word(Big32, 32L);
+ BN_sub(BigMinus1, Big1, Big2);
+
+ BN_exp(B, Big2, Big32, bn_ctx); /* B = 2^32 */
+
+ /* Calculate and output N0inv = -1 / N[0] mod 2^32 */
+ BN_mod_inverse(N0inv, N, B, bn_ctx);
+ BN_sub(N0inv, B, N0inv);
+ n0invout = BN_get_word(N0inv);
+
+ *outbuf++ = n0invout;
+
+ /* Calculate R = 2^(# of key bits) */
+ BN_set_word(NnumBits, BN_num_bits(N));
+ BN_exp(R, Big2, NnumBits, bn_ctx);
+
+ /* Calculate RR = R^2 mod N */
+ BN_copy(RR, R);
+ BN_mul(RRTemp, RR, R, bn_ctx);
+ BN_mod(RR, RRTemp, N, bn_ctx);
+
+
+ /* Write out modulus as little endian array of integers. */
+ for (i = 0; i < nwords; ++i) {
+ uint32_t nout;
+
+ BN_mod(n, N, B, bn_ctx); /* n = N mod B */
+ nout = BN_get_word(n);
+ *outbuf++ = nout;
+
+ BN_rshift(N, N, 32); /* N = N/B */
+ }
+
+ /* Write R^2 as little endian array of integers. */
+ for (i = 0; i < nwords; ++i) {
+ uint32_t rrout;
+
+ BN_mod(rr, RR, B, bn_ctx); /* rr = RR mod B */
+ rrout = BN_get_word(rr);
+ *outbuf++ = rrout;
+
+ BN_rshift(RR, RR, 32); /* RR = RR/B */
+ }
+
+ outbuf = NULL;
+ retval = 0;
+
+done:
+ free(outbuf);
+ /* Free BIGNUMs. */
+ BN_free(Big1);
+ BN_free(Big2);
+ BN_free(Big32);
+ BN_free(BigMinus1);
+ BN_free(N0inv);
+ BN_free(R);
+ BN_free(RRTemp);
+ BN_free(NnumBits);
+ BN_free(n);
+ BN_free(rr);
+
+ return retval;
}
diff --git a/host/lib21/host_key.c b/host/lib21/host_key.c
index 5123b85d..4acba9cb 100644
--- a/host/lib21/host_key.c
+++ b/host/lib21/host_key.c
@@ -5,11 +5,10 @@
* Host functions for keys.
*/
+#include <stdio.h>
+
#define OPENSSL_NO_SHA
-#include <openssl/engine.h>
#include <openssl/pem.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
#include "2sysincludes.h"
#include "2common.h"
@@ -20,6 +19,57 @@
#include "host_key2.h"
#include "host_misc.h"
+struct vb2_text_vs_enum vb2_text_vs_algorithm[] = {
+ {"RSA1024 SHA1", VB2_ALG_RSA1024_SHA1},
+ {"RSA1024 SHA256", VB2_ALG_RSA1024_SHA256},
+ {"RSA1024 SHA512", VB2_ALG_RSA1024_SHA512},
+ {"RSA2048 SHA1", VB2_ALG_RSA2048_SHA1},
+ {"RSA2048 SHA256", VB2_ALG_RSA2048_SHA256},
+ {"RSA2048 SHA512", VB2_ALG_RSA2048_SHA512},
+ {"RSA4096 SHA1", VB2_ALG_RSA4096_SHA1},
+ {"RSA4096 SHA256", VB2_ALG_RSA4096_SHA256},
+ {"RSA4096 SHA512", VB2_ALG_RSA4096_SHA512},
+ {"RSA8192 SHA1", VB2_ALG_RSA8192_SHA1},
+ {"RSA8192 SHA256", VB2_ALG_RSA8192_SHA256},
+ {"RSA8192 SHA512", VB2_ALG_RSA8192_SHA512},
+ {0, 0}
+};
+
+struct vb2_text_vs_enum vb2_text_vs_sig[] = {
+ {"RSA1024", VB2_SIG_RSA1024},
+ {"RSA2048", VB2_SIG_RSA2048},
+ {"RSA4096", VB2_SIG_RSA4096},
+ {"RSA8192", VB2_SIG_RSA8192},
+ {0, 0}
+};
+
+struct vb2_text_vs_enum vb2_text_vs_hash[] = {
+ {"SHA1", VB2_HASH_SHA1},
+ {"SHA256", VB2_HASH_SHA256},
+ {"SHA512", VB2_HASH_SHA512},
+ {0, 0}
+};
+
+const struct vb2_text_vs_enum *vb2_lookup_by_num(
+ const struct vb2_text_vs_enum *table,
+ const unsigned int num)
+{
+ for (; table->name; table++)
+ if (table->num == num)
+ return table;
+ return 0;
+}
+
+const struct vb2_text_vs_enum *vb2_lookup_by_name(
+ const struct vb2_text_vs_enum *table,
+ const char *name)
+{
+ for (; table->name; table++)
+ if (!strcasecmp(table->name, name))
+ return table;
+ return 0;
+}
+
void vb2_private_key_free(struct vb2_private_key *key)
{
if (!key)
@@ -284,19 +334,8 @@ int vb2_private_key_hash(const struct vb2_private_key **key_ptr,
}
}
-/**
- * Allocate a public key buffer of sufficient size for the signature algorithm.
- *
- * This only initializes the sig_alg field and the guid field to an empty
- * guid. It does not set any of the other fields in *key_ptr.
- *
- * @param key_ptr Destination for newly allocated key; this must be
- * freed with vb2_public_key_free().
- * @param sig_alg Signature algorithm for key.
- * @return VB2_SUCCESS, or non-zero error code if error.
- */
-static int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
- enum vb2_signature_algorithm sig_alg)
+int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
+ enum vb2_signature_algorithm sig_alg)
{
struct vb2_public_key *key;
uint32_t key_data_size = vb2_packed_key_size(sig_alg);
@@ -322,18 +361,16 @@ static int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
void vb2_public_key_free(struct vb2_public_key *key)
{
+ if (!key)
+ return;
+
if (key->desc)
free((void *)key->desc);
free(key);
}
-/**
- * Return the packed data for a key allocated with vb2_public_key_alloc().
- *
- * The packed data is in the same buffer, following the key struct and GUID.
- */
-static uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key)
+uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key)
{
return (uint8_t *)(key->guid + 1);
}
@@ -505,3 +542,38 @@ int vb2_public_key_hash(struct vb2_public_key *key,
key->guid = vb2_hash_guid(hash_alg);
return VB2_SUCCESS;
}
+
+enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa)
+{
+ int bits = BN_num_bits(rsa->n);
+
+ switch (bits) {
+ case 1024:
+ return VB2_SIG_RSA1024;
+ case 2048:
+ return VB2_SIG_RSA2048;
+ case 4096:
+ return VB2_SIG_RSA4096;
+ case 8192:
+ return VB2_SIG_RSA8192;
+ }
+
+ /* no clue */
+ return VB2_SIG_INVALID;
+}
+
+int vb2_public_key_write(const struct vb2_public_key *key,
+ const char *filename)
+{
+ struct vb2_packed_key *pkey;
+ int ret;
+
+ ret = vb2_public_key_pack(&pkey, key);
+ if (ret)
+ return ret;
+
+ ret = vb2_write_object(filename, pkey);
+
+ free(pkey);
+ return ret;
+}
diff --git a/host/lib21/host_misc.c b/host/lib21/host_misc.c
index 555867a2..c55996eb 100644
--- a/host/lib21/host_misc.c
+++ b/host/lib21/host_misc.c
@@ -13,6 +13,7 @@
#include "2sha.h"
#include "vb2_common.h"
#include "host_common.h"
+#include "host_misc2.h"
int vb2_read_file(const char *filename, uint8_t **data_ptr, uint32_t *size_ptr)
{
@@ -93,3 +94,71 @@ uint32_t vb2_desc_size(const char *desc)
return roundup32(strlen(desc) + 1);
}
+int vb2_str_to_guid(const char *str, struct vb2_guid *guid)
+{
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_high_and_version;
+ unsigned int chunk[11];
+
+ if (!str ||
+ 11 != sscanf(str,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ chunk+0,
+ chunk+1,
+ chunk+2,
+ chunk+3,
+ chunk+4,
+ chunk+5,
+ chunk+6,
+ chunk+7,
+ chunk+8,
+ chunk+9,
+ chunk+10)) {
+ return VB2_ERROR_STR_TO_GUID;
+ }
+
+ time_low = chunk[0] & 0xffffffff;
+ time_mid = chunk[1] & 0xffff;
+ time_high_and_version = chunk[2] & 0xffff;
+
+ guid->uuid.time_low = htole32(time_low);
+ guid->uuid.time_mid = htole16(time_mid);
+ guid->uuid.time_high_and_version = htole16(time_high_and_version);
+
+ guid->uuid.clock_seq_high_and_reserved = chunk[3] & 0xff;
+ guid->uuid.clock_seq_low = chunk[4] & 0xff;
+ guid->uuid.node[0] = chunk[5] & 0xff;
+ guid->uuid.node[1] = chunk[6] & 0xff;
+ guid->uuid.node[2] = chunk[7] & 0xff;
+ guid->uuid.node[3] = chunk[8] & 0xff;
+ guid->uuid.node[4] = chunk[9] & 0xff;
+ guid->uuid.node[5] = chunk[10] & 0xff;
+
+ return VB2_SUCCESS;
+}
+
+int vb2_guid_to_str(const struct vb2_guid *guid,
+ char *buf, unsigned int buflen)
+{
+ int n;
+
+ if (!buf || buflen < VB2_GUID_MIN_STRLEN)
+ return VB2_ERROR_GUID_TO_STR;
+
+ n = snprintf(buf, buflen,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ le32toh(guid->uuid.time_low),
+ le16toh(guid->uuid.time_mid),
+ le16toh(guid->uuid.time_high_and_version),
+ guid->uuid.clock_seq_high_and_reserved,
+ guid->uuid.clock_seq_low,
+ guid->uuid.node[0], guid->uuid.node[1],
+ guid->uuid.node[2], guid->uuid.node[3],
+ guid->uuid.node[4], guid->uuid.node[5]);
+
+ if (n != VB2_GUID_MIN_STRLEN - 1)
+ return VB2_ERROR_GUID_TO_STR;
+
+ return VB2_SUCCESS;
+}
diff --git a/host/lib21/host_signature.c b/host/lib21/host_signature.c
index 553aa386..11785c71 100644
--- a/host/lib21/host_signature.c
+++ b/host/lib21/host_signature.c
@@ -6,8 +6,6 @@
*/
#define OPENSSL_NO_SHA
-#include <openssl/engine.h>
-#include <openssl/pem.h>
#include <openssl/rsa.h>
#include "2sysincludes.h"
diff --git a/host/lib21/include/host_key2.h b/host/lib21/include/host_key2.h
index 7c48dcaf..b219ae63 100644
--- a/host/lib21/include/host_key2.h
+++ b/host/lib21/include/host_key2.h
@@ -21,6 +21,34 @@ struct vb2_private_key {
struct vb2_guid guid; /* Key GUID */
};
+/* Convert between enums and human-readable form. Terminated with {0, 0}. */
+struct vb2_text_vs_enum {
+ const char *name;
+ unsigned int num;
+};
+
+/**
+ * @param table Table to search
+ * @param num Enum value to search for
+ * @return pointer to table entry or NULL if no match
+ */
+const struct vb2_text_vs_enum *vb2_lookup_by_num(
+ const struct vb2_text_vs_enum *table,
+ const unsigned int num);
+
+/**
+ * @param table Table to search
+ * @param name String value to search for
+ * @return pointer to table entry or NULL if no match
+ */
+const struct vb2_text_vs_enum *vb2_lookup_by_name(
+ const struct vb2_text_vs_enum *table,
+ const char *name);
+
+extern struct vb2_text_vs_enum vb2_text_vs_algorithm[];
+extern struct vb2_text_vs_enum vb2_text_vs_sig[];
+extern struct vb2_text_vs_enum vb2_text_vs_hash[];
+
/**
* Free a private key.
*
@@ -97,6 +125,27 @@ int vb2_private_key_hash(const struct vb2_private_key **key_ptr,
enum vb2_hash_algorithm hash_alg);
/**
+ * Allocate a public key buffer of sufficient size for the signature algorithm.
+ *
+ * This only initializes the sig_alg field and the guid field to an empty
+ * guid. It does not set any of the other fields in *key_ptr.
+ *
+ * @param key_ptr Destination for newly allocated key; this must be
+ * freed with vb2_public_key_free().
+ * @param sig_alg Signature algorithm for key.
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_public_key_alloc(struct vb2_public_key **key_ptr,
+ enum vb2_signature_algorithm sig_alg);
+
+/**
+ * Return the packed data for a key allocated with vb2_public_key_alloc().
+ *
+ * The packed data is in the same buffer, following the key struct and GUID.
+ */
+uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key);
+
+/**
* Free a public key allocated by one of the functions below.
*
* Note that this should ONLY be called for public keys allocated via one
@@ -165,4 +214,22 @@ int vb2_public_key_hash(struct vb2_public_key *key,
enum vb2_hash_algorithm hash_alg);
+/**
+ * Return the signature algorithm implied by the bit length of an RSA key
+ *
+ * @param rsa RSA key
+ * @return vb2 signature algorithm
+ */
+enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa);
+
+/**
+ * Write a public key to the vb2_packed_key format.
+ *
+ * @param key Key to write
+ * @param filename File to write key data to.
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_public_key_write(const struct vb2_public_key *key,
+ const char *filename);
+
#endif /* VBOOT_REFERENCE_HOST_KEY2_H_ */
diff --git a/host/lib21/include/host_misc2.h b/host/lib21/include/host_misc2.h
new file mode 100644
index 00000000..5d1679be
--- /dev/null
+++ b/host/lib21/include/host_misc2.h
@@ -0,0 +1,36 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef VBOOT_REFERENCE_HOST_MISC2_H_
+#define VBOOT_REFERENCE_HOST_MISC2_H_
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "2guid.h"
+
+/* Length of string representation, including trailing '\0' */
+#define VB2_GUID_MIN_STRLEN 37
+
+/**
+ * Convert string to struct vb2_guid.
+ *
+ * @param str Example: "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+ * @param guid Destination for binary representation
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_str_to_guid(const char *str, struct vb2_guid *guid);
+
+/**
+ * Convert struct vb2_guid to string.
+ *
+ * @param guid Binary representation
+ * @param str Buffer for result "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_guid_to_str(const struct vb2_guid *guid,
+ char *buf, unsigned int buflen);
+
+#endif /* VBOOT_REFERENCE_HOST_MISC2_H_ */