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

stefanberger / libtpms / #2000

10 Jun 2025 04:18PM UTC coverage: 77.211% (-0.004%) from 77.215%
#2000

push

travis-ci

web-flow
Merge 34d84bd97 into 95d144c51

24 of 26 new or added lines in 2 files covered. (92.31%)

167 existing lines in 5 files now uncovered.

36059 of 46702 relevant lines covered (77.21%)

121920.28 hits per line

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

89.74
/src/tpm2/RuntimeAlgorithm.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                         Algorithm Runtime Disablement                                 */
4
/*                             Written by Stefan Berger                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*                                                                                */
7
/*  Licenses and Notices                                                        */
8
/*                                                                                */
9
/*  (c) Copyright IBM Corporation, 2022                                                */
10
/*                                                                                */
11
/* All rights reserved.                                                                */
12
/*                                                                                */
13
/* Redistribution and use in source and binary forms, with or without                */
14
/* modification, are permitted provided that the following conditions are        */
15
/* met:                                                                                */
16
/*                                                                                */
17
/* Redistributions of source code must retain the above copyright notice,        */
18
/* this list of conditions and the following disclaimer.                        */
19
/*                                                                                */
20
/* Redistributions in binary form must reproduce the above copyright                */
21
/* notice, this list of conditions and the following disclaimer in the                */
22
/* documentation and/or other materials provided with the distribution.                */
23
/*                                                                                */
24
/* Neither the names of the IBM Corporation nor the names of its                */
25
/* contributors may be used to endorse or promote products derived from                */
26
/* this software without specific prior written permission.                        */
27
/*                                                                                */
28
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS                */
29
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT                */
30
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR        */
31
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT                */
32
/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,        */
33
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT                */
34
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,        */
35
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY        */
36
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT                */
37
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE        */
38
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                */
39
/*                                                                                */
40
/********************************************************************************/
41

42
#define _GNU_SOURCE
43
#include <assert.h>
44
#include <string.h>
45

46
#include "Tpm.h"
47
#include "NVMarshal.h"
48
#include "GpMacros.h"
49
#include "tpm_library_intern.h"
50

51
#define ALGO_SEPARATOR_C ','
52
#define ALGO_SEPARATOR_STR ","
53

54
struct KeySizes {
55
    BOOL enabled;
56
    UINT16 size;
57
    unsigned int stateFormatLevel; /* required stateFormatLevel to support this */
58
};
59

60
struct MinKeySize {
61
    unsigned int stateFormatLevel; /* required stateFormatLevel to support this */
62
};
63

64
static const struct KeySizes s_KeySizesAES[] = {
65
    { .enabled = AES_128, .size = 128, .stateFormatLevel = 1 },
66
    { .enabled = AES_192, .size = 192, .stateFormatLevel = 4 },
67
    { .enabled = AES_256, .size = 256, .stateFormatLevel = 1 },
68
    { .enabled = false  , .size = 0  , .stateFormatLevel = 0 },
69
};
70
static const struct KeySizes s_KeySizesSM4[] = {
71
    { .enabled = SM4_128, .size = 128, .stateFormatLevel = 0 }, // not supported
72
    { .enabled = false  , .size = 0  , .stateFormatLevel = 0 },
73
};
74
static const struct KeySizes s_KeySizesCamellia[] = {
75
    { .enabled = CAMELLIA_128, .size = 128, .stateFormatLevel = 1 },
76
    { .enabled = CAMELLIA_192, .size = 192, .stateFormatLevel = 4 },
77
    { .enabled = CAMELLIA_256, .size = 256, .stateFormatLevel = 1 },
78
    { .enabled = false       , .size = 0  , .stateFormatLevel = 0 },
79
};
80
static const struct KeySizes s_KeySizesTDES[] = {
81
    { .enabled = TDES_128, .size = 128, .stateFormatLevel = 1 },
82
    { .enabled = TDES_192, .size = 192, .stateFormatLevel = 1 },
83
    { .enabled = false   , .size = 0  , .stateFormatLevel = 0 },
84
};
85
static const struct KeySizes s_KeySizesRSA[] = {
86
    { .enabled = RSA_1024, .size = 1024, .stateFormatLevel = 1 },
87
    { .enabled = RSA_2048, .size = 2048, .stateFormatLevel = 1 },
88
    { .enabled = RSA_3072, .size = 3072, .stateFormatLevel = 1 },
89
    { .enabled = RSA_4096, .size = 4096, .stateFormatLevel = 8 },
90
    { .enabled = false   , .size = 0   , .stateFormatLevel = 0 },
91
};
92
static const struct KeySizes s_KeySizesECC[] = {
93
    { .enabled = ECC_NIST_P192, .size = 192, .stateFormatLevel = 1 },
94
    { .enabled = ECC_NIST_P224, .size = 224, .stateFormatLevel = 1 },
95
    { .enabled = ECC_NIST_P256, .size = 256, .stateFormatLevel = 1 },
96
    { .enabled = ECC_BN_P256  , .size = 256, .stateFormatLevel = 1 },
97
    { .enabled = ECC_SM2_P256 , .size = 256, .stateFormatLevel = 1 },
98
    { .enabled = ECC_NIST_P384, .size = 384, .stateFormatLevel = 1 },
99
    { .enabled = ECC_NIST_P521, .size = 521, .stateFormatLevel = 1 },
100
    { .enabled = ECC_BN_P638  , .size = 638, .stateFormatLevel = 1 },
101
    { .enabled = false        , .size = 0  , .stateFormatLevel = 0 },
102
};
103
static const struct MinKeySize s_MinKeySizeHMAC[] = {
104
    { .stateFormatLevel = 7 },
105
};
106

