1f540a430SEd Maste /*
2f540a430SEd Maste * Copyright (c) 2021 Yubico AB. All rights reserved.
3f540a430SEd Maste * Use of this source code is governed by a BSD-style
4f540a430SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
6f540a430SEd Maste */
7f540a430SEd Maste
8f540a430SEd Maste /*
9f540a430SEd Maste * Trusted Platform Module (TPM) 2.0 attestation support. Documentation
10f540a430SEd Maste * references are relative to revision 01.38 of the TPM 2.0 specification.
11f540a430SEd Maste */
12f540a430SEd Maste
13f540a430SEd Maste #include <openssl/sha.h>
14f540a430SEd Maste
15f540a430SEd Maste #include "packed.h"
16f540a430SEd Maste #include "fido.h"
17f540a430SEd Maste
18f540a430SEd Maste /* Part 1, 4.89: TPM_GENERATED_VALUE */
19f540a430SEd Maste #define TPM_MAGIC 0xff544347
20f540a430SEd Maste
21f540a430SEd Maste /* Part 2, 6.3: TPM_ALG_ID */
22f540a430SEd Maste #define TPM_ALG_RSA 0x0001
23f540a430SEd Maste #define TPM_ALG_SHA256 0x000b
24f540a430SEd Maste #define TPM_ALG_NULL 0x0010
253e696dfbSEd Maste #define TPM_ALG_ECC 0x0023
263e696dfbSEd Maste
273e696dfbSEd Maste /* Part 2, 6.4: TPM_ECC_CURVE */
283e696dfbSEd Maste #define TPM_ECC_P256 0x0003
29f540a430SEd Maste
30f540a430SEd Maste /* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
31f540a430SEd Maste #define TPM_ST_CERTIFY 0x8017
32f540a430SEd Maste
33f540a430SEd Maste /* Part 2, 8.3: TPMA_OBJECT */
34f540a430SEd Maste #define TPMA_RESERVED 0xfff8f309 /* reserved bits; must be zero */
35f540a430SEd Maste #define TPMA_FIXED 0x00000002 /* object has fixed hierarchy */
36f540a430SEd Maste #define TPMA_CLEAR 0x00000004 /* object persists */
37f540a430SEd Maste #define TPMA_FIXED_P 0x00000010 /* object has fixed parent */
38f540a430SEd Maste #define TPMA_SENSITIVE 0x00000020 /* data originates within tpm */
393e696dfbSEd Maste #define TPMA_SIGN 0x00040000 /* object may sign */
40f540a430SEd Maste
41f540a430SEd Maste /* Part 2, 10.4.2: TPM2B_DIGEST */
PACKED_TYPE(tpm_sha256_digest_t,struct tpm_sha256_digest{ uint16_t size; uint8_t body[32]; })42f540a430SEd Maste PACKED_TYPE(tpm_sha256_digest_t,
43f540a430SEd Maste struct tpm_sha256_digest {
44f540a430SEd Maste uint16_t size; /* sizeof(body) */
45f540a430SEd Maste uint8_t body[32];
46f540a430SEd Maste })
47f540a430SEd Maste
48f540a430SEd Maste /* Part 2, 10.4.3: TPM2B_DATA */
49f540a430SEd Maste PACKED_TYPE(tpm_sha1_data_t,
50f540a430SEd Maste struct tpm_sha1_data {
51*2ccfa855SEd Maste uint16_t size; /* sizeof(body) */
52f540a430SEd Maste uint8_t body[20];
53f540a430SEd Maste })
54f540a430SEd Maste
55f540a430SEd Maste /* Part 2, 10.5.3: TPM2B_NAME */
56f540a430SEd Maste PACKED_TYPE(tpm_sha256_name_t,
57f540a430SEd Maste struct tpm_sha256_name {
58f540a430SEd Maste uint16_t size; /* sizeof(alg) + sizeof(body) */
59f540a430SEd Maste uint16_t alg; /* TPM_ALG_SHA256 */
60f540a430SEd Maste uint8_t body[32];
61f540a430SEd Maste })
62f540a430SEd Maste
63f540a430SEd Maste /* Part 2, 10.11.1: TPMS_CLOCK_INFO */
64f540a430SEd Maste PACKED_TYPE(tpm_clock_info_t,
65f540a430SEd Maste struct tpm_clock_info {
66f540a430SEd Maste uint64_t timestamp_ms;
67f540a430SEd Maste uint32_t reset_count; /* obfuscated by tpm */
68f540a430SEd Maste uint32_t restart_count; /* obfuscated by tpm */
69f540a430SEd Maste uint8_t safe; /* 1 if timestamp_ms is current */
70f540a430SEd Maste })
71f540a430SEd Maste
72f540a430SEd Maste /* Part 2, 10.12.8 TPMS_ATTEST */
73f540a430SEd Maste PACKED_TYPE(tpm_sha1_attest_t,
74f540a430SEd Maste struct tpm_sha1_attest {
75f540a430SEd Maste uint32_t magic; /* TPM_MAGIC */
76f540a430SEd Maste uint16_t type; /* TPM_ST_ATTEST_CERTIFY */
77f540a430SEd Maste tpm_sha256_name_t signer; /* full tpm path of signing key */
78f540a430SEd Maste tpm_sha1_data_t data; /* signed sha1 */
79f540a430SEd Maste tpm_clock_info_t clock;
80f540a430SEd Maste uint64_t fwversion; /* obfuscated by tpm */
813e696dfbSEd Maste tpm_sha256_name_t name; /* sha256 of tpm_rs256_pubarea_t */
82f540a430SEd Maste tpm_sha256_name_t qual_name; /* full tpm path of attested key */
83f540a430SEd Maste })
84f540a430SEd Maste
85f540a430SEd Maste /* Part 2, 11.2.4.5: TPM2B_PUBLIC_KEY_RSA */
863e696dfbSEd Maste PACKED_TYPE(tpm_rs256_key_t,
873e696dfbSEd Maste struct tpm_rs256_key {
88f540a430SEd Maste uint16_t size; /* sizeof(body) */
89f540a430SEd Maste uint8_t body[256];
90f540a430SEd Maste })
91f540a430SEd Maste
923e696dfbSEd Maste /* Part 2, 11.2.5.1: TPM2B_ECC_PARAMETER */
933e696dfbSEd Maste PACKED_TYPE(tpm_es256_coord_t,
943e696dfbSEd Maste struct tpm_es256_coord {
953e696dfbSEd Maste uint16_t size; /* sizeof(body) */
963e696dfbSEd Maste uint8_t body[32];
973e696dfbSEd Maste })
983e696dfbSEd Maste
993e696dfbSEd Maste /* Part 2, 11.2.5.2: TPMS_ECC_POINT */
1003e696dfbSEd Maste PACKED_TYPE(tpm_es256_point_t,
1013e696dfbSEd Maste struct tpm_es256_point {
1023e696dfbSEd Maste tpm_es256_coord_t x;
1033e696dfbSEd Maste tpm_es256_coord_t y;
1043e696dfbSEd Maste })
1053e696dfbSEd Maste
106f540a430SEd Maste /* Part 2, 12.2.3.5: TPMS_RSA_PARMS */
1073e696dfbSEd Maste PACKED_TYPE(tpm_rs256_param_t,
1083e696dfbSEd Maste struct tpm_rs256_param {
109f540a430SEd Maste uint16_t symmetric; /* TPM_ALG_NULL */
110f540a430SEd Maste uint16_t scheme; /* TPM_ALG_NULL */
111f540a430SEd Maste uint16_t keybits; /* 2048 */
112f540a430SEd Maste uint32_t exponent; /* zero (meaning 2^16 + 1) */
113f540a430SEd Maste })
114f540a430SEd Maste
1153e696dfbSEd Maste /* Part 2, 12.2.3.6: TPMS_ECC_PARMS */
1163e696dfbSEd Maste PACKED_TYPE(tpm_es256_param_t,
1173e696dfbSEd Maste struct tpm_es256_param {
1183e696dfbSEd Maste uint16_t symmetric; /* TPM_ALG_NULL */
1193e696dfbSEd Maste uint16_t scheme; /* TPM_ALG_NULL */
1203e696dfbSEd Maste uint16_t curve_id; /* TPM_ECC_P256 */
1213e696dfbSEd Maste uint16_t kdf; /* TPM_ALG_NULL */
1223e696dfbSEd Maste })
1233e696dfbSEd Maste
124f540a430SEd Maste /* Part 2, 12.2.4: TPMT_PUBLIC */
1253e696dfbSEd Maste PACKED_TYPE(tpm_rs256_pubarea_t,
1263e696dfbSEd Maste struct tpm_rs256_pubarea {
127f540a430SEd Maste uint16_t alg; /* TPM_ALG_RSA */
128f540a430SEd Maste uint16_t hash; /* TPM_ALG_SHA256 */
129f540a430SEd Maste uint32_t attr;
130f540a430SEd Maste tpm_sha256_digest_t policy; /* must be present? */
1313e696dfbSEd Maste tpm_rs256_param_t param;
1323e696dfbSEd Maste tpm_rs256_key_t key;
1333e696dfbSEd Maste })
1343e696dfbSEd Maste
1353e696dfbSEd Maste /* Part 2, 12.2.4: TPMT_PUBLIC */
1363e696dfbSEd Maste PACKED_TYPE(tpm_es256_pubarea_t,
1373e696dfbSEd Maste struct tpm_es256_pubarea {
1383e696dfbSEd Maste uint16_t alg; /* TPM_ALG_ECC */
1393e696dfbSEd Maste uint16_t hash; /* TPM_ALG_SHA256 */
1403e696dfbSEd Maste uint32_t attr;
1413e696dfbSEd Maste tpm_sha256_digest_t policy; /* must be present? */
1423e696dfbSEd Maste tpm_es256_param_t param;
1433e696dfbSEd Maste tpm_es256_point_t point;
144f540a430SEd Maste })
145f540a430SEd Maste
146f540a430SEd Maste static int
147f540a430SEd Maste get_signed_sha1(tpm_sha1_data_t *dgst, const fido_blob_t *authdata,
148f540a430SEd Maste const fido_blob_t *clientdata)
149f540a430SEd Maste {
150f540a430SEd Maste const EVP_MD *md = NULL;
151f540a430SEd Maste EVP_MD_CTX *ctx = NULL;
152f540a430SEd Maste int ok = -1;
153f540a430SEd Maste
154f540a430SEd Maste if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
155f540a430SEd Maste (md = EVP_sha1()) == NULL ||
156f540a430SEd Maste (ctx = EVP_MD_CTX_new()) == NULL ||
157f540a430SEd Maste EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
158f540a430SEd Maste EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
159f540a430SEd Maste EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
160f540a430SEd Maste EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
161f540a430SEd Maste fido_log_debug("%s: sha1", __func__);
162f540a430SEd Maste goto fail;
163f540a430SEd Maste }
164f540a430SEd Maste
165f540a430SEd Maste ok = 0;
166f540a430SEd Maste fail:
167f540a430SEd Maste EVP_MD_CTX_free(ctx);
168f540a430SEd Maste
169f540a430SEd Maste return (ok);
170f540a430SEd Maste }
171f540a430SEd Maste
172f540a430SEd Maste static int
get_signed_name(tpm_sha256_name_t * name,const fido_blob_t * pubarea)173f540a430SEd Maste get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
174f540a430SEd Maste {
175f540a430SEd Maste name->alg = TPM_ALG_SHA256;
176f540a430SEd Maste name->size = sizeof(name->alg) + sizeof(name->body);
177f540a430SEd Maste if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
178f540a430SEd Maste SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
179f540a430SEd Maste fido_log_debug("%s: sha256", __func__);
180f540a430SEd Maste return -1;
181f540a430SEd Maste }
182f540a430SEd Maste
183f540a430SEd Maste return 0;
184f540a430SEd Maste }
185f540a430SEd Maste
186f540a430SEd Maste static void
bswap_rs256_pubarea(tpm_rs256_pubarea_t * x)1873e696dfbSEd Maste bswap_rs256_pubarea(tpm_rs256_pubarea_t *x)
188f540a430SEd Maste {
189f540a430SEd Maste x->alg = htobe16(x->alg);
190f540a430SEd Maste x->hash = htobe16(x->hash);
191f540a430SEd Maste x->attr = htobe32(x->attr);
192f540a430SEd Maste x->policy.size = htobe16(x->policy.size);
193f540a430SEd Maste x->param.symmetric = htobe16(x->param.symmetric);
194f540a430SEd Maste x->param.scheme = htobe16(x->param.scheme);
195f540a430SEd Maste x->param.keybits = htobe16(x->param.keybits);
196f540a430SEd Maste x->key.size = htobe16(x->key.size);
197f540a430SEd Maste }
198f540a430SEd Maste
199f540a430SEd Maste static void
bswap_es256_pubarea(tpm_es256_pubarea_t * x)2003e696dfbSEd Maste bswap_es256_pubarea(tpm_es256_pubarea_t *x)
2013e696dfbSEd Maste {
2023e696dfbSEd Maste x->alg = htobe16(x->alg);
2033e696dfbSEd Maste x->hash = htobe16(x->hash);
2043e696dfbSEd Maste x->attr = htobe32(x->attr);
2053e696dfbSEd Maste x->policy.size = htobe16(x->policy.size);
2063e696dfbSEd Maste x->param.symmetric = htobe16(x->param.symmetric);
2073e696dfbSEd Maste x->param.scheme = htobe16(x->param.scheme);
2083e696dfbSEd Maste x->param.curve_id = htobe16(x->param.curve_id);
2093e696dfbSEd Maste x->param.kdf = htobe16(x->param.kdf);
2103e696dfbSEd Maste x->point.x.size = htobe16(x->point.x.size);
2113e696dfbSEd Maste x->point.y.size = htobe16(x->point.y.size);
2123e696dfbSEd Maste }
2133e696dfbSEd Maste
2143e696dfbSEd Maste static void
bswap_sha1_certinfo(tpm_sha1_attest_t * x)215f540a430SEd Maste bswap_sha1_certinfo(tpm_sha1_attest_t *x)
216f540a430SEd Maste {
217f540a430SEd Maste x->magic = htobe32(x->magic);
218f540a430SEd Maste x->type = htobe16(x->type);
219f540a430SEd Maste x->signer.size = htobe16(x->signer.size);
220f540a430SEd Maste x->data.size = htobe16(x->data.size);
221f540a430SEd Maste x->name.alg = htobe16(x->name.alg);
222f540a430SEd Maste x->name.size = htobe16(x->name.size);
223f540a430SEd Maste }
224f540a430SEd Maste
225f540a430SEd Maste static int
check_rs256_pubarea(const fido_blob_t * buf,const rs256_pk_t * pk)2263e696dfbSEd Maste check_rs256_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
227f540a430SEd Maste {
2283e696dfbSEd Maste const tpm_rs256_pubarea_t *actual;
2293e696dfbSEd Maste tpm_rs256_pubarea_t expected;
230f540a430SEd Maste int ok;
231f540a430SEd Maste
232f540a430SEd Maste if (buf->len != sizeof(*actual)) {
233f540a430SEd Maste fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
234f540a430SEd Maste return -1;
235f540a430SEd Maste }
236f540a430SEd Maste actual = (const void *)buf->ptr;
237f540a430SEd Maste
238f540a430SEd Maste memset(&expected, 0, sizeof(expected));
239f540a430SEd Maste expected.alg = TPM_ALG_RSA;
240f540a430SEd Maste expected.hash = TPM_ALG_SHA256;
241f540a430SEd Maste expected.attr = be32toh(actual->attr);
242f540a430SEd Maste expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
243f540a430SEd Maste expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
244f540a430SEd Maste expected.policy = actual->policy;
245f540a430SEd Maste expected.policy.size = sizeof(expected.policy.body);
246f540a430SEd Maste expected.param.symmetric = TPM_ALG_NULL;
247f540a430SEd Maste expected.param.scheme = TPM_ALG_NULL;
248f540a430SEd Maste expected.param.keybits = 2048;
249f540a430SEd Maste expected.param.exponent = 0; /* meaning 2^16+1 */
250f540a430SEd Maste expected.key.size = sizeof(expected.key.body);
251f540a430SEd Maste memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
2523e696dfbSEd Maste bswap_rs256_pubarea(&expected);
2533e696dfbSEd Maste
2543e696dfbSEd Maste ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
2553e696dfbSEd Maste explicit_bzero(&expected, sizeof(expected));
2563e696dfbSEd Maste
2573e696dfbSEd Maste return ok != 0 ? -1 : 0;
2583e696dfbSEd Maste }
2593e696dfbSEd Maste
2603e696dfbSEd Maste static int
check_es256_pubarea(const fido_blob_t * buf,const es256_pk_t * pk)2613e696dfbSEd Maste check_es256_pubarea(const fido_blob_t *buf, const es256_pk_t *pk)
2623e696dfbSEd Maste {
2633e696dfbSEd Maste const tpm_es256_pubarea_t *actual;
2643e696dfbSEd Maste tpm_es256_pubarea_t expected;
2653e696dfbSEd Maste int ok;
2663e696dfbSEd Maste
2673e696dfbSEd Maste if (buf->len != sizeof(*actual)) {
2683e696dfbSEd Maste fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
2693e696dfbSEd Maste return -1;
2703e696dfbSEd Maste }
2713e696dfbSEd Maste actual = (const void *)buf->ptr;
2723e696dfbSEd Maste
2733e696dfbSEd Maste memset(&expected, 0, sizeof(expected));
2743e696dfbSEd Maste expected.alg = TPM_ALG_ECC;
2753e696dfbSEd Maste expected.hash = TPM_ALG_SHA256;
2763e696dfbSEd Maste expected.attr = be32toh(actual->attr);
2773e696dfbSEd Maste expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
2783e696dfbSEd Maste expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
2793e696dfbSEd Maste expected.policy = actual->policy;
2803e696dfbSEd Maste expected.policy.size = sizeof(expected.policy.body);
2813e696dfbSEd Maste expected.param.symmetric = TPM_ALG_NULL;
2823e696dfbSEd Maste expected.param.scheme = TPM_ALG_NULL; /* TCG Alg. Registry, 5.2.4 */
2833e696dfbSEd Maste expected.param.curve_id = TPM_ECC_P256;
2843e696dfbSEd Maste expected.param.kdf = TPM_ALG_NULL;
2853e696dfbSEd Maste expected.point.x.size = sizeof(expected.point.x.body);
2863e696dfbSEd Maste expected.point.y.size = sizeof(expected.point.y.body);
2873e696dfbSEd Maste memcpy(&expected.point.x.body, &pk->x, sizeof(expected.point.x.body));
2883e696dfbSEd Maste memcpy(&expected.point.y.body, &pk->y, sizeof(expected.point.y.body));
2893e696dfbSEd Maste bswap_es256_pubarea(&expected);
290f540a430SEd Maste
291f540a430SEd Maste ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
292f540a430SEd Maste explicit_bzero(&expected, sizeof(expected));
293f540a430SEd Maste
294f540a430SEd Maste return ok != 0 ? -1 : 0;
295f540a430SEd Maste }
296f540a430SEd Maste
297f540a430SEd Maste 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)298f540a430SEd Maste check_sha1_certinfo(const fido_blob_t *buf, const fido_blob_t *clientdata_hash,
299f540a430SEd Maste const fido_blob_t *authdata_raw, const fido_blob_t *pubarea)
300f540a430SEd Maste {
301f540a430SEd Maste const tpm_sha1_attest_t *actual;
302f540a430SEd Maste tpm_sha1_attest_t expected;
303f540a430SEd Maste tpm_sha1_data_t signed_data;
304f540a430SEd Maste tpm_sha256_name_t signed_name;
305f540a430SEd Maste int ok = -1;
306f540a430SEd Maste
307f540a430SEd Maste memset(&signed_data, 0, sizeof(signed_data));
308f540a430SEd Maste memset(&signed_name, 0, sizeof(signed_name));
309f540a430SEd Maste
310f540a430SEd Maste if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
311f540a430SEd Maste get_signed_name(&signed_name, pubarea) < 0) {
312f540a430SEd Maste fido_log_debug("%s: get_signed_sha1/name", __func__);
313f540a430SEd Maste goto fail;
314f540a430SEd Maste }
315f540a430SEd Maste if (buf->len != sizeof(*actual)) {
316f540a430SEd Maste fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
317f540a430SEd Maste goto fail;
318f540a430SEd Maste }
319f540a430SEd Maste actual = (const void *)buf->ptr;
320f540a430SEd Maste
321f540a430SEd Maste memset(&expected, 0, sizeof(expected));
322f540a430SEd Maste expected.magic = TPM_MAGIC;
323f540a430SEd Maste expected.type = TPM_ST_CERTIFY;
324f540a430SEd Maste expected.signer = actual->signer;
325f540a430SEd Maste expected.signer.size = sizeof(expected.signer.alg) +
326f540a430SEd Maste sizeof(expected.signer.body);
327f540a430SEd Maste expected.data = signed_data;
328f540a430SEd Maste expected.clock = actual->clock;
329f540a430SEd Maste expected.clock.safe = 1;
330f540a430SEd Maste expected.fwversion = actual->fwversion;
331f540a430SEd Maste expected.name = signed_name;
332f540a430SEd Maste expected.qual_name = actual->qual_name;
333f540a430SEd Maste bswap_sha1_certinfo(&expected);
334f540a430SEd Maste
335f540a430SEd Maste ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
336f540a430SEd Maste fail:
337f540a430SEd Maste explicit_bzero(&expected, sizeof(expected));
338f540a430SEd Maste explicit_bzero(&signed_data, sizeof(signed_data));
339f540a430SEd Maste explicit_bzero(&signed_name, sizeof(signed_name));
340f540a430SEd Maste
341f540a430SEd Maste return ok != 0 ? -1 : 0;
342f540a430SEd Maste }
343f540a430SEd Maste
344f540a430SEd Maste 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)345f540a430SEd Maste fido_get_signed_hash_tpm(fido_blob_t *dgst, const fido_blob_t *clientdata_hash,
346f540a430SEd Maste const fido_blob_t *authdata_raw, const fido_attstmt_t *attstmt,
347f540a430SEd Maste const fido_attcred_t *attcred)
348f540a430SEd Maste {
349f540a430SEd Maste const fido_blob_t *pubarea = &attstmt->pubarea;
350f540a430SEd Maste const fido_blob_t *certinfo = &attstmt->certinfo;
351f540a430SEd Maste
3523e696dfbSEd Maste if (attstmt->alg != COSE_RS1) {
3533e696dfbSEd Maste fido_log_debug("%s: unsupported alg %d", __func__,
3543e696dfbSEd Maste attstmt->alg);
355f540a430SEd Maste return -1;
356f540a430SEd Maste }
357f540a430SEd Maste
3583e696dfbSEd Maste switch (attcred->type) {
3593e696dfbSEd Maste case COSE_ES256:
3603e696dfbSEd Maste if (check_es256_pubarea(pubarea, &attcred->pubkey.es256) < 0) {
3613e696dfbSEd Maste fido_log_debug("%s: check_es256_pubarea", __func__);
3623e696dfbSEd Maste return -1;
3633e696dfbSEd Maste }
3643e696dfbSEd Maste break;
3653e696dfbSEd Maste case COSE_RS256:
3663e696dfbSEd Maste if (check_rs256_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
3673e696dfbSEd Maste fido_log_debug("%s: check_rs256_pubarea", __func__);
3683e696dfbSEd Maste return -1;
3693e696dfbSEd Maste }
3703e696dfbSEd Maste break;
3713e696dfbSEd Maste default:
3723e696dfbSEd Maste fido_log_debug("%s: unsupported type %d", __func__,
3733e696dfbSEd Maste attcred->type);
374f540a430SEd Maste return -1;
375f540a430SEd Maste }
376f540a430SEd Maste
377f540a430SEd Maste if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
378f540a430SEd Maste pubarea) < 0) {
379f540a430SEd Maste fido_log_debug("%s: check_sha1_certinfo", __func__);
380f540a430SEd Maste return -1;
381f540a430SEd Maste }
382f540a430SEd Maste
383f540a430SEd Maste if (dgst->len < SHA_DIGEST_LENGTH ||
384f540a430SEd Maste SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
385f540a430SEd Maste fido_log_debug("%s: sha1", __func__);
386f540a430SEd Maste return -1;
387f540a430SEd Maste }
388f540a430SEd Maste dgst->len = SHA_DIGEST_LENGTH;
389f540a430SEd Maste
390f540a430SEd Maste return 0;
391f540a430SEd Maste }
392