• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2077

21 Feb 2026 11:55PM UTC coverage: 77.208% (+0.004%) from 77.204%
#2077

push

travis-ci

web-flow
Merge f5287d5f3 into 5a6cc8bda

10 of 12 new or added lines in 3 files covered. (83.33%)

192 existing lines in 5 files now uncovered.

36379 of 47118 relevant lines covered (77.21%)

125365.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.46
/src/tpm2/RuntimeAlgorithm.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
// (c) Copyright IBM Corporation, 2022
4

5
#define _GNU_SOURCE
6
#include <assert.h>
7
#include <string.h>
8

9
#include "Tpm.h"
10
#include "NVMarshal.h"
11
#include "tpm_public/GpMacros.h"
12
#include "tpm_library_intern.h"
13

14
#define ALGO_SEPARATOR_C ','
15
#define ALGO_SEPARATOR_STR ","
16

17
struct KeySizes {
18
    BOOL enabled;
19
    UINT16 size;
20
    unsigned int stateFormatLevel; /* required stateFormatLevel to support this */
21
};
22

23
struct MinKeySize {
24
    unsigned int stateFormatLevel; /* required stateFormatLevel to support this */
25
};
26

27
static const struct KeySizes s_KeySizesAES[] = {
28
    { .enabled = AES_128, .size = 128, .stateFormatLevel = 1 },
29
    { .enabled = AES_192, .size = 192, .stateFormatLevel = 4 },
30
    { .enabled = AES_256, .size = 256, .stateFormatLevel = 1 },
31
    { .enabled = false  , .size = 0  , .stateFormatLevel = 0 },
32
};
33
static const struct KeySizes s_KeySizesSM4[] = {
34
    { .enabled = SM4_128, .size = 128, .stateFormatLevel = 0 }, // not supported
35
    { .enabled = false  , .size = 0  , .stateFormatLevel = 0 },
36
};
37
static const struct KeySizes s_KeySizesCamellia[] = {
38
    { .enabled = CAMELLIA_128, .size = 128, .stateFormatLevel = 1 },
39
    { .enabled = CAMELLIA_192, .size = 192, .stateFormatLevel = 4 },
40
    { .enabled = CAMELLIA_256, .size = 256, .stateFormatLevel = 1 },
41
    { .enabled = false       , .size = 0  , .stateFormatLevel = 0 },
42
};
43
static const struct KeySizes s_KeySizesTDES[] = {
44
    { .enabled = TDES_128, .size = 128, .stateFormatLevel = 1 },
45
    { .enabled = TDES_192, .size = 192, .stateFormatLevel = 1 },
46
    { .enabled = false   , .size = 0  , .stateFormatLevel = 0 },
47
};
48
static const struct KeySizes s_KeySizesRSA[] = {
49
    { .enabled = RSA_1024, .size = 1024, .stateFormatLevel = 1 },
50
    { .enabled = RSA_2048, .size = 2048, .stateFormatLevel = 1 },
51
    { .enabled = RSA_3072, .size = 3072, .stateFormatLevel = 1 },
52
    { .enabled = RSA_4096, .size = 4096, .stateFormatLevel = 8 },
53
    { .enabled = false   , .size = 0   , .stateFormatLevel = 0 },
54
};
55
static const struct KeySizes s_KeySizesECC[] = {
56
    { .enabled = ECC_NIST_P192, .size = 192, .stateFormatLevel = 1 },
57
    { .enabled = ECC_NIST_P224, .size = 224, .stateFormatLevel = 1 },
58
    { .enabled = ECC_NIST_P256, .size = 256, .stateFormatLevel = 1 },
59
    { .enabled = ECC_BN_P256  , .size = 256, .stateFormatLevel = 1 },
60
    { .enabled = ECC_SM2_P256 , .size = 256, .stateFormatLevel = 1 },
61
    { .enabled = ECC_NIST_P384, .size = 384, .stateFormatLevel = 1 },
62
    { .enabled = ECC_NIST_P521, .size = 521, .stateFormatLevel = 1 },
63
    { .enabled = ECC_BN_P638  , .size = 638, .stateFormatLevel = 1 },
64
    { .enabled = false        , .size = 0  , .stateFormatLevel = 0 },
65
};
66
static const struct MinKeySize s_MinKeySizeHMAC[] = {
67
    { .stateFormatLevel = 7 },
68
};
69

