diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/host_key.c | 3 | ||||
-rw-r--r-- | host/lib/host_signature.c | 2 | ||||
-rw-r--r-- | host/lib/include/util_misc.h | 25 | ||||
-rw-r--r-- | host/lib/signature_digest.c | 4 | ||||
-rw-r--r-- | host/lib/util_misc.c | 133 | ||||
-rw-r--r-- | host/lib21/host_key.c | 116 | ||||
-rw-r--r-- | host/lib21/host_misc.c | 69 | ||||
-rw-r--r-- | host/lib21/host_signature.c | 2 | ||||
-rw-r--r-- | host/lib21/include/host_key2.h | 67 | ||||
-rw-r--r-- | host/lib21/include/host_misc2.h | 36 |
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_ */ |