Coverage Report

Created: 2021-10-21 13:35

/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
 */
6
7
/*
8
 * Trusted Platform Module (TPM) 2.0 attestation support. Documentation
9
 * references are relative to revision 01.38 of the TPM 2.0 specification.
10
 */
11
12
#include <openssl/sha.h>
13
14
#include "packed.h"
15
#include "fido.h"
16
17
/* Part 1, 4.89: TPM_GENERATED_VALUE */
18
19
#define TPM_MAGIC       0xff544347
19
20
/* Part 2, 6.3: TPM_ALG_ID */
21
28
#define TPM_ALG_RSA     0x0001
22
49
#define TPM_ALG_SHA256  0x000b
23
56
#define TPM_ALG_NULL    0x0010
24
25
/* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
26
19
#define TPM_ST_CERTIFY  0x8017
27
28
/* Part 2, 8.3: TPMA_OBJECT */
29
28
#define TPMA_RESERVED   0xfff8f309        /* reserved bits; must be zero */
30
28
#define TPMA_FIXED      0x00000002        /* object has fixed hierarchy */
31
28
#define TPMA_CLEAR      0x00000004        /* object persists */
32
28
#define TPMA_FIXED_P    0x00000010        /* object has fixed parent */
33
28
#define TPMA_SENSITIVE  0x00000020        /* data originates within tpm */
34
28
#define TPMA_SIGN       0x00020000        /* object may sign */
35
36
/* Part 2, 10.4.2: TPM2B_DIGEST */
37
PACKED_TYPE(tpm_sha256_digest_t,
38
struct tpm_sha256_digest {
39
        uint16_t size; /* sizeof(body) */
40
        uint8_t  body[32];
41
})
42
43
/* Part 2, 10.4.3: TPM2B_DATA */
44
PACKED_TYPE(tpm_sha1_data_t,
45
struct tpm_sha1_data {
46
        uint16_t size; /* sizeof(body */
47
        uint8_t  body[20];
48
})
49
50
/* Part 2, 10.5.3: TPM2B_NAME */
51
PACKED_TYPE(tpm_sha256_name_t,
52
struct tpm_sha256_name {
53
        uint16_t size; /* sizeof(alg) + sizeof(body) */
54
        uint16_t alg;  /* TPM_ALG_SHA256 */
55
        uint8_t  body[32];
56
})
57
58
/* Part 2, 10.11.1: TPMS_CLOCK_INFO */
59
PACKED_TYPE(tpm_clock_info_t,
60
struct tpm_clock_info {
61
        uint64_t timestamp_ms;
62
        uint32_t reset_count;   /* obfuscated by tpm */
63
        uint32_t restart_count; /* obfuscated by tpm */
64
        uint8_t  safe;          /* 1 if timestamp_ms is current */
65
})
66
67
/* Part 2, 10.12.8 TPMS_ATTEST */
68
PACKED_TYPE(tpm_sha1_attest_t,
69
struct tpm_sha1_attest {
70
        uint32_t          magic;     /* TPM_MAGIC */
71
        uint16_t          type;      /* TPM_ST_ATTEST_CERTIFY */
72
        tpm_sha256_name_t signer;    /* full tpm path of signing key */
73
        tpm_sha1_data_t   data;      /* signed sha1 */
74
        tpm_clock_info_t  clock;
75
        uint64_t          fwversion; /* obfuscated by tpm */
76
        tpm_sha256_name_t name;      /* sha256 of tpm_rsa2048_pubarea_t */
77
        tpm_sha256_name_t qual_name; /* full tpm path of attested key */
78
})
79
80
/* Part 2, 11.2.4.5: TPM2B_PUBLIC_KEY_RSA */
81
PACKED_TYPE(tpm_rsa2048_key_t,
82
struct tpm_rsa2048_key {
83
        uint16_t size; /* sizeof(body) */
84
        uint8_t  body[256];
85
})
86
87
/* Part 2, 12.2.3.5: TPMS_RSA_PARMS */
88
PACKED_TYPE(tpm_rsa2048_param_t,
89
struct tpm_rsa2048_param {
90
        uint16_t symmetric; /* TPM_ALG_NULL */
91
        uint16_t scheme;    /* TPM_ALG_NULL */
92
        uint16_t keybits;   /* 2048 */
93
        uint32_t exponent;  /* zero (meaning 2^16 + 1) */
94
})
95
96
/* Part 2, 12.2.4: TPMT_PUBLIC */
97
PACKED_TYPE(tpm_rsa2048_pubarea_t,
98
struct tpm_rsa2048_pubarea {
99
        uint16_t            alg;    /* TPM_ALG_RSA */
100
        uint16_t            hash;   /* TPM_ALG_SHA256 */
101
        uint32_t            attr;
102
        tpm_sha256_digest_t policy; /* must be present? */
103
        tpm_rsa2048_param_t param;
104
        tpm_rsa2048_key_t   key;
105
})
106
107
static int
108
get_signed_sha1(tpm_sha1_data_t *dgst, const fido_blob_t *authdata,
109
    const fido_blob_t *clientdata)
