diff options
author | Randall Spangler <rspangler@chromium.org> | 2014-11-20 11:27:38 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-11-27 06:35:01 +0000 |
commit | fb9a216dd677d97f3d6963f668a9b84d349ef339 (patch) | |
tree | c4e10b1c96927f4a64c6f5a53844b80fc23baf5f | |
parent | 59c29202d2d67b97f587152b5457ed89f7430a77 (diff) | |
download | vboot-fb9a216dd677d97f3d6963f668a9b84d349ef339.tar.gz |
vboot2: Add host lib support for bare hash keys
And use them in the other vboot2 unit tests.
BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests
Change-Id: I0c3590649a0acf792e41e295ca4279ccba17a41f
Reviewed-on: https://chromium-review.googlesource.com/231345
Tested-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | firmware/2lib/2packed_key2.c | 22 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 9 | ||||
-rw-r--r-- | host/lib/host_key2.c | 148 | ||||
-rw-r--r-- | host/lib/host_misc2.c | 1 | ||||
-rw-r--r-- | host/lib/include/host_key2.h | 22 | ||||
-rw-r--r-- | tests/vb2_common_tests.c | 40 | ||||
-rw-r--r-- | tests/vb2_host_key_tests.c | 57 |
8 files changed, 238 insertions, 62 deletions
@@ -988,6 +988,7 @@ ${BUILD}/utility/pad_digest_utility: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/signature_digest_utility: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS} +${BUILD}/tests/vb2_common_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_common3_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_host_key_tests: LDLIBS += ${CRYPTO_LIBS} diff --git a/firmware/2lib/2packed_key2.c b/firmware/2lib/2packed_key2.c index 91000dfb..a67664bb 100644 --- a/firmware/2lib/2packed_key2.c +++ b/firmware/2lib/2packed_key2.c @@ -81,20 +81,22 @@ int vb2_unpack_key2(struct vb2_public_key *key, return VB2_ERROR_UNPACK_KEY_STRUCT_VERSION; /* Copy key algorithms */ - key->sig_alg = pkey->sig_alg; - sig_size = vb2_rsa_sig_size(key->sig_alg); - if (!sig_size) - return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; - key->hash_alg = pkey->hash_alg; if (!vb2_digest_size(key->hash_alg)) return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; - rv = vb2_unpack_key2_data(key, - (const uint8_t *)pkey + pkey->key_offset, - pkey->key_size); - if (rv) - return rv; + key->sig_alg = pkey->sig_alg; + if (key->sig_alg != VB2_SIG_NONE) { + sig_size = vb2_rsa_sig_size(key->sig_alg); + if (!sig_size) + return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; + rv = vb2_unpack_key2_data( + key, + (const uint8_t *)pkey + pkey->key_offset, + pkey->key_size); + if (rv) + return rv; + } /* Key description */ if (pkey->c.desc_size) diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index deae9140..f12f2c12 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -510,6 +510,9 @@ enum vb2_return_code { /* Unable to set description in vb2_private_key_unpack() */ VB2_ERROR_UNPACK_PRIVATE_KEY_DESC, + /* Bad bare hash key in vb2_private_key_unpack() */ + VB2_ERROR_UNPACK_PRIVATE_KEY_HASH, + /* Unable to create RSA data in vb2_private_key_write() */ VB2_ERROR_PRIVATE_KEY_WRITE_RSA, @@ -519,6 +522,9 @@ enum vb2_return_code { /* Unable to write file in vb2_private_key_write() */ VB2_ERROR_PRIVATE_KEY_WRITE_FILE, + /* Bad algorithm in vb2_private_key_hash() */ + VB2_ERROR_PRIVATE_KEY_HASH, + /* Unable to determine key size in vb2_public_key_alloc() */ VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE, @@ -549,6 +555,9 @@ enum vb2_return_code { /* Unable to determine key size in vb2_public_key_pack() */ VB2_ERROR_PUBLIC_KEY_PACK_SIZE, + /* Bad hash algorithm in vb2_publc_key_hash() */ + VB2_ERROR_PUBLIC_KEY_HASH, + /********************************************************************** * Highest non-zero error generated inside vboot library. Note that * error codes passed through vboot when it calls external APIs may diff --git a/host/lib/host_key2.c b/host/lib/host_key2.c index eb252ef1..8f761f65 100644 --- a/host/lib/host_key2.c +++ b/host/lib/host_key2.c @@ -14,6 +14,7 @@ #include "2sysincludes.h" #include "2common.h" #include "2rsa.h" +#include "2sha.h" #include "host_common.h" #include "host_key2.h" #include "host_misc.h" @@ -82,11 +83,19 @@ int vb2_private_key_unpack(struct vb2_private_key **key_ptr, key->guid = pkey->guid; /* Unpack RSA key */ - start = (const unsigned char *)(buf + pkey->key_offset); - key->rsa_private_key = d2i_RSAPrivateKey(0, &start, pkey->key_size); - if (!key->rsa_private_key) { - free(key); - return VB2_ERROR_UNPACK_PRIVATE_KEY_RSA; + if (pkey->sig_alg == VB2_SIG_NONE) { + if (pkey->key_size != 0) { + free(key); + return VB2_ERROR_UNPACK_PRIVATE_KEY_HASH; + } + } else { + start = (const unsigned char *)(buf + pkey->key_offset); + key->rsa_private_key = d2i_RSAPrivateKey(0, &start, + pkey->key_size); + if (!key->rsa_private_key) { + free(key); + return VB2_ERROR_UNPACK_PRIVATE_KEY_RSA; + } } /* Key description */ @@ -184,7 +193,7 @@ int vb2_private_key_write(const struct vb2_private_key *key, }; uint8_t *buf; uint8_t *rsabuf = NULL; - int rsalen; + int rsalen = 0; int rv; memcpy(&pkey.guid, &key->guid, sizeof(pkey.guid)); @@ -192,10 +201,12 @@ int vb2_private_key_write(const struct vb2_private_key *key, if (key->desc) pkey.c.desc_size = roundup32(strlen(key->desc) + 1); - /* Pack RSA key */ - rsalen = i2d_RSAPrivateKey(key->rsa_private_key, &rsabuf); - if (rsalen <= 0) - return VB2_ERROR_PRIVATE_KEY_WRITE_RSA; + if (key->sig_alg != VB2_SIG_NONE) { + /* Pack RSA key */ + rsalen = i2d_RSAPrivateKey(key->rsa_private_key, &rsabuf); + if (rsalen <= 0 || !rsabuf) + return VB2_ERROR_PRIVATE_KEY_WRITE_RSA; + } pkey.key_offset = pkey.c.fixed_size + pkey.c.desc_size; pkey.key_size = roundup32(rsalen); @@ -215,8 +226,10 @@ int vb2_private_key_write(const struct vb2_private_key *key, if (key->desc) strcpy((char *)buf + pkey.c.fixed_size, key->desc); - memcpy(buf + pkey.key_offset, rsabuf, rsalen); - free(rsabuf); + if (rsabuf) { + memcpy(buf + pkey.key_offset, rsabuf, rsalen); + free(rsabuf); + } rv = vb2_write_object(filename, buf); free(buf); @@ -224,6 +237,56 @@ int vb2_private_key_write(const struct vb2_private_key *key, return rv ? VB2_ERROR_PRIVATE_KEY_WRITE_FILE : VB2_SUCCESS; } +int vb2_private_key_hash(const struct vb2_private_key **key_ptr, + enum vb2_hash_algorithm hash_alg) +{ + *key_ptr = NULL; + + switch (hash_alg) { +#if VB2_SUPPORT_SHA1 + case VB2_HASH_SHA1: + { + static const struct vb2_private_key key = { + .hash_alg = VB2_HASH_SHA1, + .sig_alg = VB2_SIG_NONE, + .desc = "Unsigned SHA1", + .guid = VB2_GUID_NONE_SHA1, + }; + *key_ptr = &key; + return VB2_SUCCESS; + } +#endif +#if VB2_SUPPORT_SHA256 + case VB2_HASH_SHA256: + { + static const struct vb2_private_key key = { + .hash_alg = VB2_HASH_SHA256, + .sig_alg = VB2_SIG_NONE, + .desc = "Unsigned SHA-256", + .guid = VB2_GUID_NONE_SHA256, + }; + *key_ptr = &key; + return VB2_SUCCESS; + } +#endif +#if VB2_SUPPORT_SHA512 + case VB2_HASH_SHA512: + { + static const struct vb2_private_key key = { + .hash_alg = VB2_HASH_SHA512, + .sig_alg = VB2_SIG_NONE, + .desc = "Unsigned SHA-512", + .guid = VB2_GUID_NONE_SHA512, + }; + *key_ptr = &key; + return VB2_SUCCESS; + } +#endif + default: + return VB2_ERROR_PRIVATE_KEY_HASH; + } +} + /** * Allocate a public key buffer of sufficient size for the signature algorithm. * @@ -347,11 +410,11 @@ int vb2_packed_key2_read(struct vb2_packed_key2 **key_ptr, *key_ptr = NULL; - if (!vb2_read_file(filename, &buf, &size)) + if (vb2_read_file(filename, &buf, &size)) return VB2_ERROR_READ_PACKED_KEY_DATA; /* Sanity check: make sure key unpacks properly */ - if (!vb2_unpack_key(&key, buf, size)) + if (vb2_unpack_key2(&key, buf, size)) return VB2_ERROR_READ_PACKED_KEY; *key_ptr = (struct vb2_packed_key2 *)buf; @@ -375,14 +438,16 @@ int vb2_public_key_pack(struct vb2_packed_key2 **key_ptr, /* Calculate sizes and offsets */ key.c.fixed_size = sizeof(key); - if (pubk->desc) + if (pubk->desc && *pubk->desc) key.c.desc_size = roundup32(strlen(pubk->desc) + 1); key.key_offset = key.c.fixed_size + key.c.desc_size; - key.key_size = vb2_packed_key_size(pubk->sig_alg); - if (!key.key_size) - return VB2_ERROR_PUBLIC_KEY_PACK_SIZE; + if (pubk->sig_alg != VB2_SIG_NONE) { + key.key_size = vb2_packed_key_size(pubk->sig_alg); + if (!key.key_size) + return VB2_ERROR_PUBLIC_KEY_PACK_SIZE; + } key.c.total_size = key.key_offset + key.key_size; @@ -400,20 +465,51 @@ int vb2_public_key_pack(struct vb2_packed_key2 **key_ptr, memcpy(buf, &key, sizeof(key)); /* strcpy() is safe because we allocated above based on strlen() */ - if (pubk->desc) { + if (pubk->desc && *pubk->desc) { strcpy((char *)(buf + key.c.fixed_size), pubk->desc); buf[key.c.fixed_size + key.c.desc_size - 1] = 0; } - /* Re-pack the key arrays */ - buf32 = (uint32_t *)(buf + key.key_offset); - buf32[0] = pubk->arrsize; - buf32[1] = pubk->n0inv; - memcpy(buf32 + 2, pubk->n, pubk->arrsize * sizeof(uint32_t)); - memcpy(buf32 + 2 + pubk->arrsize, pubk->rr, - pubk->arrsize * sizeof(uint32_t)); + if (pubk->sig_alg != VB2_SIG_NONE) { + /* Re-pack the key arrays */ + buf32 = (uint32_t *)(buf + key.key_offset); + buf32[0] = pubk->arrsize; + buf32[1] = pubk->n0inv; + memcpy(buf32 + 2, pubk->n, pubk->arrsize * sizeof(uint32_t)); + memcpy(buf32 + 2 + pubk->arrsize, pubk->rr, + pubk->arrsize * sizeof(uint32_t)); + } *key_ptr = (struct vb2_packed_key2 *)buf; return VB2_SUCCESS; } + +int vb2_public_key_hash(struct vb2_public_key *key, + enum vb2_hash_algorithm hash_alg) +{ + switch (hash_alg) { +#if VB2_SUPPORT_SHA1 + case VB2_HASH_SHA1: + key->desc = "Unsigned SHA1"; + break; +#endif +#if VB2_SUPPORT_SHA256 + case VB2_HASH_SHA256: + key->desc = "Unsigned SHA-256"; + break; +#endif +#if VB2_SUPPORT_SHA512 + case VB2_HASH_SHA512: + key->desc = "Unsigned SHA-512"; + break; +#endif + default: + return VB2_ERROR_PUBLIC_KEY_HASH; + } + + key->sig_alg = VB2_SIG_NONE; + key->hash_alg = hash_alg; + key->guid = vb2_hash_guid(hash_alg); + return VB2_SUCCESS; +} diff --git a/host/lib/host_misc2.c b/host/lib/host_misc2.c index 88b58f5b..71a20673 100644 --- a/host/lib/host_misc2.c +++ b/host/lib/host_misc2.c @@ -10,6 +10,7 @@ #include "2sysincludes.h" #include "2common.h" +#include "2sha.h" #include "host_common.h" int vb2_read_file(const char *filename, uint8_t **data_ptr, uint32_t *size_ptr) diff --git a/host/lib/include/host_key2.h b/host/lib/include/host_key2.h index 08f55a37..813ae60f 100644 --- a/host/lib/include/host_key2.h +++ b/host/lib/include/host_key2.h @@ -84,6 +84,17 @@ int vb2_private_key_write(const struct vb2_private_key *key, const char *filename); /** + * Get a private key for an unsigned hash + * + * @param key_ptr Destination for pointer to key. The key is statically + * allocated and must not be freed. + * @param hash_alg Hash algorithm to use + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_private_key_hash(const struct vb2_private_key **key_ptr, + enum vb2_hash_algorithm hash_alg); + +/** * Free a public key allocated by one of the functions below. * * Note that this should ONLY be called for public keys allocated via one @@ -141,4 +152,15 @@ int vb2_packed_key2_read(struct vb2_packed_key2 **key_ptr, int vb2_public_key_pack(struct vb2_packed_key2 **key_ptr, const struct vb2_public_key *pubk); +/** + * Get a public key for an unsigned hash. + * + * @param key Destination for key data. + * @param hash_alg Hash algorithm to use + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_public_key_hash(struct vb2_public_key *key, + enum vb2_hash_algorithm hash_alg); + + #endif /* VBOOT_REFERENCE_HOST_KEY2_H_ */ diff --git a/tests/vb2_common_tests.c b/tests/vb2_common_tests.c index d8a714bb..37996ae3 100644 --- a/tests/vb2_common_tests.c +++ b/tests/vb2_common_tests.c @@ -8,6 +8,7 @@ #include "2sysincludes.h" #include "2common.h" #include "2rsa.h" +#include "host_key2.h" #include "vb2_convert_structs.h" #include "vboot_struct.h" /* For old struct sizes */ @@ -452,16 +453,15 @@ static void test_sig_size(void) static void test_verify_hash(void) { struct vb2_signature2 *sig; - struct vb2_public_key pubk = { - .sig_alg = VB2_SIG_NONE, - .hash_alg = VB2_HASH_SHA256, - .guid = vb2_hash_guid(VB2_HASH_SHA256) - }; + struct vb2_public_key pubk; uint8_t workbuf[VB2_VERIFY_DATA_WORKBUF_BYTES]; struct vb2_workbuf wb; vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); + TEST_SUCC(vb2_public_key_hash(&pubk, VB2_HASH_SHA256), + "create hash key"); + /* Create the signature */ sig = vb2_create_hash_sig(test_data, sizeof(test_data), pubk.hash_alg); TEST_PTR_NEQ(sig, NULL, "create hash sig"); @@ -483,6 +483,7 @@ static void test_verify_hash(void) static void test_verify_keyblock(void) { const char desc[16] = "test keyblock"; + struct vb2_public_key pubk, pubk2, pubk_not_present; struct vb2_signature2 *sig; struct vb2_keyblock2 *kbuf; uint32_t buf_size; @@ -491,21 +492,12 @@ static void test_verify_keyblock(void) uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES]; struct vb2_workbuf wb; - const struct vb2_public_key pubk = { - .sig_alg = VB2_SIG_NONE, - .hash_alg = VB2_HASH_SHA256, - .guid = vb2_hash_guid(VB2_HASH_SHA256) - }; - const struct vb2_public_key pubk2 = { - .sig_alg = VB2_SIG_NONE, - .hash_alg = VB2_HASH_SHA512, - .guid = vb2_hash_guid(VB2_HASH_SHA512) - }; - const struct vb2_public_key pubk_not_present = { - .sig_alg = VB2_SIG_NONE, - .hash_alg = VB2_HASH_SHA1, - .guid = vb2_hash_guid(VB2_HASH_SHA1) - }; + TEST_SUCC(vb2_public_key_hash(&pubk, VB2_HASH_SHA256), + "create hash key 1"); + TEST_SUCC(vb2_public_key_hash(&pubk2, VB2_HASH_SHA512), + "create hash key 2"); + TEST_SUCC(vb2_public_key_hash(&pubk_not_present, VB2_HASH_SHA1), + "create hash key 3"); /* * Test packed key only needs to initialize the fields used by keyblock @@ -663,6 +655,7 @@ static void test_verify_keyblock(void) static void test_verify_fw_preamble(void) { const char desc[16] = "test preamble"; + struct vb2_public_key pubk; struct vb2_signature2 *sig; struct vb2_fw_preamble2 *pre; uint32_t buf_size; @@ -678,11 +671,8 @@ static void test_verify_fw_preamble(void) * bare hash here saves us from needing to have a private key to do * this test. */ - const struct vb2_public_key pubk = { - .sig_alg = VB2_SIG_NONE, - .hash_alg = VB2_HASH_SHA256, - .guid = vb2_hash_guid(VB2_HASH_SHA256) - }; + TEST_SUCC(vb2_public_key_hash(&pubk, VB2_HASH_SHA256), + "create hash key"); struct vb2_fw_preamble2 fp = { .c.magic = VB2_MAGIC_FW_PREAMBLE2, diff --git a/tests/vb2_host_key_tests.c b/tests/vb2_host_key_tests.c index 9a56351c..15e0b377 100644 --- a/tests/vb2_host_key_tests.c +++ b/tests/vb2_host_key_tests.c @@ -33,6 +33,7 @@ static void private_key_tests(const struct alg_combo *combo, const char *pemfile) { struct vb2_private_key *key, *k2; + const struct vb2_private_key *ckey; struct vb2_packed_private_key2 *pkey; const char *testfile = "test.vbprik2"; const char *notapem = "not_a_pem"; @@ -136,11 +137,31 @@ static void private_key_tests(const struct alg_combo *combo, VB2_ERROR_UNPACK_PRIVATE_KEY_RSA, "Unpack private key bad rsa data"); + memcpy(buf, buf2, bufsize); + pkey->sig_alg = VB2_SIG_NONE; + TEST_EQ(vb2_private_key_unpack(&k2, buf, bufsize), + VB2_ERROR_UNPACK_PRIVATE_KEY_HASH, + "Unpack private key hash but has data"); + free(buf); free(buf2); unlink(testfile); - vb2_private_key_free(key); + TEST_EQ(vb2_private_key_hash(&ckey, VB2_HASH_INVALID), + VB2_ERROR_PRIVATE_KEY_HASH, + "Hash key invalid"); + TEST_PTR_EQ(ckey, NULL, " key_ptr"); + + TEST_SUCC(vb2_private_key_hash(&ckey, combo->hash_alg), "Hash key"); + TEST_PTR_NEQ(ckey, NULL, " key_ptr"); + TEST_EQ(ckey->hash_alg, combo->hash_alg, " hash_alg"); + TEST_EQ(ckey->sig_alg, VB2_SIG_NONE, " sig_alg"); + TEST_EQ(memcmp(&ckey->guid, vb2_hash_guid(combo->hash_alg), + sizeof(ckey->guid)), 0, " guid"); + + TEST_SUCC(vb2_private_key_write(ckey, testfile), "Write hash key"); + TEST_SUCC(vb2_private_key_read(&key, testfile), "Read hash key"); + unlink(testfile); } static void public_key_tests(const struct alg_combo *combo, @@ -213,13 +234,47 @@ static void public_key_tests(const struct alg_combo *combo, " n"); TEST_EQ(memcmp(key->rr, k2.rr, key->arrsize * sizeof(uint32_t)), 0, " rr"); + + TEST_SUCC(vb2_write_object(testfile, pkey), "Write packed key"); + free(pkey); + + TEST_SUCC(vb2_packed_key2_read(&pkey, testfile), "Read packed key"); + TEST_PTR_NEQ(pkey, NULL, " key_ptr"); + unlink(testfile); + + pkey->hash_alg = VB2_HASH_INVALID; + TEST_SUCC(vb2_write_object(testfile, pkey), "Write bad packed key"); free(pkey); + TEST_EQ(vb2_packed_key2_read(&pkey, testfile), + VB2_ERROR_READ_PACKED_KEY, "Read bad packed key"); + TEST_PTR_EQ(pkey, NULL, " key_ptr"); + unlink(testfile); + + TEST_EQ(vb2_packed_key2_read(&pkey, testfile), + VB2_ERROR_READ_PACKED_KEY_DATA, "Read missing packed key"); + key->sig_alg = VB2_SIG_INVALID; TEST_EQ(vb2_public_key_pack(&pkey, key), VB2_ERROR_PUBLIC_KEY_PACK_SIZE, "Pack invalid sig alg"); vb2_public_key_free(key); + + TEST_EQ(vb2_public_key_hash(&k2, VB2_HASH_INVALID), + VB2_ERROR_PUBLIC_KEY_HASH, + "Hash key invalid"); + + TEST_SUCC(vb2_public_key_hash(&k2, combo->hash_alg), "Hash key"); + TEST_EQ(k2.hash_alg, combo->hash_alg, " hash_alg"); + TEST_EQ(k2.sig_alg, VB2_SIG_NONE, " sig_alg"); + TEST_EQ(memcmp(k2.guid, vb2_hash_guid(combo->hash_alg), + sizeof(*k2.guid)), 0, " guid"); + + TEST_SUCC(vb2_public_key_pack(&pkey, &k2), "Pack public hash key"); + TEST_PTR_NEQ(pkey, NULL, " key_ptr"); + TEST_SUCC(vb2_unpack_key2(&k2, (uint8_t *)pkey, pkey->c.total_size), + "Unpack public hash key"); + free(pkey); } static int test_algorithm(const struct alg_combo *combo, const char *keys_dir) |