Coverage Report

Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/tpm.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2021 Yubico AB. All rights reserved.
3
 * Use of this source code is governed by a BSD-style
4
 * license that can be found in the LICENSE file.
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
/*
9
 * Trusted Platform Module (TPM) 2.0 attestation support. Documentation
10
 * references are relative to revision 01.38 of the TPM 2.0 specification.
11
 */
12
13
#include <openssl/sha.h>
14
15
#include "packed.h"
16
#include "fido.h"
17
18
/* Part 1, 4.89: TPM_GENERATED_VALUE */
19
728
#define TPM_MAGIC       0xff544347
20
21
/* Part 2, 6.3: TPM_ALG_ID */
22
15
#define TPM_ALG_RSA     0x0001
23
1.50k
#define TPM_ALG_SHA256  0x000b
24
2.28k
#define TPM_ALG_NULL    0x0010
25
751
#define TPM_ALG_ECC     0x0023
26
27
/* Part 2, 6.4: TPM_ECC_CURVE */
28
751
#define TPM_ECC_P256    0x0003
29
30
/* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
31
728
#define TPM_ST_CERTIFY  0x8017
32
33
/* Part 2, 8.3: TPMA_OBJECT */
34
766
#define TPMA_RESERVED   0xfff8f309        /* reserved bits; must be zero */
35
766
#define TPMA_FIXED      0x00000002        /* object has fixed hierarchy */
36
766
#define TPMA_CLEAR      0x00000004        /* object persists */
37
766
#define TPMA_FIXED_P    0x00000010        /* object has fixed parent */
38
766
#define TPMA_SENSITIVE  0x00000020        /* data originates within tpm */
39
766
#define TPMA_SIGN       0x00040000        /* object may sign */
40
41
/* Part 2, 10.4.2: TPM2B_DIGEST */
42
PACKED_TYPE(tpm_sha256_digest_t,
43
struct tpm_sha256_digest {
44
        uint16_t size; /* sizeof(body) */
45
        uint8_t  body[32];
46
})
47
48
/* Part 2, 10.4.3: TPM2B_DATA */
49
PACKED_TYPE(tpm_sha1_data_t,
50
struct tpm_sha1_data {
51
        uint16_t size; /* sizeof(body) */
52
        uint8_t  body[20];
53
})
54
55
/* Part 2, 10.5.3: TPM2B_NAME */
56
PACKED_TYPE(tpm_sha256_name_t,
57
struct tpm_sha256_name {
58
        uint16_t size; /* sizeof(alg) + sizeof(body) */
59
        uint16_t alg;  /* TPM_ALG_SHA256 */
60
        uint8_t  body[32];
61
})
62
63
/* Part 2, 10.11.1: TPMS_CLOCK_INFO */
64
PACKED_TYPE(tpm_clock_info_t,
65
struct tpm_clock_info {
66
        uint64_t timestamp_ms;
67
        uint32_t reset_count;   /* obfuscated by tpm */
68
        uint32_t restart_count; /* obfuscated by tpm */
69
        uint8_t  safe;          /* 1 if timestamp_ms is current */
70
})
71
72
/* Part 2, 10.12.8 TPMS_ATTEST */
73
PACKED_TYPE(tpm_sha1_attest_t,
74
struct tpm_sha1_attest {
75
        uint32_t          magic;     /* TPM_MAGIC */
76
        uint16_t          type;      /* TPM_ST_ATTEST_CERTIFY */
77
        tpm_sha256_name_t signer;    /* full tpm path of signing key */
78
        tpm_sha1_data_t   data;      /* signed sha1 */
79
        tpm_clock_info_t  clock;
80
        uint64_t          fwversion; /* obfuscated by tpm */
81
        tpm_sha256_name_t name;      /* sha256 of tpm_rs256_pubarea_t */
82
        tpm_sha256_name_t qual_name; /* full tpm path of attested key */
83
})
84
85
/* Part 2, 11.2.4.5: TPM2B_PUBLIC_KEY_RSA */
86
PACKED_TYPE(tpm_rs256_key_t,
87
struct tpm_rs256_key {
88
        uint16_t size; /* sizeof(body) */
89
        uint8_t  body[256];
90
})
91
92
/* Part 2, 11.2.5.1: TPM2B_ECC_PARAMETER */
93
PACKED_TYPE(tpm_es256_coord_t,
94
struct tpm_es256_coord {
95
        uint16_t size; /* sizeof(body) */
96
        uint8_t  body[32];
97
})
98
99
/* Part 2, 11.2.5.2: TPMS_ECC_POINT */
100
PACKED_TYPE(tpm_es256_point_t,
101
struct tpm_es256_point {
102
        tpm_es256_coord_t x;
103
        tpm_es256_coord_t y;
104
})
105
106
/* Part 2, 12.2.3.5: TPMS_RSA_PARMS */
107
PACKED_TYPE(tpm_rs256_param_t,
108
struct tpm_rs256_param {
109
        uint16_t symmetric; /* TPM_ALG_NULL */
110
        uint16_t scheme;    /* TPM_ALG_NULL */
111
        uint16_t keybits;   /* 2048 */
112
        uint32_t exponent;  /* zero (meaning 2^16 + 1) */
113
})
114
115
/* Part 2, 12.2.3.6: TPMS_ECC_PARMS */
116
PACKED_TYPE(tpm_es256_param_t,
117
struct tpm_es256_param {
118
        uint16_t symmetric; /* TPM_ALG_NULL */
119
        uint16_t scheme;    /* TPM_ALG_NULL */
120
        uint16_t curve_id;  /* TPM_ECC_P256 */
121
        uint16_t kdf;       /* TPM_ALG_NULL */
122
})
123
124
/* Part 2, 12.2.4: TPMT_PUBLIC */
125
PACKED_TYPE(tpm_rs256_pubarea_t,
126
struct tpm_rs256_pubarea {
127
        uint16_t            alg;    /* TPM_ALG_RSA */
128
        uint16_t            hash;   /* TPM_ALG_SHA256 */
129
        uint32_t            attr;
130
        tpm_sha256_digest_t policy; /* must be present? */
131
        tpm_rs256_param_t   param;
132
        tpm_rs256_key_t     key;
133
})
134
135
/* Part 2, 12.2.4: TPMT_PUBLIC */
136
PACKED_TYPE(tpm_es256_pubarea_t,
137
struct tpm_es256_pubarea {
138
        uint16_t            alg;    /* TPM_ALG_ECC */
139
        uint16_t            hash;   /* TPM_ALG_SHA256 */
140
        uint32_t            attr;
141
        tpm_sha256_digest_t policy; /* must be present? */
142
        tpm_es256_param_t   param;
143
        tpm_es256_point_t   point;
144
})
145
146
static int
147
get_signed_sha1(tpm_sha1_data_t *dgst, const fido_blob_t *authdata,
148
    const fido_blob_t *clientdata)
