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

stefanberger / libtpms / #2022

23 Sep 2025 01:11PM UTC coverage: 77.227% (+0.009%) from 77.218%
#2022

push

travis-ci

web-flow
Merge a45c293de into 4504f47c6

36116 of 46766 relevant lines covered (77.23%)

125180.04 hits per line

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

82.64
/src/tpm2/CryptUtil.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                        Interfaces to the Crypto Engine                                */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*                                                                                */
7
/*  Licenses and Notices                                                        */
8
/*                                                                                */
9
/*  1. Copyright Licenses:                                                        */
10
/*                                                                                */
11
/*  - Trusted Computing Group (TCG) grants to the user of the source code in        */
12
/*    this specification (the "Source Code") a worldwide, irrevocable,                 */
13
/*    nonexclusive, royalty free, copyright license to reproduce, create         */
14
/*    derivative works, distribute, display and perform the Source Code and        */
15
/*    derivative works thereof, and to grant others the rights granted herein.        */
16
/*                                                                                */
17
/*  - The TCG grants to the user of the other parts of the specification         */
18
/*    (other than the Source Code) the rights to reproduce, distribute,         */
19
/*    display, and perform the specification solely for the purpose of                 */
20
/*    developing products based on such documents.                                */
21
/*                                                                                */
22
/*  2. Source Code Distribution Conditions:                                        */
23
/*                                                                                */
24
/*  - Redistributions of Source Code must retain the above copyright licenses,         */
25
/*    this list of conditions and the following disclaimers.                        */
26
/*                                                                                */
27
/*  - Redistributions in binary form must reproduce the above copyright         */
28
/*    licenses, this list of conditions        and the following disclaimers in the         */
29
/*    documentation and/or other materials provided with the distribution.        */
30
/*                                                                                */
31
/*  3. Disclaimers:                                                                */
32
/*                                                                                */
33
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF        */
34
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH        */
35
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)        */
36
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.                */
37
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for                 */
38
/*  information on specification licensing rights available through TCG         */
39
/*  membership agreements.                                                        */
40
/*                                                                                */
41
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED         */
42
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR         */
43
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR                 */
44
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY                 */
45
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.                */
46
/*                                                                                */
47
/*  - Without limitation, TCG and its members and licensors disclaim all         */
48
/*    liability, including liability for infringement of any proprietary         */
49
/*    rights, relating to use of information in this specification and to the        */
50
/*    implementation of this specification, and TCG disclaims all liability for        */
51
/*    cost of procurement of substitute goods or services, lost profits, loss         */
52
/*    of use, loss of data or any incidental, consequential, direct, indirect,         */
53
/*    or special damages, whether under contract, tort, warranty or otherwise,         */
54
/*    arising in any way out of use or reliance upon this specification or any         */
55
/*    information herein.                                                        */
56
/*                                                                                */
57
/*  (c) Copyright IBM Corp. and others, 2016 - 2023                                */
58
/*                                                                                */
59
/********************************************************************************/
60

61
//** Introduction
62
//
63
//  This module contains the interfaces to the CryptoEngine and provides
64
//  miscellaneous cryptographic functions in support of the TPM.
65
//
66

67
//** Includes
68
#include "Tpm.h"
69
#include "Marshal.h"
70

71
//****************************************************************************/
72
//**     Hash/HMAC Functions
73
//****************************************************************************/
74

75
//*** CryptHmacSign()
76
// Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a
77
// message.
78
//  Return Type: TPM_RC
79
//      TPM_RC_HASH         not a valid hash
80
static TPM_RC CryptHmacSign(TPMT_SIGNATURE* signature,  // OUT: signature
48✔
81
                            OBJECT*         signKey,    // IN: HMAC key sign the hash
82
                            TPM2B_DIGEST*   hashData    // IN: hash to be signed
83
)
84
{
85
    HMAC_STATE hmacState;
48✔
86
    UINT32     digestSize;
48✔
87

88
    if (!RuntimeAlgorithmKeySizeCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm,// libtpms added begin
48✔
89
                                             TPM_ALG_HMAC,
90
                                             signKey->sensitive.sensitive.bits.t.size * 8,
48✔
91
                                             TPM_ECC_NONE,
92
                                             g_RuntimeProfile.stateFormatLevel))
93
        return TPM_RC_KEY_SIZE;                                                        // libtpms added end
94

95
    if (signature->sigAlg == TPM_ALG_HMAC)
48✔
96
    {
97
       digestSize = CryptHmacStart2B(&hmacState,
96✔
98
                                     signature->signature.any.hashAlg,
48✔
99
                                     &signKey->sensitive.sensitive.bits.b);
48✔
100
        CryptDigestUpdate2B(&hmacState.hashState, &hashData->b);
48✔
101
        CryptHmacEnd(&hmacState, digestSize, (BYTE*)&signature->signature.hmac.digest);
48✔
102
        return TPM_RC_SUCCESS;
48✔
103
    }
104
    return TPM_RC_SCHEME;
105
}
106

107
//*** CryptHMACVerifySignature()
108
// This function will verify a signature signed by a HMAC key.
109
// Note that a caller needs to prepare 'signature' with the signature algorithm
110
// (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds a
111
// signature of that type.
112
//  Return Type: TPM_RC
113
//      TPM_RC_SCHEME           not the proper scheme for this key type
114
//      TPM_RC_SIGNATURE        if invalid input or signature is not genuine
115
static TPM_RC CryptHMACVerifySignature(
20✔
116
    OBJECT*         signKey,   // IN: HMAC key signed the hash
117
    TPM2B_DIGEST*   hashData,  // IN: digest being verified
118
    TPMT_SIGNATURE* signature  // IN: signature to be verified
119
)
120
{
121
    TPMT_SIGNATURE         test;
20✔
122
    TPMT_KEYEDHASH_SCHEME* keyScheme =
20✔
123
        &signKey->publicArea.parameters.keyedHashDetail.scheme;
124

125
    if (!RuntimeAlgorithmKeySizeCheckEnabled(&g_RuntimeProfile.RuntimeAlgorithm,// libtpm added begin
20✔
126
                                             TPM_ALG_HMAC,
127
                                             signKey->sensitive.sensitive.bits.t.size * 8,
20✔
128
                                             TPM_ECC_NONE,
129
                                             g_RuntimeProfile.stateFormatLevel))
130
        return TPM_RC_KEY_SIZE;                                                        // libtpms added end
131

132
    //
133
    if((signature->sigAlg != TPM_ALG_HMAC)
20✔
134
       || (signature->signature.hmac.hashAlg == TPM_ALG_NULL))
20✔
135
        return TPM_RC_SCHEME;
136
    // This check is not really needed for verification purposes. However, it does
137
    // prevent someone from trying to validate a signature using a weaker hash
138
    // algorithm than otherwise allowed by the key. That is, a key with a scheme
139
    // other than TMP_ALG_NULL can only be used to validate signatures that have
140
    // a matching scheme.
141
    if((keyScheme->scheme != TPM_ALG_NULL)
20✔
142
       && ((keyScheme->scheme != signature->sigAlg)
20✔
143
           || (keyScheme->details.hmac.hashAlg != signature->signature.any.hashAlg)))
20✔
144
        return TPM_RC_SIGNATURE;
145

146
    if (signature->signature.any.hashAlg == TPM_ALG_SHA1 &&                        // libtpms added begin
25✔
147
        RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
5✔
148
                                             RUNTIME_ATTRIBUTE_NO_SHA1_HMAC_VERIFICATION))
149
        return TPM_RC_HASH;                                                        // libtpms added end
150

151
    test.sigAlg                 = signature->sigAlg;
20✔
152
    test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg;
20✔
153

154
    CryptHmacSign(&test, signKey, hashData);
20✔
155

156
    // Compare digest
157
    if(!MemoryEqual(&test.signature.hmac.digest,
20✔
158
                    &signature->signature.hmac.digest,
20✔
159
                    CryptHashGetDigestSize(signature->signature.any.hashAlg)))
20✔
160
        return TPM_RC_SIGNATURE;
×
161

162
    return TPM_RC_SUCCESS;
163
}
164

165
//*** CryptGenerateKeyedHash()
166
// This function creates a keyedHash object.
167
// Return type: TPM_RC
168
//      TPM_RC_NO_RESULT    cannot get values from random number generator
169
//      TPM_RC_SIZE         sensitive data size is larger than allowed for
170
//                          the scheme
171
static TPM_RC CryptGenerateKeyedHash(
62✔
172
    TPMT_PUBLIC* publicArea,                 // IN/OUT: the public area template
173
                                             //     for the new key.
174
    TPMT_SENSITIVE*        sensitive,        // OUT: sensitive area
175
    TPMS_SENSITIVE_CREATE* sensitiveCreate,  // IN: sensitive creation data
176
    RAND_STATE*            rand              // IN: "entropy" source
177
)
178
{
179
    TPMT_KEYEDHASH_SCHEME* scheme;
62✔
180
    TPM_ALG_ID             hashAlg;
62✔
181
    UINT16                 digestSize;
62✔
182

183
    scheme = &publicArea->parameters.keyedHashDetail.scheme;
62✔
184

185
    if(publicArea->type != TPM_ALG_KEYEDHASH)
62✔
186
        return TPM_RC_FAILURE;
187

188
    // Pick the limiting hash algorithm
189
    if(scheme->scheme == TPM_ALG_NULL)
62✔
190
        hashAlg = publicArea->nameAlg;
23✔
191
    else if(scheme->scheme == TPM_ALG_XOR)
39✔
192
        hashAlg = scheme->details.xor.hashAlg;
7✔
193
    else
194
        hashAlg = scheme->details.hmac.hashAlg;
32✔
195
    digestSize = CryptHashGetDigestSize(hashAlg);
62✔
196

197
    // if this is a signing or a decryption key, then the limit
198
    // for the data size is the block size of the hash. This limit
199
    // is set because larger values have lower entropy because of the
200
    // HMAC function. The lower limit is 1/2 the size of the digest
201
    //
202
    //If the user provided the key, check that it is a proper size
203
    if(sensitiveCreate->data.t.size != 0)
62✔
204
    {
205
        if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
27✔
206
           || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
27✔
207
        {
208
            if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg))
4✔
209
                return TPM_RC_SIZE;
210
#if 0  // May make this a FIPS-mode requirement
211
            if(sensitiveCreate->data.t.size < (digestSize / 2))
212
                return TPM_RC_SIZE;
213
#endif
214
        }
215
        // If this is a data blob, then anything that will get past the unmarshaling
216
        // is OK
217
        MemoryCopy2B(&sensitive->sensitive.bits.b,
27✔
218
                     &sensitiveCreate->data.b,
27✔
219
                     sizeof(sensitive->sensitive.bits.t.buffer));
220
    }
221
    else
222
    {
223
        // The TPM is going to generate the data so set the size to be the
224
        // size of the digest of the algorithm
225
        sensitive->sensitive.bits.t.size =
70✔
226
            DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize);
35✔
227
        if(sensitive->sensitive.bits.t.size == 0)
35✔
228
            return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT;
×
229
    }
230
    return TPM_RC_SUCCESS;
231
}
232

233
//*** CryptIsSchemeAnonymous()
234
// This function is used to test a scheme to see if it is an anonymous scheme
235
// The only anonymous scheme is ECDAA. ECDAA can be used to do things
236
// like U-Prove.
237
BOOL CryptIsSchemeAnonymous(TPM_ALG_ID scheme  // IN: the scheme algorithm to test
926✔
238
)
239
{
240
    return scheme == TPM_ALG_ECDAA;
926✔
241
}
242

