uboot/lib/tpm-v1.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2013 The Chromium OS Authors.
   4 * Coypright (c) 2013 Guntermann & Drunck GmbH
   5 */
   6
   7#define LOG_CATEGORY UCLASS_TPM
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <log.h>
  12#include <asm/unaligned.h>
  13#include <u-boot/sha1.h>
  14#include <tpm-common.h>
  15#include <tpm-v1.h>
  16#include "tpm-utils.h"
  17
  18#ifdef CONFIG_TPM_AUTH_SESSIONS
  19
  20#ifndef CONFIG_SHA1
  21#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
  22#endif /* !CONFIG_SHA1 */
  23
  24struct session_data {
  25        int             valid;
  26        u32     handle;
  27        u8              nonce_even[DIGEST_LENGTH];
  28        u8              nonce_odd[DIGEST_LENGTH];
  29};
  30
  31static struct session_data oiap_session = {0, };
  32
  33#endif /* CONFIG_TPM_AUTH_SESSIONS */
  34
  35u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
  36{
  37        const u8 command[12] = {
  38                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
  39        };
  40        const size_t mode_offset = 10;
  41        u8 buf[COMMAND_BUFFER_SIZE];
  42
  43        if (pack_byte_string(buf, sizeof(buf), "sw",
  44                             0, command, sizeof(command),
  45                             mode_offset, mode))
  46                return TPM_LIB_ERROR;
  47
  48        return tpm_sendrecv_command(dev, buf, NULL, NULL);
  49}
  50
  51u32 tpm1_resume(struct udevice *dev)
  52{
  53        return tpm1_startup(dev, TPM_ST_STATE);
  54}
  55
  56u32 tpm1_self_test_full(struct udevice *dev)
  57{
  58        const u8 command[10] = {
  59                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
  60        };
  61        return tpm_sendrecv_command(dev, command, NULL, NULL);
  62}
  63
  64u32 tpm1_continue_self_test(struct udevice *dev)
  65{
  66        const u8 command[10] = {
  67                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
  68        };
  69        return tpm_sendrecv_command(dev, command, NULL, NULL);
  70}
  71
  72u32 tpm1_clear_and_reenable(struct udevice *dev)
  73{
  74        u32 ret;
  75
  76        log_info("TPM: Clear and re-enable\n");
  77        ret = tpm1_force_clear(dev);
  78        if (ret != TPM_SUCCESS) {
  79                log_err("Can't initiate a force clear\n");
  80                return ret;
  81        }
  82
  83        ret = tpm1_physical_enable(dev);
  84        if (ret != TPM_SUCCESS) {
  85                log_err("TPM: Can't set enabled state\n");
  86                return ret;
  87        }
  88
  89        ret = tpm1_physical_set_deactivated(dev, 0);
  90        if (ret != TPM_SUCCESS) {
  91                log_err("TPM: Can't set deactivated state\n");
  92                return ret;
  93        }
  94
  95        return TPM_SUCCESS;
  96}
  97
  98u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
  99{
 100        const u8 command[101] = {
 101                0x0, 0xc1,              /* TPM_TAG */
 102                0x0, 0x0, 0x0, 0x65,    /* parameter size */
 103                0x0, 0x0, 0x0, 0xcc,    /* TPM_COMMAND_CODE */
 104                /* TPM_NV_DATA_PUBLIC->... */
 105                0x0, 0x18,              /* ...->TPM_STRUCTURE_TAG */
 106                0, 0, 0, 0,             /* ...->TPM_NV_INDEX */
 107                /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
 108                0x0, 0x3,
 109                0, 0, 0,
 110                0x1f,
 111                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 112                /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
 113                0x0, 0x3,
 114                0, 0, 0,
 115                0x1f,
 116                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 117                /* TPM_NV_ATTRIBUTES->... */
 118                0x0, 0x17,              /* ...->TPM_STRUCTURE_TAG */
 119                0, 0, 0, 0,             /* ...->attributes */
 120                /* End of TPM_NV_ATTRIBUTES */
 121                0,                      /* bReadSTClear */
 122                0,                      /* bWriteSTClear */
 123                0,                      /* bWriteDefine */
 124                0, 0, 0, 0,             /* size */
 125        };
 126        const size_t index_offset = 12;
 127        const size_t perm_offset = 70;
 128        const size_t size_offset = 77;
 129        u8 buf[COMMAND_BUFFER_SIZE];
 130
 131        if (pack_byte_string(buf, sizeof(buf), "sddd",
 132                             0, command, sizeof(command),
 133                             index_offset, index,
 134                             perm_offset, perm,
 135                             size_offset, size))
 136                return TPM_LIB_ERROR;
 137
 138        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 139}
 140
 141u32 tpm1_nv_set_locked(struct udevice *dev)
 142{
 143        return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
 144}
 145
 146u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 147{
 148        const u8 command[22] = {
 149                0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
 150        };
 151        const size_t index_offset = 10;
 152        const size_t length_offset = 18;
 153        const size_t data_size_offset = 10;
 154        const size_t data_offset = 14;
 155        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 156        size_t response_length = sizeof(response);
 157        u32 data_size;
 158        u32 err;
 159
 160        if (pack_byte_string(buf, sizeof(buf), "sdd",
 161                             0, command, sizeof(command),
 162                             index_offset, index,
 163                             length_offset, count))
 164                return TPM_LIB_ERROR;
 165        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 166        if (err)
 167                return err;
 168        if (unpack_byte_string(response, response_length, "d",
 169                               data_size_offset, &data_size))
 170                return TPM_LIB_ERROR;
 171        if (data_size > count)
 172                return TPM_LIB_ERROR;
 173        if (unpack_byte_string(response, response_length, "s",
 174                               data_offset, data, data_size))
 175                return TPM_LIB_ERROR;
 176
 177        return 0;
 178}
 179
 180u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
 181                        u32 length)
 182{
 183        const u8 command[256] = {
 184                0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
 185        };
 186        const size_t command_size_offset = 2;
 187        const size_t index_offset = 10;
 188        const size_t length_offset = 18;
 189        const size_t data_offset = 22;
 190        const size_t write_info_size = 12;
 191        const u32 total_length =
 192                TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
 193        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 194        size_t response_length = sizeof(response);
 195        u32 err;
 196
 197        if (pack_byte_string(buf, sizeof(buf), "sddds",
 198                             0, command, sizeof(command),
 199                             command_size_offset, total_length,
 200                             index_offset, index,
 201                             length_offset, length,
 202                             data_offset, data, length))
 203                return TPM_LIB_ERROR;
 204        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 205        if (err)
 206                return err;
 207
 208        return 0;
 209}
 210
 211u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
 212                void *out_digest)
 213{
 214        const u8 command[34] = {
 215                0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
 216        };
 217        const size_t index_offset = 10;
 218        const size_t in_digest_offset = 14;
 219        const size_t out_digest_offset = 10;
 220        u8 buf[COMMAND_BUFFER_SIZE];
 221        u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
 222        size_t response_length = sizeof(response);
 223        u32 err;
 224
 225        if (pack_byte_string(buf, sizeof(buf), "sds",
 226                             0, command, sizeof(command),
 227                             index_offset, index,
 228                             in_digest_offset, in_digest,
 229                             PCR_DIGEST_LENGTH))
 230                return TPM_LIB_ERROR;
 231        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 232        if (err)
 233                return err;
 234
 235        if (unpack_byte_string(response, response_length, "s",
 236                               out_digest_offset, out_digest,
 237                               PCR_DIGEST_LENGTH))
 238                return TPM_LIB_ERROR;
 239
 240        return 0;
 241}
 242
 243u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 244{
 245        const u8 command[14] = {
 246                0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
 247        };
 248        const size_t index_offset = 10;
 249        const size_t out_digest_offset = 10;
 250        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 251        size_t response_length = sizeof(response);
 252        u32 err;
 253
 254        if (count < PCR_DIGEST_LENGTH)
 255                return TPM_LIB_ERROR;
 256
 257        if (pack_byte_string(buf, sizeof(buf), "sd",
 258                             0, command, sizeof(command),
 259                             index_offset, index))
 260                return TPM_LIB_ERROR;
 261        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 262        if (err)
 263                return err;
 264        if (unpack_byte_string(response, response_length, "s",
 265                               out_digest_offset, data, PCR_DIGEST_LENGTH))
 266                return TPM_LIB_ERROR;
 267
 268        return 0;
 269}
 270
 271u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
 272{
 273        const u8 command[12] = {
 274                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
 275        };
 276        const size_t presence_offset = 10;
 277        u8 buf[COMMAND_BUFFER_SIZE];
 278
 279        if (pack_byte_string(buf, sizeof(buf), "sw",
 280                             0, command, sizeof(command),
 281                             presence_offset, presence))
 282                return TPM_LIB_ERROR;
 283
 284        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 285}
 286
 287u32 tpm1_finalise_physical_presence(struct udevice *dev)
 288{
 289        const u8 command[12] = {
 290                0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
 291        };
 292
 293        return tpm_sendrecv_command(dev, command, NULL, NULL);
 294}
 295
 296u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
 297{
 298        const u8 command[30] = {
 299                0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
 300        };
 301        const size_t response_size_offset = 2;
 302        const size_t data_offset = 10;
 303        const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
 304        u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
 305        size_t response_length = sizeof(response);
 306        u32 data_size;
 307        u32 err;
 308
 309        err = tpm_sendrecv_command(dev, command, response, &response_length);
 310        if (err)
 311                return err;
 312        if (unpack_byte_string(response, response_length, "d",
 313                               response_size_offset, &data_size))
 314                return TPM_LIB_ERROR;
 315        if (data_size < header_and_checksum_size)
 316                return TPM_LIB_ERROR;
 317        data_size -= header_and_checksum_size;
 318        if (data_size > count)
 319                return TPM_LIB_ERROR;
 320        if (unpack_byte_string(response, response_length, "s",
 321                               data_offset, data, data_size))
 322                return TPM_LIB_ERROR;
 323
 324        return 0;
 325}
 326
 327u32 tpm1_force_clear(struct udevice *dev)
 328{
 329        const u8 command[10] = {
 330                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
 331        };
 332
 333        return tpm_sendrecv_command(dev, command, NULL, NULL);
 334}
 335
 336u32 tpm1_physical_enable(struct udevice *dev)
 337{
 338        const u8 command[10] = {
 339                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
 340        };
 341
 342        return tpm_sendrecv_command(dev, command, NULL, NULL);
 343}
 344
 345u32 tpm1_physical_disable(struct udevice *dev)
 346{
 347        const u8 command[10] = {
 348                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
 349        };
 350
 351        return tpm_sendrecv_command(dev, command, NULL, NULL);
 352}
 353
 354u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
 355{
 356        const u8 command[11] = {
 357                0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
 358        };
 359        const size_t state_offset = 10;
 360        u8 buf[COMMAND_BUFFER_SIZE];
 361
 362        if (pack_byte_string(buf, sizeof(buf), "sb",
 363                             0, command, sizeof(command),
 364                             state_offset, state))
 365                return TPM_LIB_ERROR;
 366
 367        return tpm_sendrecv_command(dev, buf, NULL, NULL);
 368}
 369
 370u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
 371                        void *cap, size_t count)
 372{
 373        const u8 command[22] = {
 374                0x0, 0xc1,              /* TPM_TAG */
 375                0x0, 0x0, 0x0, 0x16,    /* parameter size */
 376                0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
 377                0x0, 0x0, 0x0, 0x0,     /* TPM_CAPABILITY_AREA */
 378                0x0, 0x0, 0x0, 0x4,     /* subcap size */
 379                0x0, 0x0, 0x0, 0x0,     /* subcap value */
 380        };
 381        const size_t cap_area_offset = 10;
 382        const size_t sub_cap_offset = 18;
 383        const size_t cap_offset = 14;
 384        const size_t cap_size_offset = 10;
 385        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 386        size_t response_length = sizeof(response);
 387        u32 cap_size;
 388        u32 err;
 389
 390        if (pack_byte_string(buf, sizeof(buf), "sdd",
 391                             0, command, sizeof(command),
 392                             cap_area_offset, cap_area,
 393                             sub_cap_offset, sub_cap))
 394                return TPM_LIB_ERROR;
 395        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 396        if (err)
 397                return err;
 398        if (unpack_byte_string(response, response_length, "d",
 399                               cap_size_offset, &cap_size))
 400                return TPM_LIB_ERROR;
 401        if (cap_size > response_length || cap_size > count)
 402                return TPM_LIB_ERROR;
 403        if (unpack_byte_string(response, response_length, "s",
 404                               cap_offset, cap, cap_size))
 405                return TPM_LIB_ERROR;
 406
 407        return 0;
 408}
 409
 410u32 tpm1_get_permanent_flags(struct udevice *dev,
 411                             struct tpm_permanent_flags *pflags)
 412{
 413        const u8 command[22] = {
 414                0x0, 0xc1,              /* TPM_TAG */
 415                0x0, 0x0, 0x0, 0x16,    /* parameter size */
 416                0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
 417                0x0, 0x0, 0x0, 0x4,     /* TPM_CAP_FLAG_PERM */
 418                0x0, 0x0, 0x0, 0x4,     /* subcap size */
 419                0x0, 0x0, 0x1, 0x8,     /* subcap value */
 420        };
 421        const size_t data_size_offset = TPM_HEADER_SIZE;
 422        const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
 423        u8 response[COMMAND_BUFFER_SIZE];
 424        size_t response_length = sizeof(response);
 425        u32 err;
 426        u32 data_size;
 427
 428        err = tpm_sendrecv_command(dev, command, response, &response_length);
 429        if (err)
 430                return err;
 431        if (unpack_byte_string(response, response_length, "d",
 432                               data_size_offset, &data_size)) {
 433                log_err("Cannot unpack data size\n");
 434                return TPM_LIB_ERROR;
 435        }
 436        if (data_size < sizeof(*pflags)) {
 437                log_err("Data size too small\n");
 438                return TPM_LIB_ERROR;
 439        }
 440        if (unpack_byte_string(response, response_length, "s",
 441                               data_offset, pflags, sizeof(*pflags))) {
 442                log_err("Cannot unpack pflags\n");
 443                return TPM_LIB_ERROR;
 444        }
 445
 446        return 0;
 447}
 448
 449u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 450{
 451        const u8 command[22] = {
 452                0x0, 0xc1,              /* TPM_TAG */
 453                0x0, 0x0, 0x0, 0x16,    /* parameter size */
 454                0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
 455                0x0, 0x0, 0x0, 0x11,
 456                0x0, 0x0, 0x0, 0x4,
 457        };
 458        const size_t index_offset = 18;
 459        const size_t perm_offset = 60;
 460        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 461        size_t response_length = sizeof(response);
 462        u32 err;
 463
 464        if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
 465                             index_offset, index))
 466                return TPM_LIB_ERROR;
 467        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 468        if (err)
 469                return err;
 470        if (unpack_byte_string(response, response_length, "d",
 471                               perm_offset, perm))
 472                return TPM_LIB_ERROR;
 473
 474        return 0;
 475}
 476
 477#ifdef CONFIG_TPM_FLUSH_RESOURCES
 478u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
 479{
 480        const u8 command[18] = {
 481                0x00, 0xc1,             /* TPM_TAG */
 482                0x00, 0x00, 0x00, 0x12, /* parameter size */
 483                0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
 484                0x00, 0x00, 0x00, 0x00, /* key handle */
 485                0x00, 0x00, 0x00, 0x00, /* resource type */
 486        };
 487        const size_t key_handle_offset = 10;
 488        const size_t resource_type_offset = 14;
 489        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 490        size_t response_length = sizeof(response);
 491        u32 err;
 492
 493        if (pack_byte_string(buf, sizeof(buf), "sdd",
 494                             0, command, sizeof(command),
 495                             key_handle_offset, key_handle,
 496                             resource_type_offset, resource_type))
 497                return TPM_LIB_ERROR;
 498
 499        err = tpm_sendrecv_command(dev, buf, response, &response_length);
 500        if (err)
 501                return err;
 502        return 0;
 503}
 504#endif /* CONFIG_TPM_FLUSH_RESOURCES */
 505
 506#ifdef CONFIG_TPM_AUTH_SESSIONS
 507
 508/**
 509 * Fill an authentication block in a request.
 510 * This func can create the first as well as the second auth block (for
 511 * double authorized commands).
 512 *
 513 * @param request       pointer to the request (w/ uninitialised auth data)
 514 * @param request_len0  length of the request without auth data
 515 * @param handles_len   length of the handles area in request
 516 * @param auth_session  pointer to the (valid) auth session to be used
 517 * @param request_auth  pointer to the auth block of the request to be filled
 518 * @param auth          authentication data (HMAC key)
 519 */
 520static u32 create_request_auth(const void *request, size_t request_len0,
 521                               size_t handles_len,
 522                               struct session_data *auth_session,
 523                               void *request_auth, const void *auth)
 524{
 525        u8 hmac_data[DIGEST_LENGTH * 3 + 1];
 526        sha1_context hash_ctx;
 527        const size_t command_code_offset = 6;
 528        const size_t auth_nonce_odd_offset = 4;
 529        const size_t auth_continue_offset = 24;
 530        const size_t auth_auth_offset = 25;
 531
 532        if (!auth_session || !auth_session->valid)
 533                return TPM_LIB_ERROR;
 534
 535        sha1_starts(&hash_ctx);
 536        sha1_update(&hash_ctx, request + command_code_offset, 4);
 537        if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
 538                sha1_update(&hash_ctx,
 539                            request + TPM_REQUEST_HEADER_LENGTH + handles_len,
 540                            request_len0 - TPM_REQUEST_HEADER_LENGTH
 541                            - handles_len);
 542        sha1_finish(&hash_ctx, hmac_data);
 543
 544        sha1_starts(&hash_ctx);
 545        sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
 546        sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
 547        sha1_finish(&hash_ctx, auth_session->nonce_odd);
 548
 549        if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
 550                             0, auth_session->handle,
 551                             auth_nonce_odd_offset, auth_session->nonce_odd,
 552                             DIGEST_LENGTH,
 553                             auth_continue_offset, 1))
 554                return TPM_LIB_ERROR;
 555        if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
 556                             DIGEST_LENGTH,
 557                             auth_session->nonce_even,
 558                             DIGEST_LENGTH,
 559                             2 * DIGEST_LENGTH,
 560                             request_auth + auth_nonce_odd_offset,
 561                             DIGEST_LENGTH + 1))
 562                return TPM_LIB_ERROR;
 563        sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
 564                  request_auth + auth_auth_offset);
 565
 566        return TPM_SUCCESS;
 567}
 568
 569/**
 570 * Verify an authentication block in a response.
 571 * Since this func updates the nonce_even in the session data it has to be
 572 * called when receiving a succesfull AUTH response.
 573 * This func can verify the first as well as the second auth block (for
 574 * double authorized commands).
 575 *
 576 * @param command_code  command code of the request
 577 * @param response      pointer to the request (w/ uninitialised auth data)
 578 * @param handles_len   length of the handles area in response
 579 * @param auth_session  pointer to the (valid) auth session to be used
 580 * @param response_auth pointer to the auth block of the response to be verified
 581 * @param auth          authentication data (HMAC key)
 582 */
 583static u32 verify_response_auth(u32 command_code, const void *response,
 584                                size_t response_len0, size_t handles_len,
 585                                struct session_data *auth_session,
 586                                const void *response_auth, const void *auth)
 587{
 588        u8 hmac_data[DIGEST_LENGTH * 3 + 1];
 589        u8 computed_auth[DIGEST_LENGTH];
 590        sha1_context hash_ctx;
 591        const size_t return_code_offset = 6;
 592        const size_t auth_continue_offset = 20;
 593        const size_t auth_auth_offset = 21;
 594        u8 auth_continue;
 595
 596        if (!auth_session || !auth_session->valid)
 597                return TPM_AUTHFAIL;
 598        if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
 599                             0, command_code))
 600                return TPM_LIB_ERROR;
 601        if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
 602                return TPM_LIB_ERROR;
 603
 604        sha1_starts(&hash_ctx);
 605        sha1_update(&hash_ctx, response + return_code_offset, 4);
 606        sha1_update(&hash_ctx, hmac_data, 4);
 607        if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
 608                sha1_update(&hash_ctx,
 609                            response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
 610                            response_len0 - TPM_RESPONSE_HEADER_LENGTH
 611                            - handles_len);
 612        sha1_finish(&hash_ctx, hmac_data);
 613
 614        memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
 615        auth_continue = ((u8 *)response_auth)[auth_continue_offset];
 616        if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
 617                             DIGEST_LENGTH,
 618                             response_auth,
 619                             DIGEST_LENGTH,
 620                             2 * DIGEST_LENGTH,
 621                             auth_session->nonce_odd,
 622                             DIGEST_LENGTH,
 623                             3 * DIGEST_LENGTH,
 624                             auth_continue))
 625                return TPM_LIB_ERROR;
 626
 627        sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
 628                  computed_auth);
 629
 630        if (memcmp(computed_auth, response_auth + auth_auth_offset,
 631                   DIGEST_LENGTH))
 632                return TPM_AUTHFAIL;
 633
 634        return TPM_SUCCESS;
 635}
 636
 637u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
 638{
 639        const u8 command[18] = {
 640                0x00, 0xc1,             /* TPM_TAG */
 641                0x00, 0x00, 0x00, 0x00, /* parameter size */
 642                0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
 643                0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
 644                0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
 645        };
 646        const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
 647        u8 request[COMMAND_BUFFER_SIZE];
 648
 649        if (pack_byte_string(request, sizeof(request), "sd",
 650                             0, command, sizeof(command),
 651                             req_handle_offset, auth_handle))
 652                return TPM_LIB_ERROR;
 653        if (oiap_session.valid && oiap_session.handle == auth_handle)
 654                oiap_session.valid = 0;
 655
 656        return tpm_sendrecv_command(dev, request, NULL, NULL);
 657}
 658
 659u32 tpm1_end_oiap(struct udevice *dev)
 660{
 661        u32 err = TPM_SUCCESS;
 662
 663        if (oiap_session.valid)
 664                err = tpm1_terminate_auth_session(dev, oiap_session.handle);
 665        return err;
 666}
 667
 668u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
 669{
 670        const u8 command[10] = {
 671                0x00, 0xc1,             /* TPM_TAG */
 672                0x00, 0x00, 0x00, 0x0a, /* parameter size */
 673                0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
 674        };
 675        const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
 676        const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
 677        u8 response[COMMAND_BUFFER_SIZE];
 678        size_t response_length = sizeof(response);
 679        u32 err;
 680
 681        if (oiap_session.valid)
 682                tpm1_terminate_auth_session(dev, oiap_session.handle);
 683
 684        err = tpm_sendrecv_command(dev, command, response, &response_length);
 685        if (err)
 686                return err;
 687        if (unpack_byte_string(response, response_length, "ds",
 688                               res_auth_handle_offset, &oiap_session.handle,
 689                               res_nonce_even_offset, &oiap_session.nonce_even,
 690                               (u32)DIGEST_LENGTH))
 691                return TPM_LIB_ERROR;
 692        oiap_session.valid = 1;
 693        if (auth_handle)
 694                *auth_handle = oiap_session.handle;
 695        return 0;
 696}
 697
 698u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
 699                        size_t key_length, const void *parent_key_usage_auth,
 700                        u32 *key_handle)
 701{
 702        const u8 command[14] = {
 703                0x00, 0xc2,             /* TPM_TAG */
 704                0x00, 0x00, 0x00, 0x00, /* parameter size */
 705                0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
 706                0x00, 0x00, 0x00, 0x00, /* parent handle */
 707        };
 708        const size_t req_size_offset = 2;
 709        const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
 710        const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
 711        const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
 712        u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
 713                   TPM_REQUEST_AUTH_LENGTH];
 714        u8 response[COMMAND_BUFFER_SIZE];
 715        size_t response_length = sizeof(response);
 716        u32 err;
 717
 718        if (!oiap_session.valid) {
 719                err = tpm1_oiap(dev, NULL);
 720                if (err)
 721                        return err;
 722        }
 723        if (pack_byte_string(request, sizeof(request), "sdds",
 724                             0, command, sizeof(command),
 725                             req_size_offset,
 726                             sizeof(command) + key_length
 727                             + TPM_REQUEST_AUTH_LENGTH,
 728                             req_parent_handle_offset, parent_handle,
 729                             req_key_offset, key, key_length
 730                ))
 731                return TPM_LIB_ERROR;
 732
 733        err = create_request_auth(request, sizeof(command) + key_length, 4,
 734                                  &oiap_session,
 735                                  request + sizeof(command) + key_length,
 736                                  parent_key_usage_auth);
 737        if (err)
 738                return err;
 739        err = tpm_sendrecv_command(dev, request, response, &response_length);
 740        if (err) {
 741                if (err == TPM_AUTHFAIL)
 742                        oiap_session.valid = 0;
 743                return err;
 744        }
 745
 746        err = verify_response_auth(0x00000041, response,
 747                                   response_length - TPM_RESPONSE_AUTH_LENGTH,
 748                                   4, &oiap_session,
 749                                   response + response_length -
 750                                   TPM_RESPONSE_AUTH_LENGTH,
 751                                   parent_key_usage_auth);
 752        if (err)
 753                return err;
 754
 755        if (key_handle) {
 756                if (unpack_byte_string(response, response_length, "d",
 757                                       res_handle_offset, key_handle))
 758                        return TPM_LIB_ERROR;
 759        }
 760
 761        return 0;
 762}
 763
 764u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
 765                          const void *usage_auth, void *pubkey,
 766                          size_t *pubkey_len)
 767{
 768        const u8 command[14] = {
 769                0x00, 0xc2,             /* TPM_TAG */
 770                0x00, 0x00, 0x00, 0x00, /* parameter size */
 771                0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
 772                0x00, 0x00, 0x00, 0x00, /* key handle */
 773        };
 774        const size_t req_size_offset = 2;
 775        const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
 776        const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
 777        u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
 778        u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
 779                    TPM_RESPONSE_AUTH_LENGTH];
 780        size_t response_length = sizeof(response);
 781        u32 err;
 782
 783        if (!oiap_session.valid) {
 784                err = tpm1_oiap(dev, NULL);
 785                if (err)
 786                        return err;
 787        }
 788        if (pack_byte_string(request, sizeof(request), "sdd",
 789                             0, command, sizeof(command),
 790                             req_size_offset,
 791                             (u32)(sizeof(command)
 792                             + TPM_REQUEST_AUTH_LENGTH),
 793                             req_key_handle_offset, key_handle
 794                ))
 795                return TPM_LIB_ERROR;
 796        err = create_request_auth(request, sizeof(command), 4, &oiap_session,
 797                                  request + sizeof(command), usage_auth);
 798        if (err)
 799                return err;
 800        err = tpm_sendrecv_command(dev, request, response, &response_length);
 801        if (err) {
 802                if (err == TPM_AUTHFAIL)
 803                        oiap_session.valid = 0;
 804                return err;
 805        }
 806        err = verify_response_auth(0x00000021, response,
 807                                   response_length - TPM_RESPONSE_AUTH_LENGTH,
 808                                   0, &oiap_session,
 809                                   response + response_length -
 810                                   TPM_RESPONSE_AUTH_LENGTH,
 811                                   usage_auth);
 812        if (err)
 813                return err;
 814
 815        if (pubkey) {
 816                if ((response_length - TPM_RESPONSE_HEADER_LENGTH
 817                     - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
 818                        return TPM_LIB_ERROR;
 819                *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
 820                        - TPM_RESPONSE_AUTH_LENGTH;
 821                memcpy(pubkey, response + res_pubkey_offset,
 822                       response_length - TPM_RESPONSE_HEADER_LENGTH
 823                       - TPM_RESPONSE_AUTH_LENGTH);
 824        }
 825
 826        return 0;
 827}
 828
 829#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
 830u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
 831                       const u8 pubkey_digest[20], u32 *handle)
 832{
 833        u16 key_count;
 834        u32 key_handles[10];
 835        u8 buf[288];
 836        u8 *ptr;
 837        u32 err;
 838        u8 digest[20];
 839        size_t buf_len;
 840        unsigned int i;
 841
 842        /* fetch list of already loaded keys in the TPM */
 843        err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
 844                                 sizeof(buf));
 845        if (err)
 846                return -1;
 847        key_count = get_unaligned_be16(buf);
 848        ptr = buf + 2;
 849        for (i = 0; i < key_count; ++i, ptr += 4)
 850                key_handles[i] = get_unaligned_be32(ptr);
 851
 852        /* now search a(/ the) key which we can access with the given auth */
 853        for (i = 0; i < key_count; ++i) {
 854                buf_len = sizeof(buf);
 855                err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
 856                if (err && err != TPM_AUTHFAIL)
 857                        return -1;
 858                if (err)
 859                        continue;
 860                sha1_csum(buf, buf_len, digest);
 861                if (!memcmp(digest, pubkey_digest, 20)) {
 862                        *handle = key_handles[i];
 863                        return 0;
 864                }
 865        }
 866        return 1;
 867}
 868#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
 869
 870#endif /* CONFIG_TPM_AUTH_SESSIONS */
 871
 872u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
 873{
 874        const u8 command[14] = {
 875                0x0, 0xc1,              /* TPM_TAG */
 876                0x0, 0x0, 0x0, 0xe,     /* parameter size */
 877                0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
 878        };
 879        const size_t length_offset = 10;
 880        const size_t data_size_offset = 10;
 881        const size_t data_offset = 14;
 882        u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
 883        size_t response_length = sizeof(response);
 884        u32 data_size;
 885        u8 *out = data;
 886
 887        while (count > 0) {
 888                u32 this_bytes = min((size_t)count,
 889                                     sizeof(response) - data_offset);
 890                u32 err;
 891
 892                if (pack_byte_string(buf, sizeof(buf), "sd",
 893                                     0, command, sizeof(command),
 894                                     length_offset, this_bytes))
 895                        return TPM_LIB_ERROR;
 896                err = tpm_sendrecv_command(dev, buf, response,
 897                                           &response_length);
 898                if (err)
 899                        return err;
 900                if (unpack_byte_string(response, response_length, "d",
 901                                       data_size_offset, &data_size))
 902                        return TPM_LIB_ERROR;
 903                if (data_size > count)
 904                        return TPM_LIB_ERROR;
 905                if (unpack_byte_string(response, response_length, "s",
 906                                       data_offset, out, data_size))
 907                        return TPM_LIB_ERROR;
 908
 909                count -= data_size;
 910                out += data_size;
 911        }
 912
 913        return 0;
 914}
 915