70
static const struct {
71
    const char   *name;
72
    struct {
73
        const struct KeySizes *keySizes;
74
        const struct MinKeySize *minKeySize;
75
    } u;
76
    BOOL          canBeDisabled;
77
    unsigned int  stateFormatLevel; /* required stateFormatLevel to support this */
78
} s_AlgorithmProperties[NUM_ENTRIES_ALGORITHM_PROPERTIES] = {
79
#define SYMMETRIC(ENABLED, NAME, KEYSIZES, CANDISABLE, SFL) \
80
    { .name = ENABLED ? NAME : NULL, .u.keySizes = KEYSIZES, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
81
#define ASYMMETRIC(ENABLED, NAME, KEYSIZES, CANDISABLE, SFL) \
82
    { .name = ENABLED ? NAME : NULL, .u.keySizes = KEYSIZES, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
83
#define HASH(ENABLED, NAME, CANDISABLE, SFL) \
84
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
85
#define HMAC(ENABLED, NAME, MINKEYSIZE, CANDISABLE, SFL) \
86
    { .name = ENABLED ? NAME : NULL, .u.minKeySize = MINKEYSIZE, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
87
#define SIGNING(ENABLED, NAME, CANDISABLE, SFL) \
88
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
89
#define ENCRYPTING(ENABLED, NAME, CANDISABLE, SFL) \
90
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
91
#define OTHER(ENABLED, NAME, CANDISABLE, SFL) \
92
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
93

94
    [TPM_ALG_RSA] = ASYMMETRIC(ALG_RSA, "rsa", s_KeySizesRSA, false, 1),
95
    [TPM_ALG_TDES] = SYMMETRIC(ALG_TDES, "tdes", s_KeySizesTDES, true, 1),
96
    [TPM_ALG_SHA1] = HASH(ALG_SHA1, "sha1", true, 1),
97
    [TPM_ALG_HMAC] = HMAC(ALG_HMAC, "hmac", s_MinKeySizeHMAC, false, 1),
98
    [TPM_ALG_AES] = SYMMETRIC(ALG_AES, "aes", s_KeySizesAES, false, 1), // never disable: context encryption
99
    [TPM_ALG_MGF1] = HASH(ALG_MGF1, "mgf1", false, 1),
100
    [TPM_ALG_KEYEDHASH] = HASH(ALG_KEYEDHASH, "keyedhash", false, 1),
101
    [TPM_ALG_XOR] = OTHER(ALG_XOR, "xor", false, 1),
102
    [TPM_ALG_SHA256] = HASH(ALG_SHA256, "sha256", false, 1),
103
    [TPM_ALG_SHA384] = HASH(ALG_SHA384, "sha384", false, 1),
104
    [TPM_ALG_SHA512] = HASH(ALG_SHA512, "sha512", true, 1),
105
    [TPM_ALG_NULL] = OTHER(true, "null", false, 1),
106
    [TPM_ALG_SM4] = SYMMETRIC(ALG_SM4, "sm4", s_KeySizesSM4, true, 0), // not supported
107
    [TPM_ALG_RSASSA] = SIGNING(ALG_RSASSA, "rsassa", true, 1),
108
    [TPM_ALG_RSAES] = ENCRYPTING(ALG_RSAES, "rsaes", true, 1),
109
    [TPM_ALG_RSAPSS] = SIGNING(ALG_RSAPSS, "rsapss", true, 1),
110
    [TPM_ALG_OAEP] = ENCRYPTING(ALG_OAEP, "oaep", false, 1), // never disable: CryptSecretEncrypt/Decrypt needs it
111
    [TPM_ALG_ECDSA] = SIGNING(ALG_ECDSA, "ecdsa", false, 1),
112
    [TPM_ALG_ECDH] = OTHER(ALG_ECDH, "ecdh", false, 1),
113
    [TPM_ALG_ECDAA] = OTHER(ALG_ECDAA, "ecdaa", true, 1),
114
    [TPM_ALG_SM2] = SIGNING(ALG_SM2, "sm2", true, 1),
115
    [TPM_ALG_ECSCHNORR] = SIGNING(ALG_ECSCHNORR, "ecschnorr", true, 1),
116
    [TPM_ALG_ECMQV] = OTHER(ALG_ECMQV, "ecmqv", true, 1),
117
    [TPM_ALG_KDF1_SP800_56A] = HASH(ALG_KDF1_SP800_56A, "kdf1-sp800-56a", false, 1),
118
    [TPM_ALG_KDF2] = HASH(ALG_KDF2, "kdf2", false, 1),
119
    [TPM_ALG_KDF1_SP800_108] = HASH(ALG_KDF1_SP800_108, "kdf1-sp800-108", false, 1),
120
    [TPM_ALG_ECC] = ASYMMETRIC(ALG_ECC, "ecc", s_KeySizesECC, false, 1),
121
    [TPM_ALG_SYMCIPHER] = OTHER(ALG_SYMCIPHER, "symcipher", false, 1),
122
    [TPM_ALG_CAMELLIA] = SYMMETRIC(ALG_CAMELLIA, "camellia", s_KeySizesCamellia, true, 1),
123
    [TPM_ALG_SHA3_256] = HASH(ALG_SHA3_256, "sha3-256", true, 0), // not supported
124
    [TPM_ALG_SHA3_384] = HASH(ALG_SHA3_384, "sha3-384", true, 0), // not supported
125
    [TPM_ALG_SHA3_512] = HASH(ALG_SHA3_512, "sha3-256", true, 0), // not supported
126
    [TPM_ALG_CMAC] = SIGNING(ALG_CMAC, "cmac", true, 1),
127
    [TPM_ALG_CTR] = ENCRYPTING(ALG_CTR, "ctr", true, 1),
128
    [TPM_ALG_OFB] = ENCRYPTING(ALG_OFB, "ofb", true, 1),
129
    [TPM_ALG_CBC] = ENCRYPTING(ALG_CBC, "cbc", true, 1),
130
    [TPM_ALG_CFB] = ENCRYPTING(ALG_CFB, "cfb", false, 1), // never disable: context entryption
131
    [TPM_ALG_ECB] = ENCRYPTING(ALG_ECB, "ecb", true, 1),
132
    /* all newly added algorithms must have .canBedisable=true so they can be disabled */
133
};
134

135
struct AlgorithmShortcuts {
136
    const char   *name;
137
    BOOL          canBeDisabled;
138
    const char   *prefix;
139
};
140
static const struct AlgorithmShortcuts s_EccShortcuts[] = {
141
#define ECC_SHORTCUT(NAME, CANDISABLE, PREFIX) \
142
    { .name = NAME, .canBeDisabled = CANDISABLE, .prefix = PREFIX }
143
    [RUNTIME_ALGORITHM_ECC_NIST_BIT] = ECC_SHORTCUT("ecc-nist", true, "ecc-nist-p"),
144
    [RUNTIME_ALGORITHM_ECC_BN_BIT] = ECC_SHORTCUT("ecc-bn", true, "ecc-bn-p"),
145
};
146

147
struct AlgorithmProperties {
148
    const char   *name;
149
    UINT16        keySize;
150
    BOOL          canBeDisabled;
151
    unsigned int  stateFormatLevel; /* required stateFormatLevel to support this */
152
};
153
static const struct AlgorithmProperties s_EccAlgorithmProperties[] = {
154
#define ECC(ENABLED, NAME, KEYSIZE, CANDISABLE, SFL) \
155
    { .name = ENABLED ? NAME : NULL, .keySize = KEYSIZE, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
156

157
    [TPM_ECC_NIST_P192] = ECC(ECC_NIST_P192, "ecc-nist-p192", 192, true, 1),
158
    [TPM_ECC_NIST_P224] = ECC(ECC_NIST_P224, "ecc-nist-p224", 224, true, 1),
159
    [TPM_ECC_NIST_P256] = ECC(ECC_NIST_P256, "ecc-nist-p256", 256, false, 1),
160
    [TPM_ECC_NIST_P384] = ECC(ECC_NIST_P384, "ecc-nist-p384", 384, false, 1),
161
    [TPM_ECC_NIST_P521] = ECC(ECC_NIST_P521, "ecc-nist-p521", 521, true, 1),
162
    [TPM_ECC_BN_P256] = ECC(ECC_BN_P256, "ecc-bn-p256", 256, true, 1),
163
    [TPM_ECC_BN_P638] = ECC(ECC_BN_P638, "ecc-bn-p638", 638, true, 1),
164
    [TPM_ECC_SM2_P256] = ECC(ECC_SM2_P256, "ecc-sm2-p256", 256, true, 1),
165
};
166

167
static const TPM_ALG_ID algsWithKeySizes[] = {
168
    TPM_ALG_RSA,
169
    TPM_ALG_TDES,
170
    TPM_ALG_AES,
171
    TPM_ALG_SM4,
172
    TPM_ALG_CAMELLIA,
173
};
174

175
static unsigned int
176
KeySizesGetMinimum(const struct KeySizes *ks)
177
{
178
    size_t i = 0;
179

180
    while (ks[i].size) {
176,070✔
181
        if (ks[i].enabled)
147,580✔
182
            return ks[i].size;
119,090✔
183
        i++;
28,490✔
184
    }
185
    return 0;
186
}
187

188
static void
189
RuntimeAlgorithmEnableAllAlgorithms(struct RuntimeAlgorithm *RuntimeAlgorithm)
24,333✔
190
{
191
    TPM_ECC_CURVE curveId;
24,333✔
192
    TPM_ALG_ID algId;
24,333✔
193

194
    MemorySet(RuntimeAlgorithm->enabledAlgorithms, 0 , sizeof(RuntimeAlgorithm->enabledAlgorithms));
24,333✔
195

196
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
2,822,628✔
197
        /* skip over unsupported algorithms */
198
        if (!s_AlgorithmProperties[algId].name)
2,773,962✔
199
            continue;
1,946,640✔
200
        SET_BIT(algId, RuntimeAlgorithm->enabledAlgorithms);
827,322✔
201
    }
202

203
    MemorySet(RuntimeAlgorithm->enabledEccCurves, 0 , sizeof(RuntimeAlgorithm->enabledEccCurves));
24,333✔
204

205
    for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
851,655✔
206
        if (!s_EccAlgorithmProperties[curveId].name)
802,989✔
207
            continue;
608,325✔
208
        SET_BIT(curveId, RuntimeAlgorithm->enabledEccCurves);
194,664✔
209
    }
210
}
24,333✔
211

212
LIB_EXPORT void
213
RuntimeAlgorithmInit(struct RuntimeAlgorithm *RuntimeAlgorithm)
28,490✔
214
{
215
    TPM_ALG_ID algId;
28,490✔
216
    size_t i;
28,490✔
217

218
    MemorySet(RuntimeAlgorithm->algosMinimumKeySizes, 0 , sizeof(RuntimeAlgorithm->algosMinimumKeySizes));
28,490✔
219

220
    for (i = 0; i < ARRAY_SIZE(algsWithKeySizes); i++) {
199,430✔
221
        algId = algsWithKeySizes[i];
142,450✔
222
        assert(algId < ARRAY_SIZE(RuntimeAlgorithm->algosMinimumKeySizes));
142,450✔
223
        assert(s_AlgorithmProperties[algId].u.keySizes != NULL);
142,450✔
224
        RuntimeAlgorithm->algosMinimumKeySizes[algId] = KeySizesGetMinimum(s_AlgorithmProperties[algId].u.keySizes);
142,450✔
225
    }
226
}
28,490✔
227

228
LIB_EXPORT void
229
RuntimeAlgorithmFree(struct RuntimeAlgorithm *RuntimeAlgorithm)
33,126✔
230
{
231
    free(RuntimeAlgorithm->algorithmProfile);
33,126✔
232
    RuntimeAlgorithm->algorithmProfile = NULL;
33,126✔
233
}
33,126✔
234

235
/* Set the default profile with all algorithms and all keysizes enabled */
236
static void
237
RuntimeAlgorithmSetDefault(struct RuntimeAlgorithm *RuntimeAlgorithm)
24,333✔
238
{
239
    RuntimeAlgorithmFree(RuntimeAlgorithm);
24,333✔
240
    RuntimeAlgorithmInit(RuntimeAlgorithm);
24,333✔
241
    RuntimeAlgorithmEnableAllAlgorithms(RuntimeAlgorithm);
24,333✔
242
}
24,333✔
243

244
static TPM_RC RuntimeAlgorithmSetProfileShortcuts(
134,854✔
245
    const struct AlgorithmShortcuts *shortcuts, size_t shortcuts_len,
246
    const struct AlgorithmProperties *algProps, size_t algProps_len,
247
    const char *token, const size_t token_len,
248
    unsigned int *stateFormatLevel, const unsigned int maxStateFormatLevel,
249
    unsigned char *enabledShortcuts, size_t enabledShortcuts_len,
250
    unsigned char *enabledAlgorithms, size_t enabledAlgorithms_len,
251
    const char *type,
252
    bool *found)
253
{
254
    size_t prefix_len = token_len;
134,854✔
255
    const char *prefix = token;
134,854✔
256
    bool match_one = true;
134,854✔
257
    size_t cmplen = 0;
134,854✔
258
    size_t idx;
134,854✔
259
    size_t algId;
134,854✔
260

261
    for (idx = 0; idx < shortcuts_len; idx++) {
270,490✔
262
        cmplen = MAX(strlen(shortcuts[idx].name), token_len);
225,016✔
263
        if (!strncmp(token, shortcuts[idx].name, cmplen)) {
225,016✔
264
            SetBit(idx, enabledShortcuts, enabledShortcuts_len);
89,380✔
265
            match_one = false;
89,380✔
266
            prefix = shortcuts[idx].prefix;
89,380✔
267
            prefix_len = strlen(prefix);
89,380✔
268
            break;
89,380✔
269
        }
270
    }
271
    for (algId = 0; algId < algProps_len; algId++) {
4,585,036✔
272
        if (!algProps[algId].name)
4,450,182✔
273
            continue;
3,371,350✔
274

275
        if (match_one)
1,078,832✔
276
            cmplen = MAX(strlen(algProps[algId].name), token_len);
363,792✔
277
        else
278
            cmplen = prefix_len;
279

280
        if (!strncmp(prefix, algProps[algId].name, cmplen)) {
1,078,832✔
281
            if (algProps[algId].stateFormatLevel > maxStateFormatLevel) {
358,310✔
282
                /* specific match that is not allowed causes error, otherwise skip */
283
                if (match_one) {
×
284
                    TPMLIB_LogTPM2Error("Requested %s %s requires StateFormatLevel %u but maximum allowed is %u.\n",
×
285
                                        type,
286
                                        algProps[algId].name,
287
                                        algProps[algId].stateFormatLevel,
288
                                        maxStateFormatLevel);
289
                    return TPM_RC_VALUE;
×
290
                }
291
                continue;
×
292
            }
293
            *stateFormatLevel = MAX(*stateFormatLevel,
358,310✔
294
                                    algProps[algId].stateFormatLevel);
295
            SetBit(algId, enabledAlgorithms, enabledAlgorithms_len);
358,310✔
296
            *found = true;
358,310✔
297
        }
298
    }
299
    return TPM_RC_SUCCESS;
300
}
301

302
/* Set the given profile and runtime-enable the given algorithms. A NULL pointer
303
 * for the profile parameter sets the default profile which enables all algorithms
304
 * and all key sizes without any restrictions.
305
 *
306
 * This function will adjust the stateFormatLevel to the number required for the
307
 * given algorithms and key sizes.
308
 */
309
LIB_EXPORT TPM_RC
310
RuntimeAlgorithmSetProfile(struct RuntimeAlgorithm  *RuntimeAlgorithm,
69,109✔
311
                           const char                    *newProfile,                // IN: colon-separated list of algorithm names
312
                           unsigned int             *stateFormatLevel,                // IN/OUT: stateFormatLevel
313
                           unsigned int                     maxStateFormatLevel        // IN: maximum allowed stateFormatLevel
314
                           )
315
{
316
    size_t toklen, cmplen, i;
69,109✔
317
    const char *token, *comma;
69,109✔
318
    const struct KeySizes *keysizes;
69,109✔
319
    TPM_RC retVal = TPM_RC_SUCCESS;
69,109✔
320
    unsigned long minKeySize;
69,109✔
321
    TPM_ECC_CURVE curveId;
69,109✔
322
    TPM_ALG_ID algId;
69,109✔
323
    char *endptr;
69,109✔
324
    bool found;
69,109✔
325

326
    /* NULL pointer for profile enables all */
327
    if (!newProfile) {
69,109✔
328
        RuntimeAlgorithmSetDefault(RuntimeAlgorithm);
24,333✔
329
        return TPM_RC_SUCCESS;
24,333✔
330
    }
331

332
    MemorySet(RuntimeAlgorithm->enabledAlgorithms, 0, sizeof(RuntimeAlgorithm->enabledAlgorithms));
44,776✔
333
    MemorySet(RuntimeAlgorithm->enabledEccCurves, 0 , sizeof(RuntimeAlgorithm->enabledEccCurves));
44,776✔
334
    MemorySet(RuntimeAlgorithm->enabledEccShortcuts, 0, sizeof(RuntimeAlgorithm->enabledEccShortcuts));
44,776✔
335

336
    token = newProfile;
44,776✔
337
    while (1) {
3,714,684✔
338
        comma = strchr(token, ALGO_SEPARATOR_C);
3,714,684✔
339
        if (comma)
1,879,730✔
340
            toklen = (size_t)(comma - token);
1,834,954✔
341
        else
342
            toklen = strlen(token);
44,776✔
343

344
        found = false;
1,879,730✔
345
        for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
63,160,284✔
346
            /* skip over unsupported algorithms */
347
            if (!s_AlgorithmProperties[algId].name)
63,025,430✔
348
                continue;
29,044,790✔
349
            cmplen = MAX(strlen(s_AlgorithmProperties[algId].name), toklen);
33,980,640✔
350
            if (!strncmp(token, s_AlgorithmProperties[algId].name, cmplen)) {
33,980,640✔
351
                if (s_AlgorithmProperties[algId].stateFormatLevel > maxStateFormatLevel) {
1,520,920✔
352
                    TPMLIB_LogTPM2Error("Requested algorithm %.*s requires StateFormatLevel %u but maximum allowed is %u.\n",
×
353
                                        (int)toklen, token,
354
                                        s_AlgorithmProperties[algId].stateFormatLevel,
355
                                        maxStateFormatLevel);
356
                    retVal = TPM_RC_VALUE;
×
357
                    goto exit;
×
358
                }
359
                SET_BIT(algId, RuntimeAlgorithm->enabledAlgorithms);
1,520,920✔
360
                assert(s_AlgorithmProperties[algId].stateFormatLevel > 0);
1,520,920✔
361
                *stateFormatLevel = MAX(*stateFormatLevel,
1,520,920✔
362
                                        s_AlgorithmProperties[algId].stateFormatLevel);
363
                found = true;
1,520,920✔
364
                break;
1,520,920✔
365
            } else if (s_AlgorithmProperties[algId].u.minKeySize) {
32,459,720✔
366
                size_t namelen = strlen(s_AlgorithmProperties[algId].name);
1,611,440✔
367
                if (strncmp(token,
1,611,440✔
368
                            s_AlgorithmProperties[algId].name, /* i.e., 'hmac' */
369
                            namelen) ||
152✔
370
                    strncmp(&token[namelen], "-min-key-size=", 14))
152✔
371
                    continue;
1,611,288✔
372
                minKeySize = strtoul(&token[namelen + 14], &endptr, 10);
152✔
373
                if ((*endptr != ALGO_SEPARATOR_C && *endptr != '\0')
152✔
374
                    || minKeySize > MAX_SYM_DATA * 8) {
152✔
375
                    retVal = TPM_RC_KEY_SIZE;
×
376
                    goto exit;
×
377
                }
378
                RuntimeAlgorithm->algosMinimumKeySizes[algId] = (UINT16)minKeySize;
152✔
379
                *stateFormatLevel = MAX(*stateFormatLevel,
152✔
380
                                        s_AlgorithmProperties[algId].u.minKeySize->stateFormatLevel);
381
                found = true;
152✔
382
                break;
152✔
383
            } else if (s_AlgorithmProperties[algId].u.keySizes) {
30,848,280✔
384
                size_t algnamelen = strlen(s_AlgorithmProperties[algId].name);
6,177,600✔
385
                if (strncmp(token, s_AlgorithmProperties[algId].name, algnamelen) ||
6,177,600✔
386
                    strncmp(&token[algnamelen], "-min-size=", 10))
492,594✔
387
                    continue;
5,953,796✔
388
                minKeySize = strtoul(&token[algnamelen + 10], &endptr, 10);
223,804✔
389
                if ((*endptr != ALGO_SEPARATOR_C && *endptr != '\0') ||  minKeySize > 4096) {
223,804✔
390
                    retVal = TPM_RC_KEY_SIZE;
×
391
                    goto exit;
×
392
                }
393

394
                /* determine stateFormatLevel needed; skip those key sizes that exceed max. stateFormatLevel */
395
                keysizes = s_AlgorithmProperties[algId].u.keySizes;
396
                for (i = 0; keysizes[i].size != 0; i++) {
1,119,090✔
397
                    if (keysizes[i].enabled &&
895,286✔
398
                        keysizes[i].size >= minKeySize &&
895,286✔
399
                        keysizes[i].stateFormatLevel <= maxStateFormatLevel) {
895,236✔
400
                        assert(keysizes[i].stateFormatLevel > 0);
786,176✔
401
                        *stateFormatLevel = MAX(*stateFormatLevel,
786,176✔
402
                                                keysizes[i].stateFormatLevel);
403
                    }
404
                }
405

406
                RuntimeAlgorithm->algosMinimumKeySizes[algId] = (UINT16)minKeySize;
223,804✔
407
                found = true;
223,804✔
408
                break;
223,804✔
409
            }
410
        }
411

412
        if (!found) {
1,879,730✔
413
            /* handling of ECC curves: shortcuts */
414
            retVal = RuntimeAlgorithmSetProfileShortcuts(
134,854✔
415
                        s_EccShortcuts, ARRAY_SIZE(s_EccShortcuts),
416
                        s_EccAlgorithmProperties, ARRAY_SIZE(s_EccAlgorithmProperties),
417
                        token, toklen,
418
                        stateFormatLevel, maxStateFormatLevel,
419
                        RuntimeAlgorithm->enabledEccShortcuts, sizeof(RuntimeAlgorithm->enabledEccShortcuts),
420
                        RuntimeAlgorithm->enabledEccCurves, sizeof(RuntimeAlgorithm->enabledEccCurves),
421
                        "curve",
422
                        &found);
423
            if (retVal != TPM_RC_SUCCESS)
134,854✔
424
                goto exit;
×
425
        }
426

427
        if (!found) {
1,879,730✔
428
            TPMLIB_LogTPM2Error("Requested algorithm specifier %.*s is not supported.\n",
×
429
                                (int)toklen, token);
430
            retVal = TPM_RC_VALUE;
×
431
            goto exit;
×
432
        }
433

434
        if (!comma)
1,879,730✔
435
            break;
436
        token = &comma[1];
1,834,954✔
437
    }
438

439
    /* reconcile with what can be disabled per code instrumentation */
440
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
5,149,240✔
441
        /* skip over unsupported algorithms */
442
        if (!s_AlgorithmProperties[algId].name)
5,104,464✔
443
            continue;
3,582,080✔
444
        if (!s_AlgorithmProperties[algId].canBeDisabled &&
2,328,352✔
445
            !TEST_BIT(algId, RuntimeAlgorithm->enabledAlgorithms)) {
805,968✔
446
            TPMLIB_LogTPM2Error("Algorithm %s must be enabled.\n",
×
447
                                s_AlgorithmProperties[algId].name);
448
            retVal = TPM_RC_VALUE;
×
449
            goto exit;
×
450
        }
451
    }
452
    for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
1,522,384✔
453
        if (!s_EccAlgorithmProperties[curveId].name)
1,477,608✔
454
            continue;
1,119,400✔
455
        if (!s_EccAlgorithmProperties[curveId].canBeDisabled &&
447,760✔
456
            !TEST_BIT(curveId, RuntimeAlgorithm->enabledEccCurves)) {
89,552✔
457
            TPMLIB_LogTPM2Error("Elliptic curve %s must be enabled.\n",
×
458
                                s_EccAlgorithmProperties[curveId].name);
459
            retVal = TPM_RC_VALUE;
×
460
            goto exit;
×
461
        }
462
        /* disable curves that can be disabled and not meet min. keysize */
463
        if (RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_ECC] >
358,208✔
464
               s_EccAlgorithmProperties[curveId].keySize &&
358,208✔
465
            s_EccAlgorithmProperties[curveId].canBeDisabled)