243
//**** ************************************************************************
244
//** Symmetric Functions
245
//**** ************************************************************************
246

247
//*** ParmDecryptSym()
248
//  This function performs parameter decryption using symmetric block cipher.
249
/*(See Part 1 specification)
250
// Symmetric parameter decryption
251
//      When parameter decryption uses a symmetric block cipher, a decryption
252
//      key and IV will be generated from:
253
//      KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits)    (24)
254
//      Where:
255
//      hash            the hash function associated with the session
256
//      sessionAuth     the sessionAuth associated with the session
257
//      nonceNewer      nonceCaller for a command
258
//      nonceOlder      nonceTPM for a command
259
//      bits            the number of bits required for the symmetric key
260
//                      plus an IV
261
*/
262
void ParmDecryptSym(TPM_ALG_ID symAlg,         // IN: the symmetric algorithm
67✔
263
                    TPM_ALG_ID hash,           // IN: hash algorithm for KDFa
264
                    UINT16     keySizeInBits,  // IN: the key size in bits
265
                    TPM2B*     key,            // IN: KDF HMAC key
266
                    TPM2B*     nonceCaller,    // IN: nonce caller
267
                    TPM2B*     nonceTpm,       // IN: nonce TPM
268
                    UINT32     dataSize,       // IN: size of parameter buffer
269
                    BYTE*      data            // OUT: buffer to be decrypted
270
)
271
{
272
    // KDF output buffer
273
    // It contains parameters for the CFB encryption
274
    // From MSB to LSB, they are the key and iv
275
    BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
67✔
276
    // Symmetric key size in byte
277
    UINT16   keySize = (keySizeInBits + 7) / 8;
67✔
278
    TPM2B_IV iv;
67✔
279

280
    iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
67✔
281
    // If there is decryption to do...
282
    if(iv.t.size > 0)
67✔
283
    {
284
        // Generate key and iv
285
        CryptKDFa(hash,
67✔
286
                  key,
287
                  CFB_KEY,
288
                  nonceCaller,
289
                  nonceTpm,
290
                  keySizeInBits + (iv.t.size * 8),
67✔
291
                  symParmString,
292
                  NULL,
293
                  FALSE);
294
        MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
67✔
295

296
        CryptSymmetricDecrypt(data,
67✔
297
                              symAlg,
298
                              keySizeInBits,
299
                              symParmString,
300
                              &iv,
301
                              TPM_ALG_CFB,
302
                              dataSize,
303
                              data);
304
    }
305
    return;
67✔
306
}
307

308
//*** ParmEncryptSym()
309
//  This function performs parameter encryption using symmetric block cipher.
310
/*(See part 1 specification)
311
//      When parameter decryption uses a symmetric block cipher, an encryption
312
//      key and IV will be generated from:
313
//      KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits)    (24)
314
//      Where:
315
//      hash            the hash function associated with the session
316
//      sessionAuth     the sessionAuth associated with the session
317
//      nonceNewer      nonceTPM for a response
318
//      nonceOlder      nonceCaller for a response
319
//      bits            the number of bits required for the symmetric key
320
//                      plus an IV
321
*/
322
void ParmEncryptSym(TPM_ALG_ID symAlg,         // IN: symmetric algorithm
64✔
323
                    TPM_ALG_ID hash,           // IN: hash algorithm for KDFa
324
                    UINT16     keySizeInBits,  // IN: symmetric key size in bits
325
                    TPM2B*     key,            // IN: KDF HMAC key
326
                    TPM2B*     nonceCaller,    // IN: nonce caller
327
                    TPM2B*     nonceTpm,       // IN: nonce TPM
328
                    UINT32     dataSize,       // IN: size of parameter buffer
329
                    BYTE*      data            // OUT: buffer to be encrypted
330
)
331
{
332
    // KDF output buffer
333
    // It contains parameters for the CFB encryption
334
    BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
64✔
335

336
    // Symmetric key size in bytes
337
    UINT16   keySize = (keySizeInBits + 7) / 8;
64✔
338

339
    TPM2B_IV iv;
64✔
340

341
    iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
64✔
342
    // See if there is any encryption to do
343
    if(iv.t.size > 0)
64✔
344
    {
345
        // Generate key and iv
346
        CryptKDFa(hash,
64✔
347
                  key,
348
                  CFB_KEY,
349
                  nonceTpm,
350
                  nonceCaller,
351
                  keySizeInBits + (iv.t.size * 8),
64✔
352
                  symParmString,
353
                  NULL,
354
                  FALSE);
355
        MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
64✔
356

357
        CryptSymmetricEncrypt(data,
64✔
358
                              symAlg,
359
                              keySizeInBits,
360
                              symParmString,
361
                              &iv,
362
                              TPM_ALG_CFB,
363
                              dataSize,
364
                              data);
365
    }
366
    return;
64✔
367
}
368

369
//*** CryptGenerateKeySymmetric()
370
// This function generates a symmetric cipher key. The derivation process is
371
// determined by the type of the provided 'rand'
372
// Return type: TPM_RC
373
//      TPM_RC_NO_RESULT    cannot get a random value
374
//      TPM_RC_KEY_SIZE     key size in the public area does not match the size
375
//                          in the sensitive creation area
376
//      TPM_RC_KEY          provided key value is not allowed
377
static TPM_RC CryptGenerateKeySymmetric(
35✔
378
    TPMT_PUBLIC* publicArea,                 // IN/OUT: The public area template
379
                                             //     for the new key.
380
    TPMT_SENSITIVE*        sensitive,        // OUT: sensitive area
381
    TPMS_SENSITIVE_CREATE* sensitiveCreate,  // IN: sensitive creation data
382
    RAND_STATE*            rand              // IN: the "entropy" source for
383
)
384
{
385
    UINT16 keyBits = publicArea->parameters.symDetail.sym.keyBits.sym;
35✔
386
    TPM_RC result;
35✔
387
    //
388
    // only do multiples of RADIX_BITS
389
    if((keyBits % RADIX_BITS) != 0)
35✔
390
        return TPM_RC_KEY_SIZE;
391
    // If this is not a new key, then the provided key data must be the right size
392
    if(sensitiveCreate->data.t.size != 0)
35✔
393
    {
394
        result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym,
×
395
                                     (TPM2B_SYM_KEY*)&sensitiveCreate->data);
×
396
        if(result == TPM_RC_SUCCESS)
×
397
            MemoryCopy2B(&sensitive->sensitive.sym.b,
×
398
                         &sensitiveCreate->data.b,
×
399
                         sizeof(sensitive->sensitive.sym.t.buffer));
400
    }
401
#if ALG_TDES
402
    else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES)
35✔
403
        {
404
            result = CryptGenerateKeyDes(publicArea, sensitive, rand);
3✔
405
        }
406
#endif
407
    else
408
    {
409
        sensitive->sensitive.sym.t.size = DRBG_Generate(
64✔
410
            rand, sensitive->sensitive.sym.t.buffer, BITS_TO_BYTES(keyBits));
32✔
411
        if(g_inFailureMode)
32✔
412
            result = TPM_RC_FAILURE;
413
        else if(sensitive->sensitive.sym.t.size == 0)
32✔
414
            result = TPM_RC_NO_RESULT;
415
        else
416
            result = TPM_RC_SUCCESS;
32✔
417
    }
418
    return result;
419
}
420

421
//*** CryptXORObfuscation()
422
// This function implements XOR obfuscation. It should not be called if the
423
// hash algorithm is not implemented. The only return value from this function
424
// is TPM_RC_SUCCESS.
425
void CryptXORObfuscation(TPM_ALG_ID hash,      // IN: hash algorithm for KDF
179✔
426
                         TPM2B*     key,       // IN: KDF key
427
                         TPM2B*     contextU,  // IN: contextU
428
                         TPM2B*     contextV,  // IN: contextV
429
                         UINT32     dataSize,  // IN: size of data buffer
430
                         BYTE*      data       // IN/OUT: data to be XORed in place
431
)
432
{
433
    BYTE   mask[MAX_DIGEST_SIZE];  // Allocate a digest sized buffer
179✔
434
    BYTE*  pm;
179✔
435
    UINT32 i;
179✔
436
    UINT32 counter     = 0;
179✔
437
    UINT16 hLen        = CryptHashGetDigestSize(hash);
179✔
438
    UINT32 requestSize = dataSize * 8;
179✔
439
    INT32  remainBytes = (INT32)dataSize;
179✔
440

441
    pAssert((key != NULL) && (data != NULL) && (hLen != 0));
179✔
442

443
    // Call KDFa to generate XOR mask
444
    for(; remainBytes > 0; remainBytes -= hLen)
727✔
445
    {
446
        // Make a call to KDFa to get next iteration
447
        CryptKDFa(hash,
548✔
448
                  key,
449
                  XOR_KEY,
450
                  contextU,
451
                  contextV,
452
                  requestSize,
453
                  mask,
454
                  &counter,
455
                  TRUE);
456

457
        // XOR next piece of the data
458
        pm = mask;
548✔
459
        for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
14,230✔
460
            *data++ ^= *pm++;
13,682✔
461
    }
462
    return;
179✔
463
}
464

465
//****************************************************************************
466
//** Initialization and shut down
467
//****************************************************************************
468

469
//*** CryptInit()
470
// This function is called when the TPM receives a _TPM_Init indication.
471
//
472
// NOTE: The hash algorithms do not have to be tested, they just need to be
473
// available. They have to be tested before the TPM can accept HMAC authorization
474
// or return any result that relies on a hash algorithm.
475
//  Return Type: BOOL
476
//      TRUE(1)         initializations succeeded
477
//      FALSE(0)        initialization failed and caller should place the TPM into
478
//                      Failure Mode
479
BOOL CryptInit(void)
12,492✔
480
{
481
    BOOL ok;
12,492✔
482
    // Initialize the vector of implemented algorithms
483
    AlgorithmGetImplementedVector(&g_implementedAlgorithms);
12,492✔
484

485
    // Indicate that all test are necessary
486
    CryptInitializeToTest();
12,492✔
487

488
    // Do any library initializations that are necessary. If any fails,
489
    // the caller should go into failure mode;
490
    ok = ExtMath_LibInit();
12,492✔
491
    ok = ok && CryptSymInit();
12,492✔
492
    ok = ok && CryptRandInit();
12,492✔
493
    ok = ok && CryptHashInit();
12,492✔
494
#if ALG_RSA
495
    ok = ok && CryptRsaInit();
12,492✔
496
#endif  // ALG_RSA
497
#if ALG_ECC
498
    ok = ok && CryptEccInit();
12,492✔
499
#endif  // ALG_ECC
500
    return ok;
12,492✔
501
}
502