149
758
{
150
758
        const EVP_MD    *md = NULL;
151
758
        EVP_MD_CTX      *ctx = NULL;
152
758
        int              ok = -1;
153
154
758
        if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
155
758
            (md = EVP_sha1()) == NULL ||
156
758
            (ctx = EVP_MD_CTX_new()) == NULL ||
157
758
            EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
158
758
            EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
159
758
            EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
160
758
            EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
161
18
                fido_log_debug("%s: sha1", __func__);
162
18
                goto fail;
163
18
        }
164
165
740
        ok = 0;
166
758
fail:
167
758
        EVP_MD_CTX_free(ctx);
168
169
758
        return (ok);
170
740
}
171
172
static int
173
get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
174
740
{
175
740
        name->alg = TPM_ALG_SHA256;
176
740
        name->size = sizeof(name->alg) + sizeof(name->body);
177
740
        if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
178
740
            SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
179
5
                fido_log_debug("%s: sha256", __func__);
180
5
                return -1;
181
5
        }
182
183
735
        return 0;
184
740
}
185
186
static void
187
bswap_rs256_pubarea(tpm_rs256_pubarea_t *x)
188
15
{
189
15
        x->alg = htobe16(x->alg);
190
15
        x->hash = htobe16(x->hash);
191
15
        x->attr = htobe32(x->attr);
192
15
        x->policy.size = htobe16(x->policy.size);
193
15
        x->param.symmetric = htobe16(x->param.symmetric);
194
15
        x->param.scheme = htobe16(x->param.scheme);
195
15
        x->param.keybits = htobe16(x->param.keybits);
196
15
        x->key.size = htobe16(x->key.size);
197
15
}
198
199
static void
200
bswap_es256_pubarea(tpm_es256_pubarea_t *x)
201
751
{
202
751
        x->alg = htobe16(x->alg);
203
751
        x->hash = htobe16(x->hash);
204
751
        x->attr = htobe32(x->attr);
205
751
        x->policy.size = htobe16(x->policy.size);
206
751
        x->param.symmetric = htobe16(x->param.symmetric);
207
751
        x->param.scheme = htobe16(x->param.scheme);
208
751
        x->param.curve_id = htobe16(x->param.curve_id);
209
751
        x->param.kdf = htobe16(x->param.kdf);
210
751
        x->point.x.size = htobe16(x->point.x.size);
211
751
        x->point.y.size = htobe16(x->point.y.size);
212
751
}
213
214
static void
215
bswap_sha1_certinfo(tpm_sha1_attest_t *x)
216
728
{
217
728
        x->magic = htobe32(x->magic);
218
728
        x->type = htobe16(x->type);
219
728
        x->signer.size = htobe16(x->signer.size);
220
728
        x->data.size = htobe16(x->data.size);
221
728
        x->name.alg = htobe16(x->name.alg);
222
728
        x->name.size = htobe16(x->name.size);
223
728
}
224
225
static int
226
check_rs256_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
227
19
{
228
19
        const tpm_rs256_pubarea_t       *actual;
229
19
        tpm_rs256_pubarea_t              expected;
230
19
        int                              ok;
231
232
19
        if (buf->len != sizeof(*actual)) {
233
4
                fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
234
4
                return -1;
235
4
        }
236
15
        actual = (const void *)buf->ptr;
237
238
15
        memset(&expected, 0, sizeof(expected));
239
15
        expected.alg = TPM_ALG_RSA;
240
15
        expected.hash = TPM_ALG_SHA256;
241
15
        expected.attr = be32toh(actual->attr);
242
15
        expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
243
15
        expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
244
15
        expected.policy = actual->policy;
245
15
        expected.policy.size = sizeof(expected.policy.body);
246
15
        expected.param.symmetric = TPM_ALG_NULL;
247
15
        expected.param.scheme = TPM_ALG_NULL;
248
15
        expected.param.keybits = 2048;
249
15
        expected.param.exponent = 0; /* meaning 2^16+1 */
250
15
        expected.key.size = sizeof(expected.key.body);
251
15
        memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
252
15
        bswap_rs256_pubarea(&expected);
253
254
15
        ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
255
15
        explicit_bzero(&expected, sizeof(expected));
256
257
15
        return ok != 0 ? -1 : 0;
258
19
}
259
260
static int
261
check_es256_pubarea(const fido_blob_t *buf, const es256_pk_t *pk)
262
756
{
263
756
        const tpm_es256_pubarea_t       *actual;
264
756
        tpm_es256_pubarea_t              expected;
265
756
        int                              ok;
266
267
756
        if (buf->len != sizeof(*actual)) {
268
5
                fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
269
5
                return -1;
270
5
        }
271
751
        actual = (const void *)buf->ptr;
272
273
751
        memset(&expected, 0, sizeof(expected));
274
751
        expected.alg = TPM_ALG_ECC;
275
751
        expected.hash = TPM_ALG_SHA256;
276
751
        expected.attr = be32toh(actual->attr);
277
751
        expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
278
751
        expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
279
751
        expected.policy = actual->policy;
280
751
        expected.policy.size = sizeof(expected.policy.body);
281
751
        expected.param.symmetric = TPM_ALG_NULL;
282
751
        expected.param.scheme = TPM_ALG_NULL; /* TCG Alg. Registry, 5.2.4 */
283
751
        expected.param.curve_id = TPM_ECC_P256;
284
751
        expected.param.kdf = TPM_ALG_NULL;
285
751
        expected.point.x.size = sizeof(expected.point.x.body);
286
751
        expected.point.y.size = sizeof(expected.point.y.body);
287
751
        memcpy(&expected.point.x.body, &pk->x, sizeof(expected.point.x.body));
288
751
        memcpy(&expected.point.y.body, &pk->y, sizeof(expected.point.y.body));
289
751
        bswap_es256_pubarea(&expected);
290
291
751
        ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
292
751
        explicit_bzero(&expected, sizeof(expected));
293
294
751
        return ok != 0 ? -1 : 0;
295
756
}
296
297
static int
298
check_sha1_certinfo(const fido_blob_t *buf, const fido_blob_t *clientdata_hash,
299
    const fido_blob_t *authdata_raw, const fido_blob_t *pubarea)
