diff options
-rw-r--r-- | firmware/2lib/include/2guid.h | 31 | ||||
-rw-r--r-- | firmware/lib21/common.c | 2 | ||||
-rw-r--r-- | firmware/lib21/include/vb2_struct.h | 6 | ||||
-rw-r--r-- | futility/cmd_create.c | 33 | ||||
-rw-r--r-- | futility/vb2_helper.c | 77 | ||||
-rw-r--r-- | host/lib21/host_misc.c | 105 | ||||
-rw-r--r-- | host/lib21/include/host_misc2.h | 2 |
7 files changed, 122 insertions, 134 deletions
diff --git a/firmware/2lib/include/2guid.h b/firmware/2lib/include/2guid.h index 3e892d9c..a8fd346b 100644 --- a/firmware/2lib/include/2guid.h +++ b/firmware/2lib/include/2guid.h @@ -9,34 +9,17 @@ #define VBOOT_REFERENCE_VBOOT_2GUID_H_ #include <stdint.h> -#define UUID_NODE_LEN 6 -#define GUID_SIZE 16 +#define NUM_GUID_BYTES 20 struct vb2_guid { - union { - struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_high_and_version; - uint8_t clock_seq_high_and_reserved; - uint8_t clock_seq_low; - uint8_t node[UUID_NODE_LEN]; - } uuid; - uint8_t raw[GUID_SIZE]; - }; + uint8_t raw[NUM_GUID_BYTES]; } __attribute__((packed)); -#define EXPECTED_GUID_SIZE GUID_SIZE +#define EXPECTED_GUID_SIZE NUM_GUID_BYTES -/* Key GUIDs to use for VB2_SIG_NONE and hash algorithms */ - -#define VB2_GUID_NONE_SHA1 \ - {{{0xcfb5687a,0x6092,0x11e4,0x96,0xe1,{0x8f,0x3b,0x1a,0x60,0xa2,0x1d}}}} - -#define VB2_GUID_NONE_SHA256 \ - {{{0x0e4114e0,0x6093,0x11e4,0x9d,0xcb,{0x8f,0x8a,0xf4,0xca,0x2e,0x32}}}} - -#define VB2_GUID_NONE_SHA512 \ - {{{0x1c695960,0x6093,0x11e4,0x82,0x63,{0xdb,0xee,0xe9,0x3c,0xcd,0x7e}}}} +/* GUIDs to use for "keys" with sig_alg==VB2_SIG_NONE */ +#define VB2_GUID_NONE_SHA1 {{0x00, 0x01,} } +#define VB2_GUID_NONE_SHA256 {{0x02, 0x56,} } +#define VB2_GUID_NONE_SHA512 {{0x05, 0x12,} } #endif /* VBOOT_REFERENCE_VBOOT_2GUID_H_ */ diff --git a/firmware/lib21/common.c b/firmware/lib21/common.c index 5adbf7ae..7a06c8c3 100644 --- a/firmware/lib21/common.c +++ b/firmware/lib21/common.c @@ -359,7 +359,7 @@ int vb2_verify_keyblock(struct vb2_keyblock *block, return rv; /* Skip signature if it doesn't match the key GUID */ - if (memcmp(&sig->guid, key->guid, GUID_SIZE)) + if (memcmp(&sig->guid, key->guid, NUM_GUID_BYTES)) continue; /* Make sure we signed the right amount of data */ diff --git a/firmware/lib21/include/vb2_struct.h b/firmware/lib21/include/vb2_struct.h index 62e1a080..5bccfab7 100644 --- a/firmware/lib21/include/vb2_struct.h +++ b/firmware/lib21/include/vb2_struct.h @@ -142,7 +142,7 @@ struct vb2_packed_key { } __attribute__((packed)); #define EXPECTED_VB2_PACKED_KEY_SIZE \ - (EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 16) + (EXPECTED_VB2_STRUCT_COMMON_SIZE + 16 + EXPECTED_GUID_SIZE) /* Current version of vb2_packed_private_key struct */ #define VB2_PACKED_PRIVATE_KEY_VERSION_MAJOR 3 @@ -181,7 +181,7 @@ struct vb2_packed_private_key { } __attribute__((packed)); #define EXPECTED_VB2_PACKED_PRIVATE_KEY_SIZE \ - (EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 12) + (EXPECTED_VB2_STRUCT_COMMON_SIZE + 12 + EXPECTED_GUID_SIZE) /* Current version of vb2_signature struct */ #define VB2_SIGNATURE_VERSION_MAJOR 3 @@ -229,7 +229,7 @@ struct vb2_signature { } __attribute__((packed)); #define EXPECTED_VB2_SIGNATURE_SIZE \ - (EXPECTED_VB2_STRUCT_COMMON_SIZE + EXPECTED_GUID_SIZE + 16) + (EXPECTED_VB2_STRUCT_COMMON_SIZE + 16 + EXPECTED_GUID_SIZE) /* Current version of vb2_keyblock struct */ diff --git a/futility/cmd_create.c b/futility/cmd_create.c index f4eb3f2a..32eed50a 100644 --- a/futility/cmd_create.c +++ b/futility/cmd_create.c @@ -41,6 +41,7 @@ static uint32_t opt_version = DEFAULT_VERSION; enum vb2_hash_algorithm opt_hash_alg = DEFAULT_HASH; static char *opt_desc; static struct vb2_guid opt_guid; +static int force_guid; static const struct option long_opts[] = { {"version", 1, 0, OPT_VERSION}, @@ -196,23 +197,15 @@ static int vb2_make_keypair() fprintf(stderr, "Unable to allocate the private key\n"); goto done; } + privkey->rsa_private_key = rsa_key; privkey->sig_alg = sig_alg; privkey->hash_alg = opt_hash_alg; - privkey->guid = opt_guid; if (opt_desc && vb2_private_key_set_desc(privkey, opt_desc)) { fprintf(stderr, "Unable to set the private key description\n"); goto done; } - /* Write it out */ - strcpy(outext, ".vbprik2"); - if (vb2_private_key_write(privkey, outfile)) { - fprintf(stderr, "unable to write private key\n"); - goto done; - } - fprintf(stderr, "wrote %s\n", outfile); - /* Create the public key */ if (vb2_public_key_alloc(&pubkey, sig_alg)) { fprintf(stderr, "Unable to allocate the public key\n"); @@ -240,13 +233,30 @@ static int vb2_make_keypair() pubkey->hash_alg = opt_hash_alg; pubkey->version = opt_version; - memcpy((struct vb2_guid *)pubkey->guid, &opt_guid, sizeof(opt_guid)); if (opt_desc && vb2_public_key_set_desc(pubkey, opt_desc)) { fprintf(stderr, "Unable to set pubkey description\n"); goto done; } - /* Write it out */ + /* Update the IDs */ + if (!force_guid) { + uint8_t *digest = DigestBuf(keyb_data, keyb_size, + SHA1_DIGEST_ALGORITHM); + memcpy(&opt_guid, digest, sizeof(opt_guid)); + free(digest); + } + + privkey->guid = opt_guid; + memcpy((struct vb2_guid *)pubkey->guid, &opt_guid, sizeof(opt_guid)); + + /* Write them out */ + strcpy(outext, ".vbprik2"); + if (vb2_private_key_write(privkey, outfile)) { + fprintf(stderr, "unable to write private key\n"); + goto done; + } + fprintf(stderr, "wrote %s\n", outfile); + strcpy(outext, ".vbpubk2"); if (vb2_public_key_write(pubkey, outfile)) { fprintf(stderr, "unable to write public key\n"); @@ -296,6 +306,7 @@ static int do_create(int argc, char *argv[]) optarg); errorcnt = 1; } + force_guid = 1; break; case OPT_HASH_ALG: diff --git a/futility/vb2_helper.c b/futility/vb2_helper.c index 68287ce1..b3349af2 100644 --- a/futility/vb2_helper.c +++ b/futility/vb2_helper.c @@ -41,31 +41,34 @@ enum futil_file_type recognize_vb2_key(uint8_t *buf, uint32_t len) return FILE_TYPE_UNKNOWN; } -static void vb2_print_public_key_sha1sum(struct vb2_public_key *key) +static inline void vb2_print_bytes(const void *ptr, uint32_t len) +{ + const uint8_t *buf = (const uint8_t *)ptr; + int i; + for (i = 0; i < len; i++) + printf("%02x", *buf++); +} + +static uint8_t *vb2_public_key_sha1sum(struct vb2_public_key *key) { struct vb2_packed_key *pkey; uint8_t *digest; - int i; - if (vb2_public_key_pack(&pkey, key)) { - printf("<error>"); - return; - } + if (vb2_public_key_pack(&pkey, key)) + return 0; digest = DigestBuf((uint8_t *)pkey + pkey->key_offset, pkey->key_size, SHA1_DIGEST_ALGORITHM); - for (i = 0; i < SHA1_DIGEST_SIZE; i++) - printf("%02x", digest[i]); - - free(digest); free(pkey); + + return digest; } int futil_cb_show_vb2_pubkey(struct futil_traverse_state_s *state) { struct vb2_public_key key; - char guid_str[VB2_GUID_MIN_STRLEN]; const struct vb2_text_vs_enum *entry; + uint8_t *sha1sum; /* The key's members will point into the state buffer after this. Don't * free anything. */ @@ -73,9 +76,7 @@ int futil_cb_show_vb2_pubkey(struct futil_traverse_state_s *state) state->my_area->len)) return 1; - if (VB2_SUCCESS != vb2_guid_to_str(key.guid, guid_str, - sizeof(guid_str))) - return 1; + sha1sum = vb2_public_key_sha1sum(&key); printf("Public Key file: %s\n", state->in_filename); printf(" Vboot API: 2.1\n"); @@ -86,50 +87,44 @@ int futil_cb_show_vb2_pubkey(struct futil_traverse_state_s *state) entry = vb2_lookup_by_num(vb2_text_vs_hash, key.hash_alg); printf(" Hash Algorithm: %d %s\n", key.hash_alg, entry ? entry->name : "(invalid)"); - printf(" GUID: %s\n", guid_str); printf(" Version: 0x%08x\n", key.version); - printf(" Key sha1sum: "); - vb2_print_public_key_sha1sum(&key); + printf(" GUID: "); + vb2_print_bytes(key.guid, sizeof(*key.guid)); printf("\n"); - + if (sha1sum && memcmp(key.guid, sha1sum, sizeof(*key.guid))) { + printf(" Key sha1sum: "); + vb2_print_bytes(sha1sum, SHA1_DIGEST_SIZE); + printf("\n"); + } + free(sha1sum); return 0; } -static void vb2_print_private_key_sha1sum(struct vb2_private_key *key) +static uint8_t *vb2_private_key_sha1sum(struct vb2_private_key *key) { uint8_t *buf, *digest; uint32_t buflen; - int i; - if (vb_keyb_from_rsa(key->rsa_private_key, &buf, &buflen)) { - printf("<error>"); - return; - } + if (vb_keyb_from_rsa(key->rsa_private_key, &buf, &buflen)) + return 0; digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); - for (i = 0; i < SHA1_DIGEST_SIZE; i++) - printf("%02x", digest[i]); - - free(digest); free(buf); + + return digest; } int futil_cb_show_vb2_privkey(struct futil_traverse_state_s *state) { struct vb2_private_key *key = 0; - char guid_str[VB2_GUID_MIN_STRLEN]; const struct vb2_text_vs_enum *entry; + uint8_t *sha1sum; if (VB2_SUCCESS != vb2_private_key_unpack(&key, state->my_area->buf, state->my_area->len)) return 1; - if (VB2_SUCCESS != vb2_guid_to_str(&key->guid, guid_str, - sizeof(guid_str))) { - vb2_private_key_free(key); - return 1; - } - + sha1sum = vb2_private_key_sha1sum(key); printf("Private key file: %s\n", state->in_filename); printf(" Vboot API: 2.1\n"); @@ -140,11 +135,15 @@ int futil_cb_show_vb2_privkey(struct futil_traverse_state_s *state) entry = vb2_lookup_by_num(vb2_text_vs_hash, key->hash_alg); printf(" Hash Algorithm: %d %s\n", key->hash_alg, entry ? entry->name : "(invalid)"); - printf(" GUID: %s\n", guid_str); - printf(" Key sha1sum: "); - vb2_print_private_key_sha1sum(key); + printf(" GUID: "); + vb2_print_bytes(&key->guid, sizeof(key->guid)); printf("\n"); - + if (sha1sum && memcmp(&key->guid, sha1sum, sizeof(key->guid))) { + printf(" Key sha1sum: "); + vb2_print_bytes(sha1sum, SHA1_DIGEST_SIZE); + printf("\n"); + } + free(sha1sum); vb2_private_key_free(key); return 0; } diff --git a/host/lib21/host_misc.c b/host/lib21/host_misc.c index c55996eb..5e8a7cb5 100644 --- a/host/lib21/host_misc.c +++ b/host/lib21/host_misc.c @@ -5,7 +5,9 @@ * Host functions for verified boot. */ +#include <ctype.h> #include <stdio.h> +#include <string.h> #include <unistd.h> #include "2sysincludes.h" @@ -94,71 +96,64 @@ 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) +static const char *onedigit(const char *str, uint8_t *vptr) { - 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; - } + uint8_t val = 0; + char c; - time_low = chunk[0] & 0xffffffff; - time_mid = chunk[1] & 0xffff; - time_high_and_version = chunk[2] & 0xffff; + for (; (c = *str++) && !isxdigit(c);) + ; + if (!c) + return 0; - 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); + if (c >= '0' && c <= '9') + val = c - '0'; + else if (c >= 'A' && c <= 'F') + val = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + val = 10 + c - 'a'; - 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; + *vptr = val; + return str; +} - return VB2_SUCCESS; +static const char *onebyte(const char *str, uint8_t *vptr) +{ + uint8_t val; + uint8_t digit; + + str = onedigit(str, &digit); + if (!str) + return 0; + val = digit << 4; + + str = onedigit(str, &digit); + if (!str) + return 0; + val |= digit; + + *vptr = val; + return str; } -int vb2_guid_to_str(const struct vb2_guid *guid, - char *buf, unsigned int buflen) +int vb2_str_to_guid(const char *str, struct vb2_guid *guid) { - int n; + uint8_t val; + int i; - if (!buf || buflen < VB2_GUID_MIN_STRLEN) - return VB2_ERROR_GUID_TO_STR; + if (!str) + return VB2_ERROR_STR_TO_GUID; - 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]); + memset(guid, 0, sizeof(*guid)); - if (n != VB2_GUID_MIN_STRLEN - 1) - return VB2_ERROR_GUID_TO_STR; + for (i = 0; i < NUM_GUID_BYTES; i++) { - return VB2_SUCCESS; + str = onebyte(str, &val); + if (!str) + break; + guid->raw[i] = val; + } + + /* If we get at least one valid byte, that's good enough. */ + return i ? VB2_SUCCESS : VB2_ERROR_STR_TO_GUID; } diff --git a/host/lib21/include/host_misc2.h b/host/lib21/include/host_misc2.h index 5d1679be..86ec13f0 100644 --- a/host/lib21/include/host_misc2.h +++ b/host/lib21/include/host_misc2.h @@ -12,7 +12,7 @@ #include "2guid.h" /* Length of string representation, including trailing '\0' */ -#define VB2_GUID_MIN_STRLEN 37 +#define VB2_GUID_MIN_STRLEN (2 * NUM_GUID_BYTES + 1) /** * Convert string to struct vb2_guid. |