107
static const struct {
108
    const char   *name;
109
    struct {
110
        const struct KeySizes *keySizes;
111
        const struct MinKeySize *minKeySize;
112
    } u;
113
    BOOL          canBeDisabled;
114
    unsigned int  stateFormatLevel; /* required stateFormatLevel to support this */
115
} s_AlgorithmProperties[NUM_ENTRIES_ALGORITHM_PROPERTIES] = {
116
#define SYMMETRIC(ENABLED, NAME, KEYSIZES, CANDISABLE, SFL) \
117
    { .name = ENABLED ? NAME : NULL, .u.keySizes = KEYSIZES, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
118
#define ASYMMETRIC(ENABLED, NAME, KEYSIZES, CANDISABLE, SFL) \
119
    { .name = ENABLED ? NAME : NULL, .u.keySizes = KEYSIZES, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
120
#define HASH(ENABLED, NAME, CANDISABLE, SFL) \
121
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
122
#define HMAC(ENABLED, NAME, MINKEYSIZE, CANDISABLE, SFL) \
123
    { .name = ENABLED ? NAME : NULL, .u.minKeySize = MINKEYSIZE, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
124
#define SIGNING(ENABLED, NAME, CANDISABLE, SFL) \
125
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
126
#define ENCRYPTING(ENABLED, NAME, CANDISABLE, SFL) \
127
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
128
#define OTHER(ENABLED, NAME, CANDISABLE, SFL) \
129
    { .name = ENABLED ? NAME : NULL, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
130

131
    [TPM_ALG_RSA] = ASYMMETRIC(ALG_RSA, "rsa", s_KeySizesRSA, false, 1),
132
    [TPM_ALG_TDES] = SYMMETRIC(ALG_TDES, "tdes", s_KeySizesTDES, true, 1),
133
    [TPM_ALG_SHA1] = HASH(ALG_SHA1, "sha1", true, 1),
134
    [TPM_ALG_HMAC] = HMAC(ALG_HMAC, "hmac", s_MinKeySizeHMAC, false, 1),
135
    [TPM_ALG_AES] = SYMMETRIC(ALG_AES, "aes", s_KeySizesAES, false, 1), // never disable: context encryption
136
    [TPM_ALG_MGF1] = HASH(ALG_MGF1, "mgf1", false, 1),
137
    [TPM_ALG_KEYEDHASH] = HASH(ALG_KEYEDHASH, "keyedhash", false, 1),
138
    [TPM_ALG_XOR] = OTHER(ALG_XOR, "xor", false, 1),
139
    [TPM_ALG_SHA256] = HASH(ALG_SHA256, "sha256", false, 1),
140
    [TPM_ALG_SHA384] = HASH(ALG_SHA384, "sha384", false, 1),
141
    [TPM_ALG_SHA512] = HASH(ALG_SHA512, "sha512", true, 1),
142
    [TPM_ALG_NULL] = OTHER(true, "null", false, 1),
143
    [TPM_ALG_SM4] = SYMMETRIC(ALG_SM4, "sm4", s_KeySizesSM4, true, 0), // not supported
144
    [TPM_ALG_RSASSA] = SIGNING(ALG_RSASSA, "rsassa", true, 1),
145
    [TPM_ALG_RSAES] = ENCRYPTING(ALG_RSAES, "rsaes", true, 1),
146
    [TPM_ALG_RSAPSS] = SIGNING(ALG_RSAPSS, "rsapss", true, 1),
147
    [TPM_ALG_OAEP] = ENCRYPTING(ALG_OAEP, "oaep", false, 1), // never disable: CryptSecretEncrypt/Decrypt needs it
148
    [TPM_ALG_ECDSA] = SIGNING(ALG_ECDSA, "ecdsa", false, 1),
149
    [TPM_ALG_ECDH] = OTHER(ALG_ECDH, "ecdh", false, 1),
150
    [TPM_ALG_ECDAA] = OTHER(ALG_ECDAA, "ecdaa", true, 1),
151
    [TPM_ALG_SM2] = SIGNING(ALG_SM2, "sm2", true, 1),
152
    [TPM_ALG_ECSCHNORR] = SIGNING(ALG_ECSCHNORR, "ecschnorr", true, 1),
153
    [TPM_ALG_ECMQV] = OTHER(ALG_ECMQV, "ecmqv", true, 1),
154
    [TPM_ALG_KDF1_SP800_56A] = HASH(ALG_KDF1_SP800_56A, "kdf1-sp800-56a", false, 1),
155
    [TPM_ALG_KDF2] = HASH(ALG_KDF2, "kdf2", false, 1),
156
    [TPM_ALG_KDF1_SP800_108] = HASH(ALG_KDF1_SP800_108, "kdf1-sp800-108", false, 1),
157
    [TPM_ALG_ECC] = ASYMMETRIC(ALG_ECC, "ecc", s_KeySizesECC, false, 1),
158
    [TPM_ALG_SYMCIPHER] = OTHER(ALG_SYMCIPHER, "symcipher", false, 1),
159
    [TPM_ALG_CAMELLIA] = SYMMETRIC(ALG_CAMELLIA, "camellia", s_KeySizesCamellia, true, 1),
160
    [TPM_ALG_SHA3_256] = HASH(ALG_SHA3_256, "sha3-256", true, 0), // not supported
161
    [TPM_ALG_SHA3_384] = HASH(ALG_SHA3_384, "sha3-384", true, 0), // not supported
162
    [TPM_ALG_SHA3_512] = HASH(ALG_SHA3_512, "sha3-256", true, 0), // not supported
163
    [TPM_ALG_CMAC] = SIGNING(ALG_CMAC, "cmac", true, 1),
164
    [TPM_ALG_CTR] = ENCRYPTING(ALG_CTR, "ctr", true, 1),
165
    [TPM_ALG_OFB] = ENCRYPTING(ALG_OFB, "ofb", true, 1),
166
    [TPM_ALG_CBC] = ENCRYPTING(ALG_CBC, "cbc", true, 1),
167
    [TPM_ALG_CFB] = ENCRYPTING(ALG_CFB, "cfb", false, 1), // never disable: context entryption
168
    [TPM_ALG_ECB] = ENCRYPTING(ALG_ECB, "ecb", true, 1),
169
    /* all newly added algorithms must have .canBedisable=true so they can be disabled */
170
};
171

172
static const struct {
173
    const char   *name;
174
    BOOL          canBeDisabled;
175
    const char   *prefix;
176
} s_EccShortcuts[] = {
177
#define ECC_SHORTCUT(NAME, CANDISABLE, PREFIX) \
178
    { .name = NAME, .canBeDisabled = CANDISABLE, .prefix = PREFIX }
179
    [RUNTIME_ALGORITHM_ECC_NIST_BIT] = ECC_SHORTCUT("ecc-nist", true, "ecc-nist-p"),
180
    [RUNTIME_ALGORITHM_ECC_BN_BIT] = ECC_SHORTCUT("ecc-bn", true, "ecc-bn-p"),
181
};
182

183
static const struct {
184
    const char   *name;
185
    UINT16        keySize;
186
    BOOL          canBeDisabled;
187
    unsigned int  stateFormatLevel; /* required stateFormatLevel to support this */
188
} s_EccAlgorithmProperties[] = {
189
#define ECC(ENABLED, NAME, KEYSIZE, CANDISABLE, SFL) \
190
    { .name = ENABLED ? NAME : NULL, .keySize = KEYSIZE, .canBeDisabled = CANDISABLE, .stateFormatLevel = SFL }
191

192
    [TPM_ECC_NIST_P192] = ECC(ECC_NIST_P192, "ecc-nist-p192", 192, true, 1),
193
    [TPM_ECC_NIST_P224] = ECC(ECC_NIST_P224, "ecc-nist-p224", 224, true, 1),
194
    [TPM_ECC_NIST_P256] = ECC(ECC_NIST_P256, "ecc-nist-p256", 256, false, 1),
195
    [TPM_ECC_NIST_P384] = ECC(ECC_NIST_P384, "ecc-nist-p384", 384, false, 1),
196
    [TPM_ECC_NIST_P521] = ECC(ECC_NIST_P521, "ecc-nist-p521", 521, true, 1),
197
    [TPM_ECC_BN_P256] = ECC(ECC_BN_P256, "ecc-bn-p256", 256, true, 1),
198
    [TPM_ECC_BN_P638] = ECC(ECC_BN_P638, "ecc-bn-p638", 638, true, 1),
199
    [TPM_ECC_SM2_P256] = ECC(ECC_SM2_P256, "ecc-sm2-p256", 256, true, 1),
200
};
201

202
static const TPM_ALG_ID algsWithKeySizes[] = {
203
    TPM_ALG_RSA,
204
    TPM_ALG_TDES,
205
    TPM_ALG_AES,
206
    TPM_ALG_SM4,
207
    TPM_ALG_CAMELLIA,
208
};
209

210
static unsigned int
211
KeySizesGetMinimum(const struct KeySizes *ks)
212
{
213
    size_t i = 0;
214

215
    while (ks[i].size) {
175,666✔
216
        if (ks[i].enabled)
147,200✔
217
            return ks[i].size;
118,734✔
218
        i++;
28,466✔
219
    }
220
    return 0;
221
}
222

223
static void
224
RuntimeAlgorithmEnableAllAlgorithms(struct RuntimeAlgorithm *RuntimeAlgorithm)
24,318✔
225
{
226
    TPM_ECC_CURVE curveId;
24,318✔
227
    TPM_ALG_ID algId;
24,318✔
228

229
    MemorySet(RuntimeAlgorithm->enabledAlgorithms, 0 , sizeof(RuntimeAlgorithm->enabledAlgorithms));
24,318✔
230

231
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
1,726,578✔
232
        /* skip over unsupported algorithms */
233
        if (!s_AlgorithmProperties[algId].name)
1,677,942✔
234
            continue;
851,130✔
235
        SET_BIT(algId, RuntimeAlgorithm->enabledAlgorithms);
826,812✔
236
    }
237

238
    MemorySet(RuntimeAlgorithm->enabledEccCurves, 0 , sizeof(RuntimeAlgorithm->enabledEccCurves));
24,318✔
239

240
    for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
851,130✔
241
        if (!s_EccAlgorithmProperties[curveId].name)
802,494✔
242
            continue;
607,950✔
243
        SET_BIT(curveId, RuntimeAlgorithm->enabledEccCurves);
194,544✔
244
    }
245
}
24,318✔
246

247
LIB_EXPORT void
248
RuntimeAlgorithmInit(struct RuntimeAlgorithm *RuntimeAlgorithm)
28,466✔
249
{
250
    TPM_ALG_ID algId;
28,466✔
251
    size_t i;
28,466✔
252

253
    MemorySet(RuntimeAlgorithm->algosMinimumKeySizes, 0 , sizeof(RuntimeAlgorithm->algosMinimumKeySizes));
28,466✔
254

255
    for (i = 0; i < ARRAY_SIZE(algsWithKeySizes); i++) {
199,262✔
256
        algId = algsWithKeySizes[i];
142,330✔
257
        assert(algId < ARRAY_SIZE(RuntimeAlgorithm->algosMinimumKeySizes));
142,330✔
258
        assert(s_AlgorithmProperties[algId].u.keySizes != NULL);
142,330✔
259
        RuntimeAlgorithm->algosMinimumKeySizes[algId] = KeySizesGetMinimum(s_AlgorithmProperties[algId].u.keySizes);
142,330✔
260
    }
261
}
28,466✔
262

263
LIB_EXPORT void
264
RuntimeAlgorithmFree(struct RuntimeAlgorithm *RuntimeAlgorithm)
33,085✔
265
{
266
    free(RuntimeAlgorithm->algorithmProfile);
33,085✔
267
    RuntimeAlgorithm->algorithmProfile = NULL;
33,085✔
268
}
33,085✔
269

270
/* Set the default profile with all algorithms and all keysizes enabled */
271
static void
272
RuntimeAlgorithmSetDefault(struct RuntimeAlgorithm *RuntimeAlgorithm)
24,318✔
273
{
274
    RuntimeAlgorithmFree(RuntimeAlgorithm);
24,318✔
275
    RuntimeAlgorithmInit(RuntimeAlgorithm);
24,318✔
276
    RuntimeAlgorithmEnableAllAlgorithms(RuntimeAlgorithm);
24,318✔
277
}
24,318✔
278

279
/* Set the given profile and runtime-enable the given algorithms. A NULL pointer
280
 * for the profile parameter sets the default profile which enables all algorithms
281
 * and all key sizes without any restrictions.
282
 *
283
 * This function will adjust the stateFormatLevel to the number required for the
284
 * given algorithms and key sizes.
285
 */
286
LIB_EXPORT TPM_RC
287
RuntimeAlgorithmSetProfile(struct RuntimeAlgorithm  *RuntimeAlgorithm,
69,055✔
288
                           const char                    *newProfile,                // IN: colon-separated list of algorithm names
289
                           unsigned int             *stateFormatLevel,                // IN/OUT: stateFormatLevel
290
                           unsigned int                     maxStateFormatLevel        // IN: maximum allowed stateFormatLevel
291
                           )
292
{
293
    size_t toklen, cmplen, i, prefix_len, idx;
69,055✔
294
    const char *token, *comma, *prefix;
69,055✔
295
    const struct KeySizes *keysizes;
69,055✔
296
    TPM_RC retVal = TPM_RC_SUCCESS;
69,055✔
297
    unsigned long minKeySize;
69,055✔
298
    TPM_ECC_CURVE curveId;
69,055✔
299
    TPM_ALG_ID algId;
69,055✔
300
    char *endptr;
69,055✔
301
    bool found;
69,055✔
302

303
    /* NULL pointer for profile enables all */
304
    if (!newProfile) {
69,055✔
305
        RuntimeAlgorithmSetDefault(RuntimeAlgorithm);
24,318✔
306
        return TPM_RC_SUCCESS;
24,318✔
307
    }
308

309
    MemorySet(RuntimeAlgorithm->enabledAlgorithms, 0, sizeof(RuntimeAlgorithm->enabledAlgorithms));
44,737✔
310
    MemorySet(RuntimeAlgorithm->enabledEccCurves, 0 , sizeof(RuntimeAlgorithm->enabledEccCurves));
44,737✔
311
    MemorySet(RuntimeAlgorithm->enabledEccShortcuts, 0, sizeof(RuntimeAlgorithm->enabledEccShortcuts));
44,737✔
312

313
    token = newProfile;
44,737✔
314
    while (1) {
3,711,447✔
315
        comma = strchr(token, ALGO_SEPARATOR_C);
3,711,447✔
316
        if (comma)
1,878,092✔
317
            toklen = (size_t)(comma - token);
1,833,355✔
318
        else
319
            toklen = strlen(token);
44,737✔
320

321
        found = false;
1,878,092✔
322
        for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
57,042,129✔
323
            /* skip over unsupported algorithms */
324
            if (!s_AlgorithmProperties[algId].name)
56,907,392✔
325
                continue;
22,956,353✔
326
            cmplen = MAX(strlen(s_AlgorithmProperties[algId].name), toklen);
33,951,039✔
327
            if (!strncmp(token, s_AlgorithmProperties[algId].name, cmplen)) {
33,951,039✔
328
                if (s_AlgorithmProperties[algId].stateFormatLevel > maxStateFormatLevel) {
1,519,594✔
UNCOV
329
                    TPMLIB_LogTPM2Error("Requested algorithm %.*s requires StateFormatLevel %u but maximum allowed is %u.\n",
×
330
                                        (int)toklen, token,
331
                                        s_AlgorithmProperties[algId].stateFormatLevel,
332
                                        maxStateFormatLevel);
333
                    retVal = TPM_RC_VALUE;
×
UNCOV
334
                    goto exit;
×
335
                }
336
                SET_BIT(algId, RuntimeAlgorithm->enabledAlgorithms);
1,519,594✔
337
                assert(s_AlgorithmProperties[algId].stateFormatLevel > 0);
1,519,594✔
338
                *stateFormatLevel = MAX(*stateFormatLevel,
1,519,594✔
339
                                        s_AlgorithmProperties[algId].stateFormatLevel);
340
                found = true;
1,519,594✔
341
                break;
1,519,594✔
342
            } else if (s_AlgorithmProperties[algId].u.minKeySize) {
32,431,445✔
343
                size_t namelen = strlen(s_AlgorithmProperties[algId].name);
1,610,036✔
344
                if (strncmp(token,
1,610,036✔
345
                            s_AlgorithmProperties[algId].name, /* i.e., 'hmac' */
346
                            namelen) ||
152✔
347
                    strncmp(&token[namelen], "-min-key-size=", 14))
152✔
348
                    continue;
1,609,884✔
349
                minKeySize = strtoul(&token[namelen + 14], &endptr, 10);
152✔
350
                if ((*endptr != ALGO_SEPARATOR_C && *endptr != '\0')
152✔
351
                    || minKeySize > MAX_SYM_DATA * 8) {
152✔
352
                    retVal = TPM_RC_KEY_SIZE;
×
UNCOV
353
                    goto exit;
×
354
                }
355
                RuntimeAlgorithm->algosMinimumKeySizes[algId] = (UINT16)minKeySize;
152✔
356
                *stateFormatLevel = MAX(*stateFormatLevel,
152✔
357
                                        s_AlgorithmProperties[algId].u.minKeySize->stateFormatLevel);
358
                found = true;
152✔
359
                break;
152✔
360
            } else if (s_AlgorithmProperties[algId].u.keySizes) {
30,821,409✔
361
                size_t algnamelen = strlen(s_AlgorithmProperties[algId].name);
6,172,218✔
362
                if (strncmp(token, s_AlgorithmProperties[algId].name, algnamelen) ||
6,172,218✔
363
                    strncmp(&token[algnamelen], "-min-size=", 10))
492,165✔
364
                    continue;
5,948,609✔
365
                minKeySize = strtoul(&token[algnamelen + 10], &endptr, 10);
223,609✔
366
                if ((*endptr != ALGO_SEPARATOR_C && *endptr != '\0') ||  minKeySize > 4096) {
223,609✔
367
                    retVal = TPM_RC_KEY_SIZE;
×
UNCOV
368
                    goto exit;
×
369
                }
370

371
                /* determine stateFormatLevel needed; skip those key sizes that exceed max. stateFormatLevel */
372
                keysizes = s_AlgorithmProperties[algId].u.keySizes;
373
                for (i = 0; keysizes[i].size != 0; i++) {
1,118,115✔
374
                    if (keysizes[i].enabled &&
894,506✔
375
                        keysizes[i].size >= minKeySize &&
894,506✔
376
                        keysizes[i].stateFormatLevel <= maxStateFormatLevel) {
894,456✔
377
                        assert(keysizes[i].stateFormatLevel > 0);
785,390✔
378
                        *stateFormatLevel = MAX(*stateFormatLevel,
785,390✔
379
                                                keysizes[i].stateFormatLevel);
380
                    }
381
                }
382

383
                RuntimeAlgorithm->algosMinimumKeySizes[algId] = (UINT16)minKeySize;
223,609✔
384
                found = true;
223,609✔
385
                break;
223,609✔
386
            }
387
        }
388

389
        if (!found) {
1,743,355✔
390
            bool match_one = true;
270,256✔
391

392
            /* handling of ECC curves: shortcuts */
393
            for (idx = 0; idx < ARRAY_SIZE(s_EccShortcuts); idx++) {
270,256✔
394
                cmplen = MAX(strlen(s_EccShortcuts[idx].name), toklen);
224,821✔
395
                if (!strncmp(token, s_EccShortcuts[idx].name, cmplen)) {
224,821✔
396
                    SET_BIT(idx, RuntimeAlgorithm->enabledEccShortcuts);
89,302✔
397
                    match_one = false;
89,302✔
398
                    prefix = s_EccShortcuts[idx].prefix;
89,302✔
399
                    prefix_len = strlen(prefix);
89,302✔
400
                    break;
89,302✔
401
                }
402
            }
403
            if (match_one) {
134,737✔
404
                prefix = token;
45,435✔
405
                prefix_len = toklen;
45,435✔
406
            }
407
            for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
4,581,058✔
408
                if (!s_EccAlgorithmProperties[curveId].name)
4,446,321✔
409
                    continue;
3,368,425✔
410

411
                if (match_one)
1,077,896✔
412
                    cmplen = MAX(strlen(s_EccAlgorithmProperties[curveId].name), toklen);
363,480✔
413
                else
414
                    cmplen = prefix_len;
415

416
                if (!strncmp(prefix, s_EccAlgorithmProperties[curveId].name, cmplen)) {
1,077,896✔
417
                    if (s_EccAlgorithmProperties[curveId].stateFormatLevel > maxStateFormatLevel) {
357,998✔
418
                        /* specific match that is not allowed causes error, otherwise skip */
419
                        if (match_one) {
×
UNCOV
420
                            TPMLIB_LogTPM2Error("Requested curve %s requires StateFormatLevel %u but maximum allowed is %u.\n",
×
421
                                                s_EccAlgorithmProperties[curveId].name,
422
                                                s_EccAlgorithmProperties[curveId].stateFormatLevel,
423
                                                maxStateFormatLevel);
424
                            retVal = TPM_RC_VALUE;
×
UNCOV
425
                            goto exit;
×
426
                        }
UNCOV
427
                        continue;
×
428
                    }
429
                    *stateFormatLevel = MAX(*stateFormatLevel,
357,998✔
430
                                            s_EccAlgorithmProperties[curveId].stateFormatLevel);
431
                    SET_BIT(curveId, RuntimeAlgorithm->enabledEccCurves);
357,998✔
432
                    found = true;
357,998✔
433
                }
434
            }
435
        }
436

437
        if (!found) {
1,878,092✔
UNCOV
438
            TPMLIB_LogTPM2Error("Requested algorithm specifier %.*s is not supported.\n",
×
439
                                (int)toklen, token);
440
            retVal = TPM_RC_VALUE;
×
UNCOV
441
            goto exit;
×
442
        }
443

444
        if (!comma)
1,878,092✔
445
            break;
446
        token = &comma[1];
1,833,355✔
447
    }
448

449
    /* reconcile with what can be disabled per code instrumentation */
450
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
3,131,590✔
451
        /* skip over unsupported algorithms */
452
        if (!s_AlgorithmProperties[algId].name)
3,086,853✔
453
            continue;
1,565,795✔
454
        if (!s_AlgorithmProperties[algId].canBeDisabled &&
2,326,324✔
455
            !TEST_BIT(algId, RuntimeAlgorithm->enabledAlgorithms)) {
805,266✔
UNCOV
456
            TPMLIB_LogTPM2Error("Algorithm %s must be enabled.\n",
×
457
                                s_AlgorithmProperties[algId].name);
458
            retVal = TPM_RC_VALUE;
×
UNCOV
459
            goto exit;
×
460
        }
461
    }
