Home | History | Annotate | Line # | Download | only in src
      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 */
     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
    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
    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
    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
    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
    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
    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
    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
    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