466
            CLEAR_BIT(curveId, RuntimeAlgorithm->enabledEccCurves);
24✔
467
    }
468

469
    /* some consistency checks */
470
    /* Do not allow aes-min-size > 128 while RSA=2048 otherwise standard EK certs cannot be created anymore */
471
    if (RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_AES] > 128 &&
44,776✔
472
        RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_RSA] == 2048) {
×
473
        TPMLIB_LogTPM2Error("AES minimum key size must be 128 when "
×
474
                            "2048 bit %s keys are used.\n",
475
                            "RSA");
476
        retVal = TPM_RC_KEY_SIZE;
×
477
        goto exit;
×
478
    }
479

480
    free(RuntimeAlgorithm->algorithmProfile);
44,776✔
481
    RuntimeAlgorithm->algorithmProfile = strdup(newProfile);
44,776✔
482
    if (!RuntimeAlgorithm->algorithmProfile)
44,776✔
483
        retVal = TPM_RC_MEMORY;
484

485
exit:
44,776✔
486
    if (retVal != TPM_RC_SUCCESS)
44,776✔
487
        RuntimeAlgorithmSetDefault(RuntimeAlgorithm);
×
488

489
    return retVal;
490
}
491

492
LIB_EXPORT TPM_RC
493
RuntimeAlgorithmSwitchProfile(struct RuntimeAlgorithm  *RuntimeAlgorithm,
8,046✔
494
                              const char               *newProfile,
495
                              unsigned int              maxStateFormatLevel,
496
                              char                    **oldProfile)
