diff options
author | Randall Spangler <rspangler@chromium.org> | 2016-10-14 11:04:27 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-10-29 19:41:08 -0700 |
commit | 13b109762a3bfec025a9bfcb3ead927d0291280e (patch) | |
tree | 7cc62ff1a42b8979223ab0ee3894cd70bcb71983 | |
parent | f41cd04d9eeefe7b7b98c67484ee96ba4fbf1125 (diff) | |
download | vboot-13b109762a3bfec025a9bfcb3ead927d0291280e.tar.gz |
vboot: use vb2 verification functions for kernel verification
This removes old vboot1 functions in favor of the new vboot2 functions.
BUG=chromium:611535
BRANCH=none
TEST=make runtests; emerge-kevin coreboot depthcharge
Change-Id: Idc64f7714bbd9d4fa82d14b6b5d73d71c61de854
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/400900
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | firmware/2lib/include/2common.h | 6 | ||||
-rw-r--r-- | firmware/lib/include/vboot_common.h | 42 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 69 | ||||
-rw-r--r-- | firmware/lib/vboot_common.c | 255 | ||||
-rw-r--r-- | firmware/lib/vboot_kernel.c | 88 | ||||
-rw-r--r-- | firmware/lib20/kernel.c | 2 | ||||
-rw-r--r-- | firmware/linktest/main.c | 5 | ||||
-rw-r--r-- | tests/vboot_api_kernel5_tests.c | 75 | ||||
-rw-r--r-- | tests/vboot_common2_tests.c | 303 | ||||
-rw-r--r-- | tests/vboot_common3_tests.c | 270 | ||||
-rw-r--r-- | tests/vboot_kernel_tests.c | 76 |
12 files changed, 209 insertions, 992 deletions
@@ -740,8 +740,6 @@ TEST_NAMES = \ tests/vboot_api_kernel6_tests \ tests/vboot_audio_tests \ tests/vboot_common_tests \ - tests/vboot_common2_tests \ - tests/vboot_common3_tests \ tests/vboot_display_tests \ tests/vboot_kernel_tests \ tests/vboot_nvstorage_test \ @@ -941,7 +939,7 @@ fwlinktest: ${BUILD}/firmware/linktest/main .PHONY: fwlib fwlib: $(if ${FIRMWARE_ARCH},${FWLIB},fwlinktest) -${FWLIB}: ${FWLIB_OBJS} ${FWLIB2X_OBJS} +${FWLIB}: ${FWLIB_OBJS} ${FWLIB2X_OBJS} ${FWLIB20_OBJS} @${PRINTF} " RM $(subst ${BUILD}/,,$@)\n" ${Q}rm -f $@ @${PRINTF} " AR $(subst ${BUILD}/,,$@)\n" @@ -1260,8 +1258,6 @@ ${BUILD}/utility/bdb_extend: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/bdb_extend: LIBS += ${UTILBDB} ${FWLIB2X} ${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS} -${BUILD}/tests/vboot_common2_tests: LDLIBS += ${CRYPTO_LIBS} -${BUILD}/tests/vboot_common3_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb20_common2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb20_common3_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/verify_kernel: LDLIBS += ${CRYPTO_LIBS} @@ -1438,8 +1434,6 @@ endif ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel6_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_audio_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_common_tests - ${RUNTEST} ${BUILD_RUN}/tests/vboot_common2_tests ${TEST_KEYS} - ${RUNTEST} ${BUILD_RUN}/tests/vboot_common3_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vboot_display_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_nvstorage_test @@ -1488,8 +1482,6 @@ runfutiltests: test_setup # Not run by automated build. .PHONY: runlongtests runlongtests: test_setup genkeys genfuzztestcases - ${RUNTEST} ${BUILD_RUN}/tests/vboot_common2_tests ${TEST_KEYS} --all - ${RUNTEST} ${BUILD_RUN}/tests/vboot_common3_tests ${TEST_KEYS} --all ${RUNTEST} ${BUILD_RUN}/tests/vb20_common2_tests ${TEST_KEYS} --all ${RUNTEST} ${BUILD_RUN}/tests/vb20_common3_tests ${TEST_KEYS} --all ${RUNTEST} ${BUILD_RUN}/tests/vb21_common2_tests ${TEST_KEYS} --all diff --git a/firmware/2lib/include/2common.h b/firmware/2lib/include/2common.h index 4622ab13..39c8caff 100644 --- a/firmware/2lib/include/2common.h +++ b/firmware/2lib/include/2common.h @@ -194,4 +194,10 @@ const struct vb2_id *vb2_hash_id(enum vb2_hash_algorithm hash_alg); /* Size of work buffer sufficient for vb2_verify_fw_preamble() worst case. */ #define VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES +/* + * Size of work buffer sufficient for vb2_verify_kernel_preamble() worst + * case. + */ +#define VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES + #endif /* VBOOT_REFERENCE_VBOOT_2COMMON_H_ */ diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h index 5b783e27..762448bb 100644 --- a/firmware/lib/include/vboot_common.h +++ b/firmware/lib/include/vboot_common.h @@ -90,48 +90,6 @@ void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size); int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src); /** - * Convert a public key to RsaPublicKey format. The returned key must be freed - * using RSAPublicKeyFree(). - * - * Returns NULL if error. - */ -RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key); - -/** - * Verify [data] matches signature [sig] using [key]. [size] is the size of - * the data buffer; the amount of data to be validated is contained in - * sig->data_size. - */ -int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig, - const RSAPublicKey *key); - -/** - * Verify a secure hash digest from vb2_digest_buffer() or - * vb2_digest_finalize(), using [key]. Returns 0 on success. - */ -int VerifyDigest(const uint8_t *digest, const VbSignature *sig, - const RSAPublicKey *key); - -/** - * Check the sanity of a key block of size [size] bytes, using public key - * [key]. If hash_only is non-zero, uses only the block checksum to verify the - * key block. Header fields are also checked for sanity. Does not verify key - * index or key block flags. - */ -int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size, - const VbPublicKey *key, int hash_only); - -/** - * Check the sanity of a kernel preamble of size [size] bytes, using public key - * [key]. - * - * Returns VBOOT_SUCCESS if successful. - */ -int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, - uint64_t size, const RSAPublicKey *key); - - -/** * Retrieve the 16-bit vmlinuz header address and size from the kernel preamble * if there is one. These are only available in Kernel Preamble Header version * >= 2.1. If given a header 2.0 or lower, will set address and size to 0 (this diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 1360971f..6f896fbf 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -9,12 +9,14 @@ #include "2sysincludes.h" #include "2common.h" +#include "2rsa.h" #include "gbb_access.h" #include "gbb_header.h" #include "load_kernel_fw.h" #include "region.h" #include "rollback_index.h" #include "utility.h" +#include "vb2_common.h" #include "vboot_api.h" #include "vboot_audio.h" #include "vboot_common.h" @@ -1335,12 +1337,13 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams, VbKeyBlockHeader *key_block; VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - RSAPublicKey *data_key = NULL; VbKernelPreambleHeader *preamble; uint64_t body_offset; int hash_only = 0; int dev_switch; uint32_t allow_fastboot_full_cap = 0; + uint8_t *workbuf = NULL; + struct vb2_workbuf wb; if ((boot_image == NULL) || (image_size == 0)) return VBERROR_INVALID_PARAMETER; @@ -1399,10 +1402,35 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams, /* If we fail at any step, retval returned would be invalid kernel. */ retval = VBERROR_INVALID_KERNEL_FOUND; + /* Allocate work buffer */ + workbuf = (uint8_t *) + VbExMalloc(VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES); + if (!workbuf) + goto fail; + vb2_workbuf_init(&wb, workbuf, + VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES); + /* Verify the key block. */ key_block = (VbKeyBlockHeader *)kbuf; - if (0 != KeyBlockVerify(key_block, image_size, kernel_subkey, - hash_only)) { + struct vb2_keyblock *keyblock2 = (struct vb2_keyblock *)kbuf; + int rv; + if (hash_only) { + rv = vb2_verify_keyblock_hash(keyblock2, image_size, &wb); + } else { + /* Unpack kernel subkey */ + struct vb2_public_key kernel_subkey2; + if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2, + (const uint8_t *)kernel_subkey, + kernel_subkey->key_offset + + kernel_subkey->key_size)) { + VBDEBUG(("Unable to unpack kernel subkey\n")); + goto fail; + } + rv = vb2_verify_keyblock(keyblock2, image_size, + &kernel_subkey2, &wb); + } + + if (VB2_SUCCESS != rv) { VBDEBUG(("Verifying key block signature/hash failed.\n")); goto fail; } @@ -1423,18 +1451,27 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams, } /* Get key for preamble/data verification from the key block. */ - data_key = PublicKeyToRSA(&key_block->data_key); - if (!data_key) { - VBDEBUG(("Data key bad.\n")); + struct vb2_public_key data_key2; + if (VB2_SUCCESS != + vb2_unpack_key(&data_key2, + (const uint8_t *)&keyblock2->data_key, + keyblock2->data_key.key_offset + + keyblock2->data_key.key_size)) { + VBDEBUG(("Unable to unpack kernel data key\n")); goto fail; } /* Verify the preamble, which follows the key block */ preamble = (VbKernelPreambleHeader *)(kbuf + key_block->key_block_size); - if ((0 != VerifyKernelPreamble(preamble, - image_size - - key_block->key_block_size, - data_key))) { + struct vb2_kernel_preamble *preamble2 = + (struct vb2_kernel_preamble *) + (kbuf + key_block->key_block_size); + + if (VB2_SUCCESS != vb2_verify_kernel_preamble( + preamble2, + image_size - key_block->key_block_size, + &data_key2, + &wb)) { VBDEBUG(("Preamble verification failed.\n")); goto fail; } @@ -1443,9 +1480,11 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams, /* Verify kernel data */ body_offset = key_block->key_block_size + preamble->preamble_size; - if (0 != VerifyData((const uint8_t *)(kbuf + body_offset), - image_size - body_offset, - &preamble->body_signature, data_key)) { + if (VB2_SUCCESS != vb2_verify_data( + (const uint8_t *)(kbuf + body_offset), + image_size - body_offset, + (struct vb2_signature *)&preamble->body_signature, + &data_key2, &wb)) { VBDEBUG(("Kernel data verification failed.\n")); goto fail; } @@ -1464,10 +1503,10 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams, fail: VbApiKernelFree(cparams); - if (NULL != data_key) - RSAPublicKeyFree(data_key); if (NULL != kernel_subkey) VbExFree(kernel_subkey); + if (NULL != workbuf) + VbExFree(workbuf); return retval; } diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c index 56ba35df..3d5f2e22 100644 --- a/firmware/lib/vboot_common.c +++ b/firmware/lib/vboot_common.c @@ -123,261 +123,6 @@ int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src) return 0; } -RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key) -{ - RSAPublicKey *rsa; - uint64_t key_size; - - if (kNumAlgorithms <= key->algorithm) { - VBDEBUG(("Invalid algorithm.\n")); - return NULL; - } - if (!RSAProcessedKeySize(key->algorithm, &key_size) || - key_size != key->key_size) { - VBDEBUG(("Wrong key size for algorithm\n")); - return NULL; - } - - rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size); - if (!rsa) - return NULL; - - rsa->algorithm = (unsigned int)key->algorithm; - return rsa; -} - -int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig, - const RSAPublicKey *key) -{ - VBDEBUG((" - sig_size=%d, expecting %d for algorithm %d\n", - (unsigned)sig->sig_size, siglen_map[key->algorithm], - key->algorithm)); - if (sig->sig_size != siglen_map[key->algorithm]) { - VBDEBUG(("Wrong data signature size for algorithm, " - "sig_size=%d, expected %d for algorithm %d.\n", - (int)sig->sig_size, siglen_map[key->algorithm], - key->algorithm)); - return 1; - } - if (sig->data_size > size) { - VBDEBUG(("Data buffer smaller than length of signed data.\n")); - return 1; - } - - if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size, - GetSignatureDataC(sig), key->algorithm)) - return 1; - - return 0; -} - -int VerifyDigest(const uint8_t *digest, const VbSignature *sig, - const RSAPublicKey *key) -{ - if (sig->sig_size != siglen_map[key->algorithm]) { - VBDEBUG(("Wrong digest signature size for algorithm.\n")); - return 1; - } - - if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest, - GetSignatureDataC(sig), - key->algorithm)) - return 1; - - return 0; -} - -int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size, - const VbPublicKey *key, int hash_only) -{ - const VbSignature *sig; - - /* Sanity checks before attempting signature of data */ - if(size < sizeof(VbKeyBlockHeader)) { - VBDEBUG(("Not enough space for key block header.\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (vb2_safe_memcmp(block->magic, KEY_BLOCK_MAGIC, - KEY_BLOCK_MAGIC_SIZE)) { - VBDEBUG(("Not a valid verified boot key block.\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) { - VBDEBUG(("Incompatible key block header version.\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (size < block->key_block_size) { - VBDEBUG(("Not enough data for key block.\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (!hash_only && !key) { - VBDEBUG(("Missing required public key.\n")); - return VBOOT_PUBLIC_KEY_INVALID; - } - - /* - * Check signature or hash, depending on the hash_only parameter. Note - * that we don't require a key even if the keyblock has a signature, - * because the caller may not care if the keyblock itself is signed - * (for example, booting a Google-signed kernel in developer mode). - */ - if (hash_only) { - /* Check hash */ - uint8_t header_checksum[VB2_SHA512_DIGEST_SIZE]; - int rv; - - sig = &block->key_block_checksum; - - if (VerifySignatureInside(block, block->key_block_size, sig)) { - VBDEBUG(("Key block hash off end of block\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (sig->sig_size != VB2_SHA512_DIGEST_SIZE) { - VBDEBUG(("Wrong hash size for key block.\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - - /* Make sure advertised signature data sizes are sane. */ - if (block->key_block_size < sig->data_size) { - VBDEBUG(("Signature calculated past end of block\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - - VBDEBUG(("Checking key block hash only...\n")); - rv = vb2_digest_buffer((const uint8_t *)block, - sig->data_size, - VB2_HASH_SHA512, - header_checksum, - sizeof(header_checksum)); - if (!rv) - rv = vb2_safe_memcmp(header_checksum, - GetSignatureDataC(sig), - sizeof(header_checksum)); - - if (rv) { - VBDEBUG(("Invalid key block hash.\n")); - return VBOOT_KEY_BLOCK_HASH; - } - } else { - /* Check signature */ - RSAPublicKey *rsa; - int rv; - - sig = &block->key_block_signature; - - if (VerifySignatureInside(block, block->key_block_size, sig)) { - VBDEBUG(("Key block signature off end of block\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - - rsa = PublicKeyToRSA(key); - if (!rsa) { - VBDEBUG(("Invalid public key\n")); - return VBOOT_PUBLIC_KEY_INVALID; - } - - /* Make sure advertised signature data sizes are sane. */ - if (block->key_block_size < sig->data_size) { - VBDEBUG(("Signature calculated past end of block\n")); - RSAPublicKeyFree(rsa); - return VBOOT_KEY_BLOCK_INVALID; - } - - VBDEBUG(("Checking key block signature...\n")); - rv = VerifyData((const uint8_t *)block, size, sig, rsa); - RSAPublicKeyFree(rsa); - if (rv) { - VBDEBUG(("Invalid key block signature.\n")); - return VBOOT_KEY_BLOCK_SIGNATURE; - } - } - - /* Verify we signed enough data */ - if (sig->data_size < sizeof(VbKeyBlockHeader)) { - VBDEBUG(("Didn't sign enough data\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - - /* Verify data key is inside the block and inside signed data */ - if (VerifyPublicKeyInside(block, block->key_block_size, - &block->data_key)) { - VBDEBUG(("Data key off end of key block\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) { - VBDEBUG(("Data key off end of signed data\n")); - return VBOOT_KEY_BLOCK_INVALID; - } - - /* Success */ - return VBOOT_SUCCESS; -} - -int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, - uint64_t size, const RSAPublicKey *key) -{ - const VbSignature *sig = &preamble->preamble_signature; - - /* Sanity checks before attempting signature of data */ - if(size < sizeof(VbKernelPreambleHeader)) { - VBDEBUG(("Not enough data for preamble header.\n")); - return VBOOT_PREAMBLE_INVALID; - } - if (preamble->header_version_major != - KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) { - VBDEBUG(("Incompatible kernel preamble header version.\n")); - return VBOOT_PREAMBLE_INVALID; - } - if (size < preamble->preamble_size) { - VBDEBUG(("Not enough data for preamble.\n")); - return VBOOT_PREAMBLE_INVALID; - } - - /* Check signature */ - if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) { - VBDEBUG(("Preamble signature off end of preamble\n")); - return VBOOT_PREAMBLE_INVALID; - } - if (VerifyData((const uint8_t *)preamble, size, sig, key)) { - VBDEBUG(("Preamble signature validation failed\n")); - return VBOOT_PREAMBLE_SIGNATURE; - } - - /* Verify we signed enough data */ - if (sig->data_size < sizeof(VbKernelPreambleHeader)) { - VBDEBUG(("Didn't sign enough data\n")); - return VBOOT_PREAMBLE_INVALID; - } - - /* Verify body signature is inside the signed data */ - if (VerifySignatureInside(preamble, sig->data_size, - &preamble->body_signature)) { - VBDEBUG(("Kernel body signature off end of preamble\n")); - return VBOOT_PREAMBLE_INVALID; - } - - /* - * If the preamble header version is at least 2.1, verify we have space - * for the added fields from >2.1. - */ - if (preamble->header_version_minor >= 1) { - if((preamble->header_version_minor == 1) && - (size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE)) { - VBDEBUG(("Not enough data for preamble header 2.1.\n")); - return VBOOT_PREAMBLE_INVALID; - } - - if((preamble->header_version_minor == 2) && - (size < EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE)) { - VBDEBUG(("Not enough data for preamble header 2.2.\n")); - return VBOOT_PREAMBLE_INVALID; - } - } - - /* Success */ - return VBOOT_SUCCESS; -} - int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble, uint64_t *vmlinuz_header_address, uint64_t *vmlinuz_header_size) diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index be5389a4..cf6f92bc 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -7,8 +7,10 @@ */ #include "sysincludes.h" +#include "2sysincludes.h" #include "2common.h" +#include "2rsa.h" #include "2sha.h" #include "cgptlib.h" #include "cgptlib_internal.h" @@ -19,6 +21,7 @@ #include "load_kernel_fw.h" #include "rollback_index.h" #include "utility.h" +#include "vb2_common.h" #include "vboot_api.h" #include "vboot_common.h" #include "vboot_kernel.h" @@ -37,14 +40,14 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) VbSharedDataHeader *shared = (VbSharedDataHeader *)params->shared_data_blob; VbSharedDataKernelCall *shcall = NULL; - VbNvContext* vnc = params->nv_context; - VbPublicKey* kernel_subkey = NULL; + VbNvContext *vnc = params->nv_context; + VbPublicKey *kernel_subkey = NULL; int free_kernel_subkey = 0; GptData gpt; uint64_t part_start, part_size; uint64_t blba; uint64_t kbuf_sectors; - uint8_t* kbuf = NULL; + uint8_t *kbuf = NULL; int found_partitions = 0; int good_partition = -1; int good_partition_key_block_valid = 0; @@ -58,6 +61,9 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) VbError_t retval = VBERROR_UNKNOWN; int recovery = VBNV_RECOVERY_LK_UNSPECIFIED; + uint8_t *workbuf = NULL; + struct vb2_workbuf wb; + /* Sanity Checks */ if (!params->bytes_per_lba || !params->streaming_lba_count) { @@ -141,17 +147,34 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) } /* Allocate kernel header buffers */ - kbuf = (uint8_t*)VbExMalloc(KBUF_SIZE); + kbuf = (uint8_t *)VbExMalloc(KBUF_SIZE); if (!kbuf) goto bad_gpt; + /* Allocate work buffer */ + workbuf = (uint8_t *) + VbExMalloc(VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES); + if (!workbuf) + goto bad_gpt; + vb2_workbuf_init(&wb, workbuf, + VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES); + + /* Unpack kernel subkey */ + struct vb2_public_key kernel_subkey2; + if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2, + (const uint8_t *)kernel_subkey, + kernel_subkey->key_offset + + kernel_subkey->key_size)) { + VBDEBUG(("Unable to unpack kernel subkey\n")); + goto bad_gpt; + } + /* Loop over candidate kernel partitions */ while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { VbSharedDataKernelPart *shpart = NULL; VbKeyBlockHeader *key_block; VbKernelPreambleHeader *preamble; - RSAPublicKey *data_key = NULL; VbExStream_t stream = NULL; uint64_t key_version; uint32_t combined_version; @@ -197,8 +220,9 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) /* Verify the key block. */ key_block = (VbKeyBlockHeader*)kbuf; - if (0 != KeyBlockVerify(key_block, KBUF_SIZE, - kernel_subkey, 0)) { + struct vb2_keyblock *keyblock2 = (struct vb2_keyblock *)kbuf; + if (VB2_SUCCESS != vb2_verify_keyblock(keyblock2, KBUF_SIZE, + &kernel_subkey2, &wb)) { VBDEBUG(("Verifying key block signature failed.\n")); shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_SIG; key_block_valid = 0; @@ -222,8 +246,9 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) * Allow the kernel if the SHA-512 hash of the key * block is valid. */ - if (0 != KeyBlockVerify(key_block, KBUF_SIZE, - kernel_subkey, 1)) { + if (VB2_SUCCESS != + vb2_verify_keyblock_hash(keyblock2, KBUF_SIZE, + &wb)) { VBDEBUG(("Verifying key block hash failed.\n")); shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH; @@ -309,20 +334,29 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) } /* Get key for preamble/data verification from the key block. */ - data_key = PublicKeyToRSA(&key_block->data_key); - if (!data_key) { - VBDEBUG(("Data key bad.\n")); + struct vb2_public_key data_key2; + if (VB2_SUCCESS != + vb2_unpack_key(&data_key2, + (const uint8_t *)&keyblock2->data_key, + keyblock2->data_key.key_offset + + keyblock2->data_key.key_size)) { + VBDEBUG(("Unable to unpack kernel data key\n")); shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE; goto bad_kernel; } /* Verify the preamble, which follows the key block */ preamble = (VbKernelPreambleHeader *) - (kbuf + key_block->key_block_size); - if ((0 != VerifyKernelPreamble( - preamble, - KBUF_SIZE - key_block->key_block_size, - data_key))) { + (kbuf + key_block->key_block_size); + struct vb2_kernel_preamble *preamble2 = + (struct vb2_kernel_preamble *) + (kbuf + key_block->key_block_size); + + if (VB2_SUCCESS != vb2_verify_kernel_preamble( + preamble2, + KBUF_SIZE - key_block->key_block_size, + &data_key2, + &wb)) { VBDEBUG(("Preamble verification failed.\n")); shpart->check_result = VBSD_LKP_CHECK_VERIFY_PREAMBLE; goto bad_kernel; @@ -442,18 +476,17 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams) stream = NULL; /* Verify kernel data */ - if (0 != VerifyData((const uint8_t *)params->kernel_buffer, - params->kernel_buffer_size, - &preamble->body_signature, data_key)) { + struct vb2_signature *body_sig = (struct vb2_signature *) + &preamble->body_signature; + if (VB2_SUCCESS != vb2_verify_data( + (const uint8_t *)params->kernel_buffer, + params->kernel_buffer_size, + body_sig, &data_key2, &wb)) { VBDEBUG(("Kernel data verification failed.\n")); shpart->check_result = VBSD_LKP_CHECK_VERIFY_DATA; goto bad_kernel; } - /* Done with the kernel signing key, so can free it now */ - RSAPublicKeyFree(data_key); - data_key = NULL; - /* * If we're still here, the kernel is valid. Save the first * good partition we find; that's the one we'll boot. @@ -517,8 +550,6 @@ bad_kernel: /* Handle errors parsing this kernel */ if (NULL != stream) VbExStreamClose(stream); - if (NULL != data_key) - RSAPublicKeyFree(data_key); VBDEBUG(("Marking kernel as invalid.\n")); GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD); @@ -527,8 +558,9 @@ bad_kernel: } /* while(GptNextKernelEntry) */ bad_gpt: - - /* Free kernel buffer */ + /* Free buffers */ + if (workbuf) + VbExFree(workbuf); if (kbuf) VbExFree(kbuf); diff --git a/firmware/lib20/kernel.c b/firmware/lib20/kernel.c index c50614df..809e1b66 100644 --- a/firmware/lib20/kernel.c +++ b/firmware/lib20/kernel.c @@ -462,7 +462,7 @@ void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble, * Set header and size only if the preamble header version is > * 2.1 as they don't exist in version 2.0 (Note that we don't * need to check header_version_major; if that's not 2 then - * VerifyKernelPreamble() would have already failed. + * vb2_verify_kernel_preamble() would have already failed. */ *vmlinuz_header_address = preamble->vmlinuz_header_address; *vmlinuz_header_size = preamble->vmlinuz_header_size; diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c index 9dca9571..6629cc5c 100644 --- a/firmware/linktest/main.c +++ b/firmware/linktest/main.c @@ -67,11 +67,6 @@ int main(void) VerifySignatureInside(0, 0, 0); PublicKeyInit(0, 0, 0); PublicKeyCopy(0, 0); - PublicKeyToRSA(0); - VerifyData(0, 0, 0, 0); - VerifyDigest(0, 0, 0); - KeyBlockVerify(0, 0, 0, 0); - VerifyKernelPreamble(0, 0, 0); VbSharedDataInit(0, 0); VbSharedDataReserve(0, 0); VbSharedDataSetKernelKey(0, 0); diff --git a/tests/vboot_api_kernel5_tests.c b/tests/vboot_api_kernel5_tests.c index 04ee7669..d752f6b7 100644 --- a/tests/vboot_api_kernel5_tests.c +++ b/tests/vboot_api_kernel5_tests.c @@ -10,10 +10,14 @@ #include <stdlib.h> #include <string.h> +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" #include "gbb_header.h" #include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" +#include "vb2_common.h" #include "vboot_api.h" #include "vboot_common.h" #include "vboot_kernel.h" @@ -31,8 +35,7 @@ static uint8_t kernel_buffer[80000]; static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */ static int preamble_verify_fail; static int verify_data_fail; -static RSAPublicKey *mock_data_key; -static int mock_data_key_allocated; +static int unpack_key_fail; static VbNvContext vnc; static VbKeyBlockHeader kbh; @@ -69,9 +72,6 @@ static void ResetMocks(void) preamble_verify_fail = 0; verify_data_fail = 0; - mock_data_key = (RSAPublicKey *)"TestDataKey"; - mock_data_key_allocated = 0; - memset(&kbh, 0, sizeof(kbh)); kbh.data_key.key_version = 2; kbh.key_block_flags = -1; @@ -96,53 +96,68 @@ static void copy_kbh(void) } /* Mocks */ -int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size, - const VbPublicKey *key, int hash_only) { - hash_only_check = hash_only; +int vb2_unpack_key(struct vb2_public_key *key, + const uint8_t *buf, + uint32_t size) +{ + if (--unpack_key_fail == 0) + return VB2_ERROR_MOCK; + + return VB2_SUCCESS; +} + +int vb2_verify_keyblock(struct vb2_keyblock *block, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + hash_only_check = 0; if (key_block_verify_fail) - return VBERROR_SIMULATED; + return VB2_ERROR_MOCK; /* Use this as an opportunity to override the key block */ memcpy((void *)block, &kbh, sizeof(kbh)); - return VBERROR_SUCCESS; + return VB2_SUCCESS; } -RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key) +int vb2_verify_keyblock_hash(const struct vb2_keyblock *block, + uint32_t size, + const struct vb2_workbuf *wb) { - TEST_EQ(mock_data_key_allocated, 0, " mock data key not allocated"); - - if (mock_data_key) - mock_data_key_allocated++; + hash_only_check = 1; - return mock_data_key; -} + if (key_block_verify_fail) + return VB2_ERROR_MOCK; -void RSAPublicKeyFree(RSAPublicKey* key) -{ - TEST_EQ(mock_data_key_allocated, 1, " mock data key allocated"); - TEST_PTR_EQ(key, mock_data_key, " data key ptr"); - mock_data_key_allocated--; + /* Use this as an opportunity to override the key block */ + memcpy((void *)block, &kbh, sizeof(kbh)); + return VB2_SUCCESS; } -int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, - uint64_t size, const RSAPublicKey *key) +int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) { if (preamble_verify_fail) - return VBERROR_SIMULATED; + return VB2_ERROR_MOCK; /* Use this as an opportunity to override the preamble */ memcpy((void *)preamble, &kph, sizeof(kph)); - return VBERROR_SUCCESS; + return VB2_SUCCESS; } -int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig, - const RSAPublicKey *key) +int vb2_verify_data(const uint8_t *data, + uint32_t size, + struct vb2_signature *sig, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) { if (verify_data_fail) - return VBERROR_SIMULATED; + return VB2_ERROR_MOCK; - return VBERROR_SUCCESS; + return VB2_SUCCESS; } VbError_t VbExNvStorageRead(uint8_t *buf) diff --git a/tests/vboot_common2_tests.c b/tests/vboot_common2_tests.c deleted file mode 100644 index 386f487f..00000000 --- a/tests/vboot_common2_tests.c +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright (c) 2013 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. - * - * Tests for firmware image library. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "2sysincludes.h" -#include "2common.h" -#include "2sha.h" -#include "cryptolib.h" -#include "file_keys.h" -#include "host_common.h" -#include "test_common.h" -#include "vboot_common.h" - -static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key) -{ - RSAPublicKey *rsa; - VbPublicKey *key = - (VbPublicKey *)vb2_alloc_packed_key(orig_key->key_size, 0, 0); - - PublicKeyCopy(key, orig_key); - key->algorithm = kNumAlgorithms; - TEST_EQ((size_t)PublicKeyToRSA(key), 0, - "PublicKeyToRSA() invalid algorithm"); - - PublicKeyCopy(key, orig_key); - key->key_size -= 1; - TEST_EQ((size_t)PublicKeyToRSA(key), 0, - "PublicKeyToRSA() invalid size"); - - rsa = PublicKeyToRSA(orig_key); - TEST_NEQ((size_t)rsa, 0, "PublicKeyToRSA() ok"); - if (rsa) { - TEST_EQ((int)rsa->algorithm, (int)key->algorithm, - "PublicKeyToRSA() algorithm"); - RSAPublicKeyFree(rsa); - } - - free(key); -} - -static void VerifyDataTest(const VbPublicKey *public_key, - const struct vb2_private_key *private_key) -{ - const uint8_t test_data[] = "This is some test data to sign."; - const uint64_t test_size = sizeof(test_data); - VbSignature *sig; - RSAPublicKey *rsa; - - sig = (VbSignature *)vb2_calculate_signature(test_data, test_size, - private_key); - TEST_PTR_NEQ(sig, 0, "VerifyData() calculate signature"); - - rsa = PublicKeyToRSA(public_key); - TEST_PTR_NEQ(rsa, 0, "VerifyData() calculate rsa"); - - if (!sig || !rsa) - return; - - TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 0, - "VerifyData() ok"); - - sig->sig_size -= 16; - TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1, - "VerifyData() wrong sig size"); - sig->sig_size += 16; - - TEST_EQ(VerifyData(test_data, test_size - 1, sig, rsa), 1, - "VerifyData() input buffer too small"); - - GetSignatureData(sig)[0] ^= 0x5A; - TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1, - "VerifyData() wrong sig"); - - RSAPublicKeyFree(rsa); - free(sig); -} - -static void VerifyDigestTest(const VbPublicKey *public_key, - const struct vb2_private_key *private_key) -{ - const uint8_t test_data[] = "This is some other test data to sign."; - VbSignature *sig; - RSAPublicKey *rsa; - uint8_t digest[VB2_MAX_DIGEST_SIZE]; - - sig = (VbSignature *)vb2_calculate_signature(test_data, - sizeof(test_data), - private_key); - rsa = PublicKeyToRSA(public_key); - TEST_SUCC(vb2_digest_buffer(test_data, sizeof(test_data), - vb2_crypto_to_hash(public_key->algorithm), - digest, sizeof(digest)), - "VerifyData() digest"); - - TEST_NEQ(sig && rsa, 0, "VerifyData() prerequisites"); - if (!sig || !rsa) - return; - - TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok"); - - GetSignatureData(sig)[0] ^= 0x5A; - TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig"); - - sig->sig_size = 1; - TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() sig size"); - - RSAPublicKeyFree(rsa); - free(sig); -} - -static void ReSignKernelPreamble(VbKernelPreambleHeader *h, - const struct vb2_private_key *key) -{ - struct vb2_signature *sig = vb2_calculate_signature( - (const uint8_t *)h, h->preamble_signature.data_size, key); - - vb2_copy_signature((struct vb2_signature *)&h->preamble_signature, sig); - free(sig); -} - -static void VerifyKernelPreambleTest(const VbPublicKey *public_key, - const struct vb2_private_key *private_key) -{ - VbKernelPreambleHeader *hdr; - VbKernelPreambleHeader *h; - RSAPublicKey *rsa; - unsigned hsize; - - /* Create a dummy signature */ - struct vb2_signature *body_sig = vb2_alloc_signature(56, 78); - - rsa = PublicKeyToRSA(public_key); - hdr = (VbKernelPreambleHeader *) - vb2_create_kernel_preamble(0x1234, 0x100000, 0x300000, 0x4000, - body_sig, 0, 0, 0, 0, private_key); - TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites"); - if (!hdr) { - free(body_sig); - RSAPublicKeyFree(rsa); - return; - } - - hsize = (unsigned) hdr->preamble_size; - h = (VbKernelPreambleHeader *)malloc(hsize + 16384); - - TEST_EQ(VerifyKernelPreamble(hdr, hsize, rsa), 0, - "VerifyKernelPreamble() ok using key"); - TEST_NEQ(VerifyKernelPreamble(hdr, hsize - 1, rsa), 0, - "VerifyKernelPreamble() size--"); - TEST_NEQ(VerifyKernelPreamble(hdr, 4, rsa), 0, - "VerifyKernelPreamble() size tiny"); - TEST_EQ(VerifyKernelPreamble(hdr, hsize + 1, rsa), 0, - "VerifyKernelPreamble() size++"); - - /* Care about major version but not minor */ - memcpy(h, hdr, hsize); - h->header_version_major++; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() major++"); - - memcpy(h, hdr, hsize); - h->header_version_major--; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() major--"); - - memcpy(h, hdr, hsize); - h->header_version_minor++; - ReSignKernelPreamble(h, private_key); - TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() minor++"); - - memcpy(h, hdr, hsize); - h->header_version_minor--; - ReSignKernelPreamble(h, private_key); - TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() minor--"); - - /* Check signature */ - memcpy(h, hdr, hsize); - h->preamble_signature.sig_offset = hsize; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() sig off end"); - - memcpy(h, hdr, hsize); - h->preamble_signature.sig_size--; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() sig too small"); - - memcpy(h, hdr, hsize); - GetSignatureData(&h->body_signature)[0] ^= 0x34; - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() sig mismatch"); - - /* Check that we signed header and body sig */ - memcpy(h, hdr, hsize); - h->preamble_signature.data_size = 4; - h->body_signature.sig_offset = 0; - h->body_signature.sig_size = 0; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() didn't sign header"); - - memcpy(h, hdr, hsize); - h->body_signature.sig_offset = hsize; - ReSignKernelPreamble(h, private_key); - TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0, - "VerifyKernelPreamble() body sig off end"); - - /* TODO: verify parser can support a bigger header. */ - - free(h); - RSAPublicKeyFree(rsa); - free(hdr); - free(body_sig); -} - -int test_algorithm(int key_algorithm, const char *keys_dir) -{ - char filename[1024]; - int rsa_len = siglen_map[key_algorithm] * 8; - - VbPublicKey *public_key = NULL; - - printf("***Testing algorithm: %s\n", algo_strings[key_algorithm]); - - snprintf(filename, sizeof(filename), - "%s/key_rsa%d.pem", keys_dir, rsa_len); - struct vb2_private_key *private_key = - vb2_read_private_key_pem(filename, key_algorithm); - if (!private_key) { - fprintf(stderr, "Error reading private_key: %s\n", filename); - return 1; - } - - snprintf(filename, sizeof(filename), - "%s/key_rsa%d.keyb", keys_dir, rsa_len); - public_key = (VbPublicKey *)vb2_read_packed_keyb(filename, - key_algorithm, 1); - if (!public_key) { - fprintf(stderr, "Error reading public_key: %s\n", filename); - free(private_key); - return 1; - } - - VerifyPublicKeyToRSA(public_key); - VerifyDataTest(public_key, private_key); - VerifyDigestTest(public_key, private_key); - VerifyKernelPreambleTest(public_key, private_key); - - free(public_key); - free(private_key); - - return 0; -} - -/* - * Test only the algorithms we use: - * 4 (rsa2048 sha256) - * 7 (rsa4096 sha256) - * 11 (rsa8192 sha512) - */ -const int key_algs[] = {4, 7, 11}; - -int main(int argc, char *argv[]) { - if (argc == 2) { - int i; - - for (i = 0; i < ARRAY_SIZE(key_algs); i++) { - if (test_algorithm(key_algs[i], argv[1])) - return 1; - } - - } else if (argc == 3 && !strcasecmp(argv[2], "--all")) { - /* Test all the algorithms */ - int alg; - - for (alg = 0; alg < kNumAlgorithms; alg++) { - if (test_algorithm(alg, argv[1])) - return 1; - } - - } else { - fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]); - return -1; - } - - if (vboot_api_stub_check_memory()) - return 255; - - return gTestSuccess ? 0 : 255; -} diff --git a/tests/vboot_common3_tests.c b/tests/vboot_common3_tests.c deleted file mode 100644 index 390b7f30..00000000 --- a/tests/vboot_common3_tests.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Copyright (c) 2013 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. - * - * Tests for firmware image library. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "2sysincludes.h" -#include "2common.h" -#include "2sha.h" -#include "cryptolib.h" -#include "file_keys.h" -#include "host_common.h" -#include "test_common.h" -#include "vboot_common.h" - - -static void ReChecksumKeyBlock(VbKeyBlockHeader *h) -{ - vb2_digest_buffer((const uint8_t *)h, - h->key_block_checksum.data_size, - VB2_HASH_SHA512, - GetSignatureData(&h->key_block_checksum), - VB2_SHA512_DIGEST_SIZE); -} - -static void KeyBlockVerifyTest(const VbPublicKey *public_key, - const struct vb2_private_key *private_key, - const struct vb2_packed_key *data_key) -{ - VbKeyBlockHeader *hdr; - VbKeyBlockHeader *h; - unsigned hsize; - - hdr = (VbKeyBlockHeader *) - vb2_create_keyblock((struct vb2_packed_key *)data_key, - private_key, - 0x1234); - TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites"); - if (!hdr) - return; - hsize = (unsigned) hdr->key_block_size; - h = (VbKeyBlockHeader *)malloc(hsize + 1024); - - TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0, - "KeyBlockVerify() ok using checksum"); - TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0, - "KeyBlockVerify() ok using key"); - TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0, - "KeyBlockVerify() missing key"); - - TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0, - "KeyBlockVerify() size--"); - TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0, - "KeyBlockVerify() size++"); - - memcpy(h, hdr, hsize); - h->magic[0] &= 0x12; - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() magic"); - - /* Care about major version but not minor */ - memcpy(h, hdr, hsize); - h->header_version_major++; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() major++"); - - memcpy(h, hdr, hsize); - h->header_version_major--; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() major--"); - - memcpy(h, hdr, hsize); - h->header_version_minor++; - ReChecksumKeyBlock(h); - TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() minor++"); - - memcpy(h, hdr, hsize); - h->header_version_minor--; - ReChecksumKeyBlock(h); - TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() minor--"); - - /* Check hash */ - memcpy(h, hdr, hsize); - h->key_block_checksum.sig_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum off end"); - - memcpy(h, hdr, hsize); - h->key_block_checksum.sig_size /= 2; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum too small"); - - memcpy(h, hdr, hsize); - GetPublicKeyData(&h->data_key)[0] ^= 0x34; - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() checksum mismatch"); - - /* Check signature */ - memcpy(h, hdr, hsize); - h->key_block_signature.sig_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig off end"); - - memcpy(h, hdr, hsize); - h->key_block_signature.sig_size--; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig too small"); - - memcpy(h, hdr, hsize); - GetPublicKeyData(&h->data_key)[0] ^= 0x34; - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0, - "KeyBlockVerify() sig mismatch"); - - memcpy(h, hdr, hsize); - h->key_block_checksum.data_size = h->key_block_size + 1; - TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0, - "KeyBlockVerify() checksum data past end of block"); - - /* Check that we signed header and data key */ - memcpy(h, hdr, hsize); - h->key_block_checksum.data_size = 4; - h->data_key.key_offset = 0; - h->data_key.key_size = 0; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() didn't sign header"); - - memcpy(h, hdr, hsize); - h->data_key.key_offset = hsize; - ReChecksumKeyBlock(h); - TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, - "KeyBlockVerify() data key off end"); - - /* Corner cases for error checking */ - TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0, - "KeyBlockVerify size too small"); - - /* - * TODO: verify parser can support a bigger header (i.e., one where - * data_key.key_offset is bigger than expected). - */ - - free(h); - free(hdr); -} - -int test_permutation(int signing_key_algorithm, int data_key_algorithm, - const char *keys_dir) -{ - char filename[1024]; - int signing_rsa_len = siglen_map[signing_key_algorithm] * 8; - int data_rsa_len = siglen_map[data_key_algorithm] * 8; - - struct vb2_private_key *signing_private_key = NULL; - struct vb2_packed_key *data_public_key = NULL; - VbPublicKey *signing_public_key = NULL; - int retval = 1; - - printf("***Testing signing algorithm: %s\n", - algo_strings[signing_key_algorithm]); - printf("***With data key algorithm: %s\n", - algo_strings[data_key_algorithm]); - - snprintf(filename, sizeof(filename), - "%s/key_rsa%d.pem", keys_dir, signing_rsa_len); - signing_private_key = - vb2_read_private_key_pem(filename, signing_key_algorithm); - if (!signing_private_key) { - fprintf(stderr, "Error reading signing_private_key: %s\n", - filename); - goto cleanup; - } - - snprintf(filename, sizeof(filename), - "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len); - signing_public_key = (VbPublicKey *) - vb2_read_packed_keyb(filename, signing_key_algorithm, 1); - if (!signing_public_key) { - fprintf(stderr, "Error reading signing_public_key: %s\n", - filename); - goto cleanup; - } - - snprintf(filename, sizeof(filename), - "%s/key_rsa%d.keyb", keys_dir, data_rsa_len); - data_public_key = vb2_read_packed_keyb(filename, data_key_algorithm, 1); - if (!data_public_key) { - fprintf(stderr, "Error reading data_public_key: %s\n", - filename); - goto cleanup; - } - - KeyBlockVerifyTest(signing_public_key, signing_private_key, - data_public_key); - retval = 0; - -cleanup: - if (signing_public_key) - free(signing_public_key); - if (signing_private_key) - free(signing_private_key); - if (data_public_key) - free(data_public_key); - - return retval; -} - -struct test_perm -{ - int signing_algorithm; - int data_key_algorithm; -}; - -/* - * Permutations of signing and data key algorithms in active use: - * 7 (rsa4096 sha256) - 4 (rsa2048 sha256) - * 11 (rsa8192 sha512) - 4 (rsa2048 sha256) - * 11 (rsa8192 sha512) - 7 (rsa4096 sha256) - */ -const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}}; - -int main(int argc, char *argv[]) -{ - if (argc == 2) { - /* Test only the algorithms we use */ - int i; - - for (i = 0; i < ARRAY_SIZE(test_perms); i++) { - if (test_permutation(test_perms[i].signing_algorithm, - test_perms[i].data_key_algorithm, - argv[1])) - return 1; - } - - } else if (argc == 3 && !strcasecmp(argv[2], "--all")) { - /* Test all the algorithms */ - int sign_alg, data_alg; - - for (sign_alg = 0; sign_alg < kNumAlgorithms; sign_alg++) { - for (data_alg = 0; data_alg < kNumAlgorithms; - data_alg++) { - if (test_permutation(sign_alg, data_alg, - argv[1])) - return 1; - } - } - } else { - fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]); - return -1; - } - - if (vboot_api_stub_check_memory()) - return 255; - - return gTestSuccess ? 0 : 255; -} diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c index e3695ab1..994b792c 100644 --- a/tests/vboot_kernel_tests.c +++ b/tests/vboot_kernel_tests.c @@ -23,6 +23,7 @@ #include "load_kernel_fw.h" #include "rollback_index.h" #include "test_common.h" +#include "vb2_struct.h" #include "vboot_api.h" #include "vboot_common.h" #include "vboot_kernel.h" @@ -54,8 +55,7 @@ static int gpt_init_fail; static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */ static int preamble_verify_fail; static int verify_data_fail; -static RSAPublicKey *mock_data_key; -static int mock_data_key_allocated; +static int unpack_key_fail; static int gpt_flag_external; static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048]; @@ -130,9 +130,7 @@ static void ResetMocks(void) key_block_verify_fail = 0; preamble_verify_fail = 0; verify_data_fail = 0; - - mock_data_key = (RSAPublicKey *)"TestDataKey"; - mock_data_key_allocated = 0; + unpack_key_fail = 0; gpt_flag_external = 0; @@ -246,54 +244,64 @@ void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest) memcpy(dest, fake_guid, sizeof(fake_guid)); } -int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size, - const VbPublicKey *key, int hash_only) { - - if (hash_only && key_block_verify_fail >= 2) - return VBERROR_SIMULATED; - else if (!hash_only && key_block_verify_fail >= 1) - return VBERROR_SIMULATED; +int vb2_unpack_key(struct vb2_public_key *key, + const uint8_t *buf, + uint32_t size) +{ + if (--unpack_key_fail == 0) + return VB2_ERROR_MOCK; - /* Use this as an opportunity to override the key block */ - memcpy((void *)block, &kbh, sizeof(kbh)); - return VBERROR_SUCCESS; + return VB2_SUCCESS; } -RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key) +int vb2_verify_keyblock(struct vb2_keyblock *block, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) { - TEST_EQ(mock_data_key_allocated, 0, " mock data key not allocated"); + if (key_block_verify_fail >= 1) + return VB2_ERROR_MOCK; - if (mock_data_key) - mock_data_key_allocated++; - - return mock_data_key; + /* Use this as an opportunity to override the key block */ + memcpy((void *)block, &kbh, sizeof(kbh)); + return VB2_SUCCESS; } -void RSAPublicKeyFree(RSAPublicKey* key) +int vb2_verify_keyblock_hash(const struct vb2_keyblock *block, + uint32_t size, + const struct vb2_workbuf *wb) { - TEST_EQ(mock_data_key_allocated, 1, " mock data key allocated"); - TEST_PTR_EQ(key, mock_data_key, " data key ptr"); - mock_data_key_allocated--; + if (key_block_verify_fail >= 2) + return VB2_ERROR_MOCK; + + /* Use this as an opportunity to override the key block */ + memcpy((void *)block, &kbh, sizeof(kbh)); + return VB2_SUCCESS; } -int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, - uint64_t size, const RSAPublicKey *key) +int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) { if (preamble_verify_fail) - return VBERROR_SIMULATED; + return VB2_ERROR_MOCK; /* Use this as an opportunity to override the preamble */ memcpy((void *)preamble, &kph, sizeof(kph)); - return VBERROR_SUCCESS; + return VB2_SUCCESS; } -int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig, - const RSAPublicKey *key) +int vb2_verify_data(const uint8_t *data, + uint32_t size, + struct vb2_signature *sig, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) { if (verify_data_fail) - return VBERROR_SIMULATED; + return VB2_ERROR_MOCK; - return VBERROR_SUCCESS; + return VB2_SUCCESS; } int vb2_digest_buffer(const uint8_t *buf, @@ -727,7 +735,7 @@ static void LoadKernelTest(void) TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode"); ResetMocks(); - mock_data_key = NULL; + unpack_key_fail = 2; TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data key"); |