diff options
author | Randall Spangler <rspangler@chromium.org> | 2014-11-21 11:04:36 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-11-27 06:35:09 +0000 |
commit | c644a8c0f2df024798ac0e60c6028261ed389a16 (patch) | |
tree | e9d4e91959ffd0a22025f34515b6a3996b94c863 | |
parent | fb9a216dd677d97f3d6963f668a9b84d349ef339 (diff) | |
download | vboot-c644a8c0f2df024798ac0e60c6028261ed389a16.tar.gz |
vboot2: Add host library functions for signing to new struct format
Including signing with bare hashes, and signing an object with more
than one signature. With unit tests, even.
BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests
Change-Id: Iad0b9f9f6cca7129071aebf0cbc60c0daa94d382
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/231452
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 41 | ||||
-rw-r--r-- | host/lib/host_misc2.c | 9 | ||||
-rw-r--r-- | host/lib/host_signature2.c | 273 | ||||
-rw-r--r-- | host/lib/include/host_misc.h | 12 | ||||
-rw-r--r-- | host/lib/include/host_signature2.h | 88 | ||||
-rw-r--r-- | tests/vb2_api2_tests.c | 2 | ||||
-rw-r--r-- | tests/vb2_common_tests.c | 1 | ||||
-rw-r--r-- | tests/vb2_convert_structs.c | 39 | ||||
-rw-r--r-- | tests/vb2_host_misc_tests.c | 5 | ||||
-rw-r--r-- | tests/vb2_host_sig_tests.c | 199 |
11 files changed, 642 insertions, 32 deletions
@@ -378,6 +378,7 @@ ifneq (${VBOOT2},) UTILLIB_SRCS += \ host/lib/host_key2.c \ host/lib/host_misc2.c \ + host/lib/host_signature2.c \ endif @@ -635,6 +636,7 @@ TEST_NAMES += \ tests/vb2_common3_tests \ tests/vb2_host_key_tests \ tests/vb2_host_misc_tests \ + tests/vb2_host_sig_tests \ tests/vb2_misc_tests \ tests/vb2_misc2_tests \ tests/vb2_misc3_tests \ @@ -988,10 +990,12 @@ ${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_api2_tests: 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} +${BUILD}/tests/vb2_host_sig_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vboot_common2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vboot_common3_tests: LDLIBS += ${CRYPTO_LIBS} @@ -1173,6 +1177,7 @@ run2tests: test_setup ${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_key_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_misc_tests + ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_sig_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_misc_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_misc2_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_misc3_tests diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index f12f2c12..8f5a5c51 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -559,6 +559,47 @@ enum vb2_return_code { VB2_ERROR_PUBLIC_KEY_HASH, /********************************************************************** + * Errors generated by host library signature functions + */ + VB2_ERROR_HOST_SIG = VB2_ERROR_HOST_BASE + 0x030000, + + /* Bad hash algorithm in vb2_digest_info() */ + VB2_ERROR_DIGEST_INFO, + + /* + * Unable to determine signature size for key algorithm in + * vb2_sig_size_for_key(). + */ + VB2_ERROR_SIG_SIZE_FOR_KEY, + + /* Bad signature size in vb2_sign_data() */ + VB2_SIGN_DATA_SIG_SIZE, + + /* Unable to get digest info in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_INFO, + + /* Unable to get digest size in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_SIZE, + + /* Unable to allocate digest buffer in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_ALLOC, + + /* Unable to initialize digest in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_INIT, + + /* Unable to extend digest in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_EXTEND, + + /* Unable to finalize digest in vb2_sign_data() */ + VB2_SIGN_DATA_DIGEST_FINALIZE, + + /* RSA encrypt failed in vb2_sign_data() */ + VB2_SIGN_DATA_RSA_ENCRYPT, + + /* Not enough buffer space to hold signature in vb2_sign_object() */ + VB2_SIGN_OBJECT_OVERFLOW, + + /********************************************************************** * Highest non-zero error generated inside vboot library. Note that * error codes passed through vboot when it calls external APIs may * still be outside this range. diff --git a/host/lib/host_misc2.c b/host/lib/host_misc2.c index 71a20673..a78a7132 100644 --- a/host/lib/host_misc2.c +++ b/host/lib/host_misc2.c @@ -83,3 +83,12 @@ int vb2_write_object(const char *filename, const void *buf) return vb2_write_file(filename, buf, cptr->total_size); } + +uint32_t vb2_desc_size(const char *desc) +{ + if (!desc || !*desc) + return 0; + + return roundup32(strlen(desc) + 1); +} + diff --git a/host/lib/host_signature2.c b/host/lib/host_signature2.c new file mode 100644 index 00000000..c5b2c466 --- /dev/null +++ b/host/lib/host_signature2.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2014 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. + * + * Host functions for signatures. + */ + +#define OPENSSL_NO_SHA +#include <openssl/engine.h> +#include <openssl/pem.h> +#include <openssl/rsa.h> + +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" +#include "2sha.h" +#include "host_common.h" +#include "host_key2.h" +#include "host_signature2.h" +#include "host_misc.h" + +/** + * Get the digest info for a hash algorithm + * + * @param hash_alg Hash algorithm + * @param buf_ptr On success, points to the digest info + * @param size_ptr On success, contains the info size in bytes + * @return VB2_SUCCESS, or non-zero error code on failure. + */ +static int vb2_digest_info(enum vb2_hash_algorithm hash_alg, + const uint8_t **buf_ptr, + uint32_t *size_ptr) +{ + *buf_ptr = NULL; + *size_ptr = 0; + + switch (hash_alg) { +#if VB2_SUPPORT_SHA1 + case VB2_HASH_SHA1: + { + static const uint8_t info[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 + }; + *buf_ptr = info; + *size_ptr = sizeof(info); + return VB2_SUCCESS; + } +#endif +#if VB2_SUPPORT_SHA256 + case VB2_HASH_SHA256: + { + static const uint8_t info[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 + }; + *buf_ptr = info; + *size_ptr = sizeof(info); + return VB2_SUCCESS; + } +#endif +#if VB2_SUPPORT_SHA512 + case VB2_HASH_SHA512: + { + static const uint8_t info[] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 + }; + *buf_ptr = info; + *size_ptr = sizeof(info); + return VB2_SUCCESS; + } +#endif + default: + return VB2_ERROR_DIGEST_INFO; + } +} + +int vb2_sign_data(struct vb2_signature2 **sig_ptr, + const uint8_t *data, + uint32_t size, + const struct vb2_private_key *key, + const char *desc) +{ + struct vb2_signature2 s = { + .c.magic = VB2_MAGIC_SIGNATURE2, + .c.struct_version_major = VB2_SIGNATURE2_VERSION_MAJOR, + .c.struct_version_minor = VB2_SIGNATURE2_VERSION_MINOR, + .c.fixed_size = sizeof(s), + .sig_alg = key->sig_alg, + .hash_alg = key->hash_alg, + .data_size = size, + .guid = key->guid, + }; + + struct vb2_digest_context dc; + uint32_t digest_size; + const uint8_t *info = NULL; + uint32_t info_size = 0; + uint32_t sig_digest_size; + uint8_t *sig_digest; + uint8_t *buf; + + *sig_ptr = NULL; + + /* Use key description if no description supplied */ + if (!desc) + desc = key->desc; + + s.c.desc_size = vb2_desc_size(desc); + + s.sig_offset = s.c.fixed_size + s.c.desc_size; + s.sig_size = vb2_sig_size(key->sig_alg, key->hash_alg); + if (!s.sig_size) + return VB2_SIGN_DATA_SIG_SIZE; + + s.c.total_size = s.sig_offset + s.sig_size; + + /* Determine digest size and allocate buffer */ + if (s.sig_alg != VB2_SIG_NONE) { + if (vb2_digest_info(s.hash_alg, &info, &info_size)) + return VB2_SIGN_DATA_DIGEST_INFO; + } + + digest_size = vb2_digest_size(key->hash_alg); + if (!digest_size) + return VB2_SIGN_DATA_DIGEST_SIZE; + + sig_digest_size = info_size + digest_size; + sig_digest = malloc(sig_digest_size); + if (!sig_digest) + return VB2_SIGN_DATA_DIGEST_ALLOC; + + /* Prepend digest info, if any */ + if (info_size) + memcpy(sig_digest, info, info_size); + + /* Calculate hash digest */ + if (vb2_digest_init(&dc, s.hash_alg)) { + free(sig_digest); + return VB2_SIGN_DATA_DIGEST_INIT; + } + + if (vb2_digest_extend(&dc, data, size)) { + free(sig_digest); + return VB2_SIGN_DATA_DIGEST_EXTEND; + } + + if (vb2_digest_finalize(&dc, sig_digest + info_size, digest_size)) { + free(sig_digest); + return VB2_SIGN_DATA_DIGEST_FINALIZE; + } + + /* Allocate signature buffer and copy header */ + buf = malloc(s.c.total_size); + memset(buf, 0, s.c.total_size); + memcpy(buf, &s, sizeof(s)); + + /* strcpy() is ok because we allocated buffer based on desc length */ + if (desc) + strcpy((char *)buf + s.c.fixed_size, desc); + + if (s.sig_alg == VB2_SIG_NONE) { + /* Bare hash signature is just the digest */ + memcpy(buf + s.sig_offset, sig_digest, sig_digest_size); + } else { + /* RSA-encrypt the signature */ + if (RSA_private_encrypt(sig_digest_size, + sig_digest, + buf + s.sig_offset, + key->rsa_private_key, + RSA_PKCS1_PADDING) == -1) { + free(sig_digest); + free(buf); + return VB2_SIGN_DATA_RSA_ENCRYPT; + } + } + + free(sig_digest); + *sig_ptr = (struct vb2_signature2 *)buf; + return VB2_SUCCESS; +} + +int vb2_sig_size_for_key(uint32_t *size_ptr, + const struct vb2_private_key *key, + const char *desc) +{ + uint32_t size = vb2_sig_size(key->sig_alg, key->hash_alg); + + if (!size) + return VB2_ERROR_SIG_SIZE_FOR_KEY; + + size += sizeof(struct vb2_signature2); + size += vb2_desc_size(desc ? desc : key->desc); + + *size_ptr = size; + return VB2_SUCCESS; +} + +int vb2_sig_size_for_keys(uint32_t *size_ptr, + const struct vb2_private_key **key_list, + uint32_t key_count) +{ + uint32_t total = 0, size = 0; + int rv, i; + + *size_ptr = 0; + + for (i = 0; i < key_count; i++) { + rv = vb2_sig_size_for_key(&size, key_list[i], NULL); + if (rv) + return rv; + total += size; + } + + *size_ptr = total; + return VB2_SUCCESS; +} + +int vb2_sign_object(uint8_t *buf, + uint32_t sig_offset, + const struct vb2_private_key *key, + const char *desc) +{ + struct vb2_struct_common *c = (struct vb2_struct_common *)buf; + struct vb2_signature2 *sig = NULL; + int rv; + + rv = vb2_sign_data(&sig, buf, sig_offset, key, desc); + if (rv) + return rv; + + if (sig_offset + sig->c.total_size > c->total_size) { + free(sig); + return VB2_SIGN_OBJECT_OVERFLOW; + } + + memcpy(buf + sig_offset, sig, sig->c.total_size); + free(sig); + + return VB2_SUCCESS; +} + +int vb2_sign_object_multiple(uint8_t *buf, + uint32_t sig_offset, + const struct vb2_private_key **key_list, + uint32_t key_count) +{ + struct vb2_struct_common *c = (struct vb2_struct_common *)buf; + uint32_t sig_next = sig_offset; + int rv, i; + + for (i = 0; i < key_count; i++) { + struct vb2_signature2 *sig = NULL; + + rv = vb2_sign_data(&sig, buf, sig_offset, key_list[i], NULL); + if (rv) + return rv; + + if (sig_next + sig->c.total_size > c->total_size) { + free(sig); + return VB2_SIGN_OBJECT_OVERFLOW; + } + + memcpy(buf + sig_next, sig, sig->c.total_size); + sig_next += sig->c.total_size; + free(sig); + } + + return VB2_SUCCESS; +} diff --git a/host/lib/include/host_misc.h b/host/lib/include/host_misc.h index 2e18d90b..6dc225c1 100644 --- a/host/lib/include/host_misc.h +++ b/host/lib/include/host_misc.h @@ -84,4 +84,16 @@ static __inline const uint32_t roundup32(uint32_t v) return (v + 3) & ~3; } +/** + * Return the buffer size required to hold a description string. + * + * If the string is NULL or empty, the size is zero. Otherwise, it is the + * size of a buffer which can hold the string and its null terminator, + * rounded up to the nerest multiple of 32 bits. + * + * @param desc Description string + * @return The buffer size in bytes. + */ +uint32_t vb2_desc_size(const char *desc); + #endif /* VBOOT_REFERENCE_HOST_MISC_H_ */ diff --git a/host/lib/include/host_signature2.h b/host/lib/include/host_signature2.h new file mode 100644 index 00000000..2e5718b7 --- /dev/null +++ b/host/lib/include/host_signature2.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2014 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. + * + * Host-side functions for verified boot key structures + */ + +#ifndef VBOOT_REFERENCE_HOST_SIGNATURE2_H_ +#define VBOOT_REFERENCE_HOST_SIGNATURE2_H_ + +#include "2struct.h" + +struct vb2_private_key; + +/** + * Sign data buffer + * + * @param sig_ptr On success, points to a newly allocated signature. + * Caller is responsible for calling free() on this. + * @param data Pointer to data to sign + * @param size Size of data to sign in bytes + * @param key Private key to use to sign data + * @param desc Optional description for signature. If NULL, the + * key description will be used. + * @return VB2_SUCCESS, or non-zero error code on failure. + */ +int vb2_sign_data(struct vb2_signature2 **sig_ptr, + const uint8_t *data, + uint32_t size, + const struct vb2_private_key *key, + const char *desc); + +/** + * Calculate the signature size for a private key. + * + * @param size_ptr On success, contains the signature size in bytes. + * @param key Key to calculate signature length from. + * @param desc Optional description for signature. If NULL, the + * key description will be used. + * @return VB2_SUCCESS, or non-zero error code on failure. + */ +int vb2_sig_size_for_key(uint32_t *size_ptr, + const struct vb2_private_key *key, + const char *desc); + +/** + * Calculate the total signature size for a list of keys. + * + * @param size_ptr On success, contains the signature size in bytes. + * @param key_list List of keys to calculate signature length from. + * @param key_count Number of keys. + * @return VB2_SUCCESS, or non-zero error code on failure. + */ +int vb2_sig_size_for_keys(uint32_t *size_ptr, + const struct vb2_private_key **key_list, + uint32_t key_count); + +/** + * Sign object with a key. + * + * @param buf Buffer containing object to sign, starting with + * common header + * @param sig_offset Offset in buffer at which to store signature. All + * data before this in the buffer will be signed. + * @param key Key to sign object with + * @param desc If non-null, description to use for signature + */ +int vb2_sign_object(uint8_t *buf, + uint32_t sig_offset, + const struct vb2_private_key *key, + const char *desc); + +/** + * Sign object with list of keys. + * + * @param buf Buffer containing object to sign, starting with + * common header + * @param sig_offset Offset to start signatures. All data before this + * in the buffer will be signed. + * @param key_list List of keys to sign object with + * @param key_count Number of keys in list + */ +int vb2_sign_object_multiple(uint8_t *buf, + uint32_t sig_offset, + const struct vb2_private_key **key_list, + uint32_t key_count); + +#endif /* VBOOT_REFERENCE_HOST_SIGNATURE2_H_ */ diff --git a/tests/vb2_api2_tests.c b/tests/vb2_api2_tests.c index 17fc3b96..b6db1850 100644 --- a/tests/vb2_api2_tests.c +++ b/tests/vb2_api2_tests.c @@ -15,6 +15,8 @@ #include "2rsa.h" #include "2secdata.h" +#include "host_signature2.h" + #include "test_common.h" #include "vb2_convert_structs.h" diff --git a/tests/vb2_common_tests.c b/tests/vb2_common_tests.c index 37996ae3..29adfe84 100644 --- a/tests/vb2_common_tests.c +++ b/tests/vb2_common_tests.c @@ -9,6 +9,7 @@ #include "2common.h" #include "2rsa.h" #include "host_key2.h" +#include "host_signature2.h" #include "vb2_convert_structs.h" #include "vboot_struct.h" /* For old struct sizes */ diff --git a/tests/vb2_convert_structs.c b/tests/vb2_convert_structs.c index d30b337f..68cb326d 100644 --- a/tests/vb2_convert_structs.c +++ b/tests/vb2_convert_structs.c @@ -9,7 +9,9 @@ #include "2common.h" #include "2rsa.h" #include "host_common.h" +#include "host_key2.h" #include "host_misc.h" +#include "host_signature2.h" #include "vb2_convert_structs.h" #include "vboot_struct.h" /* For old struct sizes */ @@ -117,41 +119,14 @@ struct vb2_signature2 *vb2_create_hash_sig(const uint8_t *data, uint32_t size, enum vb2_hash_algorithm hash_alg) { - const char desc[12] = "hash sig"; - struct vb2_signature2 s = { - .c.magic = VB2_MAGIC_SIGNATURE2, - .c.struct_version_major = VB2_SIGNATURE2_VERSION_MAJOR, - .c.struct_version_minor = VB2_SIGNATURE2_VERSION_MINOR, - .c.fixed_size = sizeof(s), - .c.desc_size = sizeof(desc), - .sig_alg = VB2_SIG_NONE, - .hash_alg = hash_alg, - .sig_size = vb2_sig_size(VB2_SIG_NONE, hash_alg), - .data_size = size, - }; - const struct vb2_guid *hash_guid = vb2_hash_guid(hash_alg); - struct vb2_digest_context dc; - uint8_t *buf; + const struct vb2_private_key *key; + struct vb2_signature2 *sig; - /* Make sure hash algorithm was supported */ - if (!hash_guid || !s.sig_size) + if (vb2_private_key_hash(&key, hash_alg)) return NULL; - memcpy(&s.guid, hash_guid, sizeof(s.guid)); - s.sig_offset = s.c.fixed_size + s.c.desc_size; - s.c.total_size = s.sig_offset + s.sig_size; - - buf = malloc(s.c.total_size); - memset(buf, 0, s.c.total_size); - memcpy(buf, &s, sizeof(s)); - memcpy(buf + s.c.fixed_size, desc, sizeof(desc)); - - if (vb2_digest_init(&dc, hash_alg) || - vb2_digest_extend(&dc, data, size) || - vb2_digest_finalize(&dc, buf + s.sig_offset, s.sig_size)) { - free(buf); + if (vb2_sign_data(&sig, data, size, key, NULL)) return NULL; - } - return (struct vb2_signature2 *)buf; + return sig; } diff --git a/tests/vb2_host_misc_tests.c b/tests/vb2_host_misc_tests.c index e8c2a588..a78c7450 100644 --- a/tests/vb2_host_misc_tests.c +++ b/tests/vb2_host_misc_tests.c @@ -19,6 +19,11 @@ static void misc_tests(void) TEST_EQ(roundup32(0), 0, "roundup32(0)"); TEST_EQ(roundup32(15), 16, "roundup32(15)"); TEST_EQ(roundup32(16), 16, "roundup32(16)"); + + TEST_EQ(vb2_desc_size(NULL), 0, "desc size null"); + TEST_EQ(vb2_desc_size(""), 0, "desc size empty"); + TEST_EQ(vb2_desc_size("foo"), 4, "desc size 'foo'"); + TEST_EQ(vb2_desc_size("foob"), 8, "desc size 'foob'"); } static void file_tests(void) diff --git a/tests/vb2_host_sig_tests.c b/tests/vb2_host_sig_tests.c new file mode 100644 index 00000000..a2793bc9 --- /dev/null +++ b/tests/vb2_host_sig_tests.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2014 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 host library vboot2 key functions + */ + +#include <stdio.h> +#include <unistd.h> + +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" +#include "host_common.h" +#include "host_key2.h" +#include "host_signature2.h" +#include "test_common.h" + +/* Test only the algorithms we use */ +struct alg_combo { + const char *name; + enum vb2_signature_algorithm sig_alg; + enum vb2_hash_algorithm hash_alg; +}; + +static const struct alg_combo test_algs[] = { + {"RSA2048/SHA-256", VB2_SIG_RSA2048, VB2_HASH_SHA256}, + {"RSA4096/SHA-256", VB2_SIG_RSA4096, VB2_HASH_SHA256}, + {"RSA8192/SHA-512", VB2_SIG_RSA8192, VB2_HASH_SHA512}, +}; + +const struct vb2_guid test_guid = {.raw = {0xaa}}; +const char *test_desc = "The test key"; +const char *test_sig_desc = "The test signature"; +const uint8_t test_data[] = "Some test data"; +const uint32_t test_size = sizeof(test_data); + +static void sig_tests(const struct alg_combo *combo, + const char *pemfile, + const char *keybfile) +{ + struct vb2_private_key *prik, prik2; + const struct vb2_private_key *prihash, *priks[2]; + struct vb2_public_key *pubk, pubhash; + struct vb2_signature2 *sig, *sig2; + uint32_t size; + + uint8_t workbuf[VB2_VERIFY_DATA_WORKBUF_BYTES]; + struct vb2_workbuf wb; + + uint8_t *buf; + uint32_t bufsize; + struct vb2_struct_common *c; + uint32_t c_sig_offs; + + vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); + + /* Create test keys */ + /* TODO: should read these from .vbprik2, .vbpubk2 files */ + TEST_SUCC(vb2_private_key_read_pem(&prik, pemfile), "Read private key"); + prik->guid = test_guid; + prik->hash_alg = combo->hash_alg; + prik->sig_alg = combo->sig_alg; + vb2_private_key_set_desc(prik, test_desc); + + TEST_SUCC(vb2_public_key_read_keyb(&pubk, keybfile), "Read pub key"); + pubk->guid = &test_guid; + pubk->hash_alg = combo->hash_alg; + vb2_public_key_set_desc(pubk, test_desc); + + TEST_SUCC(vb2_private_key_hash(&prihash, combo->hash_alg), + "Private hash key"); + TEST_SUCC(vb2_public_key_hash(&pubhash, combo->hash_alg), + "Public hash key"); + + priks[0] = prik; + priks[1] = prihash; + + /* Sign test data */ + TEST_SUCC(vb2_sign_data(&sig, test_data, test_size, prik, NULL), + "Sign good"); + TEST_PTR_NEQ(sig, NULL, " sig_ptr"); + TEST_EQ(0, strcmp((char *)sig + sig->c.fixed_size, test_desc), + " desc"); + TEST_EQ(0, memcmp(&sig->guid, &test_guid, sizeof(test_guid)), " guid"); + TEST_EQ(sig->data_size, test_size, " data_size"); + TEST_SUCC(vb2_sig_size_for_key(&size, prik, NULL), "Sig size"); + TEST_EQ(size, sig->c.total_size, " size"); + TEST_SUCC(vb2_verify_data2(test_data, test_size, sig, pubk, &wb), + "Verify good"); + free(sig); + + TEST_SUCC(vb2_sign_data(&sig, test_data, test_size, prik, + test_sig_desc), + "Sign with desc"); + TEST_EQ(0, strcmp((char *)sig + sig->c.fixed_size, test_sig_desc), + " desc"); + free(sig); + + TEST_SUCC(vb2_sign_data(&sig, test_data, test_size, prik, ""), + "Sign with no desc"); + TEST_EQ(sig->c.desc_size, 0, " desc"); + TEST_SUCC(vb2_sig_size_for_key(&size, prik, ""), "Sig size"); + TEST_EQ(size, sig->c.total_size, " size"); + free(sig); + + TEST_SUCC(vb2_sign_data(&sig, test_data, test_size, prihash, NULL), + "Sign with hash"); + TEST_SUCC(vb2_verify_data2(test_data, test_size, sig, &pubhash, &wb), + "Verify with hash"); + free(sig); + + prik2 = *prik; + prik2.sig_alg = VB2_SIG_INVALID; + TEST_EQ(vb2_sign_data(&sig, test_data, test_size, &prik2, NULL), + VB2_SIGN_DATA_SIG_SIZE, "Sign bad sig alg"); + + /* Sign an object with a little (24 bytes) data */ + c_sig_offs = sizeof(*c) + 24; + TEST_SUCC(vb2_sig_size_for_key(&size, prik, NULL), "Sig size"); + bufsize = c_sig_offs + size; + buf = malloc(bufsize); + memset(buf, 0, bufsize); + memset(buf + sizeof(*c), 0x12, 24); + c = (struct vb2_struct_common *)buf; + c->total_size = bufsize; + + TEST_SUCC(vb2_sign_object(buf, c_sig_offs, prik, NULL), "Sign object"); + sig = (struct vb2_signature2 *)(buf + c_sig_offs); + TEST_SUCC(vb2_verify_data2(buf, c_sig_offs, sig, pubk, &wb), + "Verify object"); + + TEST_EQ(vb2_sign_object(buf, c_sig_offs + 4, prik, NULL), + VB2_SIGN_OBJECT_OVERFLOW, "Sign object overflow"); + free(buf); + + /* Multiply sign an object */ + TEST_SUCC(vb2_sig_size_for_keys(&size, priks, 2), "Sigs size"); + bufsize = c_sig_offs + size; + buf = malloc(bufsize); + memset(buf, 0, bufsize); + memset(buf + sizeof(*c), 0x12, 24); + c = (struct vb2_struct_common *)buf; + c->total_size = bufsize; + + TEST_SUCC(vb2_sign_object_multiple(buf, c_sig_offs, priks, 2), + "Sign multiple"); + sig = (struct vb2_signature2 *)(buf + c_sig_offs); + TEST_SUCC(vb2_verify_data2(buf, c_sig_offs, sig, pubk, &wb), + "Verify object with sig 1"); + sig2 = (struct vb2_signature2 *)(buf + c_sig_offs + sig->c.total_size); + TEST_SUCC(vb2_verify_data2(buf, c_sig_offs, sig2, &pubhash, &wb), + "Verify object with sig 2"); + + c->total_size -= 4; + TEST_EQ(vb2_sign_object_multiple(buf, c_sig_offs, priks, 2), + VB2_SIGN_OBJECT_OVERFLOW, "Sign multple overflow"); + + TEST_EQ(size, sig->c.total_size + sig2->c.total_size, + "Sigs size total"); + + free(buf); + + vb2_private_key_free(prik); + vb2_public_key_free(pubk); +} + +static int test_algorithm(const struct alg_combo *combo, const char *keys_dir) +{ + int rsa_bits = vb2_rsa_sig_size(combo->sig_alg) * 8; + char pemfile[1024]; + char keybfile[1024]; + + printf("***Testing algorithm: %s\n", combo->name); + + sprintf(pemfile, "%s/key_rsa%d.pem", keys_dir, rsa_bits); + sprintf(keybfile, "%s/key_rsa%d.keyb", keys_dir, rsa_bits); + + sig_tests(combo, pemfile, keybfile); + + return 0; +} + +int main(int argc, char *argv[]) { + + if (argc == 2) { + int i; + + for (i = 0; i < ARRAY_SIZE(test_algs); i++) { + if (test_algorithm(test_algs + i, argv[1])) + return 1; + } + } else { + fprintf(stderr, "Usage: %s <keys_dir>", argv[0]); + return -1; + } + + return gTestSuccess ? 0 : 255; +} |