497
{
498
    TPM_RC retVal;
8,046✔
499
    unsigned int stateFormatLevel = 0; // ignored
8,046✔
500

501
    *oldProfile = RuntimeAlgorithm->algorithmProfile;
8,046✔
502
    RuntimeAlgorithm->algorithmProfile = NULL;
8,046✔
503

504
    retVal = RuntimeAlgorithmSetProfile(RuntimeAlgorithm, newProfile,
8,046✔
505
                                        &stateFormatLevel, maxStateFormatLevel);
506
    if (retVal != TPM_RC_SUCCESS) {
8,046✔
507
        RuntimeAlgorithmSetProfile(RuntimeAlgorithm, *oldProfile,
×
508
                                   &stateFormatLevel, maxStateFormatLevel);
509
        *oldProfile = NULL;
×
510
    }
511
    return retVal;
8,046✔
512
}
513

514
/* Check whether the given algorithm is runtime-enabled */
515
LIB_EXPORT BOOL
516
RuntimeAlgorithmCheckEnabled(struct RuntimeAlgorithm *RuntimeAlgorithm,
646,864✔
517
                             TPM_ALG_ID                      algId      // IN: the algorithm to check
518
                             )
519
{
520
    if ((algId >> 3) >= sizeof(RuntimeAlgorithm->enabledAlgorithms) ||
1,293,728✔
521
        !TestBit(algId, RuntimeAlgorithm->enabledAlgorithms,
646,864✔
522
                 sizeof(RuntimeAlgorithm->enabledAlgorithms)))
523
        return FALSE;
18,702✔
524
    return TRUE;
525
}
526

