## Coverage Report

#### Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /libfido2/src/tpm.c

    Line
    Count
    Source
    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
    728
    #define TPM_MAGIC       0xff544347
    20
    21
    /* Part 2, 6.3: TPM_ALG_ID */
    22
    15
    #define TPM_ALG_RSA     0x0001
    23
    1.50k
    #define TPM_ALG_SHA256  0x000b
    24
    2.28k
    #define TPM_ALG_NULL    0x0010
    25
    751
    #define TPM_ALG_ECC     0x0023
    26
    27
    /* Part 2, 6.4: TPM_ECC_CURVE */
    28
    751
    #define TPM_ECC_P256    0x0003
    29
    30
    /* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
    31
    728
    #define TPM_ST_CERTIFY  0x8017
    32
    33
    /* Part 2, 8.3: TPMA_OBJECT */
    34
    766
    #define TPMA_RESERVED   0xfff8f309        /* reserved bits; must be zero */
    35
    766
    #define TPMA_FIXED      0x00000002        /* object has fixed hierarchy */
    36
    766
    #define TPMA_CLEAR      0x00000004        /* object persists */
    37
    766
    #define TPMA_FIXED_P    0x00000010        /* object has fixed parent */
    38
    766
    #define TPMA_SENSITIVE  0x00000020        /* data originates within tpm */
    39
    766
    #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
    758
    {
    150
    758
            const EVP_MD    *md = NULL;
    151
    758
            EVP_MD_CTX      *ctx = NULL;
    152
    758
            int              ok = -1;
    153
    154
    758
            if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
    155
    758
                (md = EVP_sha1()) == NULL ||
    156
    758
                (ctx = EVP_MD_CTX_new()) == NULL ||
    157
    758
                EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
    158
    758
                EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
    159
    758
                EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
    160
    758
                EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
    161
    18
                    fido_log_debug("%s: sha1", __func__);
    162
    18
                    goto fail;
    163
    18
            }
    164
    165
    740
            ok = 0;
    166
    758
    fail:
    167
    758
            EVP_MD_CTX_free(ctx);
    168
    169
    758
            return (ok);
    170
    740
    }
    171
    172
    static int
    173
    get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
    174
    740
    {
    175
    740
            name->alg = TPM_ALG_SHA256;
    176
    740
            name->size = sizeof(name->alg) + sizeof(name->body);
    177
    740
            if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
    178
    740
                SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
    179
    5
                    fido_log_debug("%s: sha256", __func__);
    180
    5
                    return -1;
    181
    5
            }
    182
    183
    735
            return 0;
    184
    740
    }
    185
    186
    static void
    187
    bswap_rs256_pubarea(tpm_rs256_pubarea_t *x)
    188
    15
    {
    189
    15
            x->alg = htobe16(x->alg);
    190
    15
            x->hash = htobe16(x->hash);
    191
    15
            x->attr = htobe32(x->attr);
    192
    15
            x->policy.size = htobe16(x->policy.size);
    193
    15
            x->param.symmetric = htobe16(x->param.symmetric);
    194
    15
            x->param.scheme = htobe16(x->param.scheme);
    195
    15
            x->param.keybits = htobe16(x->param.keybits);
    196
    15
            x->key.size = htobe16(x->key.size);
    197
    15
    }
    198
    199
    static void
    200
    bswap_es256_pubarea(tpm_es256_pubarea_t *x)
    201
    751
    {
    202
    751
            x->alg = htobe16(x->alg);
    203
    751
            x->hash = htobe16(x->hash);
    204
    751
            x->attr = htobe32(x->attr);
    205
    751
            x->policy.size = htobe16(x->policy.size);
    206
    751
            x->param.symmetric = htobe16(x->param.symmetric);
    207
    751
            x->param.scheme = htobe16(x->param.scheme);
    208
    751
            x->param.curve_id = htobe16(x->param.curve_id);
    209
    751
            x->param.kdf = htobe16(x->param.kdf);
    210
    751
            x->point.x.size = htobe16(x->point.x.size);
    211
    751
            x->point.y.size = htobe16(x->point.y.size);
    212
    751
    }
    213
    214
    static void
    215
    bswap_sha1_certinfo(tpm_sha1_attest_t *x)
    216
    728
    {
    217
    728
            x->magic = htobe32(x->magic);
    218
    728
            x->type = htobe16(x->type);
    219
    728
            x->signer.size = htobe16(x->signer.size);
    220
    728
            x->data.size = htobe16(x->data.size);
    221
    728
            x->name.alg = htobe16(x->name.alg);
    222
    728
            x->name.size = htobe16(x->name.size);
    223
    728
    }
    224
    225
    static int
    226
    check_rs256_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
    227
    19
    {
    228
    19
            const tpm_rs256_pubarea_t       *actual;
    229
    19
            tpm_rs256_pubarea_t              expected;
    230
    19
            int                              ok;
    231
    232
    19
            if (buf->len != sizeof(*actual)) {
    233
    4
                    fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
    234
    4
                    return -1;
    235
    4
            }
    236
    15
            actual = (const void *)buf->ptr;
    237
    238
    15
            memset(&expected, 0, sizeof(expected));
    239
    15
            expected.alg = TPM_ALG_RSA;
    240
    15
            expected.hash = TPM_ALG_SHA256;
    241
    15
            expected.attr = be32toh(actual->attr);
    242
    15
            expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
    243
    15
            expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
    244
    15
            expected.policy = actual->policy;
    245
    15
            expected.policy.size = sizeof(expected.policy.body);
    246
    15
            expected.param.symmetric = TPM_ALG_NULL;
    247
    15
            expected.param.scheme = TPM_ALG_NULL;
    248
    15
            expected.param.keybits = 2048;
    249
    15
            expected.param.exponent = 0; /* meaning 2^16+1 */
    250
    15
            expected.key.size = sizeof(expected.key.body);
    251
    15
            memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
    252
    15
            bswap_rs256_pubarea(&expected);
    253
    254
    15
            ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
    255
    15
            explicit_bzero(&expected, sizeof(expected));
    256
    257
    15
            return ok != 0 ? -1 : 0;
    258
    19
    }
    259
    260
    static int
    261
    check_es256_pubarea(const fido_blob_t *buf, const es256_pk_t *pk)
    262
    756
    {
    263
    756
            const tpm_es256_pubarea_t       *actual;
    264
    756
            tpm_es256_pubarea_t              expected;
    265
    756
            int                              ok;
    266
    267
    756
            if (buf->len != sizeof(*actual)) {
    268
    5
                    fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
    269
    5
                    return -1;
    270
    5
            }
    271
    751
            actual = (const void *)buf->ptr;
    272
    273
    751
            memset(&expected, 0, sizeof(expected));
    274
    751
            expected.alg = TPM_ALG_ECC;
    275
    751
            expected.hash = TPM_ALG_SHA256;
    276
    751
            expected.attr = be32toh(actual->attr);
    277
    751
            expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
    278
    751
            expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
    279
    751
            expected.policy = actual->policy;
    280
    751
            expected.policy.size = sizeof(expected.policy.body);
    281
    751
            expected.param.symmetric = TPM_ALG_NULL;
    282
    751
            expected.param.scheme = TPM_ALG_NULL; /* TCG Alg. Registry, 5.2.4 */
    283
    751
            expected.param.curve_id = TPM_ECC_P256;
    284
    751
            expected.param.kdf = TPM_ALG_NULL;
    285
    751
            expected.point.x.size = sizeof(expected.point.x.body);
    286
    751
            expected.point.y.size = sizeof(expected.point.y.body);
    287
    751
            memcpy(&expected.point.x.body, &pk->x, sizeof(expected.point.x.body));
    288
    751
            memcpy(&expected.point.y.body, &pk->y, sizeof(expected.point.y.body));
    289
    751
            bswap_es256_pubarea(&expected);
    290
    291
    751
            ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
    292
    751
            explicit_bzero(&expected, sizeof(expected));
    293
    294
    751
            return ok != 0 ? -1 : 0;
    295
    756
    }
    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
    758
    {
    301
    758
            const tpm_sha1_attest_t *actual;
    302
    758
            tpm_sha1_attest_t        expected;
    303
    758
            tpm_sha1_data_t          signed_data;
    304
    758
            tpm_sha256_name_t        signed_name;
    305
    758
            int                      ok = -1;
    306
    307
    758
            memset(&signed_data, 0, sizeof(signed_data));
    308
    758
            memset(&signed_name, 0, sizeof(signed_name));
    309
    310
    758
            if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
    311
    758
                get_signed_name(&signed_name, pubarea) < 0) {
    312
    23
                    fido_log_debug("%s: get_signed_sha1/name", __func__);
    313
    23
                    goto fail;
    314
    23
            }
    315
    735
            if (buf->len != sizeof(*actual)) {
    316
    7
                    fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
    317
    7
                    goto fail;
    318
    7
            }
    319
    728
            actual = (const void *)buf->ptr;
    320
    321
    728
            memset(&expected, 0, sizeof(expected));
    322
    728
            expected.magic = TPM_MAGIC;
    323
    728
            expected.type = TPM_ST_CERTIFY;
    324
    728
            expected.signer = actual->signer;
    325
    728
            expected.signer.size = sizeof(expected.signer.alg) +
    326
    728
                sizeof(expected.signer.body);
    327
    728
            expected.data = signed_data;
    328
    728
            expected.clock = actual->clock;
    329
    728
            expected.clock.safe = 1;
    330
    728
            expected.fwversion = actual->fwversion;
    331
    728
            expected.name = signed_name;
    332
    728
            expected.qual_name = actual->qual_name;
    333
    728
            bswap_sha1_certinfo(&expected);
    334
    335
    728
            ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
    336
    758
    fail:
    337
    758
            explicit_bzero(&expected, sizeof(expected));
    338
    758
            explicit_bzero(&signed_data, sizeof(signed_data));
    339
    758
            explicit_bzero(&signed_name, sizeof(signed_name));
    340
    341
    758
            return ok != 0 ? -1 : 0;
    342
    728
    }
    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
    786
    {
    349
    786
            const fido_blob_t *pubarea = &attstmt->pubarea;
    350
    786
            const fido_blob_t *certinfo = &attstmt->certinfo;
    351
    352
    786
            if (attstmt->alg != COSE_RS1) {
    353
    7
                    fido_log_debug("%s: unsupported alg %d", __func__,
    354
    7
                        attstmt->alg);
    355
    7
                    return -1;
    356
    7
            }
    357
    358
    779
            switch (attcred->type) {
    359
    756
            case COSE_ES256:
    360
    756
                    if (check_es256_pubarea(pubarea, &attcred->pubkey.es256) < 0) {
    361
    9
                            fido_log_debug("%s: check_es256_pubarea", __func__);
    362
    9
                            return -1;
    363
    9
                    }
    364
    747
                    break;
    365
    747
            case COSE_RS256:
    366
    19
                    if (check_rs256_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
    367
    8
                            fido_log_debug("%s: check_rs256_pubarea", __func__);
    368
    8
                            return -1;
    369
    8
                    }
    370
    11
                    break;
    371
    11
            default:
    372
    4
                    fido_log_debug("%s: unsupported type %d", __func__,
    373
    4
                        attcred->type);
    374
    4
                    return -1;
    375
    779
            }
    376
    377
    758
            if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
    378
    758
                pubarea) < 0) {
    379
    48
                    fido_log_debug("%s: check_sha1_certinfo", __func__);
    380
    48
                    return -1;
    381
    48
            }
    382
    383
    710
            if (dgst->len < SHA_DIGEST_LENGTH ||
    384
    710
                SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
    385
    4
                    fido_log_debug("%s: sha1", __func__);
    386
    4
                    return -1;
    387
    4
            }
    388
    706
            dgst->len = SHA_DIGEST_LENGTH;
    389
    390
    706
            return 0;
    391
    710
    }