462
    for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
1,521,058✔
463
        if (!s_EccAlgorithmProperties[curveId].name)
1,476,321✔
464
            continue;
1,118,425✔
465
        if (!s_EccAlgorithmProperties[curveId].canBeDisabled &&
447,370✔
466
            !TEST_BIT(curveId, RuntimeAlgorithm->enabledEccCurves)) {
89,474✔
UNCOV
467
            TPMLIB_LogTPM2Error("Elliptic curve %s must be enabled.\n",
×
468
                                s_EccAlgorithmProperties[curveId].name);
469
            retVal = TPM_RC_VALUE;
×
UNCOV
470
            goto exit;
×
471
        }
472
        /* disable curves that can be disabled and not meet min. keysize */
473
        if (RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_ECC] >
357,896✔
474
               s_EccAlgorithmProperties[curveId].keySize &&
357,896✔
475
            s_EccAlgorithmProperties[curveId].canBeDisabled)
476
            CLEAR_BIT(curveId, RuntimeAlgorithm->enabledEccCurves);
24✔
477
    }
478

479
    /* some consistency checks */
480
    /* Do not allow aes-min-size > 128 while RSA=2048 otherwise standard EK certs cannot be created anymore */
481
    if (RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_AES] > 128 &&
44,737✔
482
        RuntimeAlgorithm->algosMinimumKeySizes[TPM_ALG_RSA] == 2048) {
×
UNCOV
483
        TPMLIB_LogTPM2Error("AES minimum key size must be 128 when "
×
484
                            "2048 bit %s keys are used.\n",
485
                            "RSA");
486
        retVal = TPM_RC_KEY_SIZE;
×
UNCOV
487
        goto exit;
×
488
    }
489

490
    free(RuntimeAlgorithm->algorithmProfile);
44,737✔
491
    RuntimeAlgorithm->algorithmProfile = strdup(newProfile);
44,737✔
492
    if (!RuntimeAlgorithm->algorithmProfile)
44,737✔
493
        retVal = TPM_RC_MEMORY;
494

495
exit:
44,737✔
496
    if (retVal != TPM_RC_SUCCESS)
×
UNCOV
497
        RuntimeAlgorithmSetDefault(RuntimeAlgorithm);
×
498

499
    return retVal;
500
}
501

502
LIB_EXPORT TPM_RC
503
RuntimeAlgorithmSwitchProfile(struct RuntimeAlgorithm  *RuntimeAlgorithm,
8,046✔
504
                              const char               *newProfile,
505
                              unsigned int              maxStateFormatLevel,
506
                              char                    **oldProfile)
507
{
508
    TPM_RC retVal;
8,046✔
509
    unsigned int stateFormatLevel = 0; // ignored
8,046✔
510

511
    *oldProfile = RuntimeAlgorithm->algorithmProfile;
8,046✔
512
    RuntimeAlgorithm->algorithmProfile = NULL;
8,046✔
513

514
    retVal = RuntimeAlgorithmSetProfile(RuntimeAlgorithm, newProfile,
8,046✔
515
                                        &stateFormatLevel, maxStateFormatLevel);
516
    if (retVal != TPM_RC_SUCCESS) {
8,046✔
UNCOV
517
        RuntimeAlgorithmSetProfile(RuntimeAlgorithm, *oldProfile,
×
518
                                   &stateFormatLevel, maxStateFormatLevel);
UNCOV
519
        *oldProfile = NULL;
×
520
    }
521
    return retVal;
8,046✔
522
}
523

524
/* Check whether the given algorithm is runtime-enabled */
525
LIB_EXPORT BOOL
526
RuntimeAlgorithmCheckEnabled(struct RuntimeAlgorithm *RuntimeAlgorithm,
641,369✔
527
                             TPM_ALG_ID                      algId      // IN: the algorithm to check
528
                             )
529
{
530
    if ((algId >> 3) >= sizeof(RuntimeAlgorithm->enabledAlgorithms) ||
1,282,738✔
531
        !TestBit(algId, RuntimeAlgorithm->enabledAlgorithms,
641,369✔
532
                 sizeof(RuntimeAlgorithm->enabledAlgorithms)))
533
        return FALSE;
16,798✔
534
    return TRUE;
535
}
536

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

559
    if (!RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
5,263✔
560
        return FALSE;
561

562
    minKeySize = RuntimeAlgorithm->algosMinimumKeySizes[algId];
5,263✔
563
    if (minKeySize > keySizeInBits)
5,263✔
564
        return FALSE;
565

566
    if (s_AlgorithmProperties[algId].u.minKeySize)
5,259✔
567
        return TRUE;
568

569
    if (algId == TPM_ALG_ECC) {
5,191✔
570
        if ((curveId >> 3) >= sizeof(RuntimeAlgorithm->enabledEccCurves) ||
1,760✔
571
            !TestBit(curveId, RuntimeAlgorithm->enabledEccCurves,
880✔
572
                     sizeof(RuntimeAlgorithm->enabledEccCurves))) {
573
            return FALSE;
3✔
574
        }
575
    }
576

577
    keysizes = s_AlgorithmProperties[algId].u.keySizes;
5,188✔
578
    for (i = 0; keysizes[i].size != 0; i++) {
10,762✔
579
        if (keysizes[i].size == keySizeInBits) {
10,762✔
580
            if (keysizes[i].enabled &&
5,188✔
581
                keysizes[i].stateFormatLevel > maxStateFormatLevel) {
5,188✔
582
                return FALSE;
583
            }
584
            return TRUE;
5,068✔
585
        }
586
    }
587

588
    return TRUE;
589
}
590

591
static char *
592
RuntimeAlgorithmGetEcc(struct RuntimeAlgorithm   *RuntimeAlgorithm,
3,896✔
593
                       enum RuntimeAlgorithmType rat,
594
                       char                      *buffer,
595
                       BOOL                      *first)
596
{
597
    TPM_ECC_CURVE curveId;
3,896✔
598
    char *nbuffer = NULL;
3,896✔
599
    size_t idx;
3,896✔
600
    int n;
3,896✔
601

602
    for (idx = 0; idx < ARRAY_SIZE(s_EccShortcuts); idx++) {
11,688✔
603
        switch (rat) {
7,792✔
604
        case RUNTIME_ALGO_IMPLEMENTED:
605
            // no filter;
606
            break;
607
        case RUNTIME_ALGO_CAN_BE_DISABLED:
1,948✔
608
            if (!s_EccShortcuts[idx].canBeDisabled)
1,948✔
UNCOV
609
                continue;
×
610
            break;
611
        case RUNTIME_ALGO_ENABLED:
1,948✔
612
            if (!TEST_BIT(idx, RuntimeAlgorithm->enabledEccShortcuts))
1,948✔
613
                continue;
541✔
614
            break;
615
        case RUNTIME_ALGO_DISABLED:
1,948✔
616
            if (TEST_BIT(idx, RuntimeAlgorithm->enabledEccShortcuts))
1,948✔
617
                continue;
1,407✔
618
            break;
619
        default:
620
            break;
621
        }
622
        n = asprintf(&nbuffer, "%s%s%s",
11,688✔
623
                     buffer,
624
                     *first ? "" : ALGO_SEPARATOR_STR,
5,844✔
625
                     s_EccShortcuts[idx].name);
5,844✔
626
        free(buffer);
5,844✔
627
        if (n < 0)
5,844✔
628
            return NULL;
629
        buffer = nbuffer;
5,844✔
630
        *first = false;
5,844✔
631
    }
632

633
    for (curveId = 0; curveId < ARRAY_SIZE(s_EccAlgorithmProperties); curveId++) {
132,464✔
634
        if (!s_EccAlgorithmProperties[curveId].name)
128,568✔
635
            continue;
97,400✔
636

637
        switch (rat) {
31,168✔
638
        case RUNTIME_ALGO_IMPLEMENTED:
639
            // no filter
640
            break;
641
        case RUNTIME_ALGO_CAN_BE_DISABLED:
7,792✔
642
            if (!s_EccAlgorithmProperties[curveId].canBeDisabled)
7,792✔
643
               continue;
1,948✔
644
            break;
645
        case RUNTIME_ALGO_ENABLED:
7,792✔
646
            if (!TEST_BIT(curveId, RuntimeAlgorithm->enabledEccCurves))
7,792✔
647
                continue;
1,914✔
648
            break;
649
        case RUNTIME_ALGO_DISABLED:
7,792✔
650
            if (TEST_BIT(curveId, RuntimeAlgorithm->enabledEccCurves))
7,792✔
651
                continue;
5,878✔
652
            break;
653
        default:
654
            break;
655
        }
656
        n = asprintf(&nbuffer, "%s%s%s",
42,856✔
657
                     buffer,
658
                     *first ? "" : ALGO_SEPARATOR_STR,
21,428✔
659
                     s_EccAlgorithmProperties[curveId].name);
660
        free(buffer);
21,428✔
661
        if (n < 0)
21,428✔
662
            return NULL;
663
        buffer = nbuffer;
21,428✔
664
        *first = FALSE;
21,428✔
665
    }
666

667
    return buffer;
668
}
669

670
LIB_EXPORT char *
671
RuntimeAlgorithmPrint(struct RuntimeAlgorithm   *RuntimeAlgorithm,
3,896✔
672
                      enum RuntimeAlgorithmType rat)
673
{
674
    char *buffer, *nbuffer = NULL;
3,896✔
675
    unsigned int minKeySize;
3,896✔
676
    TPM_ALG_ID algId;
3,896✔
677
    int n;
3,896✔
678
    BOOL first = true;
3,896✔
679

680
    buffer = strdup("\"");
3,896✔
681
    if (!buffer)
3,896✔
682
        return NULL;
683

684
    for (algId = 0; algId < ARRAY_SIZE(s_AlgorithmProperties); algId++) {
272,720✔
685
        // skip over unsupported algorithms
686
        if (!s_AlgorithmProperties[algId].name)
268,824✔
687
            continue;
136,360✔
688
        switch (rat) {
132,464✔
689
        case RUNTIME_ALGO_IMPLEMENTED:
690
            // no filter
691
            break;
692
        case RUNTIME_ALGO_CAN_BE_DISABLED:
33,116✔
693
            if (!s_AlgorithmProperties[algId].canBeDisabled)
33,116✔
694
                 goto skip; // TPM_ALG_ECC: need to print more
17,532✔
695
            break;
696
        case RUNTIME_ALGO_ENABLED:
33,116✔
697
            // skip over disabled ones
698
            if (!RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
33,116✔
699
                goto skip;
7,981✔
700
            break;
701
        case RUNTIME_ALGO_DISABLED:
33,116✔
702
            // skip over enabled ones
703
            if (RuntimeAlgorithmCheckEnabled(RuntimeAlgorithm, algId))
33,116✔
704
                goto skip;
25,135✔
705
            break;
706
        default:
×
UNCOV
707
            continue;
×
708
        }
709
        n = asprintf(&nbuffer, "%s%s%s",
163,632✔
710
                     buffer,
711
                     first ? "" : ALGO_SEPARATOR_STR,
81,816✔
712
                     s_AlgorithmProperties[algId].name);
713
        free(buffer);
81,816✔
714
        if (n < 0)
81,816✔
715
             return NULL;
716

717
        buffer = nbuffer;
81,816✔
718
        first = false;
81,816✔
719

720
        minKeySize = 0;
81,816✔
721

722
        switch (rat) {
81,816✔
723
        case RUNTIME_ALGO_IMPLEMENTED:
33,116✔
724
            if (s_AlgorithmProperties[algId].u.keySizes) {
33,116✔
725
                minKeySize = KeySizesGetMinimum(s_AlgorithmProperties[algId].u.keySizes);
9,332✔
726
            } else if (s_AlgorithmProperties[algId].u.minKeySize) {
28,246✔
727
                /* for it to appear as 'Implemented' */
728
                minKeySize = 1;
729
            }
730
            break;
731
        case RUNTIME_ALGO_ENABLED:
25,135✔
732
            if (s_AlgorithmProperties[algId].u.keySizes ||
25,135✔
733
                s_AlgorithmProperties[algId].u.minKeySize) {
21,446✔
734
                minKeySize = RuntimeAlgorithm->algosMinimumKeySizes[algId];
4,462✔
735
            }
736
            break;
737
        default:
738
            break;
739
        }
740
        if (minKeySize > 0) {
9,332✔
741
            const char *key = "";
9,653✔
742
            if (s_AlgorithmProperties[algId].u.minKeySize)
9,653✔
743
                key = "key-";
1,098✔
744

745
            n = asprintf(&nbuffer, "%s%s%s-min-%ssize=%u",
19,306✔
746
                         buffer,
747
                         ALGO_SEPARATOR_STR,
748
                         s_AlgorithmProperties[algId].name,
9,653✔
749
                         key,
750
                         minKeySize);
751
            free(buffer);
9,653✔
752
            if (n < 0)
9,653✔
753
                return NULL;
754

755
            buffer = nbuffer;
9,653✔
756
        }
757

758
skip:
653✔
759
        if (algId == TPM_ALG_ECC)
132,464✔
760
            buffer = RuntimeAlgorithmGetEcc(RuntimeAlgorithm, rat, buffer, &first);
3,896✔
761
    }
762

763
    n = asprintf(&nbuffer, "%s\"", buffer);
3,896✔
764
    free(buffer);
3,896✔
765
    if (n < 0)
3,896✔
766
        return NULL;
767

768
    return nbuffer;
3,896✔
769
}
770

771
LIB_EXPORT void
772
RuntimeAlgorithmsFilterPCRSelection(TPML_PCR_SELECTION *pcrSelection // IN/OUT: PCRSelection to filter
131✔
773
                                    )
774
{
775
    UINT32 i = 0;
131✔
776

777
    while (i < pcrSelection->count) {
655✔
778
        if (!RuntimeAlgorithmCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm,
524✔
779
                                          pcrSelection->pcrSelections[i].hash)) {
524✔
780
            pcrSelection->count--;
53✔
781
            if (pcrSelection->count - 1 > i) {
53✔
782
                MemoryCopy(&pcrSelection->pcrSelections[i],
28✔
783
                           &pcrSelection->pcrSelections[i + 1],
28✔
784
                           sizeof(pcrSelection->pcrSelections[0]) * (pcrSelection->count - i));
28✔
785
            }
786
        } else {
787
            i++;
471✔
788
        }
789
    }
790
}
131✔
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