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