527
/* Check whether the given symmetric or asymmetric crypto algorithm is enabled
528
 * for the given keysize. The maxStateFormatLevel prevents certain key sizes
529
 * from being usable if these were only enabled after the algorithm was enabled.
530
 *
531
 * Example: Algorithm 'x' was enabled but keysize 192 was not enabled at this
532
 * point. The required stateFormatLevel for 'x' is 1. To use keysize 192
533
 * stateFormatLevel '4' is required but due to the profile's stateFormatLevel '1'
534
 * it needs to be filtered-out so that the profile doesn't need an upgrade to
535
 * stateFormatLevel '4'.
536
 */
537
static BOOL _RuntimeAlgorithmKeySizeCheckEnabled(
5,448✔
538
    struct RuntimeAlgorithm *RuntimeAlgorithm,
539
    TPM_ALG_ID               algId,                        // IN: the algorithm to check
540
    UINT16                   keySizeInBits,                // IN: size of the key in bits
541
    unsigned int             maxStateFormatLevel,        // IN: maximum stateFormatLevel
542
    TPM_ECC_CURVE            curveId                        // IN: curve Id for TPM_ALG_ECC
543
)
544
{
545
    const struct KeySizes *keysizes;
5,448✔
546
    UINT16 minKeySize;
5,448✔
547
    size_t i;
5,448✔
548

549
    if (!RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
5,448✔
550
        return FALSE;
551

552
    minKeySize = RuntimeAlgorithm->algosMinimumKeySizes[algId];
5,448✔
553
    if (minKeySize > keySizeInBits)
5,448✔
554
        return FALSE;
555

556
    if (s_AlgorithmProperties[algId].u.minKeySize)
5,444✔
557
        return TRUE;
558

559
    if (algId == TPM_ALG_ECC) {
5,376✔
560
        if ((curveId >> 3) >= sizeof(RuntimeAlgorithm->enabledEccCurves) ||
1,850✔
561
            !TestBit(curveId, RuntimeAlgorithm->enabledEccCurves,
925✔
562
                     sizeof(RuntimeAlgorithm->enabledEccCurves))) {
563
            return FALSE;
3✔
564
        }
565
    }
566

567
    keysizes = s_AlgorithmProperties[algId].u.keySizes;
5,373✔
568
    for (i = 0; keysizes[i].size != 0; i++) {
11,606✔
569
        if (keysizes[i].size == keySizeInBits) {
11,606✔
570
            if (keysizes[i].enabled &&
5,373✔
571
                keysizes[i].stateFormatLevel > maxStateFormatLevel) {
5,373✔
572
                return FALSE;
573
            }
574
            return TRUE;
5,298✔
575
        }
576
    }
577

578
    return TRUE;
579
}
580

581
LIB_EXPORT BOOL
582
RuntimeAlgorithmKeySizeCheckEnabled(
4,519✔
583
    struct RuntimeAlgorithm *RuntimeAlgorithm,
584
    TPM_ALG_ID               algId,                        // IN: the algorithm to check
585
    UINT16                   keySizeInBits,                // IN: size of the key in bits
586
    unsigned int             maxStateFormatLevel        // IN: maximum stateFormatLevel
587
   )
588
{
589
    return _RuntimeAlgorithmKeySizeCheckEnabled(
4,519✔
590
        RuntimeAlgorithm,
591
        algId,
592
        keySizeInBits,
593
        maxStateFormatLevel,
594
        TPM_ECC_NONE
595
    );
596
}
597

598
LIB_EXPORT BOOL
599
RuntimeAlgorithmEccKeySizeCheckEnabled(
929✔
600
    struct RuntimeAlgorithm *RuntimeAlgorithm,
601
    TPM_ALG_ID               algId,                        // IN: the algorithm to check
602
    UINT16                   keySizeInBits,                // IN: size of the key in bits
603
    TPM_ECC_CURVE            curveId,                        // IN: curve Id if algId == TPM_ALG_ECC
604
    unsigned int             maxStateFormatLevel        // IN: maximum stateFormatLevel
605
   )
606
{
607
    return _RuntimeAlgorithmKeySizeCheckEnabled(
929✔
608
        RuntimeAlgorithm,
609
        algId,
610
        keySizeInBits,
611
        maxStateFormatLevel,
612
        curveId
613
    );
614
}
615

616
static char *
617
RuntimeAlgorithmGet(
4,104✔
618
    const struct AlgorithmShortcuts  *shortcuts, size_t shortcuts_len,
619
    const struct AlgorithmProperties *algProps,  size_t algProps_len,
620
    unsigned char *enabledShortcuts, size_t enabledShortcuts_len,
621
    unsigned char *enabledAlgorithms, size_t enabledAlgorithms_len,
622
    enum RuntimeAlgorithmType rat,
623
    char *buffer,
624
    BOOL *first)
625
{
626
    char *nbuffer = NULL;
4,104✔
627
    size_t idx;
4,104✔
628
    int n;
4,104✔
629

630
    for (idx = 0; idx < shortcuts_len; idx++) {
12,312✔
631
        switch (rat) {
8,208✔
632
        case RUNTIME_ALGO_IMPLEMENTED:
633
            // no filter;
634
            break;
635
        case RUNTIME_ALGO_CAN_BE_DISABLED:
2,052✔
636
            if (!shortcuts[idx].canBeDisabled)
2,052✔
UNCOV
637
                continue;
×
638
            break;
639
        case RUNTIME_ALGO_ENABLED:
2,052✔
640
            if (!TestBit(idx, enabledShortcuts, enabledShortcuts_len))
2,052✔
641
                continue;
597✔
642
            break;
643
        case RUNTIME_ALGO_DISABLED:
2,052✔
644
            if (TestBit(idx, enabledShortcuts, enabledShortcuts_len))
2,052✔
645
                continue;
1,455✔
646
            break;
647
        default:
648
            break;
649
        }
650
        n = asprintf(&nbuffer, "%s%s%s",
12,312✔
651
                     buffer,
652
                     *first ? "" : ALGO_SEPARATOR_STR,
6,156✔
653
                     shortcuts[idx].name);
6,156✔
654
        free(buffer);
6,156✔
655
        if (n < 0)
6,156✔
656
            return NULL;
657
        buffer = nbuffer;
6,156✔
658
        *first = false;
6,156✔
659
    }
660

661
    for (idx = 0; idx < algProps_len; idx++) {
139,536✔
662
        if (!algProps[idx].name)
135,432✔
663
            continue;
102,600✔
664

665
        switch (rat) {
32,832✔
666
        case RUNTIME_ALGO_IMPLEMENTED:
667
            // no filter
668
            break;
669
        case RUNTIME_ALGO_CAN_BE_DISABLED:
8,208✔
670
            if (!algProps[idx].canBeDisabled)
8,208✔
671
               continue;
2,052✔
672
            break;
673
        case RUNTIME_ALGO_ENABLED:
8,208✔
674
            if (!TestBit(idx, enabledAlgorithms, enabledAlgorithms_len))
8,208✔
675
                continue;
2,138✔
676
            break;
677
        case RUNTIME_ALGO_DISABLED:
8,208✔
678
            if (TestBit(idx, enabledAlgorithms, enabledAlgorithms_len))
8,208✔
679
                continue;
6,070✔
680
            break;
681
        default:
682
            break;
683
        }
684
        n = asprintf(&nbuffer, "%s%s%s",
45,144✔
685
                     buffer,
686
                     *first ? "" : ALGO_SEPARATOR_STR,
22,572✔
687
                     algProps[idx].name);
22,572✔
688
        free(buffer);
22,572✔
689
        if (n < 0)
22,572✔
690
            return NULL;
691
        buffer = nbuffer;
22,572✔
692
        *first = FALSE;
22,572✔
693
    }
694

695
    return buffer;
696
}
697

698
static char *
699
RuntimeAlgorithmGetEcc(struct RuntimeAlgorithm   *RuntimeAlgorithm,
4,104✔
700
                       enum RuntimeAlgorithmType rat,
701
                       char                      *buffer,
702
                       BOOL                      *first)
703
{
704
    return RuntimeAlgorithmGet(
8,208✔
705
        s_EccShortcuts, ARRAY_SIZE(s_EccShortcuts),
706
        s_EccAlgorithmProperties, ARRAY_SIZE(s_EccAlgorithmProperties),
707
        RuntimeAlgorithm->enabledEccShortcuts, sizeof(RuntimeAlgorithm->enabledEccShortcuts),
4,104✔
708
        RuntimeAlgorithm->enabledEccCurves, sizeof(RuntimeAlgorithm->enabledEccCurves),
4,104✔
709
        rat, buffer, first
710
    );
711
}
712

713
LIB_EXPORT char *
714
RuntimeAlgorithmPrint(struct RuntimeAlgorithm   *RuntimeAlgorithm,
4,104✔
715
                      enum RuntimeAlgorithmType rat)
716
{
717
    char *buffer, *nbuffer = NULL;
4,104✔
718
    unsigned int minKeySize;
4,104✔
719
    TPM_ALG_ID algId;
4,104✔
720
    int n;
4,104✔
721
    BOOL first = true;
4,104✔
722

723
    buffer = strdup("\"");
4,104✔
724
    if (!buffer)
4,104✔
725
        return NULL;
726

727
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
471,960✔
728
        // skip over unsupported algorithms
729
        if (!s_AlgorithmProperties[algId].name)
467,856✔
730
            continue;
328,320✔
731
        switch (rat) {
139,536✔
732
        case RUNTIME_ALGO_IMPLEMENTED:
733
            // no filter
734
            break;
735
        case RUNTIME_ALGO_CAN_BE_DISABLED:
34,884✔
736
            if (!s_AlgorithmProperties[algId].canBeDisabled)
34,884✔
737
                 goto skip; // TPM_ALG_ECC: need to print more
18,468✔
738
            break;
739
        case RUNTIME_ALGO_ENABLED:
34,884✔
740
            // skip over disabled ones
741
            if (!RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
34,884✔
742
                goto skip;
8,933✔
743
            break;
744
        case RUNTIME_ALGO_DISABLED:
34,884✔
745
            // skip over enabled ones
746
            if (RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
34,884✔
747
                goto skip;
25,951✔
748
            break;
UNCOV
749
        default:
×
UNCOV
750
            continue;
×
751
        }
752
        n = asprintf(&nbuffer, "%s%s%s",
172,368✔
753
                     buffer,
754
                     first ? "" : ALGO_SEPARATOR_STR,
86,184✔
755
                     s_AlgorithmProperties[algId].name);
756
        free(buffer);
86,184✔
757
        if (n < 0)
86,184✔
758
             return NULL;
759

760
        buffer = nbuffer;
86,184✔
761
        first = false;
86,184✔
762

763
        minKeySize = 0;
86,184✔
764

765
        switch (rat) {
86,184✔
766
        case RUNTIME_ALGO_IMPLEMENTED:
34,884✔
767
            if (s_AlgorithmProperties[algId].u.keySizes) {
34,884✔
768
                minKeySize = KeySizesGetMinimum(s_AlgorithmProperties[algId].u.keySizes);
9,736✔
769
            } else if (s_AlgorithmProperties[algId].u.minKeySize) {
29,754✔
770
                /* for it to appear as 'Implemented' */
771
                minKeySize = 1;
772
            }
773
            break;
774
        case RUNTIME_ALGO_ENABLED:
25,951✔
775
            if (s_AlgorithmProperties[algId].u.keySizes ||
25,951✔
776
                s_AlgorithmProperties[algId].u.minKeySize) {
22,142✔
777
                minKeySize = RuntimeAlgorithm->algosMinimumKeySizes[algId];
4,606✔
778
            }
779
            break;
780
        default:
781
            break;
782
        }
783
        if (minKeySize > 0) {
9,736✔
784
            const char *key = "";
10,085✔
785
            if (s_AlgorithmProperties[algId].u.minKeySize)
10,085✔
786
                key = "key-";
1,150✔
787

788
            n = asprintf(&nbuffer, "%s%s%s-min-%ssize=%u",
20,170✔
789
                         buffer,
790
                         ALGO_SEPARATOR_STR,
791
                         s_AlgorithmProperties[algId].name,
10,085✔
792
                         key,
793
                         minKeySize);
794
            free(buffer);
10,085✔
795
            if (n < 0)
10,085✔
796
                return NULL;
797

798
            buffer = nbuffer;
10,085✔
799
        }
800

801
skip:
677✔
802
        if (algId == TPM_ALG_ECC)
139,536✔
803
            buffer = RuntimeAlgorithmGetEcc(RuntimeAlgorithm, rat, buffer, &first);
4,104✔
804
    }
805

806
    n = asprintf(&nbuffer, "%s\"", buffer);
4,104✔
807
    free(buffer);
4,104✔
808
    if (n < 0)
4,104✔
809
        return NULL;
810

811
    return nbuffer;
4,104✔
812
}
813

814
LIB_EXPORT void
815
RuntimeAlgorithmsFilterPCRSelection(TPML_PCR_SELECTION *pcrSelection // IN/OUT: PCRSelection to filter
140✔
816
                                    )
817
{
818
    UINT32 i = 0;
140✔
819

820
    while (i < pcrSelection->count) {
700✔
821
        if (!RuntimeAlgorithmCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm,
560✔
822
                                          pcrSelection->pcrSelections[i].hash)) {
560✔
823
            pcrSelection->count--;
53✔
824
            if (pcrSelection->count - 1 > i) {
53✔
825
                MemoryCopy(&pcrSelection->pcrSelections[i],
28✔
826
                           &pcrSelection->pcrSelections[i + 1],
28✔
827
                           sizeof(pcrSelection->pcrSelections[0]) * (pcrSelection->count - i));
28✔
828
            }
829
        } else {
830
            i++;
507✔
831
        }
832
    }
833
}
140✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc