Coverage Report

Created: 2026-10-17 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libtpmtss/tpm_tss_tss2_v2.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2018-2021 Andreas Steffen
3
 * Copyright (C) 2018 Tobias Brunner
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#include "tpm_tss_tss2.h"
19
#include "tpm_tss_tss2_names.h"
20
21
#ifdef TSS_TSS2_V2
22
23
#include "tpm_tss_tss2_session.h"
24
25
#include <asn1/asn1.h>
26
#include <asn1/oid.h>
27
#include <bio/bio_reader.h>
28
#include <bio/bio_writer.h>
29
#include <threading/mutex.h>
30
31
#include <dlfcn.h>
32
#include <sys/types.h>
33
#include <sys/stat.h>
34
#include <unistd.h>
35
36
#define LABEL "TPM 2.0 - "
37
38
#define PLATFORM_PCR  24
39
#define MAX_PCR_BANKS  4
40
41
typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
42
43
/**
44
 * Private data of an tpm_tss_tss2_t object.
45
 */
46
struct private_tpm_tss_tss2_t {
47
48
  /**
49
   * Public tpm_tss_tss2_t interface.
50
   */
51
  tpm_tss_t public;
52
53
  /**
54
   * TCTI context
55
   */
56
  TSS2_TCTI_CONTEXT *tcti_context;
57
58
  /**
59
   * SYS context
60
   */
61
  TSS2_SYS_CONTEXT  *sys_context;
62
63
  /**
64
   * TPM version info
65
   */
66
  chunk_t version_info;
67
68
  /**
69
   * Number of supported algorithms
70
   */
71
  size_t supported_algs_count;
72
73
  /**
74
   * List of supported algorithms
75
   */
76
  TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
77
78
  /**
79
   * Number of assigned PCR banks
80
   */
81
  size_t assigned_pcrs_count;
82
83
  /**
84
   * List of assigned PCR banks
85
   */
86
  TPM2_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
87
88
  /**
89
   * Is TPM FIPS 186-4 compliant ?
90
   */
91
  bool fips_186_4;
92
93
  /**
94
   * Does the TPM use the old TCG SHA1-only event digest format
95
   */
96
  bool old_event_digest_format;
97
98
  /**
99
   * TSS2 session used for protected communication with TPM 2.0
100
   */
101
  tpm_tss_tss2_session_t *session;
102
103
  /**
104
   * Mutex controlling access to the TPM 2.0 context
105
   */
106
  mutex_t *mutex;
107
108
};
109
110
/**
111
 * Global TCTI dynamic library handle and init function
112
 */
113
static void *tcti_handle;
114
115
static TSS2_TCTI_INIT_FUNC tcti_init;
116
117
static char *tcti_opts;
118
119
/**
120
 * Empty AUTH_COMMAND
121
 */
122
static const TPMS_AUTH_COMMAND auth_cmd_empty;
123
124
/**
125
 * Convert hash algorithm to TPM2_ALG_ID
126
 */
127
static TPM2_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
128
{
129
  switch (alg)
130
  {
131
    case HASH_SHA1:
132
      return TPM2_ALG_SHA1;
133
    case HASH_SHA256:
134
      return TPM2_ALG_SHA256;
135
    case HASH_SHA384:
136
      return TPM2_ALG_SHA384;
137
    case HASH_SHA512:
138
      return TPM2_ALG_SHA512;
139
    case HASH_SHA3_256:
140
      return TPM2_ALG_SHA3_256;
141
    case HASH_SHA3_384:
142
      return TPM2_ALG_SHA3_384;
143
    case HASH_SHA3_512:
144
      return TPM2_ALG_SHA3_512;
145
    default:
146
      return TPM2_ALG_ERROR;
147
  }
148
}
149
150
/**
151
 * Convert TPM2_ALG_ID to hash algorithm
152
 */
153
hash_algorithm_t hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg)
154
{
155
  switch (alg)
156
  {
157
    case TPM2_ALG_SHA1:
158
      return HASH_SHA1;
159
    case TPM2_ALG_SHA256:
160
      return HASH_SHA256;
161
    case TPM2_ALG_SHA384:
162
      return HASH_SHA384;
163
    case TPM2_ALG_SHA512:
164
      return HASH_SHA512;
165
    case TPM2_ALG_SHA3_256:
166
      return HASH_SHA3_256;
167
    case TPM2_ALG_SHA3_384:
168
      return HASH_SHA3_384;
169
    case TPM2_ALG_SHA3_512:
170
      return HASH_SHA3_512;
171
    default:
172
      return HASH_UNKNOWN;
173
  }
174
}
175
176
/**
177
 * Return hash length of TPM2_ALG_ID algorithm
178
 */
179
size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg)
180
{
181
  switch (alg)
182
  {
183
    case TPM2_ALG_SHA1:
184
      return TPM2_SHA1_DIGEST_SIZE;
185
    case TPM2_ALG_SHA256:
186
    case TPM2_ALG_SHA3_256:
187
      return TPM2_SHA256_DIGEST_SIZE;
188
    case TPM2_ALG_SHA384:
189
    case TPM2_ALG_SHA3_384:
190
      return TPM2_SHA384_DIGEST_SIZE;
191
    case TPM2_ALG_SHA512:
192
    case TPM2_ALG_SHA3_512:
193
      return TPM2_SHA512_DIGEST_SIZE;
194
    case TPM2_ALG_SM3_256:
195
      return TPM2_SM3_256_DIGEST_SIZE;
196
    default:
197
      return 0;
198
  }
199
}
200
201
/**
202
 * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
203
 */
204
static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id)
205
{
206
  int i;
207
208
  if (alg_id == TPM2_ALG_ERROR)
209
  {
210
    return FALSE;
211
  }
212
213
  for (i = 0; i < this->supported_algs_count; i++)
214
  {
215
    if (this->supported_algs[i] == alg_id)
216
    {
217
      return TRUE;
218
    }
219
  }
220
221
  return FALSE;
222
}
223
224
/**
225
 * Get the TPM version_info and a list of supported algorithms
226
 *
227
 *             1           2           3
228
 *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
229
 *
230
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
231
 *  |  TPM 2.0 Version_Info Tag     |   Reserved    |   Locality    |
232
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
233
 *  |                            Revision                           |
234
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235
 *  |                              Year                             |
236
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237
 *  |                             Vendor                            |
238
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239
 */
240
#define TPM2_VERSION_INFO_TAG       0x0200
241
#define TPM2_VERSION_INFO_RESERVED  0x00
242
#define TPM2_VERSION_INFO_SIZE      16
243
#define TPM2_DEFAULT_LOCALITY       3
244
245
static bool get_algs_capability(private_tpm_tss_tss2_t *this)
246
{
247
  TPMS_CAPABILITY_DATA cap_data;
248
  TPMS_TAGGED_PROPERTY tp;
249
  TPMI_YES_NO more_data;
250
  TPM2_ALG_ID alg;
251
  bio_writer_t *writer;
252
  bool fips_140_2 = FALSE;
253
  uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0;
254
  uint8_t locality = TPM2_DEFAULT_LOCALITY;
255
  size_t len = BUF_LEN;
256
  char buf[BUF_LEN], manufacturer[5], vendor_string[17];
257
  char *pos = buf;
258
  int written;
259
260
  /* get fixed properties */
261
  this->mutex->lock(this->mutex);
262
  rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
263
                  TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES,
264
                  &more_data, &cap_data, 0);
265
  this->mutex->unlock(this->mutex);
266
  if (rval != TPM2_RC_SUCCESS)
267
  {
268
    DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
269
            rval);
270
    return FALSE;
271
  }
272
  memset(manufacturer,  '\0', sizeof(manufacturer));
273
  memset(vendor_string, '\0', sizeof(vendor_string));
274
275
  /* print fixed properties */
276
  for (i = 0; i < cap_data.data.tpmProperties.count; i++)
277
  {
278
    tp = cap_data.data.tpmProperties.tpmProperty[i];
279
    switch (tp.property)
280
    {
281
      case TPM2_PT_REVISION:
282
        revision = tp.value;
283
        break;
284
      case TPM2_PT_YEAR:
285
        year = tp.value;
286
        break;
287
      case TPM2_PT_MANUFACTURER:
288
        vendor = tp.value;
289
        htoun32(manufacturer, tp.value);
290
        break;
291
      case TPM2_PT_VENDOR_STRING_1:
292
      case TPM2_PT_VENDOR_STRING_2:
293
      case TPM2_PT_VENDOR_STRING_3:
294
      case TPM2_PT_VENDOR_STRING_4:
295
        offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
296
        htoun32(vendor_string + offset, tp.value);
297
        break;
298
      case TPM2_PT_MODES:
299
        if (tp.value & TPMA_MODES_FIPS_140_2)
300
        {
301
          this->fips_186_4 = fips_140_2 = TRUE;
302
        }
303
        break;
304
      default:
305
        break;
306
    }
307
  }
308
309
  if (!fips_140_2)
310
  {
311
    this->fips_186_4 = lib->settings->get_bool(lib->settings,
312
          "%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
313
  }
314
  DBG2(DBG_PTS, LABEL "manufacturer: %s (%s) rev: %05.2f %u %s",
315
     manufacturer, vendor_string, (float)revision/100, year,
316
     fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
317
318
  /* determine if TPM uses old event digest format and a different locality */
319
  if (streq(manufacturer, "INTC"))
320
  {
321
    locality = 0;
322
323
    if (revision == 116 && year == 2016)
324
    {
325
      this->old_event_digest_format = TRUE;
326
    }
327
  }
328
329
  /* construct TPM 2.0 version_info object */
330
  writer = bio_writer_create(  TPM2_VERSION_INFO_SIZE);
331
  writer->write_uint16(writer, TPM2_VERSION_INFO_TAG);
332
  writer->write_uint8(writer,  TPM2_VERSION_INFO_RESERVED);
333
  writer->write_uint8(writer,  locality);
334
  writer->write_uint32(writer, revision);
335
  writer->write_uint32(writer, year);
336
  writer->write_uint32(writer, vendor);
337
  this->version_info = writer->extract_buf(writer);
338
  writer->destroy(writer);
339
340
  /* get supported algorithms */
341
  this->mutex->lock(this->mutex);
342
  rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
343
            0, TPM2_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
344
  this->mutex->unlock(this->mutex);
345
  if (rval != TPM2_RC_SUCCESS)
346
  {
347
    DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
348
            rval);
349
    return FALSE;
350
  }
351
352
  /* Number of supported algorithms */
353
  this->supported_algs_count = cap_data.data.algorithms.count;
354
355
  /* store and print supported algorithms */
356
  for (i = 0; i < this->supported_algs_count; i++)
357
  {
358
    alg = cap_data.data.algorithms.algProperties[i].alg;
359
    this->supported_algs[i] = alg;
360
361
    written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
362
    if (written < 0 || written >= len)
363
    {
364
      break;
365
    }
366
    pos += written;
367
    len -= written;
368
  }
369
  DBG2(DBG_PTS, LABEL "algorithms:%s", buf);
370
371
  /* get supported ECC curves */
372
  this->mutex->lock(this->mutex);
373
  rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ECC_CURVES,
374
            0, TPM2_PT_LOADED_CURVES, &more_data, &cap_data, 0);
375
  this->mutex->unlock(this->mutex);
376
  if (rval != TPM2_RC_SUCCESS)
377
  {
378
    DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
379
            rval);
380
    return FALSE;
381
  }
382
383
  /* reset print buffer */
384
  pos = buf;
385
  len = BUF_LEN;
386
387
  /* print supported ECC curves */
388
  for (i = 0; i < cap_data.data.eccCurves.count; i++)
389
  {
390
    written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
391
               cap_data.data.eccCurves.eccCurves[i]);
392
    if (written < 0 || written >= len)
393
    {
394
      break;
395
    }
396
    pos += written;
397
    len -= written;
398
  }
399
  DBG2(DBG_PTS, LABEL "ECC curves:%s", buf);
400
401
  /* get assigned PCR banks */
402
  this->mutex->lock(this->mutex);
403
  rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_PCRS,
404
            0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
405
  this->mutex->unlock(this->mutex);
406
  if (rval != TPM2_RC_SUCCESS)
407
  {
408
    DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
409
            rval);
410
    return FALSE;
411
  }
412
413
  /* Number of assigned PCR banks */
414
  this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
415
416
  /* reset print buffer */
417
  pos = buf;
418
  len = BUF_LEN;
419
420
  /* store and print assigned PCR banks */
421
  for (i = 0; i < cap_data.data.assignedPCR.count; i++)
422
  {
423
    alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
424
    this->assigned_pcrs[i] = alg;
425
    written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
426
    if (written < 0 || written >= len)
427
    {
428
      break;
429
    }
430
    pos += written;
431
    len -= written;
432
  }
433
  DBG2(DBG_PTS, LABEL "PCR banks:%s", buf);
434
435
  return TRUE;
436
}
437
438
/**
439
 * Initialize TSS2 TCTI context
440
 */
441
static bool initialize_tcti_context(private_tpm_tss_tss2_t *this)
442
{
443
  size_t tcti_context_size;
444
  uint32_t rval;
445
446
  if (!tcti_init)
447
  {
448
    return FALSE;
449
  }
450
451
  /* determine size of tcti context */
452
  rval = tcti_init(NULL, &tcti_context_size, tcti_opts);
453
  if (rval != TSS2_RC_SUCCESS)
454
  {
455
    DBG1(DBG_PTS, LABEL "tcti init setup failed: 0x%06x", rval);
456
    return FALSE;
457
  }
458
459
  /* allocate and initialize memory for tcti context */
460
  this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
461
  memset(this->tcti_context, 0x00, tcti_context_size);
462
463
  /* initialize tcti context */
464
  rval = tcti_init(this->tcti_context, &tcti_context_size, tcti_opts);
465
  if (rval != TSS2_RC_SUCCESS)
466
  {
467
    DBG1(DBG_PTS, LABEL "tcti init allocation failed: 0x%06x", rval);
468
    return FALSE;
469
  }
470
  return TRUE;
471
}
472
473
/**
474
 * Initialize TSS2 Sys context
475
 */
476
static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
477
{
478
  uint32_t sys_context_size;
479
  uint32_t rval;
480
481
  TSS2_ABI_VERSION abi_version = {
482
    .tssCreator = 1,
483
    .tssFamily = 2,
484
    .tssLevel = 1,
485
    .tssVersion = 108
486
  };
487
488
  /* determine size of sys context */
489
  sys_context_size = Tss2_Sys_GetContextSize(0);
490
491
  /* allocate memory for sys context */
492
  this->sys_context = (TSS2_SYS_CONTEXT*)malloc(sys_context_size);
493
494
  /* initialize sys context */
495
  rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
496
                 this->tcti_context, &abi_version);
497
  if (rval != TSS2_RC_SUCCESS)
498
  {
499
    DBG1(DBG_PTS, LABEL "could not get sys_context: 0x%06x", rval);
500
    return FALSE;
501
  }
502
503
  /* get a list of supported algorithms and ECC curves */
504
  return get_algs_capability(this);
505
}
506
507
/**
508
 * Finalize TSS context
509
 */
510
static void finalize_context(private_tpm_tss_tss2_t *this)
511
{
512
  if (this->tcti_context)
513
  {
514
    Tss2_Tcti_Finalize(this->tcti_context);
515
    free(this->tcti_context);
516
  }
517
  if (this->sys_context)
518
  {
519
    Tss2_Sys_Finalize(this->sys_context);
520
    free(this->sys_context);
521
  }
522
}
523
524
METHOD(tpm_tss_t, get_version, tpm_version_t,
525
  private_tpm_tss_tss2_t *this)
526
{
527
  return TPM_VERSION_2_0;
528
}
529
530
METHOD(tpm_tss_t, get_version_info, chunk_t,
531
  private_tpm_tss_tss2_t *this)
532
{
533
  return this->version_info;
534
}
535
536
/**
537
 * read the public key portion of a TSS 2.0 key from NVRAM
538
 */
539
static bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
540
            TPM2B_PUBLIC *public)
541
{
542
  uint32_t rval;
543
544
  TPM2B_NAME name = { sizeof(TPM2B_NAME)-2, };
545
  TPM2B_NAME qualified_name = { sizeof(TPM2B_NAME)-2, };
546
  TSS2L_SYS_AUTH_RESPONSE auth_rsp;
547
548
549
  /* read public key for a given object handle from TPM 2.0 NVRAM */
550
  this->mutex->lock(this->mutex);
551
  rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
552
                 &qualified_name, &auth_rsp);
553
  this->mutex->unlock(this->mutex);
554
  if (rval != TPM2_RC_SUCCESS)
555
  {
556
    DBG1(DBG_PTS, LABEL "could not read public key from handle 0x%08x: 0x%06x",
557
            handle, rval);
558
    return FALSE;
559
  }
560
  return TRUE;
561
}
562
563
METHOD(tpm_tss_t, generate_aik, bool,
564
  private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
565
  chunk_t *aik_pubkey, chunk_t *identity_req)
566
{
567
  return FALSE;
568
}
569
570
METHOD(tpm_tss_t, get_public, chunk_t,
571
  private_tpm_tss_tss2_t *this, uint32_t handle)
572
{
573
  TPM2B_PUBLIC public = { 0, };
574
  chunk_t aik_pubkey = chunk_empty;
575
576
  if (!read_public(this, handle, &public))
577
  {
578
    return chunk_empty;
579
  }
580
581
  /* convert TSS 2.0 public key blot into PKCS#1 format */
582
  switch (public.publicArea.type)
583
  {
584
    case TPM2_ALG_RSA:
585
    {
586
      TPM2B_PUBLIC_KEY_RSA *rsa;
587
      chunk_t aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
588
      chunk_t aik_modulus;
589
      uint32_t exponent;
590
591
      rsa = &public.publicArea.unique.rsa;
592
      aik_modulus = chunk_create(rsa->buffer, rsa->size);
593
      exponent = htonl(public.publicArea.parameters.rsaDetail.exponent);
594
      if (exponent)
595
      {
596
        aik_exponent = chunk_from_thing(exponent);
597
      }
598
599
      /* subjectPublicKeyInfo encoding of RSA public key */
600
      if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
601
          NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
602
          CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
603
      {
604
        DBG1(DBG_PTS, LABEL "subjectPublicKeyInfo encoding of public key "
605
                  "failed");
606
        return chunk_empty;
607
      }
608
      break;
609
    }
610
    case TPM2_ALG_ECC:
611
    {
612
      TPMS_ECC_POINT *ecc;
613
      chunk_t ecc_point;
614
      int curve_oid;
615
      uint8_t *pos;
616
617
      /* determine ECC curveID */
618
      switch (public.publicArea.parameters.eccDetail.curveID)
619
      {
620
        case TPM2_ECC_NIST_P192:
621
          curve_oid = OID_PRIME192V1;
622
          break;
623
        case TPM2_ECC_NIST_P224:
624
          curve_oid = OID_SECP224R1;
625
          break;
626
        case TPM2_ECC_NIST_P256:
627
          curve_oid = OID_PRIME256V1;
628
          break;
629
        case TPM2_ECC_NIST_P384:
630
          curve_oid = OID_SECP384R1;
631
          break;
632
        case TPM2_ECC_NIST_P521:
633
          curve_oid = OID_SECP521R1;
634
          break;
635
        default:
636
          DBG1(DBG_PTS, "ECC curve type not supported");
637
          return chunk_empty;
638
      }
639
640
      ecc = &public.publicArea.unique.ecc;
641
642
      /* allocate space for bit string */
643
      pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
644
                  2 + ecc->x.size + ecc->y.size);
645
      /* bit string length is a multiple of octets */
646
      *pos++ = 0x00;
647
      /* uncompressed ECC point format */
648
      *pos++ = 0x04;
649
      /* copy x coordinate of ECC point */
650
      memcpy(pos, ecc->x.buffer, ecc->x.size);
651
      pos += ecc->x.size;
652
      /* copy y coordinate of ECC point */
653
      memcpy(pos, ecc->y.buffer, ecc->y.size);
654
655
      /* subjectPublicKeyInfo encoding of ECC public key */
656
      aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
657
              asn1_wrap(ASN1_SEQUENCE, "mm",
658
                asn1_build_known_oid(OID_EC_PUBLICKEY),
659
                asn1_build_known_oid(curve_oid)),
660
              ecc_point);
661
      break;
662
    }
663
    default:
664
      DBG1(DBG_PTS, LABEL "unsupported key type");
665
      return chunk_empty;
666
  }
667
668
#if DEBUG_LEVEL >= 1
669
  if (public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT)
670
  {
671
    TPMT_ASYM_SCHEME *s;
672
673
    s = &public.publicArea.parameters.asymDetail.scheme;
674
    DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
675
            tpm_alg_id_names, s->scheme,
676
            tpm_alg_id_names, s->details.anySig.hashAlg);
677
  }
678
  if (public.publicArea.objectAttributes & TPMA_OBJECT_DECRYPT)
679
  {
680
    TPMT_SYM_DEF_OBJECT *s;
681
682
    s = &public.publicArea.parameters.asymDetail.symmetric;
683
    DBG1(DBG_PTS, "encryption algorithm is %N-%N with %u bits",
684
            tpm_alg_id_names, s->algorithm,
685
            tpm_alg_id_names, s->mode, s->keyBits.sym);
686
  }
687
#endif
688
689
  return aik_pubkey;
690
}
691
692
METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
693
  private_tpm_tss_tss2_t *this, uint32_t handle)
694
{
695
  TPM2B_PUBLIC public = { 0, };
696
  hash_algorithm_t digest;
697
  signature_params_t supported_scheme;
698
699
  if (!read_public(this, handle, &public))
700
  {
701
    return enumerator_create_empty();
702
  }
703
704
  switch (public.publicArea.type)
705
  {
706
    case TPM2_ALG_RSA:
707
    {
708
      TPMS_RSA_PARMS *rsa;
709
      TPMT_RSA_SCHEME *scheme;
710
711
      rsa = &public.publicArea.parameters.rsaDetail;
712
      scheme = &rsa->scheme;
713
      digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
714
715
      switch (scheme->scheme)
716
      {
717
        case TPM2_ALG_RSAPSS:
718
        {
719
          ssize_t salt_len;
720
721
          salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
722
                          RSA_PSS_SALT_LEN_MAX;
723
          rsa_pss_params_t pss_params = {
724
            .hash = digest,
725
            .mgf1_hash = digest,
726
            .salt_len = salt_len,
727
          };
728
          supported_scheme = (signature_params_t){
729
            .scheme = SIGN_RSA_EMSA_PSS,
730
            .params = &pss_params,
731
          };
732
          if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
733
          {
734
            return enumerator_create_empty();
735
          }
736
          break;
737
        }
738
        case TPM2_ALG_RSASSA:
739
          supported_scheme = (signature_params_t){
740
            .scheme = signature_scheme_from_oid(
741
                  hasher_signature_algorithm_to_oid(digest,
742
                                    KEY_RSA)),
743
          };
744
          break;
745
        default:
746
          return enumerator_create_empty();
747
      }
748
      break;
749
    }
750
    case TPM2_ALG_ECC:
751
    {
752
      TPMT_ECC_SCHEME *scheme;
753
754
      scheme = &public.publicArea.parameters.eccDetail.scheme;
755
      digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
756
757
      switch (scheme->scheme)
758
      {
759
        case TPM2_ALG_ECDSA:
760
          supported_scheme = (signature_params_t){
761
            .scheme = signature_scheme_from_oid(
762
                  hasher_signature_algorithm_to_oid(digest,
763
                                  KEY_ECDSA)),
764
          };
765
          break;
766
        default:
767
          return enumerator_create_empty();
768
      }
769
      break;
770
    }
771
    default:
772
      DBG1(DBG_PTS, LABEL "unsupported key type");
773
      return enumerator_create_empty();
774
  }
775
  return enumerator_create_single(signature_params_clone(&supported_scheme),
776
                  (void*)signature_params_destroy);
777
}
778
779
METHOD(tpm_tss_t, has_pcr_bank, bool,
780
  private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
781
{
782
  TPM2_ALG_ID alg_id;
783
  int i;
784
785
  alg_id = hash_alg_to_tpm_alg_id(alg);
786
787
  for (i = 0; i < this->assigned_pcrs_count; i++)
788
  {
789
    if (this->assigned_pcrs[i] == alg_id)
790
    {
791
      return TRUE;
792
    }
793
  }
794
795
  return FALSE;
796
}
797
798
/**
799
 * Configure a PCR Selection assuming a maximum of 24 registers
800
 */
801
static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
802
                 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
803
{
804
  uint32_t pcr;
805
806
  /* check if there is an assigned PCR bank for this hash algorithm */
807
  if (!has_pcr_bank(this, alg))
808
  {
809
    DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by any PCR bank",
810
            hash_algorithm_short_names, alg);
811
    return FALSE;
812
  }
813
814
  /* initialize the PCR Selection structure,*/
815
  pcr_sel->count = 1;
816
  pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
817
818
  pcr_sel->pcrSelections[0].sizeofSelect = 3;
819
  pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
820
  pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
821
  pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
822
823
  /* set the selected PCRs */
824
  for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
825
  {
826
    if (pcrs & (1 << pcr))
827
    {
828
      pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
829
    }
830
  }
831
  return TRUE;
832
}
833
834
METHOD(tpm_tss_t, read_pcr, bool,
835
  private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
836
  hash_algorithm_t alg)
837
{
838
  TPML_PCR_SELECTION pcr_selection;
839
  TPML_DIGEST pcr_values;
840
841
  uint32_t pcr_update_counter, rval;
842
  uint8_t *pcr_value_ptr;
843
  size_t   pcr_value_len;
844
845
  if (pcr_num >= PLATFORM_PCR)
846
  {
847
    DBG1(DBG_PTS, LABEL "maximum number of supported PCR is %d",
848
            PLATFORM_PCR);
849
    return FALSE;
850
  }
851
852
  if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
853
  {
854
    return FALSE;
855
  }
856
857
  /* initialize the PCR Digest structure */
858
  memset(&pcr_values, 0, sizeof(TPML_DIGEST));
859
860
  /* read the PCR value */
861
  this->mutex->lock(this->mutex);
862
  rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
863
        &pcr_update_counter, &pcr_selection, &pcr_values, 0);
864
  this->mutex->unlock(this->mutex);
865
  if (rval != TPM2_RC_SUCCESS)
866
  {
867
    DBG1(DBG_PTS, LABEL "PCR bank could not be read: 0x%60x", rval);
868
    return FALSE;
869
  }
870
  pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
871
  pcr_value_len = (size_t)   pcr_values.digests[0].size;
872
873
  *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
874
875
  return TRUE;
876
}
877
878
METHOD(tpm_tss_t, extend_pcr, bool,
879
  private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
880
  chunk_t data, hash_algorithm_t alg)
881
{
882
  uint32_t rval;
883
  TPML_DIGEST_VALUES digest_values;
884
  TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
885
  TSS2L_SYS_AUTH_RESPONSE auth_rsp;
886
887
  auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
888
889
  /* check if there is an assigned PCR bank for this hash algorithm */
890
  if (!has_pcr_bank(this, alg))
891
  {
892
    DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by any PCR bank",
893
            hash_algorithm_short_names, alg);
894
    return FALSE;
895
  }
896
897
  digest_values.count = 1;
898
  digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
899
900
  switch (alg)
901
  {
902
    case HASH_SHA1:
903
      if (data.len != HASH_SIZE_SHA1)
904
      {
905
        return FALSE;
906
      }
907
      memcpy(digest_values.digests[0].digest.sha1, data.ptr,
908
           HASH_SIZE_SHA1);
909
      break;
910
    case HASH_SHA256:
911
    case HASH_SHA3_256:
912
      if (data.len != HASH_SIZE_SHA256)
913
      {
914
        return FALSE;
915
      }
916
      memcpy(digest_values.digests[0].digest.sha256, data.ptr,
917
            HASH_SIZE_SHA256);
918
      break;
919
    case HASH_SHA384:
920
    case HASH_SHA3_384:
921
      if (data.len != HASH_SIZE_SHA384)
922
      {
923
        return FALSE;
924
      }
925
      memcpy(digest_values.digests[0].digest.sha384, data.ptr,
926
            HASH_SIZE_SHA384);
927
      break;
928
    case HASH_SHA512:
929
    case HASH_SHA3_512:
930
      if (data.len != HASH_SIZE_SHA512)
931
      {
932
        return FALSE;
933
      }
934
      memcpy(digest_values.digests[0].digest.sha512, data.ptr,
935
            HASH_SIZE_SHA512);
936
      break;
937
    default:
938
      return FALSE;
939
  }
940
941
  /* extend PCR */
942
  this->mutex->lock(this->mutex);
943
  rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
944
                 &digest_values, &auth_rsp);
945
  this->mutex->unlock(this->mutex);
946
  if (rval != TPM2_RC_SUCCESS)
947
  {
948
    DBG1(DBG_PTS, LABEL "PCR %02u could not be extended: 0x%06x",
949
            pcr_num, rval);
950
    return FALSE;
951
  }
952
953
  /* get updated PCR value */
954
  return read_pcr(this, pcr_num, pcr_value, alg);
955
}
956
957
METHOD(tpm_tss_t, quote, bool,
958
  private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
959
  hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
960
  tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
961
{
962
  chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
963
      firmware_version, pcr_select, pcr_digest;
964
  hash_algorithm_t pcr_digest_alg;
965
  bio_reader_t *reader;
966
  uint32_t rval;
967
968
  TPM2B_DATA qualifying_data;
969
  TPML_PCR_SELECTION  pcr_selection;
970
  TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
971
  TPMT_SIG_SCHEME scheme;
972
  TPMT_SIGNATURE sig;
973
  TPMI_ALG_HASH hash_alg;
974
  TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
975
  TSS2L_SYS_AUTH_RESPONSE auth_rsp;
976
977
  auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
978
979
  qualifying_data.size = data.len;
980
  memcpy(qualifying_data.buffer, data.ptr, data.len);
981
982
  scheme.scheme = TPM2_ALG_NULL;
983
  memset(&sig, 0x00, sizeof(sig));
984
985
  /* set Quote mode */
986
  *quote_mode = TPM_QUOTE_TPM2;
987
988
  if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
989
  {
990
    return FALSE;
991
  }
992
993
  this->mutex->lock(this->mutex);
994
  rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
995
              &qualifying_data, &scheme, &pcr_selection,  &quoted,
996
              &sig, &auth_rsp);
997
  this->mutex->unlock(this->mutex);
998
  if (rval != TPM2_RC_SUCCESS)
999
  {
1000
    DBG1(DBG_PTS, LABEL "Tss2_Sys_Quote failed: 0x%06x", rval);
1001
    return FALSE;
1002
  }
1003
  quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
1004
1005
  reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
1006
  if (!reader->read_data16(reader, &qualified_signer) ||
1007
    !reader->read_data16(reader, &extra_data) ||
1008
    !reader->read_data  (reader, 17, &clock_info) ||
1009
    !reader->read_data  (reader,  8, &firmware_version) ||
1010
    !reader->read_data  (reader, 10, &pcr_select) ||
1011
    !reader->read_data16(reader, &pcr_digest))
1012
  {
1013
    DBG1(DBG_PTS, LABEL "parsing of quoted struct failed");
1014
    reader->destroy(reader);
1015
    return FALSE;
1016
  }
1017
  reader->destroy(reader);
1018
1019
  DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
1020
  DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
1021
  DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
1022
  DBG2(DBG_PTS, "extraData: %B", &extra_data);
1023
  DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
1024
  DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
1025
  DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
1026
1027
  /* extract signature */
1028
  switch (sig.sigAlg)
1029
  {
1030
    case TPM2_ALG_RSASSA:
1031
    case TPM2_ALG_RSAPSS:
1032
      *quote_sig = chunk_clone(
1033
              chunk_create(
1034
                sig.signature.rsassa.sig.buffer,
1035
                sig.signature.rsassa.sig.size));
1036
      hash_alg = sig.signature.rsassa.hash;
1037
      break;
1038
    case TPM2_ALG_ECDSA:
1039
    case TPM2_ALG_ECDAA:
1040
    case TPM2_ALG_SM2:
1041
    case TPM2_ALG_ECSCHNORR:
1042
      *quote_sig = chunk_cat("cc",
1043
              chunk_create(
1044
                sig.signature.ecdsa.signatureR.buffer,
1045
                sig.signature.ecdsa.signatureR.size),
1046
              chunk_create(
1047
                sig.signature.ecdsa.signatureS.buffer,
1048
                sig.signature.ecdsa.signatureS.size));
1049
      hash_alg = sig.signature.ecdsa.hash;
1050
      break;
1051
    default:
1052
      DBG1(DBG_PTS, LABEL "unsupported %N signature algorithm",
1053
              tpm_alg_id_names, sig.sigAlg);
1054
      return FALSE;
1055
  }
1056
1057
  DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
1058
  pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
1059
1060
  DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
1061
1062
  /* Create and initialize Quote Info object */
1063
  *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
1064
                             pcr_digest);
1065
  (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
1066
                             pcr_select);
1067
  (*quote_info)->set_version_info(*quote_info, firmware_version);
1068
1069
  return TRUE;
1070
}
1071
1072
METHOD(tpm_tss_t, sign, bool,
1073
  private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1074
  signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
1075
  chunk_t *signature)
