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 #define TPM_MAGIC 0xff544347
20
21 /* Part 2, 6.3: TPM_ALG_ID */
22 #define TPM_ALG_RSA 0x0001
23 #define TPM_ALG_SHA256 0x000b
24 #define TPM_ALG_NULL 0x0010
25 #define TPM_ALG_ECC 0x0023
26
27 /* Part 2, 6.4: TPM_ECC_CURVE */
28 #define TPM_ECC_P256 0x0003
29
30 /* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
31 #define TPM_ST_CERTIFY 0x8017
32
33 /* Part 2, 8.3: TPMA_OBJECT */
34 #define TPMA_RESERVED 0xfff8f309 /* reserved bits; must be zero */
35 #define TPMA_FIXED 0x00000002 /* object has fixed hierarchy */
36 #define TPMA_CLEAR 0x00000004 /* object persists */
37 #define TPMA_FIXED_P 0x00000010 /* object has fixed parent */
38 #define TPMA_SENSITIVE 0x00000020 /* data originates within tpm */
39 #define TPMA_SIGN 0x00040000 /* object may sign */
40
41 /* Part 2, 10.4.2: TPM2B_DIGEST */
PACKED_TYPE(tpm_sha256_digest_t,struct tpm_sha256_digest{ uint16_t size; uint8_t body[32]; })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 {
150 const EVP_MD *md = NULL;
151 EVP_MD_CTX *ctx = NULL;
152 int ok = -1;
153
154 if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
155 (md = EVP_sha1()) == NULL ||
156 (ctx = EVP_MD_CTX_new()) == NULL ||
157 EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
158 EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
159 EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
160 EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
161 fido_log_debug("%s: sha1", __func__);
162 goto fail;
163 }
164
165 ok = 0;
166 fail:
167 EVP_MD_CTX_free(ctx);
168
169 return (ok);
170 }
171
172 static int
get_signed_name(tpm_sha256_name_t * name,const fido_blob_t * pubarea)173 get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
174 {
175 name->alg = TPM_ALG_SHA256;
176 name->size = sizeof(name->alg) + sizeof(name->body);
177 if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
178 SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
179 fido_log_debug("%s: sha256", __func__);
180 return -1;
181 }
182
183 return 0;
184 }
185
186 static void
bswap_rs256_pubarea(tpm_rs256_pubarea_t * x)187 bswap_rs256_pubarea(tpm_rs256_pubarea_t *x)
188 {
189 x->alg = htobe16(x->alg);
190 x->hash = htobe16(x->hash);
191 x->attr = htobe32(x->attr);
192 x->policy.size = htobe16(x->policy.size);
193 x->param.symmetric = htobe16(x->param.symmetric);
194 x->param.scheme = htobe16(x->param.scheme);
195 x->param.keybits = htobe16(x->param.keybits);
196 x->key.size = htobe16(x->key.size);
197 }
198
199 static void
bswap_es256_pubarea(tpm_es256_pubarea_t * x)200 bswap_es256_pubarea(tpm_es256_pubarea_t *x)
201 {
202 x->alg = htobe16(x->alg);
203 x->hash = htobe16(x->hash);
204 x->attr = htobe32(x->attr);
205 x->policy.size = htobe16(x->policy.size);
206 x->param.symmetric = htobe16(x->param.symmetric);
207 x->param.scheme = htobe16(x->param.scheme);
208 x->param.curve_id = htobe16(x->param.curve_id);
209 x->param.kdf = htobe16(x->param.kdf);
210 x->point.x.size = htobe16(x->point.x.size);
211 x->point.y.size = htobe16(x->point.y.size);
212 }
213
214 static void
bswap_sha1_certinfo(tpm_sha1_attest_t * x)215 bswap_sha1_certinfo(tpm_sha1_attest_t *x)
216 {
217 x->magic = htobe32(x->magic);
218 x->type = htobe16(x->type);
219 x->signer.size = htobe16(x->signer.size);
220 x->data.size = htobe16(x->data.size);
221 x->name.alg = htobe16(x->name.alg);
222 x->name.size = htobe16(x->name.size);
223 }
224
225 static int
check_rs256_pubarea(const fido_blob_t * buf,const rs256_pk_t * pk)226 check_rs256_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
227 {
228 const tpm_rs256_pubarea_t *actual;
229 tpm_rs256_pubarea_t expected;
230 int ok;
231
232 if (buf->len != sizeof(*actual)) {
233 fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
234 return -1;
235 }
236 actual = (const void *)buf->ptr;
237
238 memset(&expected, 0, sizeof(expected));
239 expected.alg = TPM_ALG_RSA;
240 expected.hash = TPM_ALG_SHA256;
241 expected.attr = be32toh(actual->attr);
242 expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
243 expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
244 expected.policy = actual->policy;
245 expected.policy.size = sizeof(expected.policy.body);
246 expected.param.symmetric = TPM_ALG_NULL;
247 expected.param.scheme = TPM_ALG_NULL;
248 expected.param.keybits = 2048;
249 expected.param.exponent = 0; /* meaning 2^16+1 */
250 expected.key.size = sizeof(expected.key.body);
251 memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
252 bswap_rs256_pubarea(&expected);
253
254 ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
255 explicit_bzero(&expected, sizeof(expected));
256
257 return ok != 0 ? -1 : 0;
258 }
259
260 static int
check_es256_pubarea(const fido_blob_t * buf,const es256_pk_t * pk)261 check_es256_pubarea(const fido_blob_t *buf, const es256_pk_t *pk)
262 {
263 const tpm_es256_pubarea_t *actual;
264 tpm_es256_pubarea_t expected;
265 int ok;
266
267 if (buf->len != sizeof(*actual)) {
268 fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
269 return -1;
270 }
271 actual = (const void *)buf->ptr;
272
273 memset(&expected, 0, sizeof(expected));
274 expected.alg = TPM_ALG_ECC;
275 expected.hash = TPM_ALG_SHA256;
276 expected.attr = be32toh(actual->attr);
277 expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
278 expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
279 expected.policy = actual->policy;
280 expected.policy.size = sizeof(expected.policy.body);
281 expected.param.symmetric = TPM_ALG_NULL;
282 expected.param.scheme = TPM_ALG_NULL; /* TCG Alg. Registry, 5.2.4 */
283 expected.param.curve_id = TPM_ECC_P256;
284 expected.param.kdf = TPM_ALG_NULL;
285 expected.point.x.size = sizeof(expected.point.x.body);
286 expected.point.y.size = sizeof(expected.point.y.body);
287 memcpy(&expected.point.x.body, &pk->x, sizeof(expected.point.x.body));
288 memcpy(&expected.point.y.body, &pk->y, sizeof(expected.point.y.body));
289 bswap_es256_pubarea(&expected);
290
291 ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
292 explicit_bzero(&expected, sizeof(expected));
293
294 return ok != 0 ? -1 : 0;
295 }
296
297 static int
check_sha1_certinfo(const fido_blob_t * buf,const fido_blob_t * clientdata_hash,const fido_blob_t * authdata_raw,const fido_blob_t * pubarea)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 {
301 const tpm_sha1_attest_t *actual;
302 tpm_sha1_attest_t expected;
303 tpm_sha1_data_t signed_data;
304 tpm_sha256_name_t signed_name;
305 int ok = -1;
306
307 memset(&signed_data, 0, sizeof(signed_data));
308 memset(&signed_name, 0, sizeof(signed_name));
309
310 if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
311 get_signed_name(&signed_name, pubarea) < 0) {
312 fido_log_debug("%s: get_signed_sha1/name", __func__);
313 goto fail;
314 }
315 if (buf->len != sizeof(*actual)) {
316 fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
317 goto fail;
318 }
319 actual = (const void *)buf->ptr;
320
321 memset(&expected, 0, sizeof(expected));
322 expected.magic = TPM_MAGIC;
323 expected.type = TPM_ST_CERTIFY;
324 expected.signer = actual->signer;
325 expected.signer.size = sizeof(expected.signer.alg) +
326 sizeof(expected.signer.body);
327 expected.data = signed_data;
328 expected.clock = actual->clock;
329 expected.clock.safe = 1;
330 expected.fwversion = actual->fwversion;
331 expected.name = signed_name;
332 expected.qual_name = actual->qual_name;
333 bswap_sha1_certinfo(&expected);
334
335 ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
336 fail:
337 explicit_bzero(&expected, sizeof(expected));
338 explicit_bzero(&signed_data, sizeof(signed_data));
339 explicit_bzero(&signed_name, sizeof(signed_name));
340
341 return ok != 0 ? -1 : 0;
342 }
343
344 int
fido_get_signed_hash_tpm(fido_blob_t * dgst,const fido_blob_t * clientdata_hash,const fido_blob_t * authdata_raw,const fido_attstmt_t * attstmt,const fido_attcred_t * attcred)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 {
349 const fido_blob_t *pubarea = &attstmt->pubarea;
350 const fido_blob_t *certinfo = &attstmt->certinfo;
351
352 if (attstmt->alg != COSE_RS1) {
353 fido_log_debug("%s: unsupported alg %d", __func__,
354 attstmt->alg);
355 return -1;
356 }
357
358 switch (attcred->type) {
359 case COSE_ES256:
360 if (check_es256_pubarea(pubarea, &attcred->pubkey.es256) < 0) {
361 fido_log_debug("%s: check_es256_pubarea", __func__);
362 return -1;
363 }
364 break;
365 case COSE_RS256:
366 if (check_rs256_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
367 fido_log_debug("%s: check_rs256_pubarea", __func__);
368 return -1;
369 }
370 break;
371 default:
372 fido_log_debug("%s: unsupported type %d", __func__,
373 attcred->type);
374 return -1;
375 }
376
377 if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
378 pubarea) < 0) {
379 fido_log_debug("%s: check_sha1_certinfo", __func__);
380 return -1;
381 }
382
383 if (dgst->len < SHA_DIGEST_LENGTH ||
384 SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
385 fido_log_debug("%s: sha1", __func__);
386 return -1;
387 }
388 dgst->len = SHA_DIGEST_LENGTH;
389
390 return 0;
391 }
392