300
758
{
301
758
        const tpm_sha1_attest_t *actual;
302
758
        tpm_sha1_attest_t        expected;
303
758
        tpm_sha1_data_t          signed_data;
304
758
        tpm_sha256_name_t        signed_name;
305
758
        int                      ok = -1;
306
307
758
        memset(&signed_data, 0, sizeof(signed_data));
308
758
        memset(&signed_name, 0, sizeof(signed_name));
309
310
758
        if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
311
758
            get_signed_name(&signed_name, pubarea) < 0) {
312
23
                fido_log_debug("%s: get_signed_sha1/name", __func__);
313
23
                goto fail;
314
23
        }
315
735
        if (buf->len != sizeof(*actual)) {
316
7
                fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
317
7
                goto fail;
318
7
        }
319
728
        actual = (const void *)buf->ptr;
320
321
728
        memset(&expected, 0, sizeof(expected));
322
728
        expected.magic = TPM_MAGIC;
323
728
        expected.type = TPM_ST_CERTIFY;
324
728
        expected.signer = actual->signer;
325
728
        expected.signer.size = sizeof(expected.signer.alg) +
326
728
            sizeof(expected.signer.body);
327
728
        expected.data = signed_data;
328
728
        expected.clock = actual->clock;
329
728
        expected.clock.safe = 1;