110
27
{
111
27
        const EVP_MD    *md = NULL;
112
27
        EVP_MD_CTX      *ctx = NULL;
113
27
        int              ok = -1;
114
115
27
        if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
116
27
            (md = EVP_sha1()) == NULL ||
117
27
            (ctx = EVP_MD_CTX_new()) == NULL ||
118
27
            EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
119
27
            EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
120
27
            EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
121
27
            EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
122
6
                fido_log_debug("%s: sha1", __func__);
123
6
                goto fail;
124
6
        }
125
126
21
        ok = 0;
127
27
fail:
128
27
        EVP_MD_CTX_free(ctx);
129
130
27
        return (ok);
131
21
}
132
133
static int
134
get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
135
21
{
136
21
        name->alg = TPM_ALG_SHA256;
137
21
        name->size = sizeof(name->alg) + sizeof(name->body);
138
21
        if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
139
21
            SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
140
1
                fido_log_debug("%s: sha256", __func__);
141
1
                return -1;
142
1
        }
143
144
20
        return 0;
145
20
}
146
147
static void
148
bswap_rsa2048_pubarea(tpm_rsa2048_pubarea_t *x)
149
28
{
150
28
        x->alg = htobe16(x->alg);
151
28
        x->hash = htobe16(x->hash);
152
28
        x->attr = htobe32(x->attr);
153
28
        x->policy.size = htobe16(x->policy.size);
154
28
        x->param.symmetric = htobe16(x->param.symmetric);
155
28
        x->param.scheme = htobe16(x->param.scheme);
156
28
        x->param.keybits = htobe16(x->param.keybits);
157
28
        x->key.size = htobe16(x->key.size);
158
28
}
159
160
static void
161
bswap_sha1_certinfo(tpm_sha1_attest_t *x)
162
19
{
163
19
        x->magic = htobe32(x->magic);
164
19
        x->type = htobe16(x->type);
165
19
        x->signer.size = htobe16(x->signer.size);
166
19
        x->data.size = htobe16(x->data.size);
167
19
        x->name.alg = htobe16(x->name.alg);
168
19
        x->name.size = htobe16(x->name.size);
169
19
}
170
171
static int
172
check_rsa2048_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
173
29
{
174
29
        const tpm_rsa2048_pubarea_t     *actual;
175
29
        tpm_rsa2048_pubarea_t            expected;
176
29
        int                              ok;
177
178
29
        if (buf->len != sizeof(*actual)) {
179
1
                fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
180
1
                return -1;
181
1
        }
182
28
        actual = (const void *)buf->ptr;
183
184
28
        memset(&expected, 0, sizeof(expected));
185
28
        expected.alg = TPM_ALG_RSA;
186
28
        expected.hash = TPM_ALG_SHA256;
187
28
        expected.attr = be32toh(actual->attr);
188
28
        expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
189
28
        expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
190
28
        expected.policy = actual->policy;
191
28
        expected.policy.size = sizeof(expected.policy.body);
192
28
        expected.param.symmetric = TPM_ALG_NULL;
193
28
        expected.param.scheme = TPM_ALG_NULL;
194
28
        expected.param.keybits = 2048;
195
28
        expected.param.exponent = 0; /* meaning 2^16+1 */
196
28
        expected.key.size = sizeof(expected.key.body);
197
28
        memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
198
28
        bswap_rsa2048_pubarea(&expected);
199
200
28
        ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
201
28
        explicit_bzero(&expected, sizeof(expected));
202
203
28
        return ok != 0 ? -1 : 0;
204
28
}
205
206
static int
207
check_sha1_certinfo(const fido_blob_t *buf, const fido_blob_t *clientdata_hash,
208
    const fido_blob_t *authdata_raw, const fido_blob_t *pubarea)
