Commit dc26e913a8d1a62bd4112f41232e0273ee66423d

Authored by Miquel Raynal
Committed by Tom Rini
1 parent da9c3392e6

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 <miquel.raynal@bootlin.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Tom Rini <trini@konsulko.com>

Showing 3 changed files with 105 additions and 12 deletions Side-by-side Diff

... ... @@ -234,6 +234,36 @@
234 234 lockout_recovery));
235 235 }
236 236  
  237 +static int do_tpm_change_auth(cmd_tbl_t *cmdtp, int flag, int argc,
  238 + char *const argv[])
  239 +{
  240 + u32 handle;
  241 + const char *newpw = argv[2];
  242 + const char *oldpw = (argc == 3) ? NULL : argv[3];
  243 + const ssize_t newpw_sz = strlen(newpw);
  244 + const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
  245 +
  246 + if (argc < 3 || argc > 4)
  247 + return CMD_RET_USAGE;
  248 +
  249 + if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
  250 + return -EINVAL;
  251 +
  252 + if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
  253 + handle = TPM2_RH_LOCKOUT;
  254 + else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
  255 + handle = TPM2_RH_ENDORSEMENT;
  256 + else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
  257 + handle = TPM2_RH_OWNER;
  258 + else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
  259 + handle = TPM2_RH_PLATFORM;
  260 + else
  261 + return CMD_RET_USAGE;
  262 +
  263 + return report_return_code(tpm2_change_auth(handle, newpw, newpw_sz,
  264 + oldpw, oldpw_sz));
  265 +}
  266 +
237 267 static cmd_tbl_t tpm2_commands[] = {
238 268 U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
239 269 U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
... ... @@ -245,6 +275,7 @@
245 275 U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
246 276 U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
247 277 U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
  278 + U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
248 279 };
249 280  
250 281 cmd_tbl_t *get_tpm_commands(unsigned int *size)
... ... @@ -291,17 +322,21 @@
291 322 " <property>: property\n"
292 323 " <addr>: address to store <count> entries of 4 bytes\n"
293 324 " <count>: number of entries to retrieve\n"
294   -" dam_reset_counter [<password>]\n"
295   -" - If the TPM is not in a LOCKOUT state, reset the internal error\n"
296   -" counter (TPMv2 only)\n"
297   -" dam_set_parameters <maxTries> <recoveryTime> <lockoutRecovery> [<password>]\n"
298   -" - If the TPM is not in a LOCKOUT state, set the dictionary attack\n"
299   -" parameters:\n"
300   -" * maxTries: maximum number of failures before lockout.\n"
301   -" 0 means always locking.\n"
302   -" * recoveryTime: time before decrementation of the error counter,\n"
303   -" 0 means no lockout.\n"
304   -" * lockoutRecovery: time of a lockout (before the next try)\n"
305   -" 0 means a reboot is needed.\n"
  325 +"dam_reset [<password>]\n"
  326 +" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n"
  327 +" <password>: optional password\n"
  328 +"dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n"
  329 +" If the TPM is not in a LOCKOUT state, set the DAM parameters\n"
  330 +" <maxTries>: maximum number of failures before lockout,\n"
  331 +" 0 means always locking\n"
  332 +" <recoveryTime>: time before decrement of the error counter,\n"
  333 +" 0 means no lockout\n"
  334 +" <lockoutRecovery>: time of a lockout (before the next try),\n"
  335 +" 0 means a reboot is needed\n"
  336 +" <password>: optional password of the LOCKOUT hierarchy\n"
  337 +"change_auth <hierarchy> <new_pw> [<old_pw>]\n"
  338 +" <hierarchy>: the hierarchy\n"
  339 +" <new_pw>: new password for <hierarchy>\n"
  340 +" <old_pw>: optional previous password of <hierarchy>\n"
306 341 );
... ... @@ -216,5 +216,19 @@
216 216 unsigned int max_tries, unsigned int recovery_time,
217 217 unsigned int lockout_recovery);
218 218  
  219 +/**
  220 + * Issue a TPM2_HierarchyChangeAuth command.
  221 + *
  222 + * @handle Handle
  223 + * @newpw New password
  224 + * @newpw_sz Length of the new password
  225 + * @oldpw Old password
  226 + * @oldpw_sz Length of the old password
  227 + *
  228 + * @return code of the operation
  229 + */
  230 +int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz,
  231 + const char *oldpw, const ssize_t oldpw_sz);
  232 +
219 233 #endif /* __TPM_V2_H */
... ... @@ -273,4 +273,48 @@
273 273  
274 274 return tpm_sendrecv_command(command_v2, NULL, NULL);
275 275 }
  276 +
  277 +int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz,
  278 + const char *oldpw, const ssize_t oldpw_sz)
  279 +{
  280 + unsigned int offset = 27;
  281 + u8 command_v2[COMMAND_BUFFER_SIZE] = {
  282 + tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  283 + tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
  284 + tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
  285 +
  286 + /* HANDLE */
  287 + tpm_u32(handle), /* TPM resource handle */
  288 +
  289 + /* AUTH_SESSION */
  290 + tpm_u32(9 + oldpw_sz), /* Authorization size */
  291 + tpm_u32(TPM2_RS_PW), /* Session handle */
  292 + tpm_u16(0), /* Size of <nonce> */
  293 + /* <nonce> (if any) */
  294 + 0, /* Attributes: Cont/Excl/Rst */
  295 + tpm_u16(oldpw_sz) /* Size of <hmac/password> */
  296 + /* STRING(oldpw) <hmac/password> (if any) */
  297 +
  298 + /* TPM2B_AUTH (TPM2B_DIGEST) */
  299 + /* tpm_u16(newpw_sz) Digest size, new pw length */
  300 + /* STRING(newpw) Digest buffer, new pw */
  301 + };
  302 + int ret;
  303 +
  304 + /*
  305 + * Fill the command structure starting from the first buffer:
  306 + * - the old password (if any)
  307 + * - size of the new password
  308 + * - new password
  309 + */
  310 + ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
  311 + offset, oldpw, oldpw_sz,
  312 + offset + oldpw_sz, newpw_sz,
  313 + offset + oldpw_sz + 2, newpw, newpw_sz);
  314 + offset += oldpw_sz + 2 + newpw_sz;
  315 + if (ret)
  316 + return TPM_LIB_ERROR;
  317 +
  318 + return tpm_sendrecv_command(command_v2, NULL, NULL);
  319 +}