503
//*** CryptStartup()
504
// This function is called by TPM2_Startup() to initialize the functions in
505
// this cryptographic library and in the provided CryptoLibrary. This function
506
// and CryptUtilInit() are both provided so that the implementation may move the
507
// initialization around to get the best interaction.
508
//  Return Type: BOOL
509
//      TRUE(1)         startup succeeded
510
//      FALSE(0)        startup failed and caller should place the TPM into
511
//                      Failure Mode
512
BOOL CryptStartup(STARTUP_TYPE type  // IN: the startup type
8,407✔
513
)
514
{
515
    BOOL OK;
8,407✔
516
    NOT_REFERENCED(type);
8,407✔
517

518
    OK = CryptSymStartup() && CryptRandStartup() && CryptHashStartup()
16,814✔
519
#if ALG_RSA
520
         && CryptRsaStartup()
8,407✔
521
#endif  // ALG_RSA
522
#if ALG_ECC
523
         && CryptEccStartup()
16,814✔
524
#endif  // ALG_ECC
525
        ;
526
#if ALG_ECC
527
    // Don't directly check for SU_RESET because that is the default
528
    if(OK && (type != SU_RESTART) && (type != SU_RESUME))
8,407✔
529
    {
530
        // If the shutdown was orderly, then the values recovered from NV will
531
        // be OK to use.
532
        // Get a new  random commit nonce
533
        gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
8,376✔
534
        CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
8,376✔
535
        // Reset the counter and commit array
536
        gr.commitCounter = 0;
8,376✔
537
        MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
8,376✔
538
    }
539
#endif  // ALG_ECC
540
    return OK;
8,407✔
541
}
542

543
//****************************************************************************
544
//** Algorithm-Independent Functions
545
//****************************************************************************
546
//*** Introduction
547
// These functions are used generically when a function of a general type
548
// (e.g., symmetric encryption) is required.  The functions will modify the
549
// parameters as required to interface to the indicated algorithms.
550
//
551
//*** CryptIsAsymAlgorithm()
552
// This function indicates if an algorithm is an asymmetric algorithm.
553
//  Return Type: BOOL
554
//      TRUE(1)         if it is an asymmetric algorithm
555
//      FALSE(0)        if it is not an asymmetric algorithm
556
BOOL CryptIsAsymAlgorithm(TPM_ALG_ID algID  // IN: algorithm ID
757✔
557
)
558
{
559
    switch(algID)
757✔
560
    {
561
#if ALG_RSA
562
        case TPM_ALG_RSA:
563
#endif
564
#if ALG_ECC
565
        case TPM_ALG_ECC:
566
#endif
567
            return TRUE;
568
            break;
32✔
569
        default:
570
            break;
32✔
571
    }
572
    return FALSE;
32✔
573
}
574

575
//*** CryptSecretEncrypt()
576
// This function creates a secret value and its associated secret structure using
577
// an asymmetric algorithm.
578
//
579
// This function is used by TPM2_Rewrap() TPM2_MakeCredential(),
580
// and TPM2_Duplicate().
581
//  Return Type: TPM_RC
582
//      TPM_RC_ATTRIBUTES   'keyHandle' does not reference a valid decryption key
583
//      TPM_RC_KEY          invalid ECC key (public point is not on the curve)
584
//      TPM_RC_SCHEME       RSA key with an unsupported padding scheme
585
//      TPM_RC_VALUE        numeric value of the data to be decrypted is greater
586
//                          than the RSA key modulus
587
TPM_RC
588
CryptSecretEncrypt(OBJECT*      encryptKey,  // IN: encryption key object
35✔
589
                   const TPM2B* label,       // IN: a null-terminated string as L
590
                   TPM2B_DATA*  data,        // OUT: secret value
591
                   TPM2B_ENCRYPTED_SECRET* secret  // OUT: secret structure
592
)
593
{
594
    TPM_RC result = TPM_RC_SUCCESS;
35✔
595
    //
596
    if(data == NULL || secret == NULL)
35✔
597
        return TPM_RC_FAILURE;
598

599
    // CryptKDFe was fixed to not add a NULL byte as per NIST.SP.800-56Cr2.pdf
600
    // (required for ACVP tests). This check ensures backwards compatibility with
601
    // previous versions of the TPM reference code by verifying the label itself
602
    // has a NULL terminator.  Note the TPM spec specifies that the label must be NULL
603
    // terminated.  This is only a "new" failure path in the sense that it adds a
604
    // runtime check of hardcoded constants; provided the code is correct it will never
605
    // fail, and running the compliance tests will verify this isn't hit.
606
    if((label == NULL) || (label->size == 0) || (label->buffer[label->size - 1] != 0))
35✔
607
        return TPM_RC_FAILURE;
608

609
    // The output secret value has the size of the digest produced by the nameAlg.
610
    data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg);
35✔
611

612
    if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
35✔
613
        return TPM_RC_ATTRIBUTES;
614
    switch(encryptKey->publicArea.type)
35✔
615
    {
616
#if ALG_RSA
617
        case TPM_ALG_RSA:
16✔
618
        {
619
            // The encryption scheme is OAEP using the nameAlg of the encrypt key.
620
            TPMT_RSA_DECRYPT scheme;
16✔
621
            scheme.scheme                 = TPM_ALG_OAEP;
16✔
622
            scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg;
16✔
623

624
            // Create secret data from RNG
625
            CryptRandomGenerate(data->t.size, data->t.buffer);
16✔
626

627
            // Encrypt the data by RSA OAEP into encrypted secret
628
            result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA*)secret,
16✔
629
                                     &data->b,
630
                                     encryptKey,
631
                                     &scheme,
632
                                     label,
633
                                     NULL);
634
        }
635
        break;
16✔
636
#endif  // ALG_RSA
637

638
#if ALG_ECC
639
        case TPM_ALG_ECC:
19✔
640
        {
641
            TPMS_ECC_POINT      eccPublic;
19✔
642
            TPM2B_ECC_PARAMETER eccPrivate;
19✔
643
            TPMS_ECC_POINT      eccSecret;
19✔
644
            BYTE*               buffer = secret->t.secret;
19✔
645

646
            // Need to make sure that the public point of the key is on the
647
            // curve defined by the key.
648
            if(!CryptEccIsPointOnCurve(
19✔
649
                   encryptKey->publicArea.parameters.eccDetail.curveID,
19✔
650
                   &encryptKey->publicArea.unique.ecc))
651
                result = TPM_RC_KEY;
652
            else
653
            {
654
                // Call crypto engine to create an auxiliary ECC key
655
                // We assume crypt engine initialization should always success.
656
                // Otherwise, TPM should go to failure mode.
657

658
                CryptEccNewKeyPair(
19✔
659
                    &eccPublic,
660
                    &eccPrivate,
661
                    encryptKey->publicArea.parameters.eccDetail.curveID);
19✔
662
                // Marshal ECC public to secret structure. This will be used by the
663
                // recipient to decrypt the secret with their private key.
664
                secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);
19✔
665

666
                // Compute ECDH shared secret which is R = [d]Q where d is the
667
                // private part of the ephemeral key and Q is the public part of a
668
                // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
669
                // because the auxiliary ECC key is just created according to the
670
                // parameters of input ECC encrypt key.
671
                if(CryptEccPointMultiply(
19✔
672
                       &eccSecret,
673
                       encryptKey->publicArea.parameters.eccDetail.curveID,
19✔
674
                       &encryptKey->publicArea.unique.ecc,
675
                       &eccPrivate,
676
                       NULL,
677
                       NULL)
678
                   != TPM_RC_SUCCESS)
679
                    result = TPM_RC_KEY;
680
                else
681
                {
682
                    // The secret value is computed from Z using KDFe as:
683
                    // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
684
                    // Where:
685
                    //  HashID  the nameAlg of the decrypt key
686
                    //  Z   the x coordinate (Px) of the product (P) of the point
687
                    //      (Q) of the secret and the private x coordinate (de,V)
688
                    //      of the decryption key
689
                    //  Use a null-terminated string containing "SECRET"
690
                    //  PartyUInfo  the x coordinate of the point in the secret
691
                    //              (Qe,U )
692
                    //  PartyVInfo  the x coordinate of the public key (Qs,V )
693
                    //  bits    the number of bits in the digest of HashID
694
                    // Retrieve seed from KDFe
695
                    CryptKDFe(encryptKey->publicArea.nameAlg,
19✔
696
                              &eccSecret.x.b,
697
                              label,
698
                              &eccPublic.x.b,
699
                              &encryptKey->publicArea.unique.ecc.x.b,
700
                              data->t.size * 8,
19✔
701
                              data->t.buffer);
19✔
702
                }
703
            }
704
        }
705
        break;
19✔
706
#endif  // ALG_ECC
707
        default:
×
708
            FAIL(FATAL_ERROR_INTERNAL);
×
709
            break;
710
    }
711
    return result;
712
}
713

714
//*** CryptSecretDecrypt()
715
// Decrypt a secret value by asymmetric (or symmetric) algorithm
716
// This function is used for ActivateCredential and Import for asymmetric
717
// decryption, and StartAuthSession for both asymmetric and symmetric
718
// decryption process
719
//
720
//  Return Type: TPM_RC
721
//      TPM_RC_ATTRIBUTES        RSA key is not a decryption key
722
//      TPM_RC_BINDING           Invalid RSA key (public and private parts are not
723
//                               cryptographically bound.
724
//      TPM_RC_ECC_POINT         ECC point in the secret is not on the curve
725
//      TPM_RC_INSUFFICIENT      failed to retrieve ECC point from the secret
726
//      TPM_RC_NO_RESULT         multiplication resulted in ECC point at infinity
727
//      TPM_RC_SIZE              data to decrypt is not of the same size as RSA key
728
//      TPM_RC_VALUE             For RSA key, numeric value of the encrypted data is
729
//                               greater than the modulus, or the recovered data is
730
//                               larger than the output buffer.
731
//                               For keyedHash or symmetric key, the secret is
732
//                               larger than the size of the digest produced by
733
//                               the name algorithm.
734
//      TPM_RC_FAILURE           internal error
735
TPM_RC
736
CryptSecretDecrypt(OBJECT*      decryptKey,   // IN: decrypt key
88✔
737
                   TPM2B_NONCE* nonceCaller,  // IN: nonceCaller.  It is needed for
738
                                              //     symmetric decryption.  For
739
                                              //     asymmetric decryption, this
740
                                              //     parameter is NULL
741
                   const TPM2B*            label,   // IN: a value for L
742
                   TPM2B_ENCRYPTED_SECRET* secret,  // IN: input secret
743
                   TPM2B_DATA*             data     // OUT: decrypted secret value
744
)
745
{
746
    TPM_RC result = TPM_RC_SUCCESS;
88✔
747

748
    // CryptKDFe was fixed to not add a NULL byte as per NIST.SP.800-56Cr2.pdf
749
    // (required for ACVP tests). This check ensures backwards compatibility with
750
    // previous versions of the TPM reference code by verifying the label itself
751
    // has a NULL terminator.  Note the TPM spec specifies that the label must be NULL
752
    // terminated.  This is only a "new" failure path in the sense that it adds a
753
    // runtime check of hardcoded constants; provided the code is correct it will never
754
    // fail, and running the compliance tests will verify this isn't hit.
755
    if((label == NULL) || (label->size == 0) || (label->buffer[label->size - 1] != 0))
88✔
756
        return TPM_RC_FAILURE;
757

758
    // Decryption for secret
759
    switch(decryptKey->publicArea.type)
88✔
760
    {
761
#if ALG_RSA
762
        case TPM_ALG_RSA:
57✔
763
        {
764
            TPMT_RSA_DECRYPT scheme;
57✔
765
            TPMT_RSA_SCHEME* keyScheme =
57✔
766
                &decryptKey->publicArea.parameters.rsaDetail.scheme;
767
            UINT16 digestSize;
57✔
768

769
            scheme = *(TPMT_RSA_DECRYPT*)keyScheme;
57✔
770
            // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and
771
            // set the algorithm to the name algorithm.
772
            if(scheme.scheme == TPM_ALG_NULL)
57✔
773
            {
774
                // Use OAEP scheme
775
                scheme.scheme               = TPM_ALG_OAEP;
45✔
776
                scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
45✔
777
            }
778
            // use the digestSize as an indicator of whether or not the scheme
779
            // is using a supported hash algorithm.
780
            // Note: depending on the scheme used for encryption, a hashAlg might
781
            // not be needed. However, the return value has to have some upper
782
            // limit on the size. In this case, it is the size of the digest of the
783
            // hash algorithm. It is checked after the decryption is done but, there
784
            // is no point in doing the decryption if the size is going to be
785
            // 'wrong' anyway.
786
            digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg);
57✔
787
            if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0)
57✔
788
                return TPM_RC_SCHEME;
×
789

790
            // Set the output buffer capacity
791
            data->t.size = sizeof(data->t.buffer);
57✔
792

793
            // Decrypt seed by RSA OAEP
794
            result =
57✔
795
                CryptRsaDecrypt(&data->b, &secret->b, decryptKey, &scheme, label);
57✔
796
            if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize))
57✔
797
                result = TPM_RC_VALUE;
×
798
        }
799
        break;
57✔
800
#endif  // ALG_RSA
801
#if ALG_ECC
802
        case TPM_ALG_ECC:
31✔
803
        {
804
            TPMS_ECC_POINT eccPublic;
31✔
805
            TPMS_ECC_POINT eccSecret;
31✔
806
            BYTE*          buffer = secret->t.secret;
31✔
807
            INT32          size   = secret->t.size;
31✔
808

809
            MemorySet(&eccPublic, 0, sizeof(eccPublic));                // libtpms added: Coverity
31✔
810

811
            // Retrieve ECC point from secret buffer
812
            result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
31✔
813
            if(result == TPM_RC_SUCCESS)
31✔
814
            {
815
                result = CryptEccPointMultiply(
62✔
816
                    &eccSecret,
817
                    decryptKey->publicArea.parameters.eccDetail.curveID,
31✔
818
                    &eccPublic,
819
                    &decryptKey->sensitive.sensitive.ecc,
820
                    NULL,
821
                    NULL);
822
                if(result == TPM_RC_SUCCESS)
31✔
823
                {
824
                    // Set the size of the "recovered" secret value to be the size
825
                    // of the digest produced by the nameAlg.
826
                    data->t.size =
62✔
827
                        CryptHashGetDigestSize(decryptKey->publicArea.nameAlg);
31✔
828

829
                    // The secret value is computed from Z using KDFe as:
830
                    // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
831
                    // Where:
832
                    //  HashID -- the nameAlg of the decrypt key
833
                    //  Z --  the x coordinate (Px) of the product (P) of the point
834
                    //        (Q) of the secret and the private x coordinate (de,V)
835
                    //        of the decryption key
836
                    //  Use -- a null-terminated string containing "SECRET"
837
                    //  PartyUInfo -- the x coordinate of the point in the secret
838
                    //              (Qe,U )
839
                    //  PartyVInfo -- the x coordinate of the public key (Qs,V )
840
                    //  bits -- the number of bits in the digest of HashID
841
                    // Retrieve seed from KDFe
842
                    CryptKDFe(decryptKey->publicArea.nameAlg,
31✔
843
                              &eccSecret.x.b,
844
                              label,
845
                              &eccPublic.x.b,
846
                              &decryptKey->publicArea.unique.ecc.x.b,
847
                              data->t.size * 8,
31✔
848
                              data->t.buffer);
31✔
849
                }
850
            }
851
        }
852
        break;
31✔
853
#endif  // ALG_ECC
854
#if !ALG_KEYEDHASH
855
#  error "KEYEDHASH support is required"
856
#endif
857
        case TPM_ALG_KEYEDHASH:
×
858
            // The seed size can not be bigger than the digest size of nameAlg
859
            if(secret->t.size
×
860
               > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
×
861
                result = TPM_RC_VALUE;
862
            else
863
            {
864
                // Retrieve seed by XOR Obfuscation:
865
                //    seed = XOR(secret, hash, key, nonceCaller, nullNonce)
866
                //    where:
867
                //    secret  the secret parameter from the TPM2_StartAuthHMAC
868
                //            command that contains the seed value
869
                //    hash    nameAlg  of tpmKey
870
                //    key     the key or data value in the object referenced by
871
                //            entityHandle in the TPM2_StartAuthHMAC command
872
                //    nonceCaller the parameter from the TPM2_StartAuthHMAC command
873
                //    nullNonce   a zero-length nonce
874
                // XOR Obfuscation in place
875
                CryptXORObfuscation(decryptKey->publicArea.nameAlg,
×
876
                                    &decryptKey->sensitive.sensitive.bits.b,
877
                                    &nonceCaller->b,
878
                                    NULL,
879
                                    secret->t.size,
×
880
                                    secret->t.secret);
×
881
                // Copy decrypted seed
882
                MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
×
883
            }
884
            break;
885
        case TPM_ALG_SYMCIPHER:
×
886
        {
887
            TPM2B_IV             iv = {{0}};
×
888
            TPMT_SYM_DEF_OBJECT* symDef;
×
889
            // The seed size can not be bigger than the digest size of nameAlg
890
            if(secret->t.size
×
891
               > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
×
892
                result = TPM_RC_VALUE;
893
            else
894
            {
895
                symDef    = &decryptKey->publicArea.parameters.symDetail.sym;
×
896
                iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
×
897
                                                       symDef->keyBits.sym);
×
898
                if(iv.t.size == 0)
×
899
                    return TPM_RC_FAILURE;
×
900
                if(nonceCaller->t.size >= iv.t.size)
×
901
                {
902
                    MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size);
×
903
                }
904
                else
905
                {
906
                    if(nonceCaller->t.size > sizeof(iv.t.buffer))
×
907
                        return TPM_RC_FAILURE;
908
                    MemoryCopy(
×
909
                        iv.t.buffer, nonceCaller->t.buffer, nonceCaller->t.size); // libtpms changed: use iv.t.buffer
×
910
                }
911
                // make sure secret will fit
912
                if(secret->t.size > sizeof(data->t.buffer))
×
913
                    return TPM_RC_FAILURE;
914
                data->t.size = secret->t.size;
×
915
                // CFB decrypt, using nonceCaller as iv
916
                CryptSymmetricDecrypt(data->t.buffer,
×
917
                                      symDef->algorithm,
×
918
                                      symDef->keyBits.sym,
×
919
                                      decryptKey->sensitive.sensitive.sym.t.buffer,
×
920
                                      &iv,
921
                                      TPM_ALG_CFB,
922
                                      secret->t.size,
923
                                      secret->t.secret);
×
924
            }
925
        }
926
        break;
×
927
        default:
×
928
            FAIL(FATAL_ERROR_INTERNAL);
×
929
            break;
930
    }
931
    return result;
932
}
933

934
//*** CryptParameterEncryption()
935
// This function does in-place encryption of a response parameter.
936
void CryptParameterEncryption(
152✔
937
    TPM_HANDLE handle,             // IN: encrypt session handle
938
    TPM2B*     nonceCaller,        // IN: nonce caller
939
    INT32      bufferSize,         // IN: size of parameter buffer
940
    UINT16     leadingSizeInByte,  // IN: the size of the leading size field in
941
                                   //     bytes
942
    TPM2B_AUTH* extraKey,          // IN: additional key material other than
943
                                   //     sessionAuth
944
    BYTE* buffer                   // IN/OUT: parameter buffer to be encrypted
945
)
946
{
947
    SESSION* session = SessionGet(handle);  // encrypt session
152✔
948
    TPM2B_TYPE(TEMP_KEY,
152✔
949
               (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer)));
950
    TPM2B_TEMP_KEY key;             // encryption key
152✔
951
    UINT16         cipherSize = 0;  // size of cipher text
152✔
952

953
    if(bufferSize < leadingSizeInByte)
152✔
954
    {
955
        FAIL(FATAL_ERROR_INTERNAL);
×
956
        return;
957
    }
958

959
    // Parameter encryption for a non-2B is not supported.
960
    if(leadingSizeInByte != 2)
152✔
961
    {
962
        FAIL(FATAL_ERROR_INTERNAL);
×
963
        return;
964
    }
965

966
    // Retrieve encrypted data size.
967
    if(UINT16_Unmarshal(&cipherSize, &buffer, &bufferSize) != TPM_RC_SUCCESS)
152✔
968
    {
969
        FAIL(FATAL_ERROR_INTERNAL);
×
970
        return;
971
    }
972

973
    if(cipherSize > bufferSize)
152✔
974
    {
975
        FAIL(FATAL_ERROR_INTERNAL);
×
976
        return;
977
    }
978

979
    // Compute encryption key by concatenating sessionKey with extra key
980
    MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
152✔
981
    MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
152✔
982

983
    if(session->symmetric.algorithm == TPM_ALG_XOR)
152✔
984

985
        // XOR parameter encryption formulation:
986
        //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
987
        CryptXORObfuscation(session->authHashAlg,
88✔
988
                            &(key.b),
989
                            &(session->nonceTPM.b),
990
                            nonceCaller,
991
                            (UINT32)cipherSize,
992
                            buffer);
993
    else
994
        ParmEncryptSym(session->symmetric.algorithm,
64✔
995
                       session->authHashAlg,
64✔
996
                       session->symmetric.keyBits.aes,
64✔
997
                       &(key.b),
998
                       nonceCaller,
999
                       &(session->nonceTPM.b),
1000
                       (UINT32)cipherSize,
1001
                       buffer);
1002
    return;
152✔
1003
}
1004

1005
//*** CryptParameterDecryption()
1006
// This function does in-place decryption of a command parameter.
1007
//  Return Type: TPM_RC
1008
//      TPM_RC_SIZE             The number of bytes in the input buffer is less than
1009
//                              the number of bytes to be decrypted.
1010
TPM_RC
1011
CryptParameterDecryption(
160✔
1012
    TPM_HANDLE handle,             // IN: encrypted session handle
1013
    TPM2B*     nonceCaller,        // IN: nonce caller
1014
    INT32      bufferSize,         // IN: size of parameter buffer
1015
    UINT16     leadingSizeInByte,  // IN: the size of the leading size field in
1016
                                   //     byte
1017
    TPM2B_AUTH* extraKey,          // IN: the authValue
1018
    BYTE*       buffer             // IN/OUT: parameter buffer to be decrypted
1019
)
1020
{
1021
    SESSION* session = SessionGet(handle);  // encrypt session
160✔
1022
    // The HMAC key is going to be the concatenation of the session key and any
1023
    // additional key material (like the authValue). The size of both of these
1024
    // is the size of the buffer which can contain a TPMT_HA.
1025
    TPM2B_TYPE(HMAC_KEY,
160✔
1026
               (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer)));
1027
    TPM2B_HMAC_KEY key;             // decryption key
160✔
1028
    UINT16         cipherSize = 0;  // size of ciphertext
160✔
1029

1030
    if(bufferSize < leadingSizeInByte)
160✔
1031
    {
1032
        return TPM_RC_INSUFFICIENT;
1033
    }
1034

1035
    // Parameter encryption for a non-2B is not supported.
1036
    if(leadingSizeInByte != 2)
159✔
1037
    {
1038
        FAIL_RC(FATAL_ERROR_INTERNAL);
×
1039
    }
1040

1041
    // Retrieve encrypted data size.
1042
    if(UINT16_Unmarshal(&cipherSize, &buffer, &bufferSize) != TPM_RC_SUCCESS)
159✔
1043
    {
1044
        return TPM_RC_INSUFFICIENT;
1045
    }
1046

1047
    if(cipherSize > bufferSize)
159✔
1048
    {
1049
        return TPM_RC_SIZE;
1050
    }
1051

1052
    // Compute decryption key by concatenating sessionAuth with extra input key
1053
    MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
158✔
1054
    MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
158✔
1055

1056
    if(session->symmetric.algorithm == TPM_ALG_XOR)
158✔
1057
        // XOR parameter decryption formulation:
1058
        //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
1059
        // Call XOR obfuscation function
1060
        CryptXORObfuscation(session->authHashAlg,
91✔
1061
                            &key.b,
1062
                            nonceCaller,
1063
                            &(session->nonceTPM.b),
1064
                            (UINT32)cipherSize,
1065
                            buffer);
1066
    else
1067
        // Assume that it is one of the symmetric block ciphers.
1068
        ParmDecryptSym(session->symmetric.algorithm,
67✔
1069
                       session->authHashAlg,
67✔
1070
                       session->symmetric.keyBits.sym,
67✔
1071
                       &key.b,
1072
                       nonceCaller,
1073
                       &session->nonceTPM.b,
1074
                       (UINT32)cipherSize,
1075
                       buffer);
1076

1077
    return TPM_RC_SUCCESS;
1078
}
1079

1080
//*** CryptComputeSymmetricUnique()
1081
// This function computes the unique field in public area for symmetric objects.
1082
void CryptComputeSymmetricUnique(
110✔
1083
    TPMT_PUBLIC*    publicArea,  // IN: the object's public area
1084
    TPMT_SENSITIVE* sensitive,   // IN: the associated sensitive area
1085
    TPM2B_DIGEST*   unique       // OUT: unique buffer
1086
)
1087
{
1088
    // For parents (symmetric and derivation), use an HMAC to compute
1089
    // the 'unique' field
1090
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
110✔
1091
       && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt))
110✔
1092
    {
1093
        // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive)
1094
        HMAC_STATE hmacState;
7✔
1095
        unique->b.size = CryptHmacStart2B(
14✔
1096
            &hmacState, publicArea->nameAlg, &sensitive->seedValue.b);
7✔
1097
        CryptDigestUpdate2B(&hmacState.hashState, &sensitive->sensitive.any.b);
7✔
1098
        CryptHmacEnd2B(&hmacState, &unique->b);
7✔
1099
    }
1100
    else
1101
    {
1102
        HASH_STATE hashState;
103✔
1103
        // Unique := Hash(sensitive->seedValue || sensitive->sensitive)
1104
        unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg);
103✔
1105
        CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b);
103✔
1106
        CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b);
103✔
1107
        CryptHashEnd2B(&hashState, &unique->b);
103✔
1108
    }
1109
    return;
110✔
1110
}
1111

1112
//*** CryptCreateObject()
1113
// This function creates an object.
1114
// For an asymmetric key, it will create a key pair and, for a parent key, a seed
1115
// value for child protections.
1116
//
1117
// For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will
1118
// create a secret key if the caller did not provide one. It will create a random
1119
// secret seed value that is hashed with the secret value to create the public
1120
// unique value.
1121
//
1122
// 'publicArea', 'sensitive', and 'sensitiveCreate' are the only required parameters
1123
// and are the only ones that are used by TPM2_Create(). The other parameters
1124
// are optional and are used when the generated Object needs to be deterministic.
1125
// This is the case for both Primary Objects and Derived Objects.
1126
//
1127
// When a seed value is provided, a RAND_STATE will be populated and used for
1128
// all operations in the object generation that require a random number. In the
1129
// simplest case, TPM2_CreatePrimary() will use 'seed', 'label' and 'context' with
1130
// context being the hash of the template. If the Primary Object is in
1131
// the Endorsement hierarchy, it will also populate 'proof' with ehProof.
1132
//
1133
// For derived keys, 'seed' will be the secret value from the parent, 'label' and
1134
// 'context' will be set according to the parameters of TPM2_CreateLoaded() and
1135
// 'hashAlg' will be set which causes the RAND_STATE to be a KDF generator.
1136
//
1137
//  Return Type: TPM_RC
1138
//      TPM_RC_KEY          a provided key is not an allowed value
1139
//      TPM_RC_KEY_SIZE     key size in the public area does not match the size
1140
//                          in the sensitive creation area for a symmetric key
1141
//      TPM_RC_NO_RESULT    unable to get random values (only in derivation)
1142
//      TPM_RC_RANGE        for an RSA key, the exponent is not supported
1143
//      TPM_RC_SIZE         sensitive data size is larger than allowed for the
1144
//                          scheme for a keyed hash object
1145
//      TPM_RC_VALUE        exponent is not prime or could not find a prime using
1146
//                          the provided parameters for an RSA key;
1147
//                          unsupported name algorithm for an ECC key
1148
TPM_RC
1149
CryptCreateObject(OBJECT*                object,  // IN: new object structure pointer
963✔
1150
                  TPMS_SENSITIVE_CREATE* sensitiveCreate,  // IN: sensitive creation
1151
                  RAND_STATE*            rand  // IN: the random number generator
1152
                                               //      to use
1153
)
1154
{
1155
    TPMT_PUBLIC*    publicArea = &object->publicArea;
963✔
1156
    TPMT_SENSITIVE* sensitive  = &object->sensitive;
963✔
1157
    TPM_RC          result     = TPM_RC_SUCCESS;
963✔
1158
    //
1159
    // Set the sensitive type for the object
1160
    sensitive->sensitiveType = publicArea->type;
963✔
1161

1162
    // For all objects, copy the initial authorization data
1163
    sensitive->authValue = sensitiveCreate->userAuth;
963✔
1164

1165
    // If the TPM is the source of the data, set the size of the provided data to
1166
    // zero so that there's no confusion about what to do.
1167
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin))
963✔
1168
        sensitiveCreate->data.t.size = 0;
923✔
1169

1170
    // Generate the key and unique fields for the asymmetric keys and just the
1171
    // sensitive value for symmetric object
1172
    switch(publicArea->type)
963✔
1173
    {
1174
#if ALG_RSA
1175
        // Create RSA key
1176
        case TPM_ALG_RSA:
690✔
1177
            // RSA uses full object so that it has a place to put the private
1178
            // exponent
1179
            result = CryptRsaGenerateKey(publicArea, sensitive, object, rand); // libtpms: added object
690✔
1180
            break;
690✔
1181
#endif  // ALG_RSA
1182

1183
#if ALG_ECC
1184
        // Create ECC key
1185
        case TPM_ALG_ECC:
176✔
1186
            result = CryptEccGenerateKey(publicArea, sensitive, rand);
176✔
1187
            break;
176✔
1188
#endif  // ALG_ECC
1189
        case TPM_ALG_SYMCIPHER:
35✔
1190
            result = CryptGenerateKeySymmetric(
35✔
1191
                publicArea, sensitive, sensitiveCreate, rand);
1192
            break;
35✔
1193
        case TPM_ALG_KEYEDHASH:
62✔
1194
            result =
62✔
1195
                CryptGenerateKeyedHash(publicArea, sensitive, sensitiveCreate, rand);
62✔
1196
            break;
62✔
1197
        default:
×
1198
            FAIL(FATAL_ERROR_INTERNAL);
×
1199
            break;
963✔
1200
    }
1201
    if(result != TPM_RC_SUCCESS)
963✔
1202
        return result;
1203
    // Create the sensitive seed value
1204
    // If this is a primary key in the endorsement hierarchy, stir the DRBG state
1205
    // This implementation uses both shProof and ehProof to make sure that there
1206
    // is no leakage of either.
1207
    if(object->attributes.primary && object->attributes.epsHierarchy)
959✔
1208
    {
1209
        DRBG_AdditionalData((DRBG_STATE*)rand, &gp.shProof.b);
342✔
1210
        DRBG_AdditionalData((DRBG_STATE*)rand, &gp.ehProof.b);
342✔
1211
    }
1212
    // Generate a seedValue that is the size of the digest produced by nameAlg
1213
    sensitive->seedValue.t.size =
1,918✔
1214
        DRBG_Generate(rand,
959✔
1215
                      sensitive->seedValue.t.buffer,
959✔
1216
                      CryptHashGetDigestSize(publicArea->nameAlg));
959✔
1217
    if(g_inFailureMode)
959✔
1218
        return TPM_RC_FAILURE;
1219
    else if(sensitive->seedValue.t.size == 0)
959✔
1220
        return TPM_RC_NO_RESULT;
1221
    // For symmetric objects, need to compute the unique value for the public area
1222
    if(publicArea->type == TPM_ALG_SYMCIPHER || publicArea->type == TPM_ALG_KEYEDHASH)
959✔
1223
    {
1224
        CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym);
97✔
1225
    }
1226
    else
1227
    {
1228
        // if this is an asymmetric key and it isn't a parent, then
1229
        // get rid of the seed.
1230
        if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
862✔
1231
           || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
862✔
1232
            memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue));
456✔
1233
    }
1234
    // Compute the name
1235
    PublicMarshalAndComputeName(publicArea, &object->name);
959✔
1236
    return result;
959✔
1237
}
1238

1239
//*** CryptGetSignHashAlg()
1240
// Get the hash algorithm of signature from a TPMT_SIGNATURE structure.
1241
// It assumes the signature is not NULL
1242
//  This is a function for easy access
1243
TPMI_ALG_HASH
1244
CryptGetSignHashAlg(TPMT_SIGNATURE* auth  // IN: signature
20✔
1245
)
1246
{
1247
    if(auth->sigAlg == TPM_ALG_NULL)
20✔
1248
        FAIL(FATAL_ERROR_INTERNAL);
×
1249

1250
    // Get authHash algorithm based on signing scheme
1251
    switch(auth->sigAlg)
20✔
1252
    {
1253
#if ALG_RSA
1254
        // If RSA is supported, both RSASSA and RSAPSS are required
1255
#  if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS
1256
#    error "RSASSA and RSAPSS are required for RSA"
1257
#  endif
1258
        case TPM_ALG_RSASSA:
20✔
1259
            return auth->signature.rsassa.hash;
20✔
1260
        case TPM_ALG_RSAPSS:
×
1261
            return auth->signature.rsapss.hash;
×
1262
#endif  // ALG_RSA
1263

1264
#if ALG_ECC
1265
            // If ECC is defined, ECDSA is mandatory
1266
#  if !ALG_ECDSA
1267
#    error "ECDSA is requried for ECC"
1268
#  endif
1269
        case TPM_ALG_ECDSA:
×
1270
            // SM2 and ECSCHNORR are optional
1271

1272
#  if ALG_SM2
1273
        case TPM_ALG_SM2:
1274
#  endif
1275
#  if ALG_ECSCHNORR
1276
        case TPM_ALG_ECSCHNORR:
1277
#  endif
1278
            //all ECC signatures look the same
1279
            return auth->signature.ecdsa.hash;
×
1280

1281
#  if ALG_ECDAA
1282
        // Don't know how to verify an ECDAA signature
1283
        case TPM_ALG_ECDAA:
1284
            break;
1285
#  endif
1286

1287
#endif  // ALG_ECC
1288

1289
        case TPM_ALG_HMAC:
×
1290
            return auth->signature.hmac.hashAlg;
×
1291

1292
        default:
1293
            break;
1294
    }
1295
    return TPM_ALG_NULL;
1296
}
1297

1298
//*** CryptIsSplitSign()
1299
// This function us used to determine if the signing operation is a split
1300
// signing operation that required a TPM2_Commit().
1301
//
1302
BOOL CryptIsSplitSign(TPM_ALG_ID scheme  // IN: the algorithm selector
×
1303
)
1304
{
1305
    switch(scheme)
×
1306
    {
1307
#if ALG_ECDAA
1308
        case TPM_ALG_ECDAA:
1309
            return TRUE;
1310
            break;
×
1311
#endif  // ALG_ECDAA
1312
        default:
×
1313
            return FALSE;
×
1314
            break;
×
1315
    }
1316
}
1317

1318
//*** CryptIsAsymSignScheme()
1319
// This function indicates if a scheme algorithm is a sign algorithm.
1320
BOOL CryptIsAsymSignScheme(TPMI_ALG_PUBLIC      publicType,  // IN: Type of the object
1,511✔
1321
                           TPMI_ALG_ASYM_SCHEME scheme       // IN: the scheme
1322
)
1323
{
1324
    BOOL isSignScheme = TRUE;
1,511✔
1325

1326
    switch(publicType)
1,511✔
1327
    {
1328
#if ALG_RSA
1329
        case TPM_ALG_RSA:
938✔
1330
            switch(scheme)
938✔
1331
            {
1332
#  if !ALG_RSASSA || !ALG_RSAPSS
1333
#    error "RSASSA and PSAPSS required if RSA used."
1334
#  endif
1335
                case TPM_ALG_RSASSA:
1336
                case TPM_ALG_RSAPSS:
1337
                    break;
1338
                default:
305✔
1339
                    isSignScheme = FALSE;
305✔
1340
                    break;
305✔
1341
            }
1342
            break;
1343
#endif  // ALG_RSA
1344

1345
#if ALG_ECC
1346
        // If ECC is implemented ECDSA is required
1347
        case TPM_ALG_ECC:
573✔
1348
#  if !ALG_ECDSA
1349
#    error "ECDSA required if ECC enabled."
1350
#  endif
1351
            switch(scheme)
573✔
1352
            {
1353
                // Support for ECDSA is required for ECC
1354
                case TPM_ALG_ECDSA:
1355
#  if ALG_ECDAA  // ECDAA is optional
1356
                case TPM_ALG_ECDAA:
1357
#  endif
1358
#  if ALG_ECSCHNORR  // Schnorr is also optional
1359
                case TPM_ALG_ECSCHNORR:
1360
#  endif
1361
#  if ALG_SM2  // SM2 is optional
1362
                case TPM_ALG_SM2:
1363
#  endif
1364
                    break;
1365
                default:
98✔
1366
                    isSignScheme = FALSE;
98✔
1367
                    break;
98✔
1368
            }
1369
            break;
1370
#endif  // ALG_ECC
1371
        default:
1372
            isSignScheme = FALSE;
1373
            break;
1374
    }
1375
    return isSignScheme;
1,511✔
1376
}
1377

1378
//*** CryptIsValidSignScheme()
1379
// This function checks that a signing scheme is valid. This includes verifying
1380
// that the scheme signing algorithm is compatible with the signing object type
1381
// and that the scheme specifies a valid hash algorithm.
1382
static BOOL CryptIsValidSignScheme(TPMI_ALG_PUBLIC   publicType,  // IN: Type of the object
702✔
1383
                                   TPMT_SIG_SCHEME*  scheme       // IN: the signing scheme
1384
)
1385
{
1386
    BOOL isValidSignScheme = TRUE;
702✔
1387

1388
    switch(publicType)
702✔
1389
    {
1390
#if ALG_RSA
1391
        case TPM_ALG_RSA:
534✔
1392
            isValidSignScheme = CryptIsAsymSignScheme(publicType, scheme->scheme);
534✔
1393
            break;
534✔
1394
#endif  // ALG_RSA
1395

1396
#if ALG_ECC
1397
        case TPM_ALG_ECC:
136✔
1398
            isValidSignScheme = CryptIsAsymSignScheme(publicType, scheme->scheme);
136✔
1399
            break;
136✔
1400
#endif  // ALG_ECC
1401

1402
        case TPM_ALG_KEYEDHASH:
32✔
1403
            if(scheme->scheme != TPM_ALG_HMAC)
32✔
1404
            {
1405
                isValidSignScheme = FALSE;
×
1406
            }
1407
            break;
1408

1409
        default:
1410
            isValidSignScheme = FALSE;
1411
            break;
1412
    }
1413

1414
    // Ensure that a valid hash algorithm is specified. Pass 'flag' = FALSE to
1415
    // indicate that TPM_ALG_NULL should not be treated as valid.
1416
    //
1417
    // NOTE: 'details' is of type TPMU_SIG_SCHEME which is a union of many
1418
    // different signature scheme types. In all these types (including the type
1419
    // of 'any'), the very first member is of type TPMI_ALG_HASH. Therefore,
1420
    // when 'any.hashAlg' is set to a valid hash algorithm ID, the hash for any
1421
    // signature scheme type will also be a valid hash algorithm ID. (All valid
1422
    // hash algorithm IDs are the same for all signature scheme types.)
1423
    if(!CryptHashIsValidAlg(scheme->details.any.hashAlg, /* flag = */ FALSE))
702✔
1424
    {
1425
        isValidSignScheme = FALSE;
×
1426
    }
1427

1428
    return isValidSignScheme;
702✔
1429
}
1430

1431
//*** CryptIsAsymDecryptScheme()
1432
// This function indicate if a scheme algorithm is a decrypt algorithm.
1433
BOOL CryptIsAsymDecryptScheme(TPMI_ALG_PUBLIC publicType,  // IN: Type of the object
144✔
1434
                              TPMI_ALG_ASYM_SCHEME scheme  // IN: the scheme
1435
)
1436
{
1437
    BOOL isDecryptScheme = TRUE;
144✔
1438

1439
    switch(publicType)
144✔
1440
    {
1441
#if ALG_RSA
1442
        case TPM_ALG_RSA:
140✔
1443
            switch(scheme)
140✔
1444
            {
1445
                case TPM_ALG_RSAES:
1446
                case TPM_ALG_OAEP:
1447
                    break;
1448
                default:
4✔
1449
                    isDecryptScheme = FALSE;
4✔
1450
                    break;
4✔
1451
            }
1452
            break;
1453
#endif  // ALG_RSA
1454

1455
#if ALG_ECC
1456
        // If ECC is implemented ECDH is required
1457
        case TPM_ALG_ECC:
4✔
1458
            switch(scheme)
4✔
1459
            {
1460
#  if !ALG_ECDH
1461
#    error "ECDH is required for ECC"
1462
#  endif
1463
                case TPM_ALG_ECDH:
1464
#  if ALG_SM2
1465
                case TPM_ALG_SM2:
1466
#  endif
1467
#  if ALG_ECMQV
1468
                case TPM_ALG_ECMQV:
1469
#  endif
1470
                    break;
1471
                default:
×
1472
                    isDecryptScheme = FALSE;
×
1473
                    break;
×
1474
            }
1475
            break;
1476
#endif  // ALG_ECC
1477
        default:
1478
            isDecryptScheme = FALSE;
1479
            break;
1480
    }
1481
    return isDecryptScheme;
144✔
1482
}
1483

1484
//*** CryptSelectSignScheme()
1485
// This function is used by the attestation and signing commands.  It implements
1486
// the rules for selecting the signature scheme to use in signing. This function
1487
// requires that the signing key either be TPM_RH_NULL or be loaded.
1488
//
1489
// If a default scheme is defined in object, the default scheme should be chosen,
1490
// otherwise, the input scheme should be chosen.
1491
// In the case that  both object and input scheme has a non-NULL scheme
1492
// algorithm, if the schemes are compatible, the input scheme will be chosen.
1493
//
1494
// This function should not be called if 'signObject->publicArea.type' ==
1495
// ALG_SYMCIPHER.
1496
//
1497
//  Return Type: BOOL
1498
//      TRUE(1)         scheme selected
1499
//      FALSE(0)        both 'scheme' and key's default scheme are empty; or
1500
//                      'scheme' is empty while key's default scheme requires
1501
//                      explicit input scheme (split signing); or
1502
//                      non-empty default key scheme differs from 'scheme'
1503
BOOL CryptSelectSignScheme(OBJECT*          signObject,  // IN: signing key
710✔
1504
                           TPMT_SIG_SCHEME* scheme       // IN/OUT: signing scheme
1505
)
1506
{
1507
    TPMT_SIG_SCHEME* objectScheme;
710✔
1508
    TPMT_PUBLIC*     publicArea;
710✔
1509
    BOOL             OK;
710✔
1510

1511
    // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
1512
    // of the setting of scheme
1513
    if(signObject == NULL)
710✔
1514
    {
1515
        OK                          = TRUE;
8✔
1516
        scheme->scheme              = TPM_ALG_NULL;
8✔
1517
        scheme->details.any.hashAlg = TPM_ALG_NULL;
8✔
1518
    }
1519
    else
1520
    {
1521
        // assignment to save typing.
1522
        publicArea = &signObject->publicArea;
702✔
1523

1524
        // Get a pointer to the scheme object.
1525
        if(CryptIsAsymAlgorithm(publicArea->type))
702✔
1526
        {
1527
           objectScheme =
670✔
1528
            (TPMT_SIG_SCHEME*)&publicArea->parameters.asymDetail.scheme;
1529
        }
1530
        else if(publicArea->type == TPM_ALG_KEYEDHASH)
32✔
1531
        {
1532
            objectScheme =
32✔
1533
            (TPMT_SIG_SCHEME*)&publicArea->parameters.keyedHashDetail.scheme;
1534
        }
1535
        else
1536
        {
1537
            // Only asymmetric key types (RSA, ECC) and keyed hashes can be
1538
            // used for signing. A symmetric cipher can be used to encrypt and
1539
            // decrypt but can't be used for signing.
1540
            return FALSE;
1541
        }
1542

1543
        // If the object doesn't have a default scheme, then use the
1544
        // input scheme.
1545
        if(objectScheme->scheme == TPM_ALG_NULL)
702✔
1546
        {
1547
            // Input and default can't both be NULL
1548
            OK = (scheme->scheme != TPM_ALG_NULL);
513✔
1549
            // Assume that the scheme is compatible with the key. If not,
1550
            // an error will be generated in the signing operation.
1551
        }
1552
        else if(scheme->scheme == TPM_ALG_NULL)
189✔
1553
        {
1554
            // input scheme is NULL so use default
1555

1556
            // First, check to see if the default requires that the caller
1557
            // provided scheme data
1558
            OK = !CryptIsSplitSign(objectScheme->scheme);
×
1559
            if(OK)
×
1560
            {
1561
                // The object has a scheme and the input is TPM_ALG_NULL so copy
1562
                // the object scheme as the final scheme. It is better to use a
1563
                // structure copy than a copy of the individual fields.
1564
                *scheme = *objectScheme;
×
1565
            }
1566
        }
1567
        else
1568
        {
1569
            // Both input and object have scheme selectors
1570
            // If the scheme and the hash are not the same then...
1571
            // NOTE: the reason that there is no copy here is that the input
1572
            // might contain extra data for a split signing scheme and that
1573
            // data is not in the object so, it has to be preserved.
1574
            OK =
189✔
1575
                (objectScheme->scheme == scheme->scheme)
1576
                && (objectScheme->details.any.hashAlg == scheme->details.any.hashAlg);
189✔
1577
        }
1578

1579
        if(OK)
513✔
1580
        {
1581
            // Check that the scheme is compatible with the key type and has a
1582
            // valid hash algorithm specified.
1583
            OK = CryptIsValidSignScheme(publicArea->type, scheme);
702✔
1584
        }
1585
    }
1586
    return OK;
1587
}
1588

1589
//*** CryptSign()
1590
// Sign a digest with asymmetric key or HMAC.
1591
// This function is called by attestation commands and the generic TPM2_Sign
1592
// command.
1593
// This function checks the key scheme and digest size.  It does not
1594
// check if the sign operation is allowed for restricted key.  It should be
1595
// checked before the function is called.
1596
// The function will assert if the key is not a signing key.
1597
//
1598
//  Return Type: TPM_RC
1599
//      TPM_RC_SCHEME      'signScheme' is not compatible with the signing key type
1600
//      TPM_RC_VALUE       'digest' value is greater than the modulus of
1601
//                         'signHandle' or size of 'hashData' does not match hash
1602
//                         algorithm in'signScheme' (for an RSA key);
1603
//                         invalid commit status or failed to generate "r" value
1604
//                         (for an ECC key)
1605
TPM_RC
1606
CryptSign(OBJECT*          signKey,     // IN: signing key
663✔
1607
          TPMT_SIG_SCHEME* signScheme,  // IN: sign scheme.
1608
          TPM2B_DIGEST*    digest,      // IN: The digest being signed
1609
          TPMT_SIGNATURE*  signature    // OUT: signature
1610
)
1611
{
1612
    TPM_RC result = TPM_RC_SCHEME;
663✔
1613

1614
    // Initialize signature scheme
1615
    signature->sigAlg = signScheme->scheme;
663✔
1616

1617
    // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL,
1618
    // then we are done
1619
    if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL))
663✔
1620
        return TPM_RC_SUCCESS;
1621

1622
    // Initialize signature hash
1623
    // Note: need to do the check for TPM_ALG_NULL first because the null scheme
1624
    // doesn't have a hashAlg member.
1625
    signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
663✔
1626

1627
    switch(signKey->publicArea.type)                                // libtpms added begin
663✔
1628
        {
1629
          case TPM_ALG_RSA:
635✔
1630
          case TPM_ALG_ECC:
1631
            if (signScheme->details.any.hashAlg == TPM_ALG_SHA1 &&
714✔
1632
                RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
79✔
1633
                                                     RUNTIME_ATTRIBUTE_NO_SHA1_SIGNING))
1634
                return TPM_RC_HASH;
1635
            break;
1636
          case TPM_ALG_KEYEDHASH:
28✔
1637
            if (signScheme->details.any.hashAlg == TPM_ALG_SHA1 &&
35✔
1638
                RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
7✔
1639
                                                     RUNTIME_ATTRIBUTE_NO_SHA1_HMAC_CREATION))
1640
                return TPM_RC_HASH;
1641
            break;
1642
        }                                                        // libtpms added end
1643

1644
    // perform sign operation based on different key type
1645
    switch(signKey->publicArea.type)
663✔
1646
    {
1647
#if ALG_RSA
1648
        case TPM_ALG_RSA:
501✔
1649
            result = CryptRsaSign(signature, signKey, digest, NULL);
501✔
1650
            break;
501✔
1651
#endif  // ALG_RSA
1652
#if ALG_ECC
1653
        case TPM_ALG_ECC:
134✔
1654
            // The reason that signScheme is passed to CryptEccSign but not to the
1655
            // other signing methods is that the signing for ECC may be split and
1656
            // need the 'r' value that is in the scheme but not in the signature.
1657
            result = CryptEccSign(
134✔
1658
                signature, signKey, digest, (TPMT_ECC_SCHEME*)signScheme, NULL);
1659
            break;
134✔
1660
#endif  // ALG_ECC
1661
        case TPM_ALG_KEYEDHASH:
28✔
1662
            result = CryptHmacSign(signature, signKey, digest);
28✔
1663
            break;
28✔
1664
        default:
×
1665
            FAIL(FATAL_ERROR_INTERNAL);
×
1666
            break;
1667
    }
1668
    return result;
1669
}
1670

1671
//*** CryptValidateSignature()
1672
// This function is used to verify a signature.  It is called by
1673
// TPM2_VerifySignature() and TPM2_PolicySigned.
1674
//
1675
// Since this operation only requires use of a public key, no consistency
1676
// checks are necessary for the key to signature type because a caller can load
1677
// any public key that they like with any scheme that they like. This routine
1678
// simply makes sure that the signature is correct, whatever the type.
1679
//
1680
//  Return Type: TPM_RC
1681
//      TPM_RC_SIGNATURE            the signature is not genuine
1682
//      TPM_RC_SCHEME               the scheme is not supported
1683
//      TPM_RC_HANDLE               an HMAC key was selected but the
1684
//                                  private part of the key is not loaded
1685
TPM_RC
1686
CryptValidateSignature(TPMI_DH_OBJECT  keyHandle,  // IN: The handle of sign key
699✔
1687
                       TPM2B_DIGEST*   digest,     // IN: The digest being validated
1688
                       TPMT_SIGNATURE* signature   // IN: signature
1689
)
1690
{
1691
    // NOTE: HandleToObject will either return a pointer to a loaded object or
1692
    // will assert. It will never return a non-valid value. This makes it save
1693
    // to initialize 'publicArea' with the return value from HandleToObject()
1694
    // without checking it first.
1695
    OBJECT*      signObject = HandleToObject(keyHandle);
699✔
1696
    TPMT_PUBLIC* publicArea = &signObject->publicArea;
699✔
1697
    TPM_RC       result     = TPM_RC_SCHEME;
699✔
1698

1699
    // The input unmarshaling should prevent any input signature from being
1700
    // a NULL signature, but just in case
1701
    if(signature->sigAlg == TPM_ALG_NULL)
699✔
1702
        return TPM_RC_SIGNATURE;
1703

1704
    switch(publicArea->type)
699✔
1705
    {
1706
#if ALG_RSA
1707
        case TPM_ALG_RSA:
555✔
1708
        {
1709
            //
1710
            // Call RSA code to verify signature
1711
            result = CryptRsaValidateSignature(signature, signObject, digest);
555✔
1712
            break;
555✔
1713
        }
1714
#endif  // ALG_RSA
1715

1716
#if ALG_ECC
1717
        case TPM_ALG_ECC:
124✔
1718
            result = CryptEccValidateSignature(signature, signObject, digest);
124✔
1719
            break;
124✔
1720
#endif  // ALG_ECC
1721

1722
        case TPM_ALG_KEYEDHASH:
20✔
1723
            if(signObject->attributes.publicOnly)
20✔
1724
                result = TPM_RCS_HANDLE;
1725
            else
1726
                result = CryptHMACVerifySignature(signObject, digest, signature);
20✔
1727
            break;
1728
        default:
1729
            break;
1730
    }
1731
    return result;
1732
}
1733

1734
//*** CryptGetTestResult
1735
// This function returns the results of a self-test function.
1736
// Note: the behavior in this function is NOT the correct behavior for a real
1737
// TPM implementation.  An artificial behavior is placed here due to the
1738
// limitation of a software simulation environment.  For the correct behavior,
1739
// consult the part 3 specification for TPM2_GetTestResult().
1740
TPM_RC
1741
CryptGetTestResult(TPM2B_MAX_BUFFER* outData  // OUT: test result data
5✔
1742
)
1743
{
1744
    outData->t.size = 0;
5✔
1745
    return TPM_RC_SUCCESS;
5✔
1746
}
1747

1748
//*** CryptValidateKeys()
1749
// This function is used to verify that the key material of and object is valid.
1750
// For a 'publicOnly' object, the key is verified for size and, if it is an ECC
1751
// key, it is verified to be on the specified curve. For a key with a sensitive
1752
// area, the binding between the public and private parts of the key are verified.
1753
// If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area
1754
// is verified but the public portion is not verified, unless the key is an RSA key.
1755
// For an RSA key, the reason for loading the sensitive area is to use it. The
1756
// only way to use a private RSA key is to compute the private exponent. To compute
1757
// the private exponent, the public modulus is used.
1758
//  Return Type: TPM_RC
1759
//      TPM_RC_BINDING      the public and private parts are not cryptographically
1760
//                          bound
1761
//      TPM_RC_HASH         cannot have a publicOnly key with nameAlg of TPM_ALG_NULL
1762
//      TPM_RC_KEY          the public unique is not valid
1763
//      TPM_RC_KEY_SIZE     the private area key is not valid
1764
//      TPM_RC_TYPE         the types of the sensitive and private parts do not match
1765
TPM_RC
1766
CryptValidateKeys(TPMT_PUBLIC*    publicArea,
577✔
1767
                  TPMT_SENSITIVE* sensitive,
1768
                  TPM_RC          blamePublic,
1769
                  TPM_RC          blameSensitive)
1770
{
1771
    TPM_RC             result;
577✔
1772
    UINT16             keySizeInBytes;
577✔
1773
    UINT16             digestSize = CryptHashGetDigestSize(publicArea->nameAlg);
577✔
1774
    TPMU_PUBLIC_PARMS* params     = &publicArea->parameters;
577✔
1775
    TPMU_PUBLIC_ID*    unique     = &publicArea->unique;
577✔
1776

1777
    if(sensitive != NULL)
577✔
1778
    {
1779
        // Make sure that the types of the public and sensitive are compatible
1780
        if(publicArea->type != sensitive->sensitiveType)
457✔
1781
            return TPM_RCS_TYPE + blameSensitive;
4✔
1782
        // Make sure that the authValue is not bigger than allowed
1783
        // If there is no name algorithm, then the size just needs to be less than
1784
        // the maximum size of the buffer used for authorization. That size check
1785
        // was made during unmarshaling of the sensitive area
1786
        if((sensitive->authValue.t.size) > digestSize && (digestSize > 0))
453✔
1787
            return TPM_RCS_SIZE + blameSensitive;
×
1788
    }
1789
    switch(publicArea->type)
573✔
1790
    {
1791
#if ALG_RSA
1792
        case TPM_ALG_RSA:
225✔
1793
            keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits);
225✔
1794

1795
            // Regardless of whether there is a sensitive area, the public modulus
1796
            // needs to have the correct size. Otherwise, it can't be used for
1797
            // any public key operation nor can it be used to compute the private
1798
            // exponent.
1799
            // NOTE: This implementation only supports key sizes that are multiples
1800
            // of 1024 bits which means that the MSb of the 0th byte will always be
1801
            // SET in any prime and in the public modulus.
1802
            if((unique->rsa.t.size != keySizeInBytes)
225✔
1803
               || (unique->rsa.t.buffer[0] < 0x80))
225✔
1804
                return TPM_RCS_KEY + blamePublic;
56✔
1805
            if(params->rsaDetail.exponent != 0 && params->rsaDetail.exponent < 7)
169✔
1806
                return TPM_RCS_VALUE + blamePublic;
4✔
1807
            if(sensitive != NULL)
165✔
1808
            {
1809
                // If there is a sensitive area, it has to be the correct size
1810
                // including having the correct high order bit SET.
1811
                if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes)
124✔
1812
                   || (sensitive->sensitive.rsa.t.buffer[0] < 0x80))
124✔
1813
                    return TPM_RCS_KEY_SIZE + blameSensitive;
