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