
Acked-by: Che-Liang Chiou clchiou@chromium.org
On Wed, Jun 12, 2013 at 1:08 AM, dirk.eibach@gdsys.cc wrote:
From: Reinhard Pfau pfau@gdsys.de
Extend the tpm library with support for single authorized (AUTH1) commands as specified in the TCG Main Specification 1.2. (The internally used helper functions are implemented in a way that they could also be used for double authorized commands if someone needs it.)
Provide enums with the return codes from the TCG Main specification.
For now only a single OIAP session is supported.
OIAP authorized version of the commands TPM_LoadKey2 and TPM_GetPubKey are provided. Both features are available using the 'tpm' command, too.
Authorized commands are enabled with CONFIG_TPM_AUTH_SESSIONS. (Note that this also requires CONFIG_SHA1 to be enabled.)
Signed-off-by: Reinhard Pfau reinhard.pfau@gdsys.cc
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc
Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3:
- fix email addresses
Changes in v2:
- replace some numeric constants with named constants
- style fixes (as shown by checkpatch.pl) in common/cmd_tpm.c and lib/tpm.c
README | 14 +++ common/cmd_tpm.c | 100 ++++++++++++++++ include/tpm.h | 174 +++++++++++++++++++++++++++ lib/tpm.c | 351 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 638 insertions(+), 1 deletion(-)
diff --git a/README b/README index 33bda8c..3d1fa08 100644 --- a/README +++ b/README @@ -1234,6 +1234,20 @@ The following options need to be configured: to. Contemporary x86 systems usually map it at 0xfed40000.
CONFIG_CMD_TPM
Add tpm monitor functions.
Requires CONFIG_TPM. If CONFIG_TPM_AUTH_SESSIONS is set, also
provides monitor access to authorized functions.
CONFIG_TPM
Define this to enable the TPM support library which provides
functional interfaces to some TPM commands.
Requires support for a TPM device.
CONFIG_TPM_AUTH_SESSIONS
Define this to enable authorized functions in the TPM library.
Requires CONFIG_TPM and CONFIG_SHA1.
- USB Support: At the moment only the UHCI host controller is supported (PIP405, MIP405, MPC5200); define
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 46fae18..c34000a 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -27,6 +27,13 @@ #include <asm/unaligned.h> #include <linux/string.h>
+/* Useful constants */ +enum {
DIGEST_LENGTH = 20,
/* max lengths, valid for RSA keys <= 2048 bits */
TPM_PUBKEY_MAX_LENGTH = 288,
+};
/**
- Print a byte string in hexdecimal format, 16-bytes per line.
@@ -546,6 +553,72 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, return convert_return_code(err); }
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
uint32_t auth_handle, err;
err = tpm_oiap(&auth_handle);
return convert_return_code(err);
+}
+static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
uint32_t parent_handle, key_len, key_handle, err;
uint8_t usage_auth[DIGEST_LENGTH];
void *key;
if (argc < 5)
return CMD_RET_USAGE;
parent_handle = simple_strtoul(argv[1], NULL, 0);
key = (void *)simple_strtoul(argv[2], NULL, 0);
key_len = simple_strtoul(argv[3], NULL, 0);
if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
return CMD_RET_FAILURE;
parse_byte_string(argv[4], usage_auth, NULL);
err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
&key_handle);
if (!err)
printf("Key handle is 0x%x\n", key_handle);
return convert_return_code(err);
+}
+static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
uint32_t key_handle, err;
uint8_t usage_auth[DIGEST_LENGTH];
uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
size_t pub_key_len = sizeof(pub_key_buffer);
if (argc < 3)
return CMD_RET_USAGE;
key_handle = simple_strtoul(argv[1], NULL, 0);
if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
return CMD_RET_FAILURE;
parse_byte_string(argv[2], usage_auth, NULL);
err = tpm_get_pub_key_oiap(key_handle, usage_auth,
pub_key_buffer, &pub_key_len);
if (!err) {
printf("dump of received pub key structure:\n");
print_byte_string(pub_key_buffer, pub_key_len);
}
return convert_return_code(err);
+}
+TPM_COMMAND_NO_ARG(tpm_end_oiap)
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
#define MAKE_TPM_CMD_ENTRY(cmd) \ U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
@@ -590,6 +663,16 @@ static cmd_tbl_t tpm_commands[] = { do_tpm_nv_read, "", ""), U_BOOT_CMD_MKENT(nv_write, 0, 1, do_tpm_nv_write, "", ""), +#ifdef CONFIG_TPM_AUTH_SESSIONS
U_BOOT_CMD_MKENT(oiap, 0, 1,
do_tpm_oiap, "", ""),
U_BOOT_CMD_MKENT(end_oiap, 0, 1,
do_tpm_end_oiap, "", ""),
U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
do_tpm_load_key2_oiap, "", ""),
U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
do_tpm_get_pub_key_oiap, "", ""),
+#endif /* CONFIG_TPM_AUTH_SESSIONS */ };
static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -638,6 +721,16 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, " get_capability cap_area sub_cap addr count\n" " - Read <count> bytes of TPM capability indexed by <cap_area> and\n" " <sub_cap> to memory address <addr>.\n" +#ifdef CONFIG_TPM_AUTH_SESSIONS +"Storage functions\n" +" loadkey2_oiap parent_handle key_addr key_len usage_auth\n" +" - loads a key data from memory address <key_addr>, <key_len> bytes\n" +" into TPM using the parent key <parent_handle> with authorization\n" +" <usage_auth> (20 bytes hex string).\n" +" get_pub_key_oiap key_handle usage_auth\n" +" - get the public key portion of a loaded key <key_handle> using\n" +" authorization <usage auth> (20 bytes hex string)\n" +#endif /* CONFIG_TPM_AUTH_SESSIONS */ "Endorsement Key Handling Commands:\n" " read_pubek addr count\n" " - Read <count> bytes of the public endorsement key to memory\n" @@ -648,6 +741,13 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, " <digest_hex_string>\n" " pcr_read index addr count\n" " - Read <count> bytes from PCR <index> to memory address <addr>.\n" +#ifdef CONFIG_TPM_AUTH_SESSIONS +"Authorization Sessions\n" +" oiap\n" +" - setup an OIAP session\n" +" end_oiap\n" +" - terminates an active OIAP session\n" +#endif /* CONFIG_TPM_AUTH_SESSIONS */ "Non-volatile Storage Commands:\n" " nv_define_space index permission size\n" " - Establish a space at index <index> with <permission> of <size> bytes.\n" diff --git a/include/tpm.h b/include/tpm.h index 7219b73..5e9f832 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -1,5 +1,6 @@ /*
- Copyright (c) 2013 The Chromium OS Authors.
- Coypright (c) 2013 Guntermann & Drunck GmbH
- See file CREDITS for list of people who contributed to this
- project.
@@ -54,6 +55,120 @@ enum tpm_nv_index { };
/**
- TPM return codes as defined in the TCG Main specification
- (TPM Main Part 2 Structures; Specification version 1.2)
- */
+enum tpm_return_code {
TPM_BASE = 0x00000000,
TPM_NON_FATAL = 0x00000800,
TPM_SUCCESS = TPM_BASE,
/* TPM-defined fatal error codes */
TPM_AUTHFAIL = TPM_BASE + 1,
TPM_BADINDEX = TPM_BASE + 2,
TPM_BAD_PARAMETER = TPM_BASE + 3,
TPM_AUDITFAILURE = TPM_BASE + 4,
TPM_CLEAR_DISABLED = TPM_BASE + 5,
TPM_DEACTIVATED = TPM_BASE + 6,
TPM_DISABLED = TPM_BASE + 7,
TPM_DISABLED_CMD = TPM_BASE + 8,
TPM_FAIL = TPM_BASE + 9,
TPM_BAD_ORDINAL = TPM_BASE + 10,
TPM_INSTALL_DISABLED = TPM_BASE + 11,
TPM_INVALID_KEYHANDLE = TPM_BASE + 12,
TPM_KEYNOTFOUND = TPM_BASE + 13,
TPM_INAPPROPRIATE_ENC = TPM_BASE + 14,
TPM_MIGRATE_FAIL = TPM_BASE + 15,
TPM_INVALID_PCR_INFO = TPM_BASE + 16,
TPM_NOSPACE = TPM_BASE + 17,
TPM_NOSRK = TPM_BASE + 18,
TPM_NOTSEALED_BLOB = TPM_BASE + 19,
TPM_OWNER_SET = TPM_BASE + 20,
TPM_RESOURCES = TPM_BASE + 21,
TPM_SHORTRANDOM = TPM_BASE + 22,
TPM_SIZE = TPM_BASE + 23,
TPM_WRONGPCRVAL = TPM_BASE + 24,
TPM_BAD_PARAM_SIZE = TPM_BASE + 25,
TPM_SHA_THREAD = TPM_BASE + 26,
TPM_SHA_ERROR = TPM_BASE + 27,
TPM_FAILEDSELFTEST = TPM_BASE + 28,
TPM_AUTH2FAIL = TPM_BASE + 29,
TPM_BADTAG = TPM_BASE + 30,
TPM_IOERROR = TPM_BASE + 31,
TPM_ENCRYPT_ERROR = TPM_BASE + 32,
TPM_DECRYPT_ERROR = TPM_BASE + 33,
TPM_INVALID_AUTHHANDLE = TPM_BASE + 34,
TPM_NO_ENDORSEMENT = TPM_BASE + 35,
TPM_INVALID_KEYUSAGE = TPM_BASE + 36,
TPM_WRONG_ENTITYTYPE = TPM_BASE + 37,
TPM_INVALID_POSTINIT = TPM_BASE + 38,
TPM_INAPPROPRIATE_SIG = TPM_BASE + 39,
TPM_BAD_KEY_PROPERTY = TPM_BASE + 40,
TPM_BAD_MIGRATION = TPM_BASE + 41,
TPM_BAD_SCHEME = TPM_BASE + 42,
TPM_BAD_DATASIZE = TPM_BASE + 43,
TPM_BAD_MODE = TPM_BASE + 44,
TPM_BAD_PRESENCE = TPM_BASE + 45,
TPM_BAD_VERSION = TPM_BASE + 46,
TPM_NO_WRAP_TRANSPORT = TPM_BASE + 47,
TPM_AUDITFAIL_UNSUCCESSFUL = TPM_BASE + 48,
TPM_AUDITFAIL_SUCCESSFUL = TPM_BASE + 49,
TPM_NOTRESETABLE = TPM_BASE + 50,
TPM_NOTLOCAL = TPM_BASE + 51,
TPM_BAD_TYPE = TPM_BASE + 52,
TPM_INVALID_RESOURCE = TPM_BASE + 53,
TPM_NOTFIPS = TPM_BASE + 54,
TPM_INVALID_FAMILY = TPM_BASE + 55,
TPM_NO_NV_PERMISSION = TPM_BASE + 56,
TPM_REQUIRES_SIGN = TPM_BASE + 57,
TPM_KEY_NOTSUPPORTED = TPM_BASE + 58,
TPM_AUTH_CONFLICT = TPM_BASE + 59,
TPM_AREA_LOCKED = TPM_BASE + 60,
TPM_BAD_LOCALITY = TPM_BASE + 61,
TPM_READ_ONLY = TPM_BASE + 62,
TPM_PER_NOWRITE = TPM_BASE + 63,
TPM_FAMILY_COUNT = TPM_BASE + 64,
TPM_WRITE_LOCKED = TPM_BASE + 65,
TPM_BAD_ATTRIBUTES = TPM_BASE + 66,
TPM_INVALID_STRUCTURE = TPM_BASE + 67,
TPM_KEY_OWNER_CONTROL = TPM_BASE + 68,
TPM_BAD_COUNTER = TPM_BASE + 69,
TPM_NOT_FULLWRITE = TPM_BASE + 70,
TPM_CONTEXT_GAP = TPM_BASE + 71,
TPM_MAXNVWRITES = TPM_BASE + 72,
TPM_NOOPERATOR = TPM_BASE + 73,
TPM_RESOURCEMISSING = TPM_BASE + 74,
TPM_DELEGATE_LOCK = TPM_BASE + 75,
TPM_DELEGATE_FAMILY = TPM_BASE + 76,
TPM_DELEGATE_ADMIN = TPM_BASE + 77,
TPM_TRANSPORT_NOTEXCLUSIVE = TPM_BASE + 78,
TPM_OWNER_CONTROL = TPM_BASE + 79,
TPM_DAA_RESOURCES = TPM_BASE + 80,
TPM_DAA_INPUT_DATA0 = TPM_BASE + 81,
TPM_DAA_INPUT_DATA1 = TPM_BASE + 82,
TPM_DAA_ISSUER_SETTINGS = TPM_BASE + 83,
TPM_DAA_TPM_SETTINGS = TPM_BASE + 84,
TPM_DAA_STAGE = TPM_BASE + 85,
TPM_DAA_ISSUER_VALIDITY = TPM_BASE + 86,
TPM_DAA_WRONG_W = TPM_BASE + 87,
TPM_BAD_HANDLE = TPM_BASE + 88,
TPM_BAD_DELEGATE = TPM_BASE + 89,
TPM_BADCONTEXT = TPM_BASE + 90,
TPM_TOOMANYCONTEXTS = TPM_BASE + 91,
TPM_MA_TICKET_SIGNATURE = TPM_BASE + 92,
TPM_MA_DESTINATION = TPM_BASE + 93,
TPM_MA_SOURCE = TPM_BASE + 94,
TPM_MA_AUTHORITY = TPM_BASE + 95,
TPM_PERMANENTEK = TPM_BASE + 97,
TPM_BAD_SIGNATURE = TPM_BASE + 98,
TPM_NOCONTEXTSPACE = TPM_BASE + 99,
/* TPM-defined non-fatal errors */
TPM_RETRY = TPM_BASE + TPM_NON_FATAL,
TPM_NEEDS_SELFTEST = TPM_BASE + TPM_NON_FATAL + 1,
TPM_DOING_SELFTEST = TPM_BASE + TPM_NON_FATAL + 2,
TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3,
+};
+/**
- Initialize TPM device. It must be called before any TPM commands.
- @return 0 on success, non-0 on error.
@@ -201,4 +316,63 @@ uint32_t tpm_physical_set_deactivated(uint8_t state); uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, void *cap, size_t count);
+/**
- Issue a TPM_FlushSpecific command for a AUTH ressource.
- @param auth_handle handle of the auth session
- @return return code of the operation
- */
+uint32_t tpm_terminate_auth_session(uint32_t auth_handle);
+/**
- Issue a TPM_OIAP command to setup an object independant authorization
- session.
- Information about the session is stored internally.
- If there was already an OIAP session active it is terminated and a new
- session is set up.
- @param auth_handle pointer to the (new) auth handle or NULL.
- @return return code of the operation
- */
+uint32_t tpm_oiap(uint32_t *auth_handle);
+/**
- Ends an active OIAP session.
- @return return code of the operation
- */
+uint32_t tpm_end_oiap(void);
+/**
- Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
- the usage of the parent key.
- @param parent_handle handle of the parent key.
- @param key pointer to the key structure (TPM_KEY or TPM_KEY12).
- @param key_length size of the key structure
- @param parent_key_usage_auth usage auth for the parent key
- @param key_handle pointer to the key handle
- @return return code of the operation
- */
+uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
const void *key, size_t key_length,
const void *parent_key_usage_auth,
uint32_t *key_handle);
+/**
- Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
- authenticating the usage of the key.
- @param key_handle handle of the key
- @param usage_auth usage auth for the key
- @param pubkey pointer to the pub key buffer; may be NULL if the pubkey
should not be stored.
- @param pubkey_len pointer to the pub key buffer len. On entry: the size of
the provided pubkey buffer. On successful exit: the size
of the stored TPM_PUBKEY structure (iff pubkey != NULL).
- @return return code of the operation
- */
+uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
void *pubkey, size_t *pubkey_len);
#endif /* __TPM_H */ diff --git a/lib/tpm.c b/lib/tpm.c index 42c9bea..f0b4f59 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -1,5 +1,6 @@ /*
- Copyright (c) 2013 The Chromium OS Authors.
- Coypright (c) 2013 Guntermann & Drunck GmbH
- See file CREDITS for list of people who contributed to this
- project.
@@ -22,6 +23,7 @@
#include <common.h> #include <stdarg.h> +#include <sha1.h> #include <tpm.h> #include <asm/unaligned.h>
@@ -35,8 +37,31 @@ enum { TPM_REQUEST_HEADER_LENGTH = 10, TPM_RESPONSE_HEADER_LENGTH = 10, PCR_DIGEST_LENGTH = 20,
DIGEST_LENGTH = 20,
TPM_REQUEST_AUTH_LENGTH = 45,
TPM_RESPONSE_AUTH_LENGTH = 41,
/* some max lengths, valid for RSA keys <= 2048 bits */
TPM_KEY12_MAX_LENGTH = 618,
TPM_PUBKEY_MAX_LENGTH = 288,
};
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+#ifndef CONFIG_SHA1 +#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too" +#endif /* !CONFIG_SHA1 */
+struct session_data {
int valid;
uint32_t handle;
uint8_t nonce_even[DIGEST_LENGTH];
uint8_t nonce_odd[DIGEST_LENGTH];
+};
+static struct session_data oiap_session = {0, };
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
/**
- Pack data into a byte string. The data types are specified in
- the format string: 'b' means unsigned byte, 'w' unsigned word,
@@ -235,7 +260,7 @@ static uint32_t tpm_sendrecv_command(const void *command, response, &response_length); if (err) return TPM_LIB_ERROR;
if (response)
if (size_ptr) *size_ptr = response_length; return tpm_return_code(response);
@@ -579,3 +604,327 @@ uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
return 0;
}
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+/**
- Fill an authentication block in a request.
- This func can create the first as well as the second auth block (for
- double authorized commands).
- @param request pointer to the request (w/ uninitialised auth data)
- @param request_len0 length of the request without auth data
- @param handles_len length of the handles area in request
- @param auth_session pointer to the (valid) auth session to be used
- @param request_auth pointer to the auth block of the request to be filled
- @param auth authentication data (HMAC key)
- */
+static uint32_t create_request_auth(const void *request, size_t request_len0,
size_t handles_len,
struct session_data *auth_session,
void *request_auth, const void *auth)
+{
uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
sha1_context hash_ctx;
const size_t command_code_offset = 6;
const size_t auth_nonce_odd_offset = 4;
const size_t auth_continue_offset = 24;
const size_t auth_auth_offset = 25;
if (!auth_session || !auth_session->valid)
return TPM_LIB_ERROR;
sha1_starts(&hash_ctx);
sha1_update(&hash_ctx, request + command_code_offset, 4);
if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
sha1_update(&hash_ctx,
request + TPM_REQUEST_HEADER_LENGTH + handles_len,
request_len0 - TPM_REQUEST_HEADER_LENGTH
- handles_len);
sha1_finish(&hash_ctx, hmac_data);
sha1_starts(&hash_ctx);
sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
sha1_finish(&hash_ctx, auth_session->nonce_odd);
if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
0, auth_session->handle,
auth_nonce_odd_offset, auth_session->nonce_odd,
DIGEST_LENGTH,
auth_continue_offset, 1))
return TPM_LIB_ERROR;
if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
DIGEST_LENGTH,
auth_session->nonce_even,
DIGEST_LENGTH,
2 * DIGEST_LENGTH,
request_auth + auth_nonce_odd_offset,
DIGEST_LENGTH + 1))
return TPM_LIB_ERROR;
sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
request_auth + auth_auth_offset);
return TPM_SUCCESS;
+}
+/**
- Verify an authentication block in a response.
- Since this func updates the nonce_even in the session data it has to be
- called when receiving a succesfull AUTH response.
- This func can verify the first as well as the second auth block (for
- double authorized commands).
- @param command_code command code of the request
- @param response pointer to the request (w/ uninitialised auth data)
- @param handles_len length of the handles area in response
- @param auth_session pointer to the (valid) auth session to be used
- @param response_auth pointer to the auth block of the response to be verified
- @param auth authentication data (HMAC key)
- */
+static uint32_t verify_response_auth(uint32_t command_code,
const void *response, size_t response_len0,
size_t handles_len,
struct session_data *auth_session,
const void *response_auth, const void *auth)
+{
uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
uint8_t computed_auth[DIGEST_LENGTH];
sha1_context hash_ctx;
const size_t return_code_offset = 6;
const size_t auth_continue_offset = 20;
const size_t auth_auth_offset = 21;
uint8_t auth_continue;
if (!auth_session || !auth_session->valid)
return TPM_AUTHFAIL;
if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
0, command_code))
return TPM_LIB_ERROR;
if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
return TPM_LIB_ERROR;
sha1_starts(&hash_ctx);
sha1_update(&hash_ctx, response + return_code_offset, 4);
sha1_update(&hash_ctx, hmac_data, 4);
if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
sha1_update(&hash_ctx,
response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
response_len0 - TPM_RESPONSE_HEADER_LENGTH
- handles_len);
sha1_finish(&hash_ctx, hmac_data);
memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
DIGEST_LENGTH,
response_auth,
DIGEST_LENGTH,
2 * DIGEST_LENGTH,
auth_session->nonce_odd,
DIGEST_LENGTH,
3 * DIGEST_LENGTH,
auth_continue))
return TPM_LIB_ERROR;
sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
computed_auth);
if (memcmp(computed_auth, response_auth + auth_auth_offset,
DIGEST_LENGTH))
return TPM_AUTHFAIL;
return TPM_SUCCESS;
+}
+uint32_t tpm_terminate_auth_session(uint32_t auth_handle) +{
const uint8_t command[18] = {
0x00, 0xc1, /* TPM_TAG */
0x00, 0x00, 0x00, 0x00, /* parameter size */
0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
};
const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
uint8_t request[COMMAND_BUFFER_SIZE];
if (pack_byte_string(request, sizeof(request), "sd",
0, command, sizeof(command),
req_handle_offset, auth_handle))
return TPM_LIB_ERROR;
if (oiap_session.valid && oiap_session.handle == auth_handle)
oiap_session.valid = 0;
return tpm_sendrecv_command(request, NULL, NULL);
+}
+uint32_t tpm_end_oiap(void) +{
uint32_t err = TPM_SUCCESS;
if (oiap_session.valid)
err = tpm_terminate_auth_session(oiap_session.handle);
return err;
+}
+uint32_t tpm_oiap(uint32_t *auth_handle) +{
const uint8_t command[10] = {
0x00, 0xc1, /* TPM_TAG */
0x00, 0x00, 0x00, 0x0a, /* parameter size */
0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
};
const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
uint8_t response[COMMAND_BUFFER_SIZE];
size_t response_length = sizeof(response);
uint32_t err;
if (oiap_session.valid)
tpm_terminate_auth_session(oiap_session.handle);
err = tpm_sendrecv_command(command, response, &response_length);
if (err)
return err;
if (unpack_byte_string(response, response_length, "ds",
res_auth_handle_offset, &oiap_session.handle,
res_nonce_even_offset, &oiap_session.nonce_even,
(uint32_t)DIGEST_LENGTH))
return TPM_LIB_ERROR;
oiap_session.valid = 1;
if (auth_handle)
*auth_handle = oiap_session.handle;
return 0;
+}
+uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
const void *key, size_t key_length,
const void *parent_key_usage_auth,
uint32_t *key_handle)
+{
const uint8_t command[14] = {
0x00, 0xc2, /* TPM_TAG */
0x00, 0x00, 0x00, 0x00, /* parameter size */
0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
0x00, 0x00, 0x00, 0x00, /* parent handle */
};
const size_t req_size_offset = 2;
const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
+ TPM_REQUEST_AUTH_LENGTH];
uint8_t response[COMMAND_BUFFER_SIZE];
size_t response_length = sizeof(response);
uint32_t err;
if (!oiap_session.valid) {
err = tpm_oiap(NULL);
if (err)
return err;
}
if (pack_byte_string(request, sizeof(request), "sdds",
0, command, sizeof(command),
req_size_offset,
sizeof(command) + key_length
+ TPM_REQUEST_AUTH_LENGTH,
req_parent_handle_offset, parent_handle,
req_key_offset, key, key_length
))
return TPM_LIB_ERROR;
err = create_request_auth(request, sizeof(command) + key_length, 4,
&oiap_session,
request + sizeof(command) + key_length,
parent_key_usage_auth);
if (err)
return err;
err = tpm_sendrecv_command(request, response, &response_length);
if (err) {
if (err == TPM_AUTHFAIL)
oiap_session.valid = 0;
return err;
}
err = verify_response_auth(0x00000041, response,
response_length - TPM_RESPONSE_AUTH_LENGTH,
4, &oiap_session,
response + response_length - TPM_RESPONSE_AUTH_LENGTH,
parent_key_usage_auth);
if (err)
return err;
if (key_handle) {
if (unpack_byte_string(response, response_length, "d",
res_handle_offset, key_handle))
return TPM_LIB_ERROR;
}
return 0;
+}
+uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
void *pubkey, size_t *pubkey_len)
+{
const uint8_t command[14] = {
0x00, 0xc2, /* TPM_TAG */
0x00, 0x00, 0x00, 0x00, /* parameter size */
0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
0x00, 0x00, 0x00, 0x00, /* key handle */
};
const size_t req_size_offset = 2;
const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
+ TPM_RESPONSE_AUTH_LENGTH];
size_t response_length = sizeof(response);
uint32_t err;
if (!oiap_session.valid) {
err = tpm_oiap(NULL);
if (err)
return err;
}
if (pack_byte_string(request, sizeof(request), "sdd",
0, command, sizeof(command),
req_size_offset,
(uint32_t)(sizeof(command)
+ TPM_REQUEST_AUTH_LENGTH),
req_key_handle_offset, key_handle
))
return TPM_LIB_ERROR;
err = create_request_auth(request, sizeof(command), 4, &oiap_session,
request + sizeof(command), usage_auth);
if (err)
return err;
err = tpm_sendrecv_command(request, response, &response_length);
if (err) {
if (err == TPM_AUTHFAIL)
oiap_session.valid = 0;
return err;
}
err = verify_response_auth(0x00000021, response,
response_length - TPM_RESPONSE_AUTH_LENGTH,
0, &oiap_session,
response + response_length - TPM_RESPONSE_AUTH_LENGTH,
usage_auth);
if (err)
return err;
if (pubkey) {
if ((response_length - TPM_RESPONSE_HEADER_LENGTH
- TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
return TPM_LIB_ERROR;
*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
- TPM_RESPONSE_AUTH_LENGTH;
memcpy(pubkey, response + res_pubkey_offset,
response_length - TPM_RESPONSE_HEADER_LENGTH
- TPM_RESPONSE_AUTH_LENGTH);
}
return 0;
+}
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
1.8.3