diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | firmware/lib/cryptolib/include/rsa.h | 70 | ||||
-rw-r--r-- | firmware/lib/cryptolib/rsa.c | 188 | ||||
-rw-r--r-- | firmware/lib/cryptolib/rsa_utility.c | 162 | ||||
-rw-r--r-- | host/lib/file_keys.c | 49 | ||||
-rw-r--r-- | host/lib/host_key.c | 18 | ||||
-rw-r--r-- | host/lib/host_key2.c | 6 | ||||
-rw-r--r-- | host/lib/include/file_keys.h | 15 | ||||
-rw-r--r-- | host/linktest/main.c | 2 | ||||
-rw-r--r-- | tests/rsa_padding_test.c | 91 | ||||
-rw-r--r-- | tests/rsa_utility_tests.c | 213 | ||||
-rw-r--r-- | tests/rsa_verify_benchmark.c | 95 | ||||
-rwxr-xr-x | tests/run_rsa_tests.sh | 44 | ||||
-rw-r--r-- | tests/vb20_rsa_padding_tests.c | 50 | ||||
-rw-r--r-- | utility/include/verify_data.h | 20 | ||||
-rw-r--r-- | utility/pad_digest_utility.c | 5 | ||||
-rw-r--r-- | utility/signature_digest_utility.c | 8 | ||||
-rw-r--r-- | utility/verify_data.c | 182 |
18 files changed, 138 insertions, 1089 deletions
@@ -324,8 +324,6 @@ VBINIT_SRCS = \ # Additional firmware library sources needed by VbSelectFirmware() call VBSF_SRCS = \ firmware/lib/cryptolib/padding.c \ - firmware/lib/cryptolib/rsa.c \ - firmware/lib/cryptolib/rsa_utility.c \ firmware/lib/stateful_util.c \ firmware/lib/vboot_common.c \ firmware/lib/region-fw.c \ @@ -724,9 +722,6 @@ TEST_OBJS += ${TESTLIB_OBJS} TEST_NAMES = \ tests/cgptlib_test \ tests/rollback_index3_tests \ - tests/rsa_padding_test \ - tests/rsa_utility_tests \ - tests/rsa_verify_benchmark \ tests/sha_benchmark \ tests/stateful_util_tests \ tests/utility_string_tests \ @@ -1187,6 +1182,7 @@ ${TEST2X_BINS}: LIBS += ${FWLIB2X} ${TEST20_BINS}: ${FWLIB20} ${TEST20_BINS}: LIBS += ${FWLIB20} +${TEST20_BINS}: LDLIBS += ${CRYPTO_LIBS} ${TESTBDB_BINS}: ${FWLIB2X} ${UTILBDB} ${TESTBDB_BINS}: INCLUDES += -Ifirmware/bdb @@ -1251,6 +1247,7 @@ CRYPTO_LIBS := $(shell ${PKG_CONFIG} --libs libcrypto) ${BUILD}/utility/dumpRSAPublicKey: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/pad_digest_utility: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/signature_digest_utility: LDLIBS += ${CRYPTO_LIBS} +${BUILD}/utility/verify_data: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/bdb_extend: ${FWLIB2X} ${UTILBDB} ${BUILD}/utility/bdb_extend.o: INCLUDES += -Ifirmware/bdb @@ -1408,7 +1405,6 @@ runtestscripts: test_setup genfuzztestcases tests/run_cgpt_tests.sh ${BUILD_RUN}/cgpt/cgpt tests/run_cgpt_tests.sh ${BUILD_RUN}/cgpt/cgpt -D 358400 tests/run_preamble_tests.sh - tests/run_rsa_tests.sh tests/run_vbutil_kernel_arg_tests.sh tests/run_vbutil_tests.sh tests/vb2_rsa_tests.sh @@ -1421,7 +1417,6 @@ ifeq (${TPM2_MODE},) ${RUNTEST} ${BUILD_RUN}/tests/rollback_index2_tests endif ${RUNTEST} ${BUILD_RUN}/tests/rollback_index3_tests - ${RUNTEST} ${BUILD_RUN}/tests/rsa_utility_tests ${RUNTEST} ${BUILD_RUN}/tests/stateful_util_tests ${RUNTEST} ${BUILD_RUN}/tests/utility_string_tests ${RUNTEST} ${BUILD_RUN}/tests/utility_tests diff --git a/firmware/lib/cryptolib/include/rsa.h b/firmware/lib/cryptolib/include/rsa.h index eff608dc..4e793763 100644 --- a/firmware/lib/cryptolib/include/rsa.h +++ b/firmware/lib/cryptolib/include/rsa.h @@ -22,74 +22,4 @@ #define RSA4096NUMWORDS (RSA4096NUMBYTES / sizeof(uint32_t)) #define RSA8192NUMWORDS (RSA8192NUMBYTES / sizeof(uint32_t)) -typedef struct RSAPublicKey { - uint32_t len; /* Length of n[] in number of uint32_t */ - uint32_t n0inv; /* -1 / n[0] mod 2^32 */ - uint32_t* n; /* modulus as little endian array */ - uint32_t* rr; /* R^2 as little endian array */ - unsigned int algorithm; /* Algorithm to use when verifying with the key */ -} RSAPublicKey; - -/* Verify a RSA PKCS1.5 signature [sig] of [sig_type] and length [sig_len] - * against an expected [hash] using [key]. Returns 0 on failure, 1 on success. - */ -int RSAVerify(const RSAPublicKey *key, - const uint8_t* sig, - const uint32_t sig_len, - const uint8_t sig_type, - const uint8_t* hash); - -/* Perform RSA signature verification on [buf] of length [len] against expected - * signature [sig] using signature algorithm [algorithm]. The public key used - * for verification can either be in the form of a pre-process key blob - * [key_blob] or RSAPublicKey structure [key]. One of [key_blob] or [key] must - * be non-NULL, and the other NULL or the function will fail. - * - * Returns 1 on verification success, 0 on verification failure or invalid - * arguments. - * - * Note: This function is for use in the firmware and assumes all pointers point - * to areas in the memory of the right size. - * - */ -int RSAVerifyBinary_f(const uint8_t* key_blob, - const RSAPublicKey* key, - const uint8_t* buf, - uint64_t len, - const uint8_t* sig, - unsigned int algorithm); - -/* Version of RSAVerifyBinary_f() where instead of the raw binary blob - * of data, its digest is passed as the argument. */ -int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob, - const RSAPublicKey* key, - const uint8_t* digest, - const uint8_t* sig, - unsigned int algorithm); - - -/* ----Some additional utility functions for RSA.---- */ - -/* Returns the size of a pre-processed RSA public key in - * [out_size] with the algorithm [algorithm]. - * - * Returns 1 on success, 0 on failure. - */ -uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size); - -/* Allocate a new RSAPublicKey structure and initialize its pointer fields to - * NULL */ -RSAPublicKey* RSAPublicKeyNew(void); - -/* Deep free the contents of [key]. */ -void RSAPublicKeyFree(RSAPublicKey* key); - -/* Create a RSAPublic key structure from binary blob [buf] of length - * [len]. - * - * Caller owns the returned key and must free it. - */ -RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len); - - #endif /* VBOOT_REFERENCE_RSA_H_ */ diff --git a/firmware/lib/cryptolib/rsa.c b/firmware/lib/cryptolib/rsa.c deleted file mode 100644 index a4c7262b..00000000 --- a/firmware/lib/cryptolib/rsa.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2011 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. - */ - -/* Implementation of RSA signature verification which uses a pre-processed - * key for computation. The code extends Android's RSA verification code to - * support multiple RSA key lengths and hash digest algorithms. - */ - -#include "sysincludes.h" - -#include "2sysincludes.h" -#include "2common.h" -#include "cryptolib.h" -#include "vboot_api.h" -#include "utility.h" - -/* a[] -= mod */ -static void subM(const RSAPublicKey *key, uint32_t *a) { - int64_t A = 0; - uint32_t i; - for (i = 0; i < key->len; ++i) { - A += (uint64_t)a[i] - key->n[i]; - a[i] = (uint32_t)A; - A >>= 32; - } -} - -/* return a[] >= mod */ -static int geM(const RSAPublicKey *key, uint32_t *a) { - uint32_t i; - for (i = key->len; i;) { - --i; - if (a[i] < key->n[i]) return 0; - if (a[i] > key->n[i]) return 1; - } - return 1; /* equal */ - } - -/* montgomery c[] += a * b[] / R % mod */ -static void montMulAdd(const RSAPublicKey *key, - uint32_t* c, - const uint32_t a, - const uint32_t* b) { - uint64_t A = (uint64_t)a * b[0] + c[0]; - uint32_t d0 = (uint32_t)A * key->n0inv; - uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A; - uint32_t i; - - for (i = 1; i < key->len; ++i) { - A = (A >> 32) + (uint64_t)a * b[i] + c[i]; - B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A; - c[i - 1] = (uint32_t)B; - } - - A = (A >> 32) + (B >> 32); - - c[i - 1] = (uint32_t)A; - - if (A >> 32) { - subM(key, c); - } -} - -/* montgomery c[] = a[] * b[] / R % mod */ -static void montMul(const RSAPublicKey *key, - uint32_t* c, - uint32_t* a, - uint32_t* b) { - uint32_t i; - for (i = 0; i < key->len; ++i) { - c[i] = 0; - } - for (i = 0; i < key->len; ++i) { - montMulAdd(key, c, a[i], b); - } -} - -/* In-place public exponentiation. (65537} - * Input and output big-endian byte array in inout. - */ -static void modpowF4(const RSAPublicKey *key, - uint8_t* inout) { - uint32_t* a = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t)); - uint32_t* aR = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t)); - uint32_t* aaR = (uint32_t*) VbExMalloc(key->len * sizeof(uint32_t)); - - uint32_t* aaa = aaR; /* Re-use location. */ - int i; - - /* Convert from big endian byte array to little endian word array. */ - for (i = 0; i < (int)key->len; ++i) { - uint32_t tmp = - (inout[((key->len - 1 - i) * 4) + 0] << 24) | - (inout[((key->len - 1 - i) * 4) + 1] << 16) | - (inout[((key->len - 1 - i) * 4) + 2] << 8) | - (inout[((key->len - 1 - i) * 4) + 3] << 0); - a[i] = tmp; - } - - montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ - for (i = 0; i < 16; i+=2) { - montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ - montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */ - } - montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */ - - - /* Make sure aaa < mod; aaa is at most 1x mod too large. */ - if (geM(key, aaa)) { - subM(key, aaa); - } - - /* Convert to bigendian byte array */ - for (i = (int)key->len - 1; i >= 0; --i) { - uint32_t tmp = aaa[i]; - *inout++ = (uint8_t)(tmp >> 24); - *inout++ = (uint8_t)(tmp >> 16); - *inout++ = (uint8_t)(tmp >> 8); - *inout++ = (uint8_t)(tmp >> 0); - } - - VbExFree(a); - VbExFree(aR); - VbExFree(aaR); -} - -/* Verify a RSA PKCS1.5 signature against an expected hash. - * Returns 0 on failure, 1 on success. - */ -int RSAVerify(const RSAPublicKey *key, - const uint8_t *sig, - const uint32_t sig_len, - const uint8_t sig_type, - const uint8_t *hash) { - uint8_t* buf; - const uint8_t* padding; - int padding_len; - int success = 1; - - if (!key || !sig || !hash) - return 0; - - if (sig_len != (key->len * sizeof(uint32_t))) { - VBDEBUG(("Signature is of incorrect length!\n")); - return 0; - } - - if (sig_type >= kNumAlgorithms) { - VBDEBUG(("Invalid signature type!\n")); - return 0; - } - - if (key->len != siglen_map[sig_type] / sizeof(uint32_t)) { - VBDEBUG(("Wrong key passed in!\n")); - return 0; - } - - buf = (uint8_t*) VbExMalloc(sig_len); - if (!buf) - return 0; - memcpy(buf, sig, sig_len); - - modpowF4(key, buf); - - /* Determine padding to use depending on the signature type. */ - padding = padding_map[sig_type]; - padding_len = padding_size_map[sig_type]; - - /* Even though there are probably no timing issues here, we use - * vb2_safe_memcmp() just to be on the safe side. */ - - /* Check pkcs1.5 padding bytes. */ - if (vb2_safe_memcmp(buf, padding, padding_len)) { - VBDEBUG(("In RSAVerify(): Padding check failed!\n")); - success = 0; - } - - /* Check hash. */ - if (vb2_safe_memcmp(buf + padding_len, hash, sig_len - padding_len)) { - VBDEBUG(("In RSAVerify(): Hash check failed!\n")); - success = 0; - } - VbExFree(buf); - - return success; -} diff --git a/firmware/lib/cryptolib/rsa_utility.c b/firmware/lib/cryptolib/rsa_utility.c deleted file mode 100644 index 1195da04..00000000 --- a/firmware/lib/cryptolib/rsa_utility.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (c) 2012 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. - * - * Implementation of RSA utility functions. - */ - -#include "sysincludes.h" -#include "2sysincludes.h" - -#include "2common.h" -#include "2sha.h" -#include "cryptolib.h" -#include "stateful_util.h" -#include "utility.h" -#include "vboot_api.h" - -uint64_t RSAProcessedKeySize(uint64_t algorithm, uint64_t* out_size) { - int key_len; /* Key length in bytes. (int type matches siglen_map) */ - if (algorithm < kNumAlgorithms) { - key_len = siglen_map[algorithm]; - /* Total size needed by a RSAPublicKey buffer is = - * 2 * key_len bytes for the n and rr arrays - * + sizeof len + sizeof n0inv. - */ - *out_size = (2 * key_len + sizeof(uint32_t) + sizeof(uint32_t)); - return 1; - } - return 0; -} - -RSAPublicKey* RSAPublicKeyNew(void) { - RSAPublicKey* key = (RSAPublicKey*) VbExMalloc(sizeof(RSAPublicKey)); - key->n = NULL; - key->rr = NULL; - key->len = 0; - key->algorithm = kNumAlgorithms; - return key; -} - -void RSAPublicKeyFree(RSAPublicKey* key) { - if (key) { - if (key->n) - VbExFree(key->n); - if (key->rr) - VbExFree(key->rr); - VbExFree(key); - } -} - -RSAPublicKey* RSAPublicKeyFromBuf(const uint8_t* buf, uint64_t len) { - RSAPublicKey* key = RSAPublicKeyNew(); - MemcpyState st; - uint64_t key_len; - - StatefulInit(&st, (void*)buf, len); - - StatefulMemcpy(&st, &key->len, sizeof(key->len)); - /* key length in bytes (avoiding possible 32-bit rollover) */ - key_len = key->len; - key_len *= sizeof(uint32_t); - - /* Sanity Check the key length. */ - if (RSA1024NUMBYTES != key_len && - RSA2048NUMBYTES != key_len && - RSA4096NUMBYTES != key_len && - RSA8192NUMBYTES != key_len) { - RSAPublicKeyFree(key); - return NULL; - } - - key->n = (uint32_t*) VbExMalloc(key_len); - key->rr = (uint32_t*) VbExMalloc(key_len); - - StatefulMemcpy(&st, &key->n0inv, sizeof(key->n0inv)); - StatefulMemcpy(&st, key->n, key_len); - StatefulMemcpy(&st, key->rr, key_len); - if (st.overrun || st.remaining_len != 0) { /* Underrun or overrun. */ - RSAPublicKeyFree(key); - return NULL; - } - - return key; -} - -int RSAVerifyBinary_f(const uint8_t* key_blob, - const RSAPublicKey* key, - const uint8_t* buf, - uint64_t len, - const uint8_t* sig, - unsigned int algorithm) { - RSAPublicKey* verification_key = NULL; - uint8_t digest[VB2_MAX_DIGEST_SIZE]; - uint64_t key_size; - int sig_size; - int success = 0; - - if (algorithm >= (unsigned int)kNumAlgorithms) - return 0; /* Invalid algorithm. */ - if (!RSAProcessedKeySize(algorithm, &key_size)) - return 0; - sig_size = siglen_map[algorithm]; - - if (key_blob && !key) - verification_key = RSAPublicKeyFromBuf(key_blob, key_size); - else if (!key_blob && key) - verification_key = (RSAPublicKey*) key; /* Supress const warning. */ - else - return 0; /* Both can't be NULL or non-NULL. */ - - /* Ensure we have a valid key. */ - if (!verification_key) - return 0; - - if (VB2_SUCCESS == vb2_digest_buffer(buf, len, vb2_crypto_to_hash(algorithm), - digest, sizeof(digest))) { - success = RSAVerify(verification_key, sig, (uint32_t)sig_size, - (uint8_t)algorithm, digest); - } - - if (!key) - RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */ - - return success; -} - -/* Version of RSAVerifyBinary_f() where instead of the raw binary blob - * of data, its digest is passed as the argument. */ -int RSAVerifyBinaryWithDigest_f(const uint8_t* key_blob, - const RSAPublicKey* key, - const uint8_t* digest, - const uint8_t* sig, - unsigned int algorithm) { - RSAPublicKey* verification_key = NULL; - uint64_t key_size; - int sig_size; - int success; - - if (algorithm >= (unsigned int)kNumAlgorithms) - return 0; /* Invalid algorithm. */ - if (!RSAProcessedKeySize(algorithm, &key_size)) - return 0; - sig_size = siglen_map[algorithm]; - - if (key_blob && !key) - verification_key = RSAPublicKeyFromBuf(key_blob, key_size); - else if (!key_blob && key) - verification_key = (RSAPublicKey*) key; /* Supress const warning. */ - else - return 0; /* Both can't be NULL or non-NULL. */ - - /* Ensure we have a valid key. */ - if (!verification_key) - return 0; - - success = RSAVerify(verification_key, sig, (uint32_t)sig_size, - (uint8_t)algorithm, digest); - - if (!key) - RSAPublicKeyFree(verification_key); /* Only free if we allocated it. */ - return success; -} diff --git a/host/lib/file_keys.c b/host/lib/file_keys.c index 00fbe6f5..24c794f1 100644 --- a/host/lib/file_keys.c +++ b/host/lib/file_keys.c @@ -22,55 +22,6 @@ #include "host_common.h" #include "signature_digest.h" -uint8_t *BufferFromFile(const char* input_file, uint64_t* len) -{ - int fd; - struct stat stat_fd; - uint8_t* buf = NULL; - - if ((fd = open(input_file, O_RDONLY)) == -1) { - VBDEBUG(("Couldn't open file %s\n", input_file)); - return NULL; - } - - if (-1 == fstat(fd, &stat_fd)) { - VBDEBUG(("Couldn't stat file %s\n", input_file)); - close(fd); - return NULL; - } - *len = stat_fd.st_size; - - buf = (uint8_t *)malloc(*len); - if (!buf) { - VbExError("Couldn't allocate %ld bytes for file %s\n", - *len, input_file); - close(fd); - return NULL; - } - - if (*len != read(fd, buf, *len)) { - VBDEBUG(("Couldn't read file %s into a buffer\n", input_file)); - free(buf); - close(fd); - return NULL; - } - - close(fd); - return buf; -} - -RSAPublicKey *RSAPublicKeyFromFile(const char *input_file) -{ - uint64_t len; - RSAPublicKey* key = NULL; - - uint8_t *buf = BufferFromFile(input_file, &len); - if (buf) - key = RSAPublicKeyFromBuf(buf, len); - free(buf); - return key; -} - int DigestFile(char *input_file, enum vb2_hash_algorithm alg, uint8_t *digest, uint32_t digest_size) { diff --git a/host/lib/host_key.c b/host/lib/host_key.c index 02744477..c0a0fdd6 100644 --- a/host/lib/host_key.c +++ b/host/lib/host_key.c @@ -39,21 +39,3 @@ int packed_key_looks_ok(const struct vb2_packed_key *key, uint32_t size) /* Success */ return 1; } - -/* TODO: the host code just uses this to check the embedded key length in - * uint32_t's. It should get folded into packed_key_looks_ok. */ - -RSAPublicKey *vb2_packed_key_to_rsa(const struct vb2_packed_key *key) -{ - RSAPublicKey *rsa; - - if (!packed_key_looks_ok(key, key->key_size)) - return NULL; - - rsa = RSAPublicKeyFromBuf(vb2_packed_key_data(key), key->key_size); - if (!rsa) - return NULL; - - rsa->algorithm = (unsigned int)key->algorithm; - return rsa; -} diff --git a/host/lib/host_key2.c b/host/lib/host_key2.c index 0f4168ed..7e505761 100644 --- a/host/lib/host_key2.c +++ b/host/lib/host_key2.c @@ -238,9 +238,9 @@ struct vb2_packed_key *vb2_read_packed_keyb(const char *filename, if (VB2_SUCCESS != vb2_read_file(filename, &key_data, &key_size)) return NULL; - uint64_t expected_key_size; - if (!RSAProcessedKeySize(algorithm, &expected_key_size) || - expected_key_size != key_size) { + uint32_t expected_key_size = + vb2_packed_key_size(vb2_crypto_to_signature(algorithm)); + if (!expected_key_size || expected_key_size != key_size) { fprintf(stderr, "%s() - wrong key size %u for algorithm %u\n", __func__, key_size, algorithm); free(key_data); diff --git a/host/lib/include/file_keys.h b/host/lib/include/file_keys.h index e783c85e..0879c311 100644 --- a/host/lib/include/file_keys.h +++ b/host/lib/include/file_keys.h @@ -11,21 +11,6 @@ #include "cryptolib.h" #include "2sha.h" -/* Read file named [input_file] into a buffer and stores the length into - * [len]. - * - * Returns a pointer to the buffer. Caller owns the returned pointer and - * must free it. - */ -uint8_t* BufferFromFile(const char* input_file, uint64_t* len); - -/* Read a pre-processed RSA Public Key from file [input_file]. - * - * Returns a pointer to the read key. Caller owns the returned pointer and - * must free it. - */ -RSAPublicKey* RSAPublicKeyFromFile(const char* input_file); - /* Calculates the appropriate digest for the data in [input_file] based on the * hash algorithm [alg] and stores it into [digest], which is of size * [digest_size]. Returns VB2_SUCCESS, or non-zero on error. diff --git a/host/linktest/main.c b/host/linktest/main.c index 3e132115..aca2c745 100644 --- a/host/linktest/main.c +++ b/host/linktest/main.c @@ -20,8 +20,6 @@ int main(void) WriteFile(0, 0, 0); /* file_keys.h */ - BufferFromFile(0, 0); - RSAPublicKeyFromFile(0); DigestFile(0, 0, 0, 0); /* signature_digest.h */ diff --git a/tests/rsa_padding_test.c b/tests/rsa_padding_test.c deleted file mode 100644 index c97acee0..00000000 --- a/tests/rsa_padding_test.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2011 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. - */ - - -#include <stdint.h> -#include <stdio.h> - -#include "cryptolib.h" -#include "file_keys.h" -#include "rsa_padding_test.h" -#include "test_common.h" -#include "utility.h" - -/* Test valid and invalid signatures */ -static void TestSignatures(RSAPublicKey* key) { - int unexpected_success; - int i; - - /* The first test signature is valid. */ - TEST_EQ(RSAVerify(key, signatures[0], RSA1024NUMBYTES, 0, - test_message_sha1_hash), 1, "RSA Padding Test valid sig"); - - /* All other signatures should fail verification. */ - unexpected_success = 0; - for (i = 1; i < sizeof(signatures) / sizeof(signatures[0]); i++) { - if (RSAVerify(key, signatures[i], RSA1024NUMBYTES, 0, - test_message_sha1_hash)) { - fprintf(stderr, "RSA Padding Test vector %d FAILED!\n", i); - unexpected_success++; - } - } - TEST_EQ(unexpected_success, 0, "RSA Padding Test invalid sigs"); - -} - - -/* Test other error conditions in RSAVerify() */ -static void TestRSAVerify(RSAPublicKey* key) { - uint8_t sig[RSA1024NUMBYTES]; - - TEST_EQ(RSAVerify(key, signatures[0], RSA1024NUMBYTES, 0, - test_message_sha1_hash), 1, "RSAVerify() good"); - TEST_EQ(RSAVerify(key, signatures[0], RSA1024NUMBYTES - 1, 0, - test_message_sha1_hash), 0, "RSAVerify() sig len"); - TEST_EQ(RSAVerify(key, signatures[0], RSA1024NUMBYTES, kNumAlgorithms, - test_message_sha1_hash), 0, "RSAVerify() invalid alg"); - TEST_EQ(RSAVerify(key, signatures[0], RSA1024NUMBYTES, 3, - test_message_sha1_hash), 0, "RSAVerify() wrong alg"); - - /* Corrupt the signature near start and end */ - memcpy(sig, signatures[0], RSA1024NUMBYTES); - sig[3] ^= 0x42; - TEST_EQ(RSAVerify(key, sig, RSA1024NUMBYTES, 0, test_message_sha1_hash), 0, - "RSAVerify() bad sig"); - - memcpy(sig, signatures[0], RSA1024NUMBYTES); - sig[RSA1024NUMBYTES - 3] ^= 0x56; - TEST_EQ(RSAVerify(key, sig, RSA1024NUMBYTES, 0, test_message_sha1_hash), 0, - "RSAVerify() bad sig end"); -} - - -int main(int argc, char* argv[]) { - int error = 0; - RSAPublicKey* key; - - /* Read test key */ - if (argc != 2) { - fprintf(stderr, "Usage: %s <test public key>\n", argv[0]); - return 1; - } - key = RSAPublicKeyFromFile(argv[1]); - if (!key) { - fprintf(stderr, "Couldn't read RSA public key for the test.\n"); - return 1; - } - - /* Run tests */ - TestSignatures(key); - TestRSAVerify(key); - - /* Clean up and exit */ - RSAPublicKeyFree(key); - - if (!gTestSuccess) - error = 255; - - return error; -} diff --git a/tests/rsa_utility_tests.c b/tests/rsa_utility_tests.c deleted file mode 100644 index df1480ad..00000000 --- a/tests/rsa_utility_tests.c +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (c) 2011 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. - */ - - -#include <stdint.h> -#include <stdio.h> - -#define _STUB_IMPLEMENTATION_ - -#include "cryptolib.h" -#include "file_keys.h" -#include "rsa_padding_test.h" -#include "test_common.h" -#include "utility.h" -#include "vboot_api.h" - - -/* Data for mock functions */ -static int mock_rsaverify_retval; - -int RSAVerify(const RSAPublicKey *key, - const uint8_t* sig, - const uint32_t sig_len, - const uint8_t sig_type, - const uint8_t* hash) { - return mock_rsaverify_retval; -} - -static void ResetMocks(void) { - mock_rsaverify_retval = 1; -} - -/* Test RSA utility funcs */ -static void TestUtils(void) { - RSAPublicKey* key; - uint64_t u; - - /* Processed key size */ - TEST_EQ(RSAProcessedKeySize(0, &u), 1, "Processed key size 0"); - TEST_EQ(u, RSA1024NUMBYTES * 2 + sizeof(uint32_t) * 2, - "Processed key size 0 size"); - TEST_EQ(RSAProcessedKeySize(3, &u), 1, "Processed key size 3"); - TEST_EQ(u, RSA2048NUMBYTES * 2 + sizeof(uint32_t) * 2, - "Processed key size 3 size"); - TEST_EQ(RSAProcessedKeySize(7, &u), 1, "Processed key size 7"); - TEST_EQ(u, RSA4096NUMBYTES * 2 + sizeof(uint32_t) * 2, - "Processed key size 7 size"); - TEST_EQ(RSAProcessedKeySize(11, &u), 1, "Processed key size 11"); - TEST_EQ(u, RSA8192NUMBYTES * 2 + sizeof(uint32_t) * 2, - "Processed key size 11 size"); - TEST_EQ(RSAProcessedKeySize(kNumAlgorithms, &u), 0, - "Processed key size invalid algorithm"); - - /* Alloc key */ - key = RSAPublicKeyNew(); - TEST_EQ(key == NULL, 0, "New key not null"); - /* New key fields */ - TEST_PTR_EQ(key->n, NULL, "New key no n"); - TEST_PTR_EQ(key->rr, NULL, "New key no rr"); - TEST_EQ(key->len, 0, "New key len"); - TEST_EQ(key->algorithm, kNumAlgorithms, "New key no algorithm"); - /* Free key */ - RSAPublicKeyFree(key); - /* Freeing null key shouldn't implode */ - RSAPublicKeyFree(NULL); -} - -/* Test creating key from buffer */ -static void TestKeyFromBuffer(void) { - RSAPublicKey* key; - uint8_t* buf; - uint32_t* buf_key_len; - int i; - - buf = malloc(8 + 2 * RSA8192NUMBYTES); - buf_key_len = (uint32_t*)buf; - - for (i = 0; i < 4; i++) { - uint32_t key_len = RSA1024NUMBYTES << i; - memset(buf, 0xAB, 8 + 2 * RSA8192NUMBYTES); - *buf_key_len = key_len / sizeof(uint32_t); - *(buf_key_len + 1) = 0xF00D2345; /* n0inv */ - buf[8] = 100; - buf[8 + key_len - 1] = 101; - buf[8 + key_len] = 120; - buf[8 + key_len * 2 - 1] = 121; - - /* Correct length */ - key = RSAPublicKeyFromBuf(buf, 8 + key_len * 2); - TEST_PTR_NEQ(key, NULL, "RSAPublicKeyFromBuf() ptr"); - TEST_EQ(key->len, *buf_key_len, "RSAPublicKeyFromBuf() len"); - TEST_EQ(key->n0inv, 0xF00D2345, "RSAPublicKeyFromBuf() n0inv"); - TEST_PTR_NEQ(key->n, NULL, "RSAPublicKeyFromBuf() n ptr"); - TEST_EQ(((uint8_t*)key->n)[0], 100, "RSAPublicKeyFromBuf() n start"); - TEST_EQ(((uint8_t*)key->n)[key_len - 1], 101, - "RSAPublicKeyFromBuf() n end"); - TEST_PTR_NEQ(key->rr, NULL, "RSAPublicKeyFromBuf() rr ptr"); - TEST_EQ(((uint8_t*)key->rr)[0], 120, "RSAPublicKeyFromBuf() rr start"); - TEST_EQ(((uint8_t*)key->rr)[key_len - 1], 121, - "RSAPublicKeyFromBuf() rr end"); - RSAPublicKeyFree(key); - - /* Underflow and overflow */ - TEST_PTR_EQ(RSAPublicKeyFromBuf(buf, 8 + key_len * 2 - 1), NULL, - "RSAPublicKeyFromBuf() underflow"); - TEST_PTR_EQ(RSAPublicKeyFromBuf(buf, 8 + key_len * 2 + 1), NULL, - "RSAPublicKeyFromBuf() overflow"); - - /* Invalid key length in buffer */ - *buf_key_len = key_len / sizeof(uint32_t) + 1; - TEST_PTR_EQ(RSAPublicKeyFromBuf(buf, 8 + key_len * 2 + 1), NULL, - "RSAPublicKeyFromBuf() invalid key length"); - - /* Valid key length in buffer, but for some other length key */ - *buf_key_len = (RSA1024NUMBYTES << ((i + 1) & 3)) / sizeof(uint32_t); - TEST_PTR_EQ(RSAPublicKeyFromBuf(buf, 8 + key_len * 2 + 1), NULL, - "RSAPublicKeyFromBuf() key length for wrong key"); - } - free(buf); -} - -/* Test verifying binary */ -static void TestVerifyBinary(void) { - RSAPublicKey key; - uint8_t keybuf[8 + 2 * RSA1024NUMBYTES]; - uint32_t* keybuf_len = (uint32_t*)keybuf; - uint8_t buf[120]; - uint8_t sig[4]; - - *keybuf_len = RSA1024NUMBYTES / sizeof(uint32_t); - - /* Successful verification */ - ResetMocks(); - TEST_EQ(RSAVerifyBinary_f(NULL, &key, buf, sizeof(buf), sig, 0), - 1, "RSAVerifyBinary_f() success"); - /* Successful verification using key blob */ - TEST_EQ(RSAVerifyBinary_f(keybuf, NULL, buf, sizeof(buf), sig, 0), - 1, "RSAVerifyBinary_f() success with keyblob"); - - /* Invalid algorithm */ - ResetMocks(); - TEST_EQ(RSAVerifyBinary_f(NULL, &key, buf, sizeof(buf), sig, kNumAlgorithms), - 0, "RSAVerifyBinary_f() invalid algorithm"); - /* Must have either a key or a key blob */ - ResetMocks(); - TEST_EQ(RSAVerifyBinary_f(NULL, NULL, buf, sizeof(buf), sig, kNumAlgorithms), - 0, "RSAVerifyBinary_f() no key or key_blob"); - /* Wrong algorithm for key buffer (so key buffer is wrong size) */ - ResetMocks(); - TEST_EQ(RSAVerifyBinary_f(keybuf, NULL, buf, sizeof(buf), sig, 3), - 0, "RSAVerifyBinary_f() wrong alg for key blob"); - - /* Simulate failed verification */ - ResetMocks(); - mock_rsaverify_retval = 0; - TEST_EQ(RSAVerifyBinary_f(NULL, &key, buf, sizeof(buf), sig, 0), - 0, "RSAVerifyBinary_f() bad verify"); -} - -/* Test verifying binary with digest */ -static void TestVerifyBinaryWithDigest(void) { - RSAPublicKey key; - uint8_t keybuf[8 + 2 * RSA1024NUMBYTES]; - uint32_t* keybuf_len = (uint32_t*)keybuf; - uint8_t digest[120]; - uint8_t sig[4]; - - *keybuf_len = RSA1024NUMBYTES / sizeof(uint32_t); - - /* Successful verification */ - ResetMocks(); - TEST_EQ(RSAVerifyBinaryWithDigest_f(NULL, &key, digest, sig, 0), - 1, "RSAVerifyBinaryWithDigest_f() success"); - /* Successful verification using key blob */ - TEST_EQ(RSAVerifyBinaryWithDigest_f(keybuf, NULL, digest, sig, 0), - 1, "RSAVerifyBinaryWithDigest_f() success with keyblob"); - - /* Invalid algorithm */ - ResetMocks(); - TEST_EQ(RSAVerifyBinaryWithDigest_f(NULL, &key, digest, sig, kNumAlgorithms), - 0, "RSAVerifyBinaryWithDigest_f() invalid algorithm"); - /* Must have either a key or a key blob */ - ResetMocks(); - TEST_EQ(RSAVerifyBinaryWithDigest_f(NULL, NULL, digest, sig, kNumAlgorithms), - 0, "RSAVerifyBinaryWithDigest_f() no key or key_blob"); - /* Wrong algorithm for key buffer (so key buffer is wrong size) */ - ResetMocks(); - TEST_EQ(RSAVerifyBinaryWithDigest_f(keybuf, NULL, digest, sig, 3), - 0, "RSAVerifyBinaryWithDigest_f() wrong alg for key blob"); - - /* Simulate failed verification */ - ResetMocks(); - mock_rsaverify_retval = 0; - TEST_EQ(RSAVerifyBinaryWithDigest_f(NULL, &key, digest, sig, 0), - 0, "RSAVerifyBinaryWithDigest_f() bad verify"); -} - -int main(int argc, char* argv[]) { - int error_code = 0; - - /* Run tests */ - TestUtils(); - TestKeyFromBuffer(); - TestVerifyBinary(); - TestVerifyBinaryWithDigest(); - - if (!gTestSuccess) - error_code = 255; - - return error_code; -} diff --git a/tests/rsa_verify_benchmark.c b/tests/rsa_verify_benchmark.c deleted file mode 100644 index 7b27f9e8..00000000 --- a/tests/rsa_verify_benchmark.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (c) 2011 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. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include "cryptolib.h" -#include "file_keys.h" -#include "host_common.h" -#include "timer_utils.h" - -#define FILE_NAME_SIZE 128 -#define NUM_OPERATIONS 100 /* Number of signature operations to time. */ - -int SpeedTestAlgorithm(int algorithm) { - int i, key_size; - int error_code = 0; - double speed, msecs; - char file_name[FILE_NAME_SIZE]; - uint8_t* digest = NULL; - uint8_t* signature = NULL; - uint64_t digest_len, sig_len; - RSAPublicKey* key = NULL; - ClockTimerState ct; - char* sha_strings[] = { /* Maps algorithm->SHA algorithm. */ - "sha1", "sha256", "sha512", /* RSA-1024 */ - "sha1", "sha256", "sha512", /* RSA-2048 */ - "sha1", "sha256", "sha512", /* RSA-4096 */ - "sha1", "sha256", "sha512", /* RSA-8192 */ - }; - - key_size = siglen_map[algorithm] * 8; /* in bits. */ - /* Get key. */ - snprintf(file_name, FILE_NAME_SIZE, "testkeys/key_rsa%d.keyb", key_size); - key = RSAPublicKeyFromFile(file_name); - if (!key) { - VBDEBUG(("Couldn't read RSA Public key from file: %s\n", file_name)); - error_code = 1; - goto failure; - } - - /* Get expected digest. */ - snprintf(file_name, FILE_NAME_SIZE, "testcases/test_file.%s.digest", - sha_strings[algorithm]); - digest = BufferFromFile(file_name, &digest_len); - if (!digest) { - VBDEBUG(("Couldn't read digest file.\n")); - error_code = 1; - goto failure; - } - - /* Get signature to verify against. */ - snprintf(file_name, FILE_NAME_SIZE, "testcases/test_file.rsa%d_%s.sig", - key_size, sha_strings[algorithm]); - signature = BufferFromFile(file_name, &sig_len); - if (!signature) { - VBDEBUG(("Couldn't read signature file.\n")); - error_code = 1; - goto failure; - } - - StartTimer(&ct); - for (i = 0; i < NUM_OPERATIONS; i++) { - if (!RSAVerify(key, signature, sig_len, algorithm, digest)) - VBDEBUG(("Warning: Signature Check Failed.\n")); - } - StopTimer(&ct); - - msecs = (float) GetDurationMsecs(&ct) / NUM_OPERATIONS; - speed = 1000.0 / msecs ; - fprintf(stderr, "# rsa%d/%s:\tTime taken per verification = %.02f ms," - " Speed = %.02f verifications/s\n", key_size, sha_strings[algorithm], - msecs, speed); - fprintf(stdout, "ms_rsa%d_%s:%.02f\n", key_size, sha_strings[algorithm], - msecs); - -failure: - free(signature); - free(digest); - RSAPublicKeyFree(key); - return error_code; -} - -int main(int argc, char* argv[]) { - int i; - int error_code = 0; - for (i = 0; i < kNumAlgorithms; ++i) { - if(SpeedTestAlgorithm(i)) - error_code = 1; - } - return error_code; -} diff --git a/tests/run_rsa_tests.sh b/tests/run_rsa_tests.sh deleted file mode 100755 index d73f7374..00000000 --- a/tests/run_rsa_tests.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2010 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. -# -# Run tests for RSA Signature verification. - -# Load common constants and variables. -. "$(dirname "$0")/common.sh" - -set -e - -return_code=0 -TEST_FILE=${TESTCASE_DIR}/test_file - -function test_signatures { - algorithmcounter=0 - for keylen in ${key_lengths[@]} - do - for hashalgo in ${hash_algos[@]} - do - echo -e "For ${COL_YELLOW}RSA-$keylen and $hashalgo${COL_STOP}:" - ${BIN_DIR}/verify_data $algorithmcounter \ - ${TESTKEY_DIR}/key_rsa${keylen}.keyb \ - ${TEST_FILE}.rsa${keylen}_${hashalgo}.sig \ - ${TEST_FILE} - if [ $? -ne 0 ] - then - return_code=255 - fi - let algorithmcounter=algorithmcounter+1 - done - done - echo -e "Peforming ${COL_YELLOW}PKCS #1 v1.5 Padding Tests${COL_STOP}..." - ${TEST_DIR}/rsa_padding_test ${TESTKEY_DIR}/rsa_padding_test_pubkey.keyb -} - -check_test_keys -echo "Testing signature verification..." -test_signatures - -exit $return_code - diff --git a/tests/vb20_rsa_padding_tests.c b/tests/vb20_rsa_padding_tests.c index 6fe2e970..a70da58c 100644 --- a/tests/vb20_rsa_padding_tests.c +++ b/tests/vb20_rsa_padding_tests.c @@ -7,6 +7,8 @@ #include <stdint.h> #include <stdio.h> +#define _STUB_IMPLEMENTATION_ + #include "cryptolib.h" #include "file_keys.h" #include "rsa_padding_test.h" @@ -15,29 +17,10 @@ #include "2sysincludes.h" #include "2rsa.h" +#include "host_key.h" #include "vb2_common.h" /** - * Convert an old-style RSA public key struct to a new one. - * - * The new one does not allocate memory, so you must keep the old one around - * until you're done with the new one. - * - * @param k2 Destination new key - * @param key Source old key - */ -void vb2_public_key_to_vb2(struct vb2_public_key *k2, - const struct RSAPublicKey *key) -{ - k2->arrsize = key->len; - k2->n0inv = key->n0inv; - k2->n = key->n; - k2->rr = key->rr; - k2->sig_alg = vb2_crypto_to_signature(key->algorithm); - k2->hash_alg = vb2_crypto_to_hash(key->algorithm); -} - -/** * Test valid and invalid signatures. */ static void test_signatures(const struct vb2_public_key *key) @@ -122,37 +105,32 @@ static void test_verify_digest(struct vb2_public_key *key) { int main(int argc, char *argv[]) { - int error = 0; - RSAPublicKey *key; struct vb2_public_key k2; + struct vb2_packed_key *pk; /* Read test key */ if (argc != 2) { fprintf(stderr, "Usage: %s <test public key>\n", argv[0]); return 1; } - key = RSAPublicKeyFromFile(argv[1]); - - if (!key) { + pk = vb2_read_packed_keyb(argv[1], VB2_ALG_RSA1024_SHA1, 0); + if (!pk) { fprintf(stderr, "Couldn't read RSA public key for the test.\n"); return 1; } - // TODO: why is test key algorithm wrong? - key->algorithm = 0; - - /* Convert test key to Vb2 format */ - vb2_public_key_to_vb2(&k2, key); + if (VB2_SUCCESS != vb2_unpack_key(&k2, (const uint8_t *)pk, + pk->key_offset + pk->key_size)) { + fprintf(stderr, "Couldn't unpack RSA public key.\n"); + free(pk); + return 1; + } /* Run tests */ test_signatures(&k2); test_verify_digest(&k2); /* Clean up and exit */ - RSAPublicKeyFree(key); - - if (!gTestSuccess) - error = 255; - - return error; + free(pk); + return gTestSuccess ? 0 : 255; } diff --git a/utility/include/verify_data.h b/utility/include/verify_data.h deleted file mode 100644 index 51b9fd6d..00000000 --- a/utility/include/verify_data.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef VBOOT_REFERENCE_VERIFY_DATA_H_ -#define VBOOT_REFERENCE_VERIFY_DATA_H_ - -/* Reads a pre-processed key from [input_file] and - * returns it in a RSAPublicKey structure. - * Caller owns the returned key and must free it. - */ -RSAPublicKey* read_RSAkey(char *input_file); - -/* Return a signature of [len] bytes read from [input_file]. - * Caller owns the returned signature and must free it. - */ -uint8_t* read_signature(char *input_file, int len); - -#endif /* VBOOT_REFERENCE_VERIFY_DATA_H_ */ diff --git a/utility/pad_digest_utility.c b/utility/pad_digest_utility.c index 86d6694b..440cca3a 100644 --- a/utility/pad_digest_utility.c +++ b/utility/pad_digest_utility.c @@ -31,7 +31,7 @@ int main(int argc, char* argv[]) { int error_code = 0; uint8_t* digest = NULL; uint8_t* padded_digest = NULL; - uint64_t len; + uint32_t len; uint32_t padded_digest_len; if (argc != 3) { @@ -44,8 +44,7 @@ int main(int argc, char* argv[]) { return -1; } - digest = BufferFromFile(argv[2], &len); - if (!digest) { + if (VB2_SUCCESS != vb2_read_file(argv[2], &digest, &len)) { fprintf(stderr, "Could not read file: %s\n", argv[2]); return -1; } diff --git a/utility/signature_digest_utility.c b/utility/signature_digest_utility.c index 781f9ff6..0ed1a99d 100644 --- a/utility/signature_digest_utility.c +++ b/utility/signature_digest_utility.c @@ -11,6 +11,9 @@ #include <stdio.h> #include <stdlib.h> +#include "2sysincludes.h" +#include "2common.h" + #include "file_keys.h" #include "host_common.h" #include "padding.h" @@ -22,7 +25,7 @@ int main(int argc, char* argv[]) { int error_code = 0; uint8_t* buf = NULL; uint8_t* signature_digest = NULL; - uint64_t len; + uint32_t len; uint32_t signature_digest_len; if (argc != 3) { @@ -35,8 +38,7 @@ int main(int argc, char* argv[]) { return -1; } - buf = BufferFromFile(argv[2], &len); - if (!buf) { + if (VB2_SUCCESS != vb2_read_file(argv[2], &buf, &len)) { fprintf(stderr, "Could not read file: %s\n", argv[2]); return -1; } diff --git a/utility/verify_data.c b/utility/verify_data.c index ed4bcc16..d68f8909 100644 --- a/utility/verify_data.c +++ b/utility/verify_data.c @@ -15,88 +15,130 @@ #include <sys/types.h> #include <unistd.h> +#define _STUB_IMPLEMENTATION_ /* For malloc()/free() */ + #include "2sysincludes.h" #include "2common.h" #include "2sha.h" +#include "2rsa.h" #include "cryptolib.h" #include "file_keys.h" -#include "verify_data.h" +#include "host_key.h" +#include "host_misc.h" +#include "vb2_common.h" /* ANSI Color coding sequences. */ #define COL_GREEN "\e[1;32m" #define COL_RED "\e[0;31m" #define COL_STOP "\e[m" -uint8_t* read_signature(char* input_file, int len) { - int i, sigfd; - uint8_t* signature = NULL; - if ((sigfd = open(input_file, O_RDONLY)) == -1) { - fprintf(stderr, "Couldn't open signature file\n"); - return NULL; - } - - /* Read the signature into a buffer*/ - signature = (uint8_t*) malloc(len); - if (!signature) { - close(sigfd); - return NULL; - } - - if( (i = read(sigfd, signature, len)) != len ) { - fprintf(stderr, "Wrong signature length - Expected = %d, Received = %d\n", - len, i); - close(sigfd); - free(signature); - return NULL; - } - - close(sigfd); - return signature; +uint8_t* read_signature(char* input_file, int len) +{ + int i, sigfd; + uint8_t* signature = NULL; + if ((sigfd = open(input_file, O_RDONLY)) == -1) { + fprintf(stderr, "Couldn't open signature file\n"); + return NULL; + } + + /* Read the signature into a buffer*/ + signature = (uint8_t*) malloc(len); + if (!signature) { + close(sigfd); + return NULL; + } + + if( (i = read(sigfd, signature, len)) != len ) { + fprintf(stderr, "Expected signature length %d, Received %d\n", + len, i); + close(sigfd); + free(signature); + return NULL; + } + + close(sigfd); + return signature; } -int main(int argc, char* argv[]) { - int i, algorithm, sig_len; - int return_code = 1; /* Default to error. */ - uint8_t digest[VB2_MAX_DIGEST_SIZE]; - uint8_t* signature = NULL; - RSAPublicKey* key = NULL; - - if (argc!=5) { - fprintf(stderr, "Usage: %s <algorithm> <key file> <signature file>" - " <input file>\n\n", argv[0]); - fprintf(stderr, "where <algorithm> depends on the signature algorithm" - " used:\n"); - for(i = 0; i<kNumAlgorithms; i++) - fprintf(stderr, "\t%d for %s\n", i, algo_strings[i]); - return -1; - } - - algorithm = atoi(argv[1]); - if (algorithm >= kNumAlgorithms) { - fprintf(stderr, "Invalid Algorithm!\n"); - return 0; - } - /* Length of the RSA Signature/RSA Key */ - sig_len = siglen_map[algorithm]; - if ((key = RSAPublicKeyFromFile(argv[2])) && - (signature = read_signature(argv[3], sig_len)) && - (VB2_SUCCESS == DigestFile(argv[4], vb2_crypto_to_hash(algorithm), - digest, sizeof(digest)))) { - if (RSAVerify(key, signature, sig_len, algorithm, digest)) { - return_code = 0; - fprintf(stderr, "Signature Verification " - COL_GREEN "SUCCEEDED" COL_STOP "\n"); - } else { - fprintf(stderr, "Signature Verification " - COL_RED "FAILED" COL_STOP "\n"); - } - } - else - return_code = -1; - - free(key); - free(signature); - - return return_code; +int main(int argc, char* argv[]) +{ + uint8_t workbuf[VB2_VERIFY_DIGEST_WORKBUF_BYTES] + __attribute__ ((aligned (VB2_WORKBUF_ALIGN))); + struct vb2_workbuf wb; + vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); + + int return_code = 1; /* Default to error. */ + uint8_t digest[VB2_MAX_DIGEST_SIZE]; + struct vb2_packed_key *pk = NULL; + uint8_t *signature = NULL; + uint32_t sig_len = 0; + + if (argc != 5) { + int i; + fprintf(stderr, + "Usage: %s <algorithm> <key file> <signature file>" + " <input file>\n\n", argv[0]); + fprintf(stderr, + "where <algorithm> depends on the signature algorithm" + " used:\n"); + for(i = 0; i < VB2_ALG_COUNT; i++) + fprintf(stderr, "\t%d for %s\n", i, algo_strings[i]); + return -1; + } + + int algorithm = atoi(argv[1]); + if (algorithm >= kNumAlgorithms) { + fprintf(stderr, "Invalid algorithm %d\n", algorithm); + goto error; + } + + pk = vb2_read_packed_keyb(argv[2], algorithm, 0); + if (!pk) { + fprintf(stderr, "Can't read RSA public key.\n"); + goto error; + } + + struct vb2_public_key k2; + if (VB2_SUCCESS != vb2_unpack_key(&k2, (const uint8_t *)pk, + pk->key_offset + pk->key_size)) { + fprintf(stderr, "Can't unpack RSA public key.\n"); + goto error; + } + + if (VB2_SUCCESS != vb2_read_file(argv[3], &signature, &sig_len)) { + fprintf(stderr, "Can't read signature.\n"); + goto error; + } + + uint32_t expect_sig_size = + vb2_rsa_sig_size(vb2_crypto_to_signature(algorithm)); + if (sig_len != expect_sig_size) { + fprintf(stderr, "Expected signature size %u, got %u\n", + expect_sig_size, sig_len); + goto error; + } + + if (VB2_SUCCESS != DigestFile(argv[4], vb2_crypto_to_hash(algorithm), + digest, sizeof(digest))) { + fprintf(stderr, "Error calculating digest.\n"); + goto error; + } + + if (VB2_SUCCESS == vb2_rsa_verify_digest(&k2, signature, digest, &wb)) { + return_code = 0; + fprintf(stderr, "Signature Verification " + COL_GREEN "SUCCEEDED" COL_STOP "\n"); + } else { + fprintf(stderr, "Signature Verification " + COL_RED "FAILED" COL_STOP "\n"); + } + +error: + if (pk) + free(pk); + if (signature) + free(signature); + + return return_code; } |