From dc26e913a8d1a62bd4112f41232e0273ee66423d Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 15 May 2018 11:57:19 +0200 Subject: [PATCH] tpm: add TPM2_HierarchyChangeAuth command support Add support for the TPM2_HierarchyChangeAuth command. Change the command file and the help accordingly. Signed-off-by: Miquel Raynal Reviewed-by: Simon Glass Reviewed-by: Tom Rini --- cmd/tpm-v2.c | 59 ++++++++++++++++++++++++++++++++++++++++++++------------ include/tpm-v2.h | 14 ++++++++++++++ lib/tpm-v2.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 12 deletions(-) diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index 4a5b40b..c245440 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -234,6 +234,36 @@ static int do_tpm_dam_parameters(cmd_tbl_t *cmdtp, int flag, int argc, lockout_recovery)); } +static int do_tpm_change_auth(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + u32 handle; + const char *newpw = argv[2]; + const char *oldpw = (argc == 3) ? NULL : argv[3]; + const ssize_t newpw_sz = strlen(newpw); + const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0; + + if (argc < 3 || argc > 4) + return CMD_RET_USAGE; + + if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN) + return -EINVAL; + + if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1])) + handle = TPM2_RH_LOCKOUT; + else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1])) + handle = TPM2_RH_ENDORSEMENT; + else if (!strcasecmp("TPM2_RH_OWNER", argv[1])) + handle = TPM2_RH_OWNER; + else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1])) + handle = TPM2_RH_PLATFORM; + else + return CMD_RET_USAGE; + + return report_return_code(tpm2_change_auth(handle, newpw, newpw_sz, + oldpw, oldpw_sz)); +} + static cmd_tbl_t tpm2_commands[] = { U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""), U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""), @@ -245,6 +275,7 @@ static cmd_tbl_t tpm2_commands[] = { U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""), U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""), U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""), + U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""), }; cmd_tbl_t *get_tpm_commands(unsigned int *size) @@ -291,16 +322,20 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command", " : property\n" " : address to store entries of 4 bytes\n" " : number of entries to retrieve\n" -" dam_reset_counter []\n" -" - If the TPM is not in a LOCKOUT state, reset the internal error\n" -" counter (TPMv2 only)\n" -" dam_set_parameters []\n" -" - If the TPM is not in a LOCKOUT state, set the dictionary attack\n" -" parameters:\n" -" * maxTries: maximum number of failures before lockout.\n" -" 0 means always locking.\n" -" * recoveryTime: time before decrementation of the error counter,\n" -" 0 means no lockout.\n" -" * lockoutRecovery: time of a lockout (before the next try)\n" -" 0 means a reboot is needed.\n" +"dam_reset []\n" +" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n" +" : optional password\n" +"dam_parameters []\n" +" If the TPM is not in a LOCKOUT state, set the DAM parameters\n" +" : maximum number of failures before lockout,\n" +" 0 means always locking\n" +" : time before decrement of the error counter,\n" +" 0 means no lockout\n" +" : time of a lockout (before the next try),\n" +" 0 means a reboot is needed\n" +" : optional password of the LOCKOUT hierarchy\n" +"change_auth []\n" +" : the hierarchy\n" +" : new password for \n" +" : optional previous password of \n" ); diff --git a/include/tpm-v2.h b/include/tpm-v2.h index ab8f113..be1aa2c 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -216,4 +216,18 @@ u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz, unsigned int max_tries, unsigned int recovery_time, unsigned int lockout_recovery); +/** + * Issue a TPM2_HierarchyChangeAuth command. + * + * @handle Handle + * @newpw New password + * @newpw_sz Length of the new password + * @oldpw Old password + * @oldpw_sz Length of the old password + * + * @return code of the operation + */ +int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz, + const char *oldpw, const ssize_t oldpw_sz); + #endif /* __TPM_V2_H */ diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 9a65e7d..ffe8613 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -273,3 +273,47 @@ u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz, return tpm_sendrecv_command(command_v2, NULL, NULL); } + +int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz, + const char *oldpw, const ssize_t oldpw_sz) +{ + unsigned int offset = 27; + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */ + tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */ + + /* HANDLE */ + tpm_u32(handle), /* TPM resource handle */ + + /* AUTH_SESSION */ + tpm_u32(9 + oldpw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of */ + /* (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(oldpw_sz) /* Size of */ + /* STRING(oldpw) (if any) */ + + /* TPM2B_AUTH (TPM2B_DIGEST) */ + /* tpm_u16(newpw_sz) Digest size, new pw length */ + /* STRING(newpw) Digest buffer, new pw */ + }; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the old password (if any) + * - size of the new password + * - new password + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "sws", + offset, oldpw, oldpw_sz, + offset + oldpw_sz, newpw_sz, + offset + oldpw_sz + 2, newpw, newpw_sz); + offset += oldpw_sz + 2 + newpw_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +}