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

stefanberger / libtpms / #2040

14 Dec 2025 07:31PM UTC coverage: 77.163% (-0.01%) from 77.176%
#2040

push

travis-ci

web-flow
Merge 7788dcce7 into 4f71e9b45

1062 of 1261 new or added lines in 87 files covered. (84.22%)

1813 existing lines in 64 files now uncovered.

36347 of 47104 relevant lines covered (77.16%)

126364.7 hits per line

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

89.14
/src/tpm2/TPMCmd/tpm/src/crypt/AlgorithmTests.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
//** Introduction
4
// This file contains the code to perform the various self-test functions.
5
//
6
// NOTE: In this implementation, large local variables are made static to minimize
7
// stack usage, which is critical for stack-constrained platforms.
8

9
//** Includes and Defines
10
#include "Tpm.h"
11

12
#define SELF_TEST_DATA
13

14
#if ENABLE_SELF_TESTS
15

16
// These includes pull in the data structures. They contain data definitions for the
17
// various tests.
18
#  include "SelfTest.h"
19
#  include "SymmetricTest.h"
20
#  include "RsaTestData.h"
21
#  include "EccTestData.h"
22
#  include "HashTestData.h"
23
#  include "KdfTestData.h"
24

25
#  define TEST_DEFAULT_TEST_HASH(vector)        \
26
      if(TEST_BIT(DEFAULT_TEST_HASH, g_toTest)) \
27
          TestHash(DEFAULT_TEST_HASH, vector);
28

29
// Make sure that the algorithm has been tested
30
#  define CLEAR_BOTH(alg)               \
31
      {                                 \
32
          CLEAR_BIT(alg, *toTest);      \
33
          if(toTest != &g_toTest)       \
34
              CLEAR_BIT(alg, g_toTest); \
35
      }
36

37
#  define SET_BOTH(alg)               \
38
      {                               \
39
          SET_BIT(alg, *toTest);      \
40
          if(toTest != &g_toTest)     \
41
              SET_BIT(alg, g_toTest); \
42
      }
43

44
#  define TEST_BOTH(alg)                                                         \
45
      ((toTest != &g_toTest) ? TEST_BIT(alg, *toTest) || TEST_BIT(alg, g_toTest) \
46
                             : TEST_BIT(alg, *toTest))
47

48
// Can only cancel if doing a list.
49
#  define CHECK_CANCELED                             \
50
      if(_plat__IsCanceled() && toTest != &g_toTest) \
51
          return TPM_RC_CANCELED;
52

53
//** Hash Tests
54

55
//*** Description
56
// The hash test does a known-value HMAC using the specified hash algorithm.
57

58
//*** TestHash()
59
// The hash test function.
60
static TPM_RC TestHash(TPM_ALG_ID hashAlg, ALGORITHM_VECTOR* toTest)
9,374✔
61
{
62
    static TPM2B_DIGEST computed;  // value computed
9,374✔
63
    static HMAC_STATE   state;
9,374✔
64
    UINT16              digestSize;
9,374✔
65
    const TPM2B*        testDigest = NULL;
9,374✔
66
    //    TPM2B_TYPE(HMAC_BLOCK, DEFAULT_TEST_HASH_BLOCK_SIZE);
67

68
    pAssert_RC(hashAlg != TPM_ALG_NULL);
9,374✔
69
#  define HASH_CASE_FOR_TEST(HASH, hash)     \
70
      case ALG_##HASH##_VALUE:               \
71
          testDigest = &c_##HASH##_digest.b; \
72
          break;
73
    switch(hashAlg)
9,374✔
74
    {
75
        FOR_EACH_HASH(HASH_CASE_FOR_TEST)
1,331✔
76

UNCOV
77
        default:
×
UNCOV
78
            FAIL(FATAL_ERROR_INTERNAL);
×
79
    }
80
    // Clear the to-test bits
81
    CLEAR_BOTH(hashAlg);
9,374✔
82

83
    // If there is an algorithm without test vectors, then assume that things are OK.
84
    if(testDigest == NULL || testDigest->size == 0)
9,374✔
85
        return TPM_RC_SUCCESS;
86

87
    // Set the HMAC key to twice the digest size
88
    digestSize = CryptHashGetDigestSize(hashAlg);
9,374✔
89
    CryptHmacStart(&state, hashAlg, digestSize * 2, (BYTE*)c_hashTestKey.t.buffer);
9,374✔
90
    CryptDigestUpdate(&state.hashState,
18,748✔
91
                      2 * CryptHashGetBlockSize(hashAlg),
9,374✔
92
                      (BYTE*)c_hashTestData.t.buffer);
93
    computed.t.size = digestSize;
9,374✔
94
    CryptHmacEnd(&state, digestSize, computed.t.buffer);
9,374✔
95
    if((testDigest->size != computed.t.size)
9,374✔
96
       || (memcmp(testDigest->buffer, computed.t.buffer, computed.b.size) != 0))
9,374✔
UNCOV
97
        SELF_TEST_FAILURE;
×
98
    return TPM_RC_SUCCESS;
99
}
100
// libtpms added begin
101
#if SMAC_IMPLEMENTED && ALG_CMAC
102
static TPM_RC
103
TestSMAC(
23✔
104
         ALGORITHM_VECTOR    *toTest LIBTPMS_ATTR_UNUSED
105
         )
106
{
107
    HMAC_STATE          state;
23✔
108
    UINT16              copied;
23✔
109
    BYTE                out[MAX_SYM_BLOCK_SIZE];
23✔
110
    UINT32              outSize = sizeof(out);
23✔
111
    UINT16              blocksize;
23✔
112
    int                 i;
23✔
113
    TPMU_PUBLIC_PARMS   cmac_keyParms;
23✔
114

115
    // initializing this statically seems impossible with gcc...
116
    cmac_keyParms.symDetail.sym.algorithm = TPM_ALG_AES;
23✔
117
    cmac_keyParms.symDetail.sym.keyBits.sym = 128;
23✔
118

119
    for (i = 0; CMACTests[i].key; i++ )
115✔
120
        {
121
            blocksize = CryptMacStart(&state, &cmac_keyParms,
92✔
122
                                      TPM_ALG_CMAC, CMACTests[i].key);
123
            pAssert(blocksize <= outSize);
92✔
124
            CryptDigestUpdate(&state.hashState, CMACTests[i].datalen,
92✔
125
                              CMACTests[i].data);
92✔
126
            copied = CryptMacEnd(&state, outSize, out);
92✔
127
            if((CMACTests[i].outlen != copied)
92✔
128
              || (memcmp(out, CMACTests[i].out, CMACTests[i].outlen) != 0)) {
92✔
UNCOV
129
                SELF_TEST_FAILURE;
×
130
            }
131
        }
132
    return TPM_RC_SUCCESS;
23✔
133
}
134
#endif
135
// libtpms added end
136

137
//** Symmetric Test Functions
138

139
//*** MakeIv()
140
// Internal function to make the appropriate IV depending on the mode.
141
static UINT32 MakeIv(TPM_ALG_ID mode,  // IN: symmetric mode
1,068✔
142
                     UINT32     size,  // IN: block size of the algorithm
143
                     BYTE*      iv     // OUT: IV to fill in
144
)
145
{
146
    BYTE i;
1,068✔
147

148
    if(mode == TPM_ALG_ECB)
1,068✔
149
        return 0;
150
    if(mode == TPM_ALG_CTR)
872✔
151
    {
152
        // The test uses an IV that has 0xff in the last byte
153
        for(i = 1; i <= size; i++)
2,980✔
154
            *iv++ = 0xff - (BYTE)(size - i);
2,784✔
155
    }
156
    else
157
    {
158
        for(i = 0; i < size; i++)
9,732✔
159
            *iv++ = i;
9,056✔
160
    }
161
    return size;
162
}
163

164
//*** TestSymmetricAlgorithm()
165
// Function to test a specific algorithm, key size, and mode.
166
static void TestSymmetricAlgorithm(const SYMMETRIC_TEST_VECTOR* test,  //
675✔
167
                                   TPM_ALG_ID                   mode   //
168
)
169
{
170
    static BYTE     encrypted[MAX_SYM_BLOCK_SIZE * 2];
675✔
171
    static BYTE     decrypted[MAX_SYM_BLOCK_SIZE * 2];
675✔
172
    static TPM2B_IV iv;
675✔
173

174
    // libtpms added begin
175
    if (test->dataOut[mode - TPM_ALG_CTR] == NULL)
675✔
176
        return;
177
    /* Skip test cases whose algorithms or keysizes are runtime-disabled */
178
    if (!RuntimeAlgorithmKeySizeCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm,
609✔
179
                                             test->alg, test->keyBits,
609✔
180
                                             TPM_ECC_NONE,
181
                                             g_RuntimeProfile.stateFormatLevel))
182
        return;
183
    // libtpms added end
184

185
    //
186
    // Get the appropriate IV
187
    iv.t.size = (UINT16)MakeIv(mode, test->ivSize, iv.t.buffer);
534✔
188

189
    // Encrypt known data
190
    CryptSymmetricEncrypt(encrypted,
534✔
191
                          test->alg,
534✔
192
                          test->keyBits,
534✔
193
                          test->key,
534✔
194
                          &iv,
195
                          mode,
196
                          test->dataInOutSize,
534✔
197
                          test->dataIn);
534✔
198
    // Check that it matches the expected value
199
    if(!MemoryEqual(
534✔
200
           encrypted, test->dataOut[mode - TPM_ALG_CTR], test->dataInOutSize))
534✔
UNCOV
201
        SELF_TEST_FAILURE;
×
202
    // Reinitialize the iv for decryption
203
    MakeIv(mode, test->ivSize, iv.t.buffer);
534✔
204
    CryptSymmetricDecrypt(decrypted,
534✔
205
                          test->alg,
534✔
206
                          test->keyBits,
534✔
207
                          test->key,
534✔
208
                          &iv,
209
                          mode,
210
                          test->dataInOutSize,
534✔
211
                          test->dataOut[mode - TPM_ALG_CTR]);
534✔
212
    // Make sure that it matches what we started with
213
    if(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize))
534✔
UNCOV
214
        SELF_TEST_FAILURE;
×
215
}
216

217
//*** AllSymsAreDone()
218
// Checks if both symmetric algorithms have been tested. This is put here
219
// so that addition of a symmetric algorithm will be relatively easy to handle.
220
//
221
//  Return Type: BOOL
222
//      TRUE(1)         all symmetric algorithms tested
223
//      FALSE(0)        not all symmetric algorithms tested
224
static BOOL AllSymsAreDone(ALGORITHM_VECTOR* toTest)
45✔
225
{
226
    return (!TEST_BOTH(TPM_ALG_AES) && !TEST_BOTH(TPM_ALG_SM4));
45✔
227
}
228

229
//*** AllModesAreDone()
230
// Checks if all the modes have been tested.
231
//
232
//  Return Type: BOOL
233
//      TRUE(1)         all modes tested
234
//      FALSE(0)        all modes not tested
235
static BOOL AllModesAreDone(ALGORITHM_VECTOR* toTest)
8✔
236
{
237
    TPM_ALG_ID alg;
8✔
238
    for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++)
32✔
239
        if(TEST_BOTH(alg))
40✔
240
            return FALSE;
241
    return TRUE;
242
}
243

244
//*** TestSymmetric()
245
// If 'alg' is a symmetric block cipher, then all of the modes that are selected are
246
// tested. If 'alg' is a mode, then all algorithms of that mode are tested.
247
static TPM_RC TestSymmetric(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest)
53✔
248
{
249
    SYM_INDEX  index;
53✔
250
    TPM_ALG_ID mode;
53✔
251
    //
252
    if(!TEST_BIT(alg, *toTest))
53✔
253
        return TPM_RC_SUCCESS;
254
    if(alg == TPM_ALG_AES || alg == TPM_ALG_SM4 || alg == TPM_ALG_CAMELLIA || alg == TPM_ALG_TDES)        // libtpms added TPM_ALG_TDES
53✔
255
    {
256
        // Will test the algorithm for all modes and key sizes
257
        CLEAR_BOTH(alg);
45✔
258

259
        // A test this algorithm for all modes
260
        for(index = 0; index < NUM_SYMS; index++)
495✔
261
        {
262
            if(c_symTestValues[index].alg == alg)
450✔
263
            {
264
                for(mode = SYM_MODE_FIRST; mode <= SYM_MODE_LAST; mode++)
810✔
265
                {
266
                    if(TEST_BIT(mode, g_implementedAlgorithms)) // libtpms always test implemented modes
675✔
267
                        TestSymmetricAlgorithm(&c_symTestValues[index], mode);
675✔
268
                }
269
            }
270
        }
271
        // if all the symmetric tests are done
272
        if(AllSymsAreDone(toTest))
45✔
273
        {
274
            // all symmetric algorithms tested so no modes should be set
275
            for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++)
204✔
276
                CLEAR_BOTH(alg);
170✔
277
        }
278
    }
279
    else if(SYM_MODE_FIRST <= alg && alg <= SYM_MODE_LAST)
280
    {
281
        // Test this mode for all key sizes and algorithms
282
        for(index = 0; index < NUM_SYMS; index++)
88✔
283
        {
284
            // The mode testing only comes into play when doing self tests
285
            // by command. When doing self tests by command, the block ciphers are
286
            // tested first. That means that all of their modes would have been
287
            // tested for all key sizes. If there is no block cipher left to
288
            // test, then clear this mode bit.
289
            if(!TEST_BIT(TPM_ALG_AES, *toTest) && !TEST_BIT(TPM_ALG_SM4, *toTest))
80✔
290
            {
291
                CLEAR_BOTH(alg);
80✔
292
            }
293
            else
294
            {
UNCOV
295
                for(index = 0; index < NUM_SYMS; index++)
×
296
                {
UNCOV
297
                    if(TEST_BIT(c_symTestValues[index].alg, *toTest))
×
UNCOV
298
                        TestSymmetricAlgorithm(&c_symTestValues[index], alg);
×
299
                }
300
                // have tested this mode for all algorithms
301
                CLEAR_BOTH(alg);
80✔
302
            }
303
        }
304
        if(AllModesAreDone(toTest))
8✔
305
        {
UNCOV
306
            CLEAR_BOTH(TPM_ALG_AES);
×
UNCOV
307
            CLEAR_BOTH(TPM_ALG_SM4);
×
308
        }
309
    }
310
    else
NEW
311
        pAssert_RC(alg == 0 && alg != 0);
×
312
    return TPM_RC_SUCCESS;
313
}
314

315
//** RSA Tests
316
#  if ALG_RSA
317

318
//*** Introduction
319
// The tests are for public key only operations and for private key operations.
320
// Signature verification and encryption are public key operations. They are tested
321
// by using a KVT. For signature verification, this means that a known good
322
// signature is checked by CryptRsaValidateSignature(). If it fails, then the
323
// TPM enters failure mode. For encryption, the TPM encrypts known values using
324
// the selected scheme and checks that the returned value matches the expected
325
// value.
326
//
327
// For private key operations, a full scheme check is used. For a signing key, a
328
// known key is used to sign a known message. Then that signature is verified.
329
// since the signature may involve use of random values, the signature will be
330
// different each time and we can't always check that the signature matches a
331
// known value. The same technique is used for decryption (RSADP/RSAEP).
332
//
333
// When an operation uses the public key and the verification has not been
334
// tested, the TPM will do a KVT.
335
//
336
// The test for the signing algorithm is built into the call for the algorithm
337

338
//*** RsaKeyInitialize()
339
// The test key is defined by a public modulus and a private prime. The TPM's RSA
340
// code computes the second prime and the private exponent.
341
static void RsaKeyInitialize(OBJECT* testObject)
82✔
342
{
343
    MemoryCopy2B(&testObject->publicArea.unique.rsa.b,
82✔
344
                 (P2B)&c_rsaPublicModulus,
345
                 sizeof(c_rsaPublicModulus));
346
    MemoryCopy2B(&testObject->sensitive.sensitive.rsa.b,
82✔
347
                 (P2B)&c_rsaPrivatePrime,
348
                 sizeof(testObject->sensitive.sensitive.rsa.t.buffer));
349
    testObject->publicArea.parameters.rsaDetail.keyBits = RSA_TEST_KEY_SIZE * 8;
82✔
350
    // Use the default exponent
351
    testObject->publicArea.parameters.rsaDetail.exponent = 0;
82✔
352
    testObject->attributes.privateExp = 0;                        // libtpms: keep
82✔
353
}
82✔
354

355
//*** TestRsaEncryptDecrypt()
356
// These tests are for a public key encryption that uses a random value.
357
static TPM_RC TestRsaEncryptDecrypt(TPM_ALG_ID        scheme,  // IN: the scheme
45✔
358
                                    ALGORITHM_VECTOR* toTest   //
359
)
360
{
361
    static TPM2B_PUBLIC_KEY_RSA testInput;
45✔
362
    static TPM2B_PUBLIC_KEY_RSA testOutput;
45✔
363
    static OBJECT               testObject;
45✔
364
    const TPM2B_RSA_TEST_KEY*   kvtValue  = NULL;
45✔
365
    TPM_RC                      result    = TPM_RC_SUCCESS;
45✔
366
    const TPM2B*                testLabel = NULL;
45✔
367
    TPMT_RSA_DECRYPT            rsaScheme;
45✔
368
    //
369
    // Don't need to initialize much of the test object
370
    testObject.attributes.privateExp = CLEAR;                        // libtpms: keep
45✔
371
    RsaKeyInitialize(&testObject);
45✔
372
    rsaScheme.scheme                 = scheme;
45✔
373
    rsaScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH;
45✔
374
    CLEAR_BOTH(scheme);
45✔
375
    CLEAR_BOTH(TPM_ALG_NULL);
45✔
376
    if(scheme == TPM_ALG_NULL)
45✔
377
    {
378
        if (RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,        // libtpms added begin
20✔
379
                                                 RUNTIME_ATTRIBUTE_NO_UNPADDED_ENCRYPTION))
380
            return TPM_RC_SUCCESS;        // don't test NULL with RSA        // libtpms added end
381
        // This is an encryption scheme using the private key without any encoding.
382
        memcpy(testInput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue));
20✔
383
        testInput.t.size = sizeof(c_RsaTestValue);
20✔
384
        if(TPM_RC_SUCCESS
20✔
385
           != CryptRsaEncrypt(
20✔
386
               &testOutput, &testInput.b, &testObject, &rsaScheme, NULL, NULL))
UNCOV
387
            SELF_TEST_FAILURE;
×
388
        if(!MemoryEqual(testOutput.t.buffer, c_RsaepKvt.buffer, c_RsaepKvt.size))
20✔
UNCOV
389
            SELF_TEST_FAILURE;
×
390
        MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer));
20✔
391
        if(TPM_RC_SUCCESS
20✔
392
           != CryptRsaDecrypt(
20✔
393
               &testOutput.b, &testInput.b, &testObject, &rsaScheme, NULL))
UNCOV
394
            SELF_TEST_FAILURE;
×
395
        if(!MemoryEqual(testOutput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue)))
20✔
396
            SELF_TEST_FAILURE;
×
397
    }
398
    else
399
    {
400
        // TPM_ALG_RSAES:
401
        // This is an decryption scheme using padding according to
402
        // PKCS#1v2.1, 7.2. This padding uses random bits. To test a public
403
        // key encryption that uses random data, encrypt a value and then
404
        // decrypt the value and see that we get the encrypted data back.
405
        // The hash is not used by this encryption so it can be TMP_ALG_NULL
406

407
        // TPM_ALG_OAEP:
408
        // This is also an decryption scheme and it also uses a
409
        // pseudo-random
410
        // value. However, this also uses a hash algorithm. So, we may need
411
        // to test that algorithm before use.
412
        if(scheme == TPM_ALG_OAEP)
25✔
413
        {
414
            TEST_DEFAULT_TEST_HASH(toTest);
13✔
415
            kvtValue  = &c_OaepKvt;
13✔
416
            testLabel = OAEP_TEST_STRING;
13✔
417
        }
418
        else if(scheme == TPM_ALG_RSAES)
12✔
419
        {
420
            kvtValue  = &c_RsaesKvt;
421
            testLabel = NULL;
422
        }
423
        else
UNCOV
424
            SELF_TEST_FAILURE;
×
425
        // Only use a digest-size portion of the test value
426
        memcpy(testInput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE);
25✔
427
        testInput.t.size = DEFAULT_TEST_DIGEST_SIZE;
25✔
428

429
        // See if the encryption works
430
        if(TPM_RC_SUCCESS
25✔
431
           != CryptRsaEncrypt(
25✔
432
               &testOutput, &testInput.b, &testObject, &rsaScheme, testLabel, NULL))
UNCOV
433
            SELF_TEST_FAILURE;
×
434
        MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer));
25✔
435
        // see if we can decrypt this value and get the original data back
436
        if(TPM_RC_SUCCESS
25✔
437
           != CryptRsaDecrypt(
25✔
438
               &testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel))
UNCOV
439
            SELF_TEST_FAILURE;
×
440
        // See if the results compare
441
        if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE
25✔
442
           || !MemoryEqual(
25✔
443
               testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE))
UNCOV
444
            SELF_TEST_FAILURE;
×
445
        // Now check that the decryption works on a known value
446
        MemoryCopy2B(&testInput.b, (P2B)kvtValue, sizeof(testInput.t.buffer));
25✔
447
        if(TPM_RC_SUCCESS
25✔
448
           != CryptRsaDecrypt(
25✔
449
               &testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel))
UNCOV
450
            SELF_TEST_FAILURE;
×
451
        if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE
25✔
452
           || !MemoryEqual(
25✔
453
               testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE))
UNCOV
454
            SELF_TEST_FAILURE;
×
455
    }
456
    return result;
457
}
458

459
//*** TestRsaSignAndVerify()
460
// This function does the testing of the RSA sign and verification functions. This
461
// test does a KVT.
462
static TPM_RC TestRsaSignAndVerify(TPM_ALG_ID scheme, ALGORITHM_VECTOR* toTest)
37✔
463
{
464
    TPM_RC                result = TPM_RC_SUCCESS;
37✔
465
    static OBJECT         testObject;
37✔
466
    static TPM2B_DIGEST   testDigest;
37✔
467
    static TPMT_SIGNATURE testSig;
37✔
468

469
    // Do a sign and signature verification.
470
    // RSASSA:
471
    // This is a signing scheme according to PKCS#1-v2.1 8.2. It does not
472
    // use random data so there is a KVT for the signing operation. On
473
    // first use of the scheme for signing, use the TPM's RSA key to
474
    // sign a portion of c_RsaTestData and compare the results to c_RsassaKvt. Then
475
    // decrypt the data to see that it matches the starting value. This verifies
476
    // the signature with a KVT
477

478
    // Clear the bits indicating that the function has not been checked. This is to
479
    // prevent looping
480
    CLEAR_BOTH(scheme);
37✔
481
    CLEAR_BOTH(TPM_ALG_NULL);
37✔
482
    CLEAR_BOTH(TPM_ALG_RSA);
37✔
483

484
    RsaKeyInitialize(&testObject);
37✔
485
    memcpy(testDigest.t.buffer, (BYTE*)c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE);
37✔
486
    testDigest.t.size             = DEFAULT_TEST_DIGEST_SIZE;
37✔
487
    testSig.sigAlg                = scheme;
37✔
488
    testSig.signature.rsapss.hash = DEFAULT_TEST_HASH;
37✔
489

490
    // RSAPSS:
491
    // This is a signing scheme a according to PKCS#1-v2.2 8.1 it uses
492
    // random data in the signature so there is no KVT for the signing
493
    // operation. To test signing, the TPM will use the TPM's RSA key
494
    // to sign a portion of c_RsaTestValue and then it will verify the
495
    // signature. For verification, c_RsapssKvt is verified before the
496
    // user signature blob is verified. The worst case for testing of this
497
    // algorithm is two private and one public key operation.
498

499
    // The process is to sign known data. If RSASSA is being done, verify that the
500
    // signature matches the precomputed value. For both, use the signed value and
501
    // see that the verification says that it is a good signature. Then
502
    // if testing RSAPSS, do a verify of a known good signature. This ensures that
503
    // the validation function works.
504

505
    if(TPM_RC_SUCCESS != CryptRsaSign(&testSig, &testObject, &testDigest, NULL))
37✔
UNCOV
506
        SELF_TEST_FAILURE;
×
507
    // For RSASSA, make sure the results is what we are looking for
508
    if(testSig.sigAlg == TPM_ALG_RSASSA)
37✔
509
    {
510
        if(testSig.signature.rsassa.sig.t.size != RSA_TEST_KEY_SIZE
25✔
511
           || !MemoryEqual(c_RsassaKvt.buffer,
25✔
512
                           testSig.signature.rsassa.sig.t.buffer,
513
                           RSA_TEST_KEY_SIZE))
UNCOV
514
            SELF_TEST_FAILURE;
×
515
    }
516
    // See if the TPM will validate its own signatures
517
    if(TPM_RC_SUCCESS
37✔
518
       != CryptRsaValidateSignature(&testSig, &testObject, &testDigest))
37✔
UNCOV
519
        SELF_TEST_FAILURE;
×
520
    // If this is RSAPSS, check the verification with known signature
521
    // Have to copy because  CrytpRsaValidateSignature() eats the signature
522
    if(TPM_ALG_RSAPSS == scheme)
37✔
523
    {
524
        MemoryCopy2B(&testSig.signature.rsapss.sig.b,
12✔
525
                     (P2B)&c_RsapssKvt,
526
                     sizeof(testSig.signature.rsapss.sig.t.buffer));
527
        if(TPM_RC_SUCCESS
12✔
528
           != CryptRsaValidateSignature(&testSig, &testObject, &testDigest))
12✔
UNCOV
529
            SELF_TEST_FAILURE;
×
530
    }
531
    return result;
37✔
532
}
533

534
//*** TestRSA()
535
// Function uses the provided vector to indicate which tests to run. It will clear
536
// the vector after each test is run and also clear g_toTest
537
static TPM_RC TestRsa(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest)
89✔
538
{
539
    TPM_RC result = TPM_RC_SUCCESS;
89✔
540
    //
541
    switch(alg)
89✔
542
    {
543
        case TPM_ALG_NULL:
27✔
544
            // This is the RSAEP/RSADP function. If we are processing a list, don't
545
            // need to test these now because any other test will validate
546
            // RSAEP/RSADP. Can tell this is list of test by checking to see if
547
            // 'toTest' is pointing at g_toTest. If so, this is an isolated test
548
            // an need to go ahead and do the test;
549
            if((toTest == &g_toTest)
27✔
550
               || (!TEST_BIT(TPM_ALG_RSASSA, *toTest)
27✔
551
                   && !TEST_BIT(TPM_ALG_RSAES, *toTest)
20✔
552
                   && !TEST_BIT(TPM_ALG_RSAPSS, *toTest)
20✔
553
                   && !TEST_BIT(TPM_ALG_OAEP, *toTest)))
20✔
554
                // Not running a list of tests or no other tests on the list
555
                // so run the test now
556
                result = TestRsaEncryptDecrypt(alg, toTest);
20✔
557
            // if not running the test now, leave the bit on, just in case things
558
            // get interrupted
559
            break;
560
        case TPM_ALG_OAEP:
25✔
561
        case TPM_ALG_RSAES:
562
            result = TestRsaEncryptDecrypt(alg, toTest);
25✔
563
            break;
25✔
564
        case TPM_ALG_RSAPSS:
37✔
565
        case TPM_ALG_RSASSA:
566
            result = TestRsaSignAndVerify(alg, toTest);
37✔
567
            break;
37✔
UNCOV
568
        default:
×
UNCOV
569
            SELF_TEST_FAILURE;
×
570
    }
571
    return result;
89✔
572
}
573

574
#  endif  // ALG_RSA
575

576
//** ECC Tests
577

578
#  if ALG_ECC
579

580
//*** LoadEccParameter()
581
// This function is mostly for readability and type checking
582
static void LoadEccParameter(TPM2B_ECC_PARAMETER* to,   // target
373✔
583
                             const TPM2B_EC_TEST* from  // source
584
)
585
{
586
    MemoryCopy2B(&to->b, &from->b, sizeof(to->t.buffer));
373✔
587
}
77✔
588

589
//*** LoadEccPoint()
590
static void LoadEccPoint(TPMS_ECC_POINT*      point,  // target
296✔
591
                         const TPM2B_EC_TEST* x,      // source
592
                         const TPM2B_EC_TEST* y)
593
{
594
    MemoryCopy2B(&point->x.b, (TPM2B*)x, sizeof(point->x.t.buffer));
296✔
595
    MemoryCopy2B(&point->y.b, (TPM2B*)y, sizeof(point->y.t.buffer));
296✔
596
}
296✔
597

598
//*** TestECDH()
599
// This test does a KVT on a point multiply.
600
static TPM_RC TestECDH(TPM_ALG_ID        scheme,  // IN: for consistency
219✔
601
                       ALGORITHM_VECTOR* toTest  // IN/OUT: modified after test is run
602
)
603
{
604
    static TPMS_ECC_POINT      Z;
219✔
605
    static TPMS_ECC_POINT      Qe;
219✔
606
    static TPM2B_ECC_PARAMETER ds;
219✔
607
    TPM_RC                     result = TPM_RC_SUCCESS;
219✔
608
    //
609
    NOT_REFERENCED(scheme);
219✔
610
    CLEAR_BOTH(TPM_ALG_ECDH);
219✔
611
    LoadEccParameter(&ds, &c_ecTestKey_ds);
219✔
612
    LoadEccPoint(&Qe, &c_ecTestKey_QeX, &c_ecTestKey_QeY);
219✔
613
    if(TPM_RC_SUCCESS != CryptEccPointMultiply(&Z, c_testCurve, &Qe, &ds, NULL, NULL))
219✔
UNCOV
614
        SELF_TEST_FAILURE;
×
615
    if(!MemoryEqual2B(&c_ecTestEcdh_X.b, &Z.x.b)
219✔
616
       || !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b))
219✔
UNCOV
617
        SELF_TEST_FAILURE;
×
618
    return result;
219✔
619
}
620

621
//*** TestEccSignAndVerify()
622
static TPM_RC TestEccSignAndVerify(TPM_ALG_ID scheme, ALGORITHM_VECTOR* toTest)
77✔
623
{
624
    static OBJECT          testObject;
77✔
625
    static TPMT_SIGNATURE  testSig;
77✔
626
    static TPMT_ECC_SCHEME eccScheme;
77✔
627

628
    testSig.sigAlg                   = scheme;
77✔
629
    testSig.signature.ecdsa.hash     = DEFAULT_TEST_HASH;
77✔
630

631
    eccScheme.scheme                 = scheme;
77✔
632
    eccScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH;
77✔
633

634
    CLEAR_BOTH(scheme);
77✔
635
    CLEAR_BOTH(TPM_ALG_ECDH);
77✔
636

637
    // ECC signature verification testing uses a KVT.
638
    switch(scheme)
77✔
639
    {
640
        case TPM_ALG_ECDSA:
641
            LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r);
66✔
642
            LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s);
66✔
643
            break;
644
        case TPM_ALG_ECSCHNORR:
645
            LoadEccParameter(&testSig.signature.ecschnorr.signatureR,
11✔
646
                             &c_TestEcSchnorr_r);
647
            LoadEccParameter(&testSig.signature.ecschnorr.signatureS,
11✔
648
                             &c_TestEcSchnorr_s);
649
            break;
650
        case TPM_ALG_SM2:
651
            // don't have a test for SM2
652
            return TPM_RC_SUCCESS;
UNCOV
653
        default:
×
UNCOV
654
            SELF_TEST_FAILURE;
×
655
            break;
77✔
656
    }
657
    TEST_DEFAULT_TEST_HASH(toTest);
77✔
658

659
    // Have to copy the key. This is because the size used in the test vectors
660
    // is the size of the ECC parameter for the test key while the size of a point
661
    // is TPM dependent
662
    MemoryCopy2B(&testObject.sensitive.sensitive.ecc.b,
77✔
663
                 &c_ecTestKey_ds.b,
664
                 sizeof(testObject.sensitive.sensitive.ecc.t.buffer));
665
    LoadEccPoint(
77✔
666
        &testObject.publicArea.unique.ecc, &c_ecTestKey_QsX, &c_ecTestKey_QsY);
667
    testObject.publicArea.parameters.eccDetail.curveID = c_testCurve;
77✔
668

669
    if(TPM_RC_SUCCESS
77✔
670
       != CryptEccValidateSignature(
77✔
671
           &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue.b))
672
    {
UNCOV
673
        SELF_TEST_FAILURE;
×
674
    }
675
    CHECK_CANCELED;
77✔
676

677
    // Now sign and verify some data
678
    if(TPM_RC_SUCCESS
77✔
679
       != CryptEccSign(
77✔
680
           &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue, &eccScheme, NULL))
UNCOV
681
        SELF_TEST_FAILURE;
×
682

683
    CHECK_CANCELED;
77✔
684

685
    if(TPM_RC_SUCCESS
77✔
686
       != CryptEccValidateSignature(
77✔
687
           &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue))
688
        SELF_TEST_FAILURE;
×
689

690
    CHECK_CANCELED;
77✔
691

692
    return TPM_RC_SUCCESS;
693
}
694

695
//*** TestKDFa()
696
static TPM_RC TestKDFa(ALGORITHM_VECTOR* toTest)
66✔
697
{
698
    static TPM2B_KDF_TEST_KEY keyOut;
66✔
699
    UINT32                    counter = 0;
66✔
700
    //
701
    CLEAR_BOTH(TPM_ALG_KDF1_SP800_108);
66✔
702

703
    keyOut.t.size = CryptKDFa(KDF_TEST_ALG,
66✔
704
                              &c_kdfTestKeyIn.b,
705
                              &c_kdfTestLabel.b,
706
                              &c_kdfTestContextU.b,
707
                              &c_kdfTestContextV.b,
708
                              TEST_KDF_KEY_SIZE * 8,
709
                              keyOut.t.buffer,
710
                              &counter,
711
                              FALSE);
712
    if(keyOut.t.size != TEST_KDF_KEY_SIZE
66✔
713
       || !MemoryEqual(keyOut.t.buffer, c_kdfTestKeyOut.t.buffer, TEST_KDF_KEY_SIZE))
66✔
UNCOV
714
        SELF_TEST_FAILURE;
×
715

716
    return TPM_RC_SUCCESS;
66✔
717
}
718

719
//*** TestEcc()
720
static TPM_RC TestEcc(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest)
296✔
721
{
722
    TPM_RC result = TPM_RC_SUCCESS;
296✔
723
    NOT_REFERENCED(toTest);
296✔
724
    switch(alg)
296✔
725
    {
726
        case TPM_ALG_ECC:
219✔
727
        case TPM_ALG_ECDH:
728
            // If this is in a loop then see if another test is going to deal with
729
            // this.
730
            // If toTest is not a self-test list
731
            if((toTest == &g_toTest)
219✔
732
               // or this is the only ECC test in the list
733
               || !(TEST_BIT(TPM_ALG_ECDSA, *toTest)
14✔
734
                    || TEST_BIT(TPM_ALG_ECSCHNORR, *toTest)   // libtpms: fixed
7✔
735
                    || TEST_BIT(TPM_ALG_SM2, *toTest)))
7✔
736
            {
737
                result = TestECDH(alg, toTest);
219✔
738
            }
739
            break;
740
        case TPM_ALG_ECDSA:
77✔
741
        case TPM_ALG_ECSCHNORR:
742
        case TPM_ALG_SM2:
743
            result = TestEccSignAndVerify(alg, toTest);
77✔
744
            break;
77✔
UNCOV
745
        default:
×
UNCOV
746
            SELF_TEST_FAILURE;
×
747
            break;
296✔
748
    }
749
    return result;
296✔
750
}
751

752
#  endif  // ALG_ECC
753

754
//*** TestAlgorithm()
755
// Dispatches to the correct test function for the algorithm or gets a list of
756
// testable algorithms.
757
//
758
// If 'toTest' is not NULL, then the test decisions are based on the algorithm
759
// selections in 'toTest'. Otherwise, 'g_toTest' is used. When bits are clear in
760
// 'g_toTest' they will also be cleared 'toTest'.
761
//
762
// If there doesn't happen to be a test for the algorithm, its associated bit is
763
// quietly cleared.
764
//
765
// If 'alg' is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits
766
// for which there is no test (i.e. no tests are actually run but the vector is
767
// cleared).
768
//
769
// Note: 'toTest' will only ever have bits set for implemented algorithms but 'alg'
770
// can be anything.
771
//
772
//  Return Type: TPM_RC
773
//      TPM_RC_CANCELED     test was canceled
774
LIB_EXPORT
775
TPM_RC
776
TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest)
22,446✔
777
{
778
    TPM_ALG_ID first  = (alg == TPM_ALG_ERROR) ? TPM_ALG_FIRST : alg;
22,446✔
779
    TPM_ALG_ID last   = (alg == TPM_ALG_ERROR) ? TPM_ALG_LAST : alg;
22,446✔
780
    BOOL       doTest = (alg != TPM_ALG_ERROR);
22,446✔
781
    TPM_RC     result = TPM_RC_SUCCESS;
22,446✔
782

783
    if(toTest == NULL)
22,446✔
784
        toTest = &g_toTest;
9,648✔
785

786
    // This is kind of strange. This function will either run a test of the selected
787
    // algorithm or just clear a bit if there is no test for the algorithm. So,
788
    // either this loop will be executed once for the selected algorithm or once for
789
    // each of the possible algorithms. If it is executed more than once ('alg' ==
790
    // ALG_ERROR), then no test will be run but bits will be cleared for
791
    // unimplemented algorithms. This was done this way so that there is only one
792
    // case statement with all of the algorithms. It was easier to have one case
793
    // statement than to have multiple ones to manage whenever an algorithm ID is
794
    // added.
795
    for(alg = first; (alg <= last); alg++)
1,444,220✔
796
    {
797
        // if 'alg' was TPM_ALG_ERROR, then we will be cycling through
798
        // values, some of which may not be implemented. If the bit in toTest
799
        // happens to be set, then we could either generated an assert, or just
800
        // silently CLEAR it. Decided to just clear.
801
        if(!TEST_BIT(alg, g_implementedAlgorithms))
1,421,774✔
802
        {
803
            CLEAR_BOTH(alg);
1,000,294✔
804
            continue;
1,000,294✔
805
        }
806
        // Process whatever is left.
807
        // NOTE: since this switch will only be called if the algorithm is
808
        // implemented, it is not necessary to modify this list except to comment
809
        // out the algorithms for which there is no test
810
        switch(alg)
421,480✔
811
        {
812
            // Symmetric block ciphers
813
#  if ALG_AES
814
            case TPM_ALG_AES:
12,516✔
815
// libtpms added begin
816
#  if SMAC_IMPLEMENTED && ALG_CMAC
817
                if (doTest)
12,516✔
818
                {
819
                    result = TestSMAC(toTest);
23✔
820
                    if (result != TPM_RC_SUCCESS)
23✔
821
                        break;
822
                }
823
#  endif
824
// libtpms added end
825
#  endif
826
#  if ALG_SM4
827
                // if SM4 is implemented, its test is like other block ciphers but there
828
                // aren't any test vectors for it yet
829
                //            case TPM_ALG_SM4:
830
#  endif  // ALG_SM4
831
#  if ALG_CAMELLIA
832
            /* fallthrough */
833
            case TPM_ALG_CAMELLIA:  // libtpms activated
834
#  endif
835
#  if ALG_TDES
836
            case TPM_ALG_TDES:      // libtpms added
837
#  endif
838
            // Symmetric modes
839
#  if !ALG_CFB
840
#    error CFB is required in all TPM implementations
841
#  endif  // !ALG_CFB
842
            case TPM_ALG_CFB:
843
                if(doTest)
49,891✔
844
                    result = TestSymmetric(alg, toTest);
45✔
845
                break;
846
#  if ALG_CTR
847
            case TPM_ALG_CTR:
49,942✔
848
#  endif  // ALG_CRT
849
#  if ALG_OFB
850
            case TPM_ALG_OFB:
851
#  endif  // ALG_OFB
852
#  if ALG_CBC
853
            case TPM_ALG_CBC:
854
#  endif  // ALG_CBC
855
#  if ALG_ECB
856
            case TPM_ALG_ECB:
857
#  endif
858
                if(doTest)
49,942✔
859
                    result = TestSymmetric(alg, toTest);
8✔
860
                else
861
                    // If doing the initialization of g_toTest vector, only need
862
                    // to test one of the modes for the symmetric algorithms. If
863
                    // initializing for a SelfTest(FULL_TEST), allow all the modes.
864
                    if(toTest == &g_toTest)
49,934✔
865
                        CLEAR_BIT(alg, *toTest);
49,934✔
866
                break;
867
#  if !ALG_HMAC
868
#    error HMAC is required in all TPM implementations
869
#  endif
870
            case TPM_ALG_HMAC:
12,500✔
871
                // Clear the bit that indicates that HMAC is required because
872
                // HMAC is used as the basic test for all hash algorithms.
873
                CLEAR_BOTH(alg);
12,500✔
874
                // Testing HMAC means test the default hash
875
                if(doTest)
12,500✔
876
                    TestHash(DEFAULT_TEST_HASH, toTest);
7✔
877
                else
878
                    // If not testing, then indicate that the hash needs to be
879
                    // tested because this uses HMAC
880
                    SET_BOTH(DEFAULT_TEST_HASH);
12,493✔
881
                break;
882
// Have to use two arguments for the macro even though only the first is used in the
883
// expansion.
884
#  define HASH_CASE_TEST(HASH, hash) case ALG_##HASH##_VALUE:
885
                FOR_EACH_HASH(HASH_CASE_TEST)
59,185✔
886
#  undef HASH_CASE_TEST
887
                if(doTest)
59,185✔
888
                    result = TestHash(alg, toTest);
9,363✔
889
                break;
890
                // RSA-dependent
891
#  if ALG_RSA
892
            case TPM_ALG_RSA:
12,520✔
893
                CLEAR_BOTH(alg);
12,520✔
894
                if(doTest)
12,520✔
895
                    result = TestRsa(TPM_ALG_NULL, toTest);
27✔
896
                else
897
                    SET_BOTH(TPM_ALG_NULL);
12,493✔
898
                break;
899
            case TPM_ALG_RSASSA:
49,838✔
900
            case TPM_ALG_RSAES:
901
            case TPM_ALG_RSAPSS:
902
            case TPM_ALG_OAEP:
903
            case TPM_ALG_NULL:  // used or RSADP
904
                if(doTest)
49,838✔
905
                    result = TestRsa(alg, toTest);
62✔
906
                break;
907
#  endif  // ALG_RSA
908
#  if ALG_KDF1_SP800_108
909
            case TPM_ALG_KDF1_SP800_108:
12,559✔
910
                if(doTest)
12,559✔
911
                    result = TestKDFa(toTest);
66✔
912
                break;
913
#  endif  // ALG_KDF1_SP800_108
914
#  if ALG_ECC
915
                // ECC dependent but no tests
916
                //        case TPM_ALG_ECDAA:
917
                //        case TPM_ALG_ECMQV:
918
                //        case TPM_ALG_KDF1_SP800_56a:
919
                //        case TPM_ALG_KDF2:
920
                //        case TPM_ALG_MGF1:
921
            case TPM_ALG_ECC:
12,500✔
922
                CLEAR_BOTH(alg);
12,500✔
923
                if(doTest)
12,500✔
924
                    result = TestEcc(TPM_ALG_ECDH, toTest);
7✔
925
                else
926
                    SET_BOTH(TPM_ALG_ECDH);
12,493✔
927
                break;
928
            case TPM_ALG_ECDSA:
37,716✔
929
            case TPM_ALG_ECDH:
930
            case TPM_ALG_ECSCHNORR:
931
                //            case TPM_ALG_SM2:
932
                if(doTest)
37,716✔
933
                    result = TestEcc(alg, toTest);
289✔
934
                break;
935
#  endif  // ALG_ECC
936
            default:
124,829✔
937
                CLEAR_BOTH(alg);
124,829✔
938
                break;
939
        }
940
        if(result != TPM_RC_SUCCESS)
421,480✔
941
            break;
942
    }
943
    return result;
22,446✔
944
}
945

946
#endif  // SELF_TESTS
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