4✔
1814
            }
1815
            break;
1816
#endif
1817
#if ALG_ECC
1818
        case TPM_ALG_ECC:
323✔
1819
        {
1820
            TPMI_ECC_CURVE curveId;
323✔
1821
            curveId        = params->eccDetail.curveID;
323✔
1822
            keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId));
323✔
1823
            if(sensitive == NULL)
323✔
1824
            {
1825
                // Validate the public key size
1826
                if(unique->ecc.x.t.size != keySizeInBytes
75✔
1827
                   || unique->ecc.y.t.size != keySizeInBytes)
51✔
1828
                    return TPM_RCS_KEY + blamePublic;
24✔
1829
                if(publicArea->nameAlg != TPM_ALG_NULL)
51✔
1830
                {
1831
                    if(!CryptEccIsPointOnCurve(curveId, &unique->ecc))
51✔
1832
                        return TPM_RCS_ECC_POINT + blamePublic;
4✔
1833
                }
1834
            }
1835
            else
1836
            {
1837
                // If the nameAlg is TPM_ALG_NULL, then only verify that the
1838
                // private part of the key is OK.
1839
                if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc, curveId))
248✔
1840
                    return TPM_RCS_KEY_SIZE;
1841
                if(publicArea->nameAlg != TPM_ALG_NULL)
244✔
1842
                {
1843
                    // Full key load, verify that the public point belongs to the
1844
                    // private key.
1845
                    TPMS_ECC_POINT toCompare;
244✔
1846
                    result = CryptEccPointMultiply(&toCompare,
244✔
1847
                                                   curveId,
1848
                                                   NULL,
1849
                                                   &sensitive->sensitive.ecc,
1850
                                                   NULL,
1851
                                                   NULL);
1852
                    if(result != TPM_RC_SUCCESS)
244✔
1853
                        return TPM_RCS_BINDING;
196✔
1854
                    else
1855
                    {
1856
                        // Make sure that the private key generated the public key.
1857
                        // The input values and the values produced by the point
1858
                        // multiply may not be the same size so adjust the computed
1859
                        // value to match the size of the input value by adding or
1860
                        // removing zeros.
1861
                        AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size);
244✔
1862
                        AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size);
244✔
1863
                        if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b)
244✔
1864
                           || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b))
48✔
1865
                            return TPM_RCS_BINDING;
196✔
1866
                    }
1867
                }
1868
            }
1869
            break;
1870
        }
1871
#endif
1872
        default:
25✔
1873
            // Checks for SYMCIPHER and KEYEDHASH are largely the same
1874
            // If public area has a nameAlg, then validate the public area size
1875
            // and if there is also a sensitive area, validate the binding
1876

1877
            // For consistency, if the object is public-only just make sure that
1878
            // the unique field is consistent with the name algorithm
1879
            if(sensitive == NULL)
25✔
1880
            {
1881
                if(unique->sym.t.size != digestSize)
4✔
1882
                    return TPM_RCS_KEY + blamePublic;
4✔
1883
            }
1884
            else
1885
            {
1886
                // Make sure that the key size in the sensitive area is consistent.
1887
                if(publicArea->type == TPM_ALG_SYMCIPHER)
21✔
1888
                {
1889
                    result = CryptSymKeyValidate(&params->symDetail.sym,
8✔
1890
                                                 &sensitive->sensitive.sym);
1891
                    if(result != TPM_RC_SUCCESS)
8✔
1892
                        return result + blameSensitive;
4✔
1893
                }
1894
                else
1895
                {
1896
                    // For a keyed hash object, the key has to be less than the
1897
                    // smaller of the block size of the hash used in the scheme or
1898
                    // 128 bytes. The worst case value is limited by the
1899
                    // unmarshaling code so the only thing left to be checked is
1900
                    // that it does not exceed the block size of the hash.
1901
                    // by the hash algorithm of the scheme.
1902
                    TPMT_KEYEDHASH_SCHEME* scheme;
13✔
1903
                    UINT16                 maxSize;
13✔
1904
                    scheme = &params->keyedHashDetail.scheme;
13✔
1905
                    if(scheme->scheme == TPM_ALG_XOR)
13✔
1906
                    {
1907
                        maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg);
×
1908
                    }
1909
                    else if(scheme->scheme == TPM_ALG_HMAC)
13✔
1910
                    {
1911
                        maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg);
8✔
1912
                    }
1913
                    else if(scheme->scheme == TPM_ALG_NULL)
5✔
1914
                    {
1915
                        // Not signing or xor so must be a data block
1916
                        maxSize = 128;
1917
                    }
1918
                    else
1919
                        return TPM_RCS_SCHEME + blamePublic;
×
1920
                    if(sensitive->sensitive.bits.t.size > maxSize)
13✔
1921
                        return TPM_RCS_KEY_SIZE + blameSensitive;
×
1922
                }
1923
                // If there is a nameAlg, check the binding
1924
                if(publicArea->nameAlg != TPM_ALG_NULL)
17✔
1925
                {
1926
                    TPM2B_DIGEST compare;
17✔
1927
                    if(sensitive->seedValue.t.size != digestSize)
17✔
1928
                        return TPM_RCS_KEY_SIZE + blameSensitive;
8✔
1929

1930
                    CryptComputeSymmetricUnique(publicArea, sensitive, &compare);
13✔
1931
                    if(!MemoryEqual2B(&unique->sym.b, &compare.b))
13✔
1932
                        return TPM_RC_BINDING;
1933
                }
1934
            }
1935
            break;
1936
    }
1937
    // For a parent, need to check that the seedValue is the correct size for
1938
    // protections. It should be at least half the size of the nameAlg
1939
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
265✔
1940
       && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
265✔
1941
       && sensitive != NULL && publicArea->nameAlg != TPM_ALG_NULL)
29✔
1942
    {
1943
        if((sensitive->seedValue.t.size < (digestSize / 2))
1✔
1944
           || (sensitive->seedValue.t.size > digestSize))
1✔
1945
            return TPM_RCS_SIZE + blameSensitive;
×
1946
    }
1947
    return TPM_RC_SUCCESS;
1948
}
1949

1950
//*** CryptSelectMac()
1951
// This function is used to set the MAC scheme based on the key parameters and
1952
// the input scheme.
1953
//  Return Type: TPM_RC
1954
//      TPM_RC_SCHEME       the scheme is not a valid mac scheme
1955
//      TPM_RC_TYPE         the input key is not a type that supports a mac
1956
//      TPM_RC_VALUE        the input scheme and the key scheme are not compatible
1957
TPM_RC
1958
CryptSelectMac(TPMT_PUBLIC* publicArea, TPMI_ALG_MAC_SCHEME* inMac)
40✔
1959
{
1960
    TPM_ALG_ID macAlg = TPM_ALG_NULL;
40✔
1961
    switch(publicArea->type)
40✔
1962
    {
1963
        case TPM_ALG_KEYEDHASH:
40✔
1964
        {
1965
            // Local value to keep lines from getting too long
1966
            TPMT_KEYEDHASH_SCHEME* scheme;
40✔
1967
            scheme = &publicArea->parameters.keyedHashDetail.scheme;
40✔
1968
            // Expect that the scheme is either HMAC or NULL
1969
            if(scheme->scheme != TPM_ALG_NULL)
40✔
1970
                macAlg = scheme->details.hmac.hashAlg;
40✔
1971
            break;
1972
        }
1973
        case TPM_ALG_SYMCIPHER:
×
1974
        {
1975
            TPMT_SYM_DEF_OBJECT* scheme;
×
1976
            scheme = &publicArea->parameters.symDetail.sym;
×
1977
            // Expect that the scheme is either valid symmetric cipher or NULL
1978
            if(scheme->algorithm != TPM_ALG_NULL)
×
1979
                macAlg = scheme->mode.sym;
×
1980
            break;
1981
        }
1982
        default:
1983
            return TPM_RCS_TYPE;
1984
    }
1985
    // If the input value is not TPM_ALG_NULL ...
1986
    if(*inMac != TPM_ALG_NULL)
40✔
1987
    {
1988
        // ... then either the scheme in the key must be TPM_ALG_NULL or the input
1989
        // value must match
1990
        if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg))
40✔
1991
            return TPM_RCS_VALUE;
1992
    }
1993
    else
1994
    {
1995
        // Since the input value is TPM_ALG_NULL, then the key value can't be
1996
        // TPM_ALG_NULL
1997
        if(macAlg == TPM_ALG_NULL)
×
1998
            return TPM_RCS_VALUE;
1999
        *inMac = macAlg;
×
2000
    }
2001
    if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
40✔
2002
        return TPM_RCS_SCHEME;
×
2003
    return TPM_RC_SUCCESS;
2004
}
2005

2006
//*** CryptMacIsValidForKey()
2007
// Check to see if the key type is compatible with the mac type
2008
BOOL CryptMacIsValidForKey(TPM_ALG_ID keyType, TPM_ALG_ID macAlg, BOOL flag)
40✔
2009
{
2010
    switch(keyType)
40✔
2011
    {
2012
        case TPM_ALG_KEYEDHASH:
40✔
2013
            return CryptHashIsValidAlg(macAlg, flag);
40✔
2014
            break;
×
2015
        case TPM_ALG_SYMCIPHER:
×
2016
            return CryptSmacIsValidAlg(macAlg, flag);
×
2017
            break;
2018
        default:
2019
            break;
2020
    }
2021
    return FALSE;
2022
}
2023

2024
//*** CryptSmacIsValidAlg()
2025
// This function is used to test if an algorithm is a supported SMAC algorithm. It
2026
// needs to be updated as new algorithms are added.
2027
BOOL CryptSmacIsValidAlg(TPM_ALG_ID alg,
92✔
2028
                         BOOL       FLAG  // IN: Indicates if TPM_ALG_NULL is valid
2029
)
2030
{
2031
    switch(alg)
92✔
2032
    {
2033
#if ALG_CMAC
2034
        case TPM_ALG_CMAC:
2035
            return TRUE;
2036
            break;
×
2037
#endif
2038
        case TPM_ALG_NULL:
×
2039
            return FLAG;
×
2040
            break;
×
2041
        default:
×
2042
            return FALSE;
×
2043
    }
2044
}
2045

2046
//*** CryptSymModeIsValid()
2047
// Function checks to see if an algorithm ID is a valid, symmetric block cipher
2048
// mode for the TPM. If 'flag' is SET, them TPM_ALG_NULL is a valid mode.
2049
// not include the modes used for SMAC
2050
BOOL CryptSymModeIsValid(TPM_ALG_ID mode, BOOL flag)
71✔
2051
{
2052
    switch(mode)
71✔
2053
    {
2054
#if ALG_CTR
2055
        case TPM_ALG_CTR:
2056
#endif  // ALG_CTR
2057
#if ALG_OFB
2058
        case TPM_ALG_OFB:
2059
#endif  // ALG_OFB
2060
#if ALG_CBC
2061
        case TPM_ALG_CBC:
2062
#endif  // ALG_CBC
2063
#if ALG_CFB
2064
        case TPM_ALG_CFB:
2065
#endif  // ALG_CFB
2066
#if ALG_ECB
2067
        case TPM_ALG_ECB:
2068
#endif  // ALG_ECB
2069
            return TRUE;
2070
        case TPM_ALG_NULL:
×
2071
            return flag;
×
2072
            break;
×
2073
        default:
2074
            break;
×
2075
    }
2076
    return FALSE;
×
2077
}
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