Coverage Report

Created: 2025-12-31 06:38

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