1076
{
1077
  key_type_t key_type;
1078
  hash_algorithm_t hash_alg;
1079
  rsa_pss_params_t *rsa_pss_params;
1080
  uint32_t rval;
1081
1082
  TPM2_ALG_ID alg_id;
1083
  TPM2B_MAX_BUFFER buffer;
1084
  TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
1085
  TPMT_TK_HASHCHECK validation;
1086
  TPM2B_PUBLIC public = { 0, };
1087
  TPMT_SIG_SCHEME sig_scheme;
1088
  TPMT_SIGNATURE sig;
1089
  TPMS_AUTH_COMMAND *cmd;
1090
  TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
1091
  TSS2L_SYS_AUTH_RESPONSE auth_rsp;
1092
1093
  cmd = &auth_cmd.auths[0];
1094
  cmd->sessionHandle = TPM2_RS_PW;
1095
1096
  if (pin.len > 0)
1097
  {
1098
    cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
1099
    memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
1100
  }
1101
1102
  if (scheme == SIGN_RSA_EMSA_PSS)
1103
  {
1104
    key_type = KEY_RSA;
1105
    rsa_pss_params = (rsa_pss_params_t *)params;
1106
    hash_alg = rsa_pss_params->hash;
1107
  }
1108
  else
1109
  {
1110
    key_type = key_type_from_signature_scheme(scheme);
1111
    hash_alg = hasher_from_signature_scheme(scheme, NULL);
1112
  }
1113
1114
  /* Check if hash algorithm is supported by TPM */
1115
  alg_id = hash_alg_to_tpm_alg_id(hash_alg);
1116
  if (!is_supported_alg(this, alg_id))
1117
  {
1118
    DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by TPM",
1119
            hash_algorithm_short_names, hash_alg);
1120
    return FALSE;
1121
  }
1122
1123
  /* Get public key */
1124
  if (!read_public(this, handle, &public))
1125
  {
1126
    return FALSE;
1127
  }
1128
1129
  if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
1130
  {
1131
    if (scheme == SIGN_RSA_EMSA_PSS)
1132
    {
1133
      sig_scheme.scheme = TPM2_ALG_RSAPSS;
1134
      sig_scheme.details.rsapss.hashAlg = alg_id;
1135
    }
1136
    else
1137
    {
1138
      sig_scheme.scheme = TPM2_ALG_RSASSA;
1139
      sig_scheme.details.rsassa.hashAlg = alg_id;
1140
    }
1141
  }
1142
  else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
1143
  {
1144
    sig_scheme.scheme = TPM2_ALG_ECDSA;
1145
    sig_scheme.details.ecdsa.hashAlg = alg_id;
1146
1147
  }
1148
  else
1149
  {
1150
    DBG1(DBG_PTS, LABEL "signature scheme %N not supported by TPM key",
1151
            signature_scheme_names, scheme);
1152
    return FALSE;
1153
  }
1154
1155
  if (data.len <= TPM2_MAX_DIGEST_BUFFER)
1156
  {
1157
    memcpy(buffer.buffer, data.ptr, data.len);
1158
    buffer.size = data.len;
1159
1160
    this->mutex->lock(this->mutex);
1161
    rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
1162
               &hash, &validation, 0);
1163
    this->mutex->unlock(this->mutex);
1164
    if (rval != TPM2_RC_SUCCESS)
1165
    {
1166
      DBG1(DBG_PTS,LABEL "Tss2_Sys_Hash failed: 0x%06x", rval);
1167
      return FALSE;
1168
    }
1169
  }
1170
  else
1171
  {
1172
      TPMI_DH_OBJECT sequence_handle;
1173
      TPM2B_AUTH null_auth;
1174
1175
    null_auth.size = 0;
1176
    this->mutex->lock(this->mutex);
1177
    rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
1178
                      alg_id, &sequence_handle, 0);
1179
    if (rval != TPM2_RC_SUCCESS)
1180
    {
1181
      DBG1(DBG_PTS, LABEL "Tss2_Sys_HashSequenceStart failed: 0x%06x",
1182
              rval);
1183
      this->mutex->unlock(this->mutex);
1184
      return FALSE;
1185
    }
1186
1187
    while (data.len > 0)
1188
    {
1189
      buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
1190
      memcpy(buffer.buffer, data.ptr, buffer.size);
1191
      data.ptr += buffer.size;
1192
      data.len -= buffer.size;
1193
1194
      rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
1195
                       &auth_cmd, &buffer, 0);
1196
      if (rval != TPM2_RC_SUCCESS)
1197
      {
1198
        DBG1(DBG_PTS, LABEL "Tss2_Sys_SequenceUpdate failed: 0x%06x",
1199
                rval);
1200
        this->mutex->unlock(this->mutex);
1201
        return FALSE;
1202
      }
1203
    }
1204
    buffer.size = 0;
1205
1206
    rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
1207
                     &auth_cmd, &buffer, hierarchy,
1208
                     &hash, &validation, 0);
1209
    this->mutex->unlock(this->mutex);
1210
    if (rval != TPM2_RC_SUCCESS)
1211
    {
1212
      DBG1(DBG_PTS, LABEL "Tss2_Sys_SequenceComplete failed: 0x%06x",
1213
              rval);
1214
      return FALSE;
1215
    }
1216
  }
1217
1218
  this->mutex->lock(this->mutex);
1219
  rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
1220
             &sig_scheme, &validation, &sig, &auth_rsp);
1221
  this->mutex->unlock(this->mutex);
1222
  if (rval != TPM2_RC_SUCCESS)
1223
  {
1224
    DBG1(DBG_PTS, LABEL "Tss2_Sys_Sign failed: 0x%06x", rval);
1225
    return FALSE;
1226
  }
1227
1228
  /* extract signature */
1229
  switch (scheme)
1230
  {
1231
    case SIGN_RSA_EMSA_PKCS1_SHA1:
1232
    case SIGN_RSA_EMSA_PKCS1_SHA2_256:
1233
    case SIGN_RSA_EMSA_PKCS1_SHA2_384:
1234
    case SIGN_RSA_EMSA_PKCS1_SHA2_512:
1235
      *signature = chunk_clone(
1236
              chunk_create(
1237
                sig.signature.rsassa.sig.buffer,
1238
                sig.signature.rsassa.sig.size));
1239
      break;
1240
    case SIGN_RSA_EMSA_PSS:
1241
      *signature = chunk_clone(
1242
              chunk_create(
1243
                sig.signature.rsapss.sig.buffer,
1244
                sig.signature.rsapss.sig.size));
1245
      break;
1246
    case SIGN_ECDSA_256:
1247
    case SIGN_ECDSA_384:
1248
    case SIGN_ECDSA_521:
1249
      *signature = chunk_cat("cc",
1250
              chunk_create(
1251
                sig.signature.ecdsa.signatureR.buffer,
1252
                sig.signature.ecdsa.signatureR.size),
1253
              chunk_create(
1254
                sig.signature.ecdsa.signatureS.buffer,
1255
                sig.signature.ecdsa.signatureS.size));
1256
      break;
1257
    case SIGN_ECDSA_WITH_SHA256_DER:
1258
    case SIGN_ECDSA_WITH_SHA384_DER:
1259
    case SIGN_ECDSA_WITH_SHA512_DER:
1260
      *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
1261
              asn1_integer("c",
1262
                chunk_create(
1263
                  sig.signature.ecdsa.signatureR.buffer,
1264
                  sig.signature.ecdsa.signatureR.size)),
1265
              asn1_integer("c",
1266
                chunk_create(
1267
                  sig.signature.ecdsa.signatureS.buffer,
1268
                  sig.signature.ecdsa.signatureS.size)));
