| /* 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 <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; |
| |
| /* Mock functions */ |
| uint8_t* DigestBuf(const uint8_t* buf, uint64_t len, int sig_algorithm) { |
| /* Just need to return something; it's only passed to the mock RSAVerify() */ |
| return VbExMalloc(4); |
| } |
| |
| 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, sizeof(buf)); |
| *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; |
| } |