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