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