1269
      break;
1270
    default:
1271
      DBG1(DBG_PTS, LABEL "unsupported %N signature scheme",
1272
              signature_scheme_names, scheme);
1273
      return FALSE;
1274
  }
1275
1276
  return TRUE;
1277
}
1278
1279
/**
1280
 * Check if an authenticated session with the TPM 2.0 can be started
1281
 * The handle of the RSA Endorsement Key (EK) is required
1282
 */
1283
static void try_session_start(private_tpm_tss_tss2_t *this)
1284
{
1285
  uint32_t ek_handle = 0;
1286
  chunk_t handle_chunk;
1287
  char *handle_str;
1288
1289
  TPM2B_PUBLIC public = { 0, };
1290
1291
  /* get Endorsement Key (EK) handle from settings */
1292
  handle_str = lib->settings->get_str(lib->settings,
1293
                "%s.plugins.tpm.ek_handle", NULL, lib->ns);
1294
  if (handle_str)
1295
  {
1296
    handle_chunk = chunk_from_hex(chunk_from_str(handle_str),
1297
                   (char *)&ek_handle);
1298
    ek_handle = (handle_chunk.len == 4) ? htonl(ek_handle) : 0;
1299
1300
    /* establish protected auth session if ek_handle is set */
1301
    if (ek_handle && read_public(this, ek_handle, &public))
1302
    {
1303
      this->mutex->lock(this->mutex);
1304
      this->session = tpm_tss_tss2_session_create(ek_handle, &public,
1305
                            this->sys_context);
1306
      this->mutex->unlock(this->mutex);
1307
    }
1308
  }
1309
}
1310
1311
METHOD(tpm_tss_t, get_random, bool,
1312
  private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
1313
{
1314
  size_t len, random_len = sizeof(TPM2B_DIGEST)-2;
1315
  TPM2B_DIGEST random = { random_len, };
1316
  uint8_t *pos = buffer;
1317
  uint32_t rval;
1318
1319
  if (!this->session)
1320
  {
1321
    try_session_start(this);
1322
  }
1323
1324
  while (bytes > 0)
1325
  {
1326
    bool success = FALSE;
1327
1328
    len = min(bytes, random_len);
1329
    this->mutex->lock(this->mutex);
1330
1331
    rval = Tss2_Sys_GetRandom_Prepare(this->sys_context, len);
1332
    if (rval != TSS2_RC_SUCCESS)
1333
    {
1334
      DBG1(DBG_PTS, "%s Tss2_Sys_GetRandom_Prepare failed: 0x%06x",
1335
         LABEL, rval);
1336
      goto error;
1337
      }
1338
1339
    if (this->session && !this->session->set_cmd_auths(this->session))
1340
    {
1341
      goto error;
1342
    }
1343
1344
    rval = Tss2_Sys_Execute(this->sys_context);
1345
    if (rval != TSS2_RC_SUCCESS)
1346
    {
1347
      DBG1(DBG_PTS, LABEL "Tss2_Sys_Execute failed: 0x%06x", rval);
1348
      goto error;
1349
    }
1350
1351
    if (this->session && !this->session->get_rsp_auths(this->session))
1352
    {
1353
      goto error;
1354
    }
1355
1356
    rval = Tss2_Sys_GetRandom_Complete(this->sys_context, &random);
1357
    if (rval != TSS2_RC_SUCCESS)
1358
    {
1359
      DBG1(DBG_PTS, LABEL "Tss2_Sys_GetRandom_Complete failed: 0x%06x",
1360
              rval);
1361
      goto error;
1362
    }
1363
    success = TRUE;
1364
1365
error:
1366
    this->mutex->unlock(this->mutex);
1367
    if (!success)
1368
    {
1369
      return FALSE;
1370
    }
1371
1372
    memcpy(pos, random.buffer, random.size);
1373
    pos   += random.size;
1374
    bytes -= random.size;
1375
  }
1376
1377
  return TRUE;
1378
}
1379
1380
METHOD(tpm_tss_t, get_data, bool,
1381
  private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1382
  chunk_t pin, chunk_t *data)
1383
{
1384
  uint16_t max_data_size, nv_size, nv_offset = 0;
1385
  uint32_t rval;
1386
1387
  TPMS_CAPABILITY_DATA cap_data;
1388
  TPMI_YES_NO more_data;
1389
  TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
1390
  TPM2B_NV_PUBLIC nv_public = { 0, };
1391
  TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
1392
  TPMS_AUTH_COMMAND *cmd;
1393
  TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
1394
  TSS2L_SYS_AUTH_RESPONSE auth_rsp;
1395
1396
  /* query maximum TPM data transmission size */
1397
  this->mutex->lock(this->mutex);
1398
  rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
1399
        TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
1400
  this->mutex->unlock(this->mutex);
1401
  if (rval != TPM2_RC_SUCCESS)
1402
  {
1403
    DBG1(DBG_PTS, LABEL "Tss2_Sys_GetCapability failed for "
1404
              "TPM2_CAP_TPM_PROPERTIES: 0x%06x", rval);
1405
    return FALSE;
1406
  }
1407
  max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
1408
            TPM2_MAX_NV_BUFFER_SIZE);
1409
1410
  /* get size of NV object */
1411
  this->mutex->lock(this->mutex);
1412
  rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
1413
                                &nv_name, 0);
1414
  this->mutex->unlock(this->mutex);
1415
  if (rval != TPM2_RC_SUCCESS)
1416
  {
1417
    DBG1(DBG_PTS, LABEL "Tss2_Sys_NV_ReadPublic failed: 0x%06x", rval);
1418
    return FALSE;
1419
  }
1420
  nv_size = nv_public.nvPublic.dataSize;
1421
  *data = chunk_alloc(nv_size);
1422
1423
  /* prepare NV read session */
1424
  cmd = &auth_cmd.auths[0];
1425
  cmd->sessionHandle = TPM2_RS_PW;
1426
1427
  if (pin.len > 0)
1428
  {
1429
    cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
1430
    memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
1431
  }
1432
1433
  /* read NV data a maximum data size block at a time */
1434
  while (nv_size > 0)
1435
  {
1436
    this->mutex->lock(this->mutex);
1437
    rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
1438
          min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
1439
    this->mutex->unlock(this->mutex);
1440
    if (rval != TPM2_RC_SUCCESS)
1441
    {
1442
      DBG1(DBG_PTS, LABEL "Tss2_Sys_NV_Read failed: 0x%06x", rval);
1443
      chunk_free(data);
1444
      return FALSE;
1445
    }
1446
    memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
1447
    nv_offset += nv_data.size;
1448
    nv_size   -= nv_data.size;
1449
  }