209
27
{
210
27
        const tpm_sha1_attest_t *actual;
211
27
        tpm_sha1_attest_t        expected;
212
27
        tpm_sha1_data_t          signed_data;
213
27
        tpm_sha256_name_t        signed_name;
214
27
        int                      ok = -1;
215
216
27
        memset(&signed_data, 0, sizeof(signed_data));
217
27
        memset(&signed_name, 0, sizeof(signed_name));
218
219
27
        if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
220
27
            get_signed_name(&signed_name, pubarea) < 0) {
221
7
                fido_log_debug("%s: get_signed_sha1/name", __func__);
222
7
                goto fail;
223
7
        }
224
20
        if (buf->len != sizeof(*actual)) {
225
1
                fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
226
1
                goto fail;
227
1
        }
228
19
        actual = (const void *)buf->ptr;
229
230
19
        memset(&expected, 0, sizeof(expected));
231
19
        expected.magic = TPM_MAGIC;
232
19
        expected.type = TPM_ST_CERTIFY;
233
19
        expected.signer = actual->signer;
234
19
        expected.signer.size = sizeof(expected.signer.alg) +
235
19
            sizeof(expected.signer.body);
236
19
        expected.data = signed_data;
237
19
        expected.clock = actual->clock;
238
19
        expected.clock.safe = 1;
239
19
        expected.fwversion = actual->fwversion;
240
19
        expected.name = signed_name;
241
19
        expected.qual_name = actual->qual_name;
242
19
        bswap_sha1_certinfo(&expected);
243
244
19
        ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
245
27
fail:
246
27
        explicit_bzero(&expected, sizeof(expected));
247
27
        explicit_bzero(&signed_data, sizeof(signed_data));
248
27
        explicit_bzero(&signed_name, sizeof(signed_name));
249
250
27
        return ok != 0 ? -1 : 0;
251
19
}
252
253
int
254
fido_get_signed_hash_tpm(fido_blob_t *dgst, const fido_blob_t *clientdata_hash,
255
    const fido_blob_t *authdata_raw, const fido_attstmt_t *attstmt,
256
    const fido_attcred_t *attcred)
257
30
{
258
30
        const fido_blob_t *pubarea = &attstmt->pubarea;
259
30
        const fido_blob_t *certinfo = &attstmt->certinfo;
260
261
30
        if (attstmt->alg != COSE_RS1 || attcred->type != COSE_RS256) {
262
1
                fido_log_debug("%s: unsupported alg %d, type %d", __func__,
263
1
                    attstmt->alg, attcred->type);
264
1
                return -1;
265
1
        }
266
267
29
        if (check_rsa2048_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
268
2
                fido_log_debug("%s: check_rsa2048_pubarea", __func__);
269
2
                return -1;
270
2
        }
271
272
27
        if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
273
27
            pubarea) < 0) {
274
15
                fido_log_debug("%s: check_sha1_certinfo", __func__);
275
15
                return -1;
276
15
        }
277
278
12
        if (dgst->len < SHA_DIGEST_LENGTH ||
279
12
            SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
280
1
                fido_log_debug("%s: sha1", __func__);
281
1
                return -1;
282
1
        }
283
11
        dgst->len = SHA_DIGEST_LENGTH;
284
285
11
        return 0;
286
11
}