330
728
        expected.fwversion = actual->fwversion;
331
728
        expected.name = signed_name;
332
728
        expected.qual_name = actual->qual_name;
333
728
        bswap_sha1_certinfo(&expected);
334
335
728
        ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
336
758
fail:
337
758
        explicit_bzero(&expected, sizeof(expected));
338
758
        explicit_bzero(&signed_data, sizeof(signed_data));
339
758
        explicit_bzero(&signed_name, sizeof(signed_name));
340
341
758
        return ok != 0 ? -1 : 0;
342
728
}
343
344
int
345
fido_get_signed_hash_tpm(fido_blob_t *dgst, const fido_blob_t *clientdata_hash,
346
    const fido_blob_t *authdata_raw, const fido_attstmt_t *attstmt,
347
    const fido_attcred_t *attcred)
348
786
{
349
786
        const fido_blob_t *pubarea = &attstmt->pubarea;
350
786
        const fido_blob_t *certinfo = &attstmt->certinfo;
351
352
786
        if (attstmt->alg != COSE_RS1) {
353
7
                fido_log_debug("%s: unsupported alg %d", __func__,
354
7
                    attstmt->alg);
355
7
                return -1;
356
7
        }
357
358
779
        switch (attcred->type) {
359
756
        case COSE_ES256:
360
756
                if (check_es256_pubarea(pubarea, &attcred->pubkey.es256) < 0) {
361
9
                        fido_log_debug("%s: check_es256_pubarea", __func__);
362
9
                        return -1;
363
9
                }
364
747
                break;
365
747
        case COSE_RS256:
366
19
                if (check_rs256_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
367
8
                        fido_log_debug("%s: check_rs256_pubarea", __func__);
368
8
                        return -1;
369
8
                }
370
11
                break;
371
11
        default:
372
4
                fido_log_debug("%s: unsupported type %d", __func__,
373
4
                    attcred->type);
374
4
                return -1;
375
779
        }
376
377
758
        if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
378
758
            pubarea) < 0) {
379
48
                fido_log_debug("%s: check_sha1_certinfo", __func__);
380
48
                return -1;
381
48
        }
382
383
710
        if (dgst->len < SHA_DIGEST_LENGTH ||
384
710
            SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
385
4
                fido_log_debug("%s: sha1", __func__);
386
4
                return -1;
387
4
        }
388
706
        dgst->len = SHA_DIGEST_LENGTH;
389
390
706
        return 0;
391
710
}