diff options
author | Mattias Nissler <mnissler@chromium.org> | 2017-11-21 12:17:03 +0100 |
---|---|---|
committer | Mattias Nissler <mnissler@chromium.org> | 2018-04-13 10:03:28 +0000 |
commit | 163b41233cbbfdd67da10017aab7c1ce9a6e0873 (patch) | |
tree | 6bd14c5a3eddc3e35f6a5657e51659011dde3dcf | |
parent | d6f52a05a3b54e3d80f4bded77f33daccbe04e23 (diff) | |
download | vboot-163b41233cbbfdd67da10017aab7c1ce9a6e0873.tar.gz |
tpm_lite: Implement ReadPubek command.
Add a TlclReadPubek library function to read the public endorsement
key.
BRANCH=None
BUG=chromium:788719
TEST=New unit tests.
Change-Id: I5f23b76b88198d656f4ba5782d2b4f25aaa082b1
Reviewed-on: https://chromium-review.googlesource.com/790413
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Tested-by: Mattias Nissler <mnissler@chromium.org>
Trybot-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Trybot-Ready: Mattias Nissler <mnissler@chromium.org>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | firmware/include/tlcl.h | 13 | ||||
-rw-r--r-- | firmware/include/tpm1_tss_constants.h | 10 | ||||
-rw-r--r-- | firmware/include/tss_constants.h | 5 | ||||
-rw-r--r-- | firmware/include/vboot_api.h | 15 | ||||
-rw-r--r-- | firmware/lib/tpm_lite/include/tlcl_structures.h | 3 | ||||
-rw-r--r-- | firmware/lib/tpm_lite/tlcl.c | 169 | ||||
-rw-r--r-- | firmware/stub/tpm_lite_stub.c | 17 | ||||
-rw-r--r-- | tests/tlcl_tests.c | 135 | ||||
-rw-r--r-- | utility/tlcl_generator.c | 1 |
10 files changed, 364 insertions, 6 deletions
@@ -488,8 +488,10 @@ HOSTLIB_SRCS = \ cgpt/cgpt_common.c \ cgpt/cgpt_create.c \ cgpt/cgpt_prioritize.c \ + firmware/2lib/2common.c \ firmware/2lib/2crc8.c \ firmware/2lib/2nvstorage.c \ + firmware/2lib/2sha1.c \ firmware/2lib/2stub.c \ firmware/lib/cgptlib/cgptlib_internal.c \ firmware/lib/cgptlib/crc32.c \ diff --git a/firmware/include/tlcl.h b/firmware/include/tlcl.h index b38c3d69..685925f4 100644 --- a/firmware/include/tlcl.h +++ b/firmware/include/tlcl.h @@ -230,6 +230,19 @@ uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version, */ uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO *info); +#ifdef CHROMEOS_ENVIRONMENT +#ifndef TPM2_MODE + +/** + * Read the public half of the EK. + */ +uint32_t TlclReadPubek(uint32_t* public_exponent, + uint8_t* modulus, + uint32_t* modulus_size); + +#endif /* TPM2_MODE */ +#endif /* CHROMEOS_ENVIRONMENT */ + #ifdef __cplusplus } #endif diff --git a/firmware/include/tpm1_tss_constants.h b/firmware/include/tpm1_tss_constants.h index 97d7358f..f915fb53 100644 --- a/firmware/include/tpm1_tss_constants.h +++ b/firmware/include/tpm1_tss_constants.h @@ -55,6 +55,12 @@ typedef uint32_t TPM_CAPABILITY_AREA; #define TPM_CAP_NV_INDEX ((uint32_t) 0x00000011) #define TPM_CAP_GET_VERSION_VAL ((uint32_t) 0x0000001a) +#define TPM_ALG_RSA ((uint16_t)0x0001) + +#define TPM_ES_RSAESOAEP_SHA1_MGF1 ((uint16_t)0x0003) + +#define TPM_SS_NONE ((uint16_t)0x0001) + #define TPM_ST_CLEAR ((uint16_t) 0x0001) #define TPM_ST_STATE ((uint16_t) 0x0002) #define TPM_ST_DEACTIVATED ((uint16_t) 0x0003) @@ -77,6 +83,10 @@ typedef uint32_t TPM_CAPABILITY_AREA; #define TPM_SHA1_160_HASH_LEN 0x14 #define TPM_SHA1BASED_NONCE_LEN TPM_SHA1_160_HASH_LEN +#define TPM_AUTH_DATA_LEN 0x14 + +#define TPM_RSA_2048_LEN 0x100 + typedef struct tdTPM_DIGEST { uint8_t digest[TPM_SHA1_160_HASH_LEN]; diff --git a/firmware/include/tss_constants.h b/firmware/include/tss_constants.h index 1fe92b92..d579933e 100644 --- a/firmware/include/tss_constants.h +++ b/firmware/include/tss_constants.h @@ -23,6 +23,10 @@ #define TPM_E_READ_FAILURE ((uint32_t) 0x0000500a) /* vboot local */ #define TPM_E_STRUCT_SIZE ((uint32_t) 0x0000500b) /* vboot local */ #define TPM_E_STRUCT_VERSION ((uint32_t) 0x0000500c) /* vboot local */ +#define TPM_E_INTERNAL_ERROR ((uint32_t) 0x0000500d) /* vboot local */ +#define TPM_E_INVALID_RESPONSE ((uint32_t) 0x0000500e) /* vboot local */ +#define TPM_E_BUFFER_SIZE ((uint32_t) 0x0000500f) /* vboot local */ + /* * AP firmware relies on Tlcl returning these exact TPM1.2 error codes @@ -31,6 +35,7 @@ * either 0x100 or 0x80 bit set, so there is no confusion with actual error * codes returned from a TPM2.0 chip. */ +#define TPM_E_AUTHFAIL ((uint32_t) 0x00000001) #define TPM_E_BADINDEX ((uint32_t) 0x00000002) #define TPM_E_BAD_ORDINAL ((uint32_t) 0x0000000a) #define TPM_E_OWNER_SET ((uint32_t) 0x00000014) diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index d05fef86..04836ff8 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -419,6 +419,21 @@ VbError_t VbExTpmOpen(void); VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length, uint8_t *response, uint32_t *response_length); +#ifdef CHROMEOS_ENVIRONMENT + +/** + * Obtain cryptographically secure random bytes. This function is used to + * generate random nonces for TPM auth sessions for example. As an implication, + * the generated random bytes should not be predictable for a TPM communication + * interception attack. This implies a local source of randomness should be + * used, i.e. this should not be wired to the TPM RNG directly. Otherwise, an + * attacker with communication interception abilities could launch replay + * attacks by reusing previous nonces. + */ +VbError_t VbExTpmGetRandom(uint8_t *buf, uint32_t length); + +#endif /* CHROMEOS_ENVIRONMENT */ + /*****************************************************************************/ /* Non-volatile storage */ diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h index 6ddb8855..b4ff1f5f 100644 --- a/firmware/lib/tpm_lite/include/tlcl_structures.h +++ b/firmware/lib/tpm_lite/include/tlcl_structures.h @@ -67,8 +67,9 @@ const struct s_tpm_forceclear_cmd{ const struct s_tpm_readpubek_cmd{ uint8_t buffer[30]; + uint16_t antiReplay; } tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, -}; +10, }; const struct s_tpm_continueselftest_cmd{ uint8_t buffer[10]; diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c index e87b1306..493bf84e 100644 --- a/firmware/lib/tpm_lite/tlcl.c +++ b/firmware/lib/tpm_lite/tlcl.c @@ -16,6 +16,7 @@ #include "2sysincludes.h" #include "2common.h" +#include "2sha.h" #include "sysincludes.h" #include "tlcl.h" @@ -567,7 +568,8 @@ static void ParseIFXFirmwarePackage(const uint8_t** cursor, firmware_package->StaleVersion = ReadTpmUint32(cursor); } -uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) { +uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) +{ uint32_t vendor; uint64_t firmware_version; uint32_t result = @@ -599,7 +601,7 @@ uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) { ParseIFXFirmwarePackage(&cursor, &info->sBootloaderFirmwarePackage); uint16_t fw_entry_count = ReadTpmUint16(&cursor); if (fw_entry_count > ARRAY_SIZE(info->sFirmwarePackages)) { - return TPM_E_IOERROR; + return TPM_E_INVALID_RESPONSE; } uint16_t i; for (i = 0; i < fw_entry_count; ++i) { @@ -614,8 +616,169 @@ uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info) { uint32_t parsed_bytes = cursor - response; VbAssert(parsed_bytes <= TPM_LARGE_ENOUGH_COMMAND_SIZE); if (parsed_bytes > kTpmResponseHeaderLength + sizeof(size) + size) { - return TPM_E_IOERROR; + return TPM_E_INVALID_RESPONSE; + } + + return result; +} + +#ifdef CHROMEOS_ENVIRONMENT + +static uint32_t ParseRsaKeyParms(const uint8_t* buffer, + const uint8_t* end, + uint32_t* key_len, + uint32_t* num_primes, + uint32_t* exponent) +{ + if (end - buffer < 3 * sizeof(uint32_t)) { + return TPM_E_INVALID_RESPONSE; + } + *key_len = ReadTpmUint32(&buffer); + *num_primes = ReadTpmUint32(&buffer); + uint32_t exponent_size = ReadTpmUint32(&buffer); + if (end - buffer < exponent_size) { + return TPM_E_INVALID_RESPONSE; + } + + if (exponent_size == 0) { + *exponent = 0x10001; + } else if (exponent_size <= sizeof(*exponent)) { + *exponent = 0; + int i; + for (i = 0; i < exponent_size; ++i) { + *exponent |= (*buffer++) << (8 * i); + } + } else { + return TPM_E_INTERNAL_ERROR; + } + + return TPM_SUCCESS; +} + +static uint32_t ParseTpmPubKey(const uint8_t** buffer, + const uint8_t* end, + uint32_t* algorithm, + uint16_t* enc_scheme, + uint16_t* sig_scheme, + uint32_t* key_len, + uint32_t* num_primes, + uint32_t* exponent, + uint8_t* modulus, + uint32_t* modulus_size) +{ + uint32_t result = TPM_SUCCESS; + + if (end - *buffer < 2 * sizeof(uint32_t) + 2 * sizeof(uint16_t)) { + return TPM_E_INVALID_RESPONSE; + } + + *algorithm = ReadTpmUint32(buffer); + *enc_scheme = ReadTpmUint16(buffer); + *sig_scheme = ReadTpmUint16(buffer); + + uint32_t parm_size = ReadTpmUint32(buffer); + if (end - *buffer < parm_size) { + return TPM_E_INVALID_RESPONSE; + } + + if (*algorithm == TPM_ALG_RSA) { + result = ParseRsaKeyParms(*buffer, *buffer + parm_size, + key_len, num_primes, exponent); + if (result != TPM_SUCCESS) { + return result; + } + } else { + return TPM_E_INTERNAL_ERROR; } + *buffer += parm_size; + + if (end - *buffer < sizeof(uint32_t)) { + return TPM_E_INVALID_RESPONSE; + } + + uint32_t actual_modulus_size = ReadTpmUint32(buffer); + if (end - *buffer < actual_modulus_size) { + return TPM_E_INVALID_RESPONSE; + } + + if (modulus && *modulus_size >= actual_modulus_size) { + memcpy(modulus, *buffer, actual_modulus_size); + } else { + result = TPM_E_BUFFER_SIZE; + } + *modulus_size = actual_modulus_size; + *buffer += actual_modulus_size; + return result; } + +uint32_t TlclReadPubek(uint32_t* public_exponent, + uint8_t* modulus, + uint32_t* modulus_size) +{ + struct s_tpm_readpubek_cmd cmd; + memcpy(&cmd, &tpm_readpubek_cmd, sizeof(cmd)); + if (VbExTpmGetRandom(cmd.buffer + tpm_readpubek_cmd.antiReplay, + sizeof(TPM_NONCE)) != VB2_SUCCESS) { + return TPM_E_INTERNAL_ERROR; + } + + /* The response contains the public endorsement key, so use a large + * response buffer. */ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_RSA_2048_LEN]; + uint32_t result = TlclSendReceive(cmd.buffer, response, + sizeof(response)); + if (result != TPM_SUCCESS) { + return result; + } + + const uint8_t* cursor = response + kTpmResponseHeaderLength; + const uint8_t* end = response + sizeof(response); + + /* Parse the key */ + uint32_t algorithm; + uint16_t enc_scheme; + uint16_t sig_scheme; + uint32_t key_len; + uint32_t num_primes; + result = ParseTpmPubKey(&cursor, end, &algorithm, &enc_scheme, + &sig_scheme, &key_len, &num_primes, + public_exponent, modulus, modulus_size); + if (result != TPM_SUCCESS) { + return result; + } + + /* Parse the checksum */ + if (end - cursor < TPM_SHA1_160_HASH_LEN) { + return TPM_E_INVALID_RESPONSE; + } + const uint8_t* checksum = cursor; + cursor += TPM_SHA1_160_HASH_LEN; + + /* Check the digest */ + struct vb2_sha1_context sha1_ctx; + vb2_sha1_init(&sha1_ctx); + vb2_sha1_update(&sha1_ctx, response + kTpmResponseHeaderLength, + checksum - (response + kTpmResponseHeaderLength)); + vb2_sha1_update(&sha1_ctx, cmd.buffer + tpm_readpubek_cmd.antiReplay, + sizeof(TPM_NONCE)); + uint8_t digest[TPM_SHA1_160_HASH_LEN]; + vb2_sha1_finalize(&sha1_ctx, digest); + if (vb2_safe_memcmp(digest, checksum, sizeof(digest))) { + return TPM_E_AUTHFAIL; + } + + /* Validate expectations for the EK. */ + if (algorithm != TPM_ALG_RSA || + enc_scheme != TPM_ES_RSAESOAEP_SHA1_MGF1 || + sig_scheme != TPM_SS_NONE || + key_len != 2048 || + num_primes != 2) { + return TPM_E_INVALID_RESPONSE; + } + + return result; +} + +#endif /* CHROMEOS_ENVIRONMENT */ diff --git a/firmware/stub/tpm_lite_stub.c b/firmware/stub/tpm_lite_stub.c index 97eebd0f..4c846312 100644 --- a/firmware/stub/tpm_lite_stub.c +++ b/firmware/stub/tpm_lite_stub.c @@ -253,3 +253,20 @@ VbError_t VbExTpmSendReceive(const uint8_t* request, uint32_t request_length, return VBERROR_SUCCESS; } + +VbError_t VbExTpmGetRandom(uint8_t *buf, uint32_t length) +{ + static int urandom_fd = -1; + if (urandom_fd < 0) { + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd == -1) { + return VBERROR_UNKNOWN; + } + } + + if (length != read(urandom_fd, buf, length)) { + return VBERROR_UNKNOWN; + } + + return VBERROR_SUCCESS; +} diff --git a/tests/tlcl_tests.c b/tests/tlcl_tests.c index c2f3681c..135311a4 100644 --- a/tests/tlcl_tests.c +++ b/tests/tlcl_tests.c @@ -98,6 +98,12 @@ VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length, return c->retval; } +VbError_t VbExTpmGetRandom(uint8_t *buf, uint32_t length) +{ + memset(buf, 0xa5, length); + return VBERROR_SUCCESS; +} + /** * Test assorted tlcl functions */ @@ -519,7 +525,7 @@ static void IFXFieldUpgradeInfoTest(void) calls[0].rsp_size = sizeof(version_response); calls[1].rsp = upgrade_info_response; calls[1].rsp_size = sizeof(upgrade_info_response); - TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_IOERROR, + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_INVALID_RESPONSE, "IFXFieldUpgradeInfo - short"); TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); @@ -529,11 +535,135 @@ static void IFXFieldUpgradeInfoTest(void) ResetMocks(); calls[0].rsp = version_response; calls[0].rsp_size = sizeof(version_response); - TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_IOERROR, + TEST_EQ(TlclIFXFieldUpgradeInfo(&info), TPM_E_INVALID_RESPONSE, "IFXFieldUpgradeInfo - bad vendor"); TEST_EQ(calls[1].req_cmd, TPM_ORD_FieldUpgrade, " cmd"); } +/** + * Test ReadPubek + */ +void ReadPubekTest(void) { + uint8_t response[] = { + 0x00, 0xc4, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9c, 0xa8, + 0x8f, 0x15, 0x6d, 0xbf, 0x37, 0x6f, 0x8d, 0xb7, + 0xb2, 0xe2, 0x79, 0x81, 0xf7, 0xc2, 0x3c, 0x84, + 0x64, 0x35, 0x38, 0x59, 0x6a, 0x87, 0x23, 0xe0, + 0x2a, 0xca, 0x40, 0x37, 0x78, 0x75, 0x18, 0xfc, + 0x2d, 0xbe, 0x2b, 0xd9, 0x77, 0x49, 0x4b, 0x8c, + 0xea, 0xe3, 0xcd, 0xa5, 0x27, 0x2b, 0x48, 0x2f, + 0xbe, 0x3b, 0x14, 0xca, 0xe5, 0x22, 0x31, 0xb8, + 0xa1, 0x14, 0xc6, 0x06, 0x8d, 0x14, 0xe8, 0x4a, + 0x36, 0x4d, 0xd3, 0x5f, 0xde, 0x23, 0xd1, 0x7b, + 0xec, 0x3b, 0xdd, 0x84, 0xa4, 0xd4, 0xe9, 0x9a, + 0x89, 0x94, 0x5c, 0xa0, 0x01, 0xfb, 0x95, 0x61, + 0x01, 0xaf, 0x6b, 0x17, 0x39, 0x44, 0x7e, 0x25, + 0x9b, 0x73, 0xfa, 0xde, 0x20, 0xb6, 0x92, 0x95, + 0x7b, 0x76, 0x9f, 0x44, 0xb0, 0xfb, 0x86, 0x9f, + 0xc5, 0xe2, 0x38, 0x9d, 0xcf, 0xce, 0x32, 0x53, + 0x3b, 0x3d, 0x10, 0xb7, 0x89, 0x53, 0x54, 0xc0, + 0x28, 0x52, 0xfc, 0x7a, 0xa9, 0x5b, 0x03, 0xd7, + 0x55, 0x2b, 0x07, 0xa7, 0x22, 0x5b, 0x1e, 0xe5, + 0x4f, 0x43, 0x70, 0x7d, 0x81, 0xbb, 0x3d, 0x56, + 0xfe, 0x5c, 0x47, 0xcc, 0xc0, 0x6e, 0xc8, 0xc7, + 0xd9, 0x96, 0x53, 0x2d, 0xd2, 0x28, 0xc7, 0xdf, + 0x5a, 0x07, 0x50, 0x3b, 0x17, 0x25, 0xe7, 0x51, + 0xed, 0xf7, 0x94, 0x02, 0x2a, 0x4c, 0x31, 0x57, + 0x34, 0x51, 0x05, 0x26, 0x43, 0xd4, 0x40, 0x47, + 0x3e, 0x02, 0xfe, 0xa5, 0x08, 0xc7, 0x94, 0xaa, + 0xd3, 0x14, 0x02, 0x1b, 0x41, 0x4c, 0xcd, 0xd6, + 0x8c, 0xad, 0x8e, 0x72, 0x1a, 0x36, 0xc7, 0x23, + 0xd1, 0x38, 0x83, 0x9f, 0xac, 0x66, 0xc5, 0x25, + 0x82, 0x9d, 0x18, 0x67, 0x78, 0xca, 0x15, 0x63, + 0x15, 0xd8, 0x83, 0xbd, 0xcc, 0xe7, 0xf7, 0xe9, + 0xba, 0xda, 0x23, 0xdf, 0x53, 0x30, 0x51, 0x1a, + 0xf1, 0x0c, 0x02, 0xe7, 0x65, 0x0d, 0x95, 0x52, + 0x76, 0xd1, 0x1b, 0xb0, 0x77, 0xba, 0x31, 0x0b, + 0x17, 0xb5, 0x63, 0x0d, 0x50, 0x7c, 0xbc, 0x63, + 0xbf, 0xc3, + }; + uint32_t exponent = 0; + uint8_t modulus[TPM_RSA_2048_LEN]; + uint32_t modulus_size = TPM_RSA_2048_LEN; + + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + TEST_EQ(TlclReadPubek(&exponent, modulus, &modulus_size), TPM_SUCCESS, + "ReadPubek"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + TEST_EQ(exponent, 0x10001, " exponent"); + TEST_EQ(memcmp(modulus, response + 38, sizeof(modulus)), TPM_SUCCESS, + " modulus"); + TEST_EQ(modulus_size, 0x100, " modulus_size"); + + /* Test that the command returns the full size of the modulus if the + * input buffer is too small. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + modulus_size = 0; + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_BUFFER_SIZE, "ReadPubek - returns modulus size"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + TEST_EQ(modulus_size, 0x100, " modulus_size"); + + /* Test that a too large parm_size value gets handled correctly. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + 18, 1 << 24); + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_INVALID_RESPONSE, "ReadPubek - large parm_size"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + ToTpmUint32(response + 18, 12); + + /* Test that a too small parm_size value gets handled correctly. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + 18, 11); + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_INVALID_RESPONSE, "ReadPubek - small parm_size"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + ToTpmUint32(response + 18, 12); + + /* Test that an overlong modulus size gets handled correctly. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + 34, 1 << 24); + modulus_size = sizeof(modulus); + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_INVALID_RESPONSE, "ReadPubek - large modulus size"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + ToTpmUint32(response + 34, TPM_RSA_2048_LEN); + + /* Test that a large exponent size gets handled correctly. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + ToTpmUint32(response + 20, 1 << 24); + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_INVALID_RESPONSE, "ReadPubek - large exponent size"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + ToTpmUint32(response + 20, 0); + + /* Test that an incorrect auth tag causes an error. */ + ResetMocks(); + calls[0].rsp = response; + calls[0].rsp_size = sizeof(response); + response[294] = 0; + TEST_EQ(TlclReadPubek(&exponent, NULL, &modulus_size), + TPM_E_INVALID_RESPONSE, "ReadPubek - incorrect auth"); + TEST_EQ(calls[0].req_cmd, TPM_ORD_ReadPubek, " cmd"); + response[294] = 0x60; +} + int main(void) { TlclTest(); @@ -544,6 +674,7 @@ int main(void) RandomTest(); GetVersionTest(); IFXFieldUpgradeInfoTest(); + ReadPubekTest(); return gTestSuccess ? 0 : 255; } diff --git a/utility/tlcl_generator.c b/utility/tlcl_generator.c index bb7ed819..5673c38b 100644 --- a/utility/tlcl_generator.c +++ b/utility/tlcl_generator.c @@ -265,6 +265,7 @@ Command* BuildReadPubekCommand(void) { int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE); Command* cmd = newCommand(TPM_ORD_ReadPubek, size); cmd->name = "tpm_readpubek_cmd"; + AddVisibleField(cmd, "antiReplay", kTpmRequestHeaderLength); return cmd; } |