1450
1451
  return TRUE;
1452
}
1453
1454
METHOD(tpm_tss_t, get_event_digest, bool,
1455
  private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
1456
{
1457
  uint8_t digest_buf[HASH_SIZE_SHA512];
1458
  uint32_t digest_count;
1459
  size_t digest_len = 0;
1460
  hash_algorithm_t hash_alg;
1461
  TPM2_ALG_ID alg_id;
1462
1463
  if (this->old_event_digest_format)
1464
  {
1465
    if (alg != HASH_SHA1)
1466
    {
1467
      return FALSE;
1468
    }
1469
    digest_len = HASH_SIZE_SHA1;
1470
1471
    *digest = chunk_alloc(digest_len);
1472
1473
    if (read(fd, digest->ptr, digest_len) != digest_len)
1474
    {
1475
      return FALSE;
1476
    }
1477
  }
1478
  else
1479
  {
1480
    if (read(fd, &digest_count, 4) != 4)
1481
    {
1482
      return FALSE;
1483
    }
1484
    while (digest_count--)
1485
    {
1486
      if (read(fd, &alg_id, 2) != 2)
1487
      {
1488
        return FALSE;
1489
      }
1490
      hash_alg =   hash_alg_from_tpm_alg_id(alg_id);
1491
      digest_len = hash_len_from_tpm_alg_id(alg_id);
1492
1493
      if (hash_alg == alg)
1494
      {
1495
        *digest = chunk_alloc(digest_len);
1496
        if (read(fd, digest->ptr, digest_len) != digest_len)
1497
        {
1498
        return FALSE;
1499
        }
1500
      }
1501
      else
1502
      {
1503
        /* read without storing */
1504
        if (read(fd, digest_buf, digest_len) != digest_len)
1505
        {
1506
          return FALSE;
1507
        }
1508
      }
1509
    }
1510
  }
1511
1512
  return TRUE;
1513
}
1514
1515
METHOD(tpm_tss_t, destroy, void,
1516
  private_tpm_tss_tss2_t *this)
1517
{
1518
  DESTROY_IF(this->session);
1519
  finalize_context(this);
1520
  this->mutex->destroy(this->mutex);
1521
  free(this->version_info.ptr);
1522
  free(this);
1523
}
1524
1525
/**
1526
 * See header
1527
 */
1528
tpm_tss_t *tpm_tss_tss2_create()
1529
{
1530
  private_tpm_tss_tss2_t *this;
1531
  bool available;
1532
1533
  INIT(this,
1534
    .public = {
1535
      .get_version = _get_version,
1536
      .get_version_info = _get_version_info,
1537
      .generate_aik = _generate_aik,
1538
      .get_public = _get_public,
1539
      .supported_signature_schemes = _supported_signature_schemes,
1540
      .has_pcr_bank = _has_pcr_bank,
1541
      .read_pcr = _read_pcr,
1542
      .extend_pcr = _extend_pcr,
1543
      .quote = _quote,
1544
      .sign = _sign,
1545
      .get_random = _get_random,
1546
      .get_data = _get_data,
1547
      .get_event_digest = _get_event_digest,
1548
      .destroy = _destroy,
1549
    },
1550
    .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1551
  );
1552
1553
  available = initialize_tcti_context(this);
1554
  if (available)
1555
  {
1556
    available = initialize_sys_context(this);
1557
  }
1558
  DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
1559
1560
  if (!available)
1561
  {
1562
    destroy(this);
1563
    return NULL;
1564
  }
1565
1566
  return &this->public;
1567
}
1568
1569
/**
1570
 * See header
1571
 */
1572
bool tpm_tss_tss2_init(void)
1573
{
1574
  TSS2_TCTI_INFO_FUNC infofn;
1575
  const TSS2_TCTI_INFO *info;
1576
  char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
1577
  char tcti_lib[BUF_LEN];
1578
  char *tcti_names[]   = { "device", "tabrmd", "mssim" };
1579
  char *tcti_options[] = { "/dev/tpmrm0", "", "" };
1580
  char *tcti_name;
1581
  bool match = FALSE;
1582
  struct stat st;
1583
  int i = 0;
1584
1585
  /* check for the existence of an in-kernel TPM resource manager */
1586
  if (stat(tcti_options[i], &st))
1587
  {
1588
    i = 1;
1589
  }
1590
  DBG2(DBG_PTS, LABEL "\"%s\" in-kernel resource manager is %spresent",
1591
          tcti_options[0], i ? "not " : "");
1592
1593
  /* select a dynamic TCTI library (device, tabrmd or mssim) */
1594
  tcti_name = lib->settings->get_str(lib->settings,
1595
           "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
1596
  snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
1597
1598
  for (i = 0; i < countof(tcti_names); i++)
1599
  {
1600
    if (streq(tcti_name, tcti_names[i]))
1601
    {
1602
      match = TRUE;
1603
      break;
1604
    }
1605
  }
1606
  if (!match)
1607
  {
1608
    DBG1(DBG_PTS, LABEL "\"%s\" is not a valid TCTI library name", tcti_lib);
1609
    return FALSE;
1610
  }
1611
1612
  tcti_opts = lib->settings->get_str(lib->settings,
1613
           "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
1614
1615
  /* open the selected dynamic TCTI library */
1616
  tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
1617
  if (!tcti_handle)
1618
  {
1619
    DBG1(DBG_PTS, LABEL "could not load \"%s\"", tcti_lib);
1620
    return FALSE;
1621
  }
1622
1623
  infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
1624
    if (!infofn)
1625
  {
1626
        DBG1(DBG_PTS, LABEL "symbol \"%s\" not found in \"%s\"",
1627
            TSS2_TCTI_INFO_SYMBOL, tcti_lib);
1628
    tpm_tss_tss2_deinit();
1629
1630
    return FALSE;
1631
    }
1632
  DBG2(DBG_PTS, LABEL "\"%s\" successfully loaded", tcti_lib);
1633
  info = infofn();
1634
  tcti_init = info->init;
1635
1636
  return TRUE;
1637
}
1638
1639
/**
1640
 * See header
1641
 */
1642
void tpm_tss_tss2_deinit(void)
1643
{
1644
  dlclose(tcti_handle);
1645
  tcti_handle = NULL;
1646
  tcti_init   = NULL;
1647
  tcti_opts   = NULL;
1648
}
1649
1650
#else /* TSS_TSS2_V2 */
1651
1652
/**
1653
 * See header
1654
 */
1655
bool tpm_tss_tss2_init(void)
1656
5.44k
{
1657
5.44k
  return TRUE;
1658
5.44k
}
1659
1660
/**
1661
 * See header
1662
 */
1663
void tpm_tss_tss2_deinit(void)
1664
5.44k
{
1665
  /* empty */
1666
5.44k
}
1667
1668
#endif /* TSS_TSS2_V2 */
1669