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

stefanberger / libtpms / #2029

03 Dec 2025 11:17PM UTC coverage: 77.215% (-0.002%) from 77.217%
#2029

push

travis-ci

web-flow
Merge 14fd30650 into 4f71e9b45

38 of 52 new or added lines in 7 files covered. (73.08%)

214 existing lines in 13 files now uncovered.

36121 of 46780 relevant lines covered (77.21%)

126185.61 hits per line

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

77.17
/src/tpm2/CommandCodeAttributes.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
//** Introduction
4
// This file contains the functions for testing various command properties.
5

6
//** Includes and Defines
7

8
#include "Tpm.h"
9
#include "CommandCodeAttributes_fp.h"
10

11
// Set the default value for CC_VEND if not already set
12
#ifndef CC_VEND
13
#  define CC_VEND (TPM_CC)(0x20000000)
14
#endif
15

16
typedef UINT16 ATTRIBUTE_TYPE;
17

18
// The following file is produced from the command tables in part 3 of the
19
// specification. It defines the attributes for each of the commands.
20
// NOTE: This file is currently produced by an automated process. Files
21
// produced from Part 2 or Part 3 tables through automated processes are not
22
// included in the specification so that their is no ambiguity about the
23
// table containing the information being the normative definition.
24
#define _COMMAND_CODE_ATTRIBUTES_
25
#include "CommandAttributeData.h"
26

27
//** Command Attribute Functions
28

29
//*** NextImplementedIndex()                                                        // libtpms added begin
30
// This function is used when the lists are not compressed. In a compressed list,
31
// only the implemented commands are present. So, a search might find a value
32
// but that value may not be implemented. This function checks to see if the input
33
// commandIndex points to an implemented command and, if not, it searches upwards
34
// until it finds one. When the list is compressed, this function gets defined
35
// as a no-op.
36
//  Return Type: COMMAND_INDEX
37
//  UNIMPLEMENTED_COMMAND_INDEX     command is not implemented
38
//  other                           index of the command
39
#if !COMPRESSED_LISTS
40
static COMMAND_INDEX NextImplementedIndex(COMMAND_INDEX commandIndex)
162✔
41
{
42
    for(; commandIndex < COMMAND_COUNT; commandIndex++)
163✔
43
    {
44
       if(RuntimeCommandsCheckEnabled(&g_RuntimeProfile.RuntimeCommands,        // libtpms added begin
163✔
45
                                      GET_ATTRIBUTE(s_ccAttr[commandIndex],
163✔
46
                                                    TPMA_CC, commandIndex)))        // libtpms added end
47
            return commandIndex;
162✔
48
    }
49
    return UNIMPLEMENTED_COMMAND_INDEX;
50
}
51
#else
52
#  define NextImplementedIndex(x) (x)
53
#endif                                                                                // libtpms added end
54

55
//*** GetClosestCommandIndex()
56
// This function returns the command index for the command with a value that is
57
// equal to or greater than the input value
58
//  Return Type: COMMAND_INDEX
59
//  UNIMPLEMENTED_COMMAND_INDEX     command is not implemented
60
//  other                           index of a command
61
COMMAND_INDEX
62
GetClosestCommandIndex(TPM_CC commandCode  // IN: the command code to start at
174✔
63
)
64
{
65
    BOOL          vendor      = (commandCode & CC_VEND) != 0;
174✔
66
    COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode;
174✔
67

68
    // The commandCode is a UINT32 and the search index is UINT16. We are going to
69
    // search for a match but need to make sure that the commandCode value is not
70
    // out of range. To do this, need to clear the vendor bit of the commandCode
71
    // (if set) and compare the result to the 16-bit searchIndex value. If it is
72
    // out of range, indicate that the command is not implemented
73
    if((commandCode & ~CC_VEND) != searchIndex)
174✔
74
        return UNIMPLEMENTED_COMMAND_INDEX;
75

76
    // if there is at least one vendor command, the last entry in the array will
77
    // have the v bit set. If the input commandCode is larger than the last
78
    // vendor-command, then it is out of range.
79
    if(vendor)
162✔
80
    {
81
#if VENDOR_COMMAND_ARRAY_SIZE > 0
82
        COMMAND_INDEX commandIndex;
83
        COMMAND_INDEX min;
84
        COMMAND_INDEX max;
85
        int           diff;
86
#  if LIBRARY_COMMAND_ARRAY_SIZE == COMMAND_COUNT
87
#    error "Constants are not consistent."
88
#  endif
89
        // Check to see if the value is equal to or below the minimum
90
        // entry.
91
        // Note: Put this check first so that the typical case of only one vendor-
92
        // specific command doesn't waste any more time.
93
        if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC, commandIndex)
94
           >= searchIndex)
95
        {
96
            // the vendor array is always assumed to be packed so there is
97
            // no need to check to see if the command is implemented
98
            return LIBRARY_COMMAND_ARRAY_SIZE;
99
        }
100
        // See if this is out of range on the top
101
        if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex)
102
           < searchIndex)
103
        {
104
            return UNIMPLEMENTED_COMMAND_INDEX;
105
        }
106
        commandIndex = UNIMPLEMENTED_COMMAND_INDEX;  // Needs initialization to keep
107
                                                     // compiler happy
108
        min  = LIBRARY_COMMAND_ARRAY_SIZE;           // first vendor command
109
        max  = COMMAND_COUNT - 1;                    // last vendor command
110
        diff = 1;                                    // needs initialization to keep
111
                                                     // compiler happy
112
        while(min <= max)
113
        {
114
            commandIndex = (min + max + 1) / 2;
115
            diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)
116
                   - searchIndex;
117
            if(diff == 0)
118
                return commandIndex;
119
            if(diff > 0)
120
                max = commandIndex - 1;
121
            else
122
                min = commandIndex + 1;
123
        }
124
        // didn't find and exact match. commandIndex will be pointing at the last
125
        // item tested. If 'diff' is positive, then the last item tested was
126
        // larger index of the command code so it is the smallest value
127
        // larger than the requested value.
128
        if(diff > 0)
129
            return commandIndex;
130
        // if 'diff' is negative, then the value tested was smaller than
131
        // the commandCode index and the next higher value is the correct one.
132
        // Note: this will necessarily be in range because of the earlier check
133
        // that the index was within range.
134
        return commandIndex + 1;
135
#else
136
        // If there are no vendor commands so anything with the vendor bit set is out
137
        // of range
138
        return UNIMPLEMENTED_COMMAND_INDEX;
139
#endif
140
    }
141
    // Get here if the V-Bit was not set in 'commandCode'
142

143
    if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC, commandIndex)
162✔
144
       < searchIndex)
145
    {
146
        // requested index is out of the range to the top
147
#if VENDOR_COMMAND_ARRAY_SIZE > 0
148
        // If there are vendor commands, then the first vendor command
149
        // is the next value greater than the commandCode.
150
        // NOTE: we got here if the starting index did not have the V bit but we
151
        // reached the end of the array of library commands (non-vendor). Since
152
        // there is at least one vendor command, and vendor commands are always
153
        // in a compressed list that starts after the library list, the next
154
        // index value contains a valid vendor command.
155
        return LIBRARY_COMMAND_ARRAY_SIZE;
156
#else
157
        // if there are no vendor commands, then this is out of range
158
        return UNIMPLEMENTED_COMMAND_INDEX;
159
#endif
160
    }
161
    // If the request is lower than any value in the array, then return
162
    // the lowest value (needs to be an index for an implemented command
163
    if(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex)
162✔
164
    {
165
        return NextImplementedIndex(0);                                // libtpms changed
114✔
166
    }
167
    else
168
    {
169
#if COMPRESSED_LISTS                                                        // libtpms added
170
        COMMAND_INDEX commandIndex = UNIMPLEMENTED_COMMAND_INDEX;
171
        COMMAND_INDEX min          = 0;
172
        COMMAND_INDEX max          = LIBRARY_COMMAND_ARRAY_SIZE - 1;
173
        int           diff         = 1;
174
#  if LIBRARY_COMMAND_ARRAY_SIZE == 0
175
#    error "Something is terribly wrong"
176
#  endif
177
        // The s_ccAttr array contains an extra entry at the end (a zero value).
178
        // Don't count this as an array entry. This means that max should start
179
        // out pointing to the last valid entry in the array which is - 2
180
        pAssert(
181
            max
182
            == (sizeof(s_ccAttr) / sizeof(TPMA_CC) - VENDOR_COMMAND_ARRAY_SIZE - 2));
183
        while(min <= max)
184
        {
185
            commandIndex = (min + max + 1) / 2;
186
            diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)
187
                   - searchIndex;
188
            if(diff == 0)
189
                return commandIndex;
190
            if(diff > 0)
191
                max = commandIndex - 1;
192
            else
193
                min = commandIndex + 1;
194
        }
195
        // didn't find and exact match. commandIndex will be pointing at the
196
        // last item tested. If diff is positive, then the last item tested was
197
        // larger index of the command code so it is the smallest value
198
        // larger than the requested value.
199
        if(diff > 0)
200
            return commandIndex;
201
        // if diff is negative, then the value tested was smaller than
202
        // the commandCode index and the next higher value is the correct one.
203
        // Note: this will necessarily be in range because of the earlier check
204
        // that the index was within range.
205
        return commandIndex + 1;
206
#else                                                                        // libtpms added begin
207
        // The list is not compressed so offset into the array by the command
208
        // code value of the first entry in the list. Then go find the first
209
        // implemented command.
210
        return NextImplementedIndex(
48✔
211
            searchIndex - (COMMAND_INDEX)GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex));
48✔
212
#endif                                                                        // libtpms added end
213
    }
214
}
215

216
//*** CommandCodeToComandIndex()
217
// This function returns the index in the various attributes arrays of the
218
// command.
219
//  Return Type: COMMAND_INDEX
220
//  UNIMPLEMENTED_COMMAND_INDEX     command is not implemented
221
//  other                           index of the command
222
COMMAND_INDEX
223
CommandCodeToCommandIndex(TPM_CC commandCode  // IN: the command code to look up
22,145✔
224
)
225
{
226
    // Extract the low 16-bits of the command code to get the starting search index
227
    COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode;
22,145✔
228
    BOOL          vendor      = (commandCode & CC_VEND) != 0;
22,145✔
229
    COMMAND_INDEX commandIndex;
22,145✔
230
#if !COMPRESSED_LISTS                                                        // libtpms added begin
231
    if(!vendor)
22,145✔
232
    {
233
        commandIndex = searchIndex - (COMMAND_INDEX)GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex);
22,145✔
234
        // Check for out of range or unimplemented.
235
        // Note, since a COMMAND_INDEX is unsigned, if searchIndex is smaller than
236
        // the lowest value of command, it will become a 'negative' number making
237
        // it look like a large unsigned number, this will cause it to fail
238
        // the unsigned check below.
239
        if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZE
22,145✔
240
           || !RuntimeCommandsCheckEnabled(&g_RuntimeProfile.RuntimeCommands,
22,140✔
241
                                           commandCode))
242
            return UNIMPLEMENTED_COMMAND_INDEX;
7✔
243
        return commandIndex;
244
    }
245
#endif                                                                        // libtpms added end
246
    // Need this code for any vendor code lookup or for compressed lists
UNCOV
247
    commandIndex = GetClosestCommandIndex(commandCode);
×
248

249
    // Look at the returned value from get closest. If it isn't the one that was
250
    // requested, then the command is not implemented.
251
    // libtpms: Or it may be runtime-disabled
UNCOV
252
    if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX)
×
253
    {
UNCOV
254
        if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)
×
255
            != searchIndex)
UNCOV
256
           || (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor
×
UNCOV
257
           || !RuntimeCommandsCheckEnabled(&g_RuntimeProfile.RuntimeCommands,        // libtpms added
×
258
                                           commandCode))                        // libtpms added
259
            commandIndex = UNIMPLEMENTED_COMMAND_INDEX;
260
    }
261
    return commandIndex;
262
}
263

264
//*** GetNextCommandIndex()
265
// This function returns the index of the next implemented command.
266
//  Return Type: COMMAND_INDEX
267
//  UNIMPLEMENTED_COMMAND_INDEX     no more implemented commands
268
//  other                           the index of the next implemented command
269
COMMAND_INDEX
270
GetNextCommandIndex(COMMAND_INDEX commandIndex  // IN: the starting index
10,782✔
271
)
272
{
273
    while(++commandIndex < COMMAND_COUNT)
13,179✔
274
    {
275
        if(!RuntimeCommandsCheckEnabled(&g_RuntimeProfile.RuntimeCommands,        // libtpms added begin
13,058✔
276
                                        GET_ATTRIBUTE(s_ccAttr[commandIndex],
13,058✔
277
                                                      TPMA_CC, commandIndex)))
278
            continue;                                                                // libtpms added end
2,397✔
279
        return commandIndex;
280
    }
281
    return UNIMPLEMENTED_COMMAND_INDEX;
282
}
283

284
//*** GetCommandCode()
285
// This function returns the commandCode associated with the command index
286
TPM_CC
287
GetCommandCode(COMMAND_INDEX commandIndex  // IN: the command index
57✔
288
)
289
{
290
    TPM_CC commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex);
57✔
291
    if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
57✔
UNCOV
292
        commandCode += CC_VEND;
×
293
    return commandCode;
57✔
294
}
295

296
//*** CommandAuthRole()
297
//
298
//  This function returns the authorization role required of a handle.
299
//
300
//  Return Type: AUTH_ROLE
301
//  AUTH_NONE       no authorization is required
302
//  AUTH_USER       user role authorization is required
303
//  AUTH_ADMIN      admin role authorization is required
304
//  AUTH_DUP        duplication role authorization is required
305
AUTH_ROLE
306
CommandAuthRole(COMMAND_INDEX commandIndex,  // IN: command index
17,608✔
307
                UINT32        handleIndex    // IN: handle index (zero based)
308
)
309
{
310
    if(0 == handleIndex)
17,608✔
311
    {
312
        // Any authorization role set?
313
        COMMAND_ATTRIBUTES properties = s_commandAttributes[commandIndex];
14,412✔
314

315
        if(properties & HANDLE_1_USER)
14,412✔
316
            return AUTH_USER;
317
        if(properties & HANDLE_1_ADMIN)
2,627✔
318
            return AUTH_ADMIN;
319
        if(properties & HANDLE_1_DUP)
2,058✔
320
            return AUTH_DUP;
33✔
321
    }
322
    else if(1 == handleIndex)
3,196✔
323
    {
324
        if(s_commandAttributes[commandIndex] & HANDLE_2_USER)
3,090✔
325
            return AUTH_USER;
825✔
326
    }
327
    return AUTH_NONE;
328
}
329

330
//*** EncryptSize()
331
// This function returns the size of the decrypt size field. This function returns
332
// 0 if encryption is not allowed
333
//  Return Type: int
334
//  0       encryption not allowed
335
//  2       size field is two bytes
336
//  4       size field is four bytes
337
int EncryptSize(COMMAND_INDEX commandIndex  // IN: command index
306✔
338
)
339
{
340
    return ((s_commandAttributes[commandIndex] & ENCRYPT_2)   ? 2
306✔
341
            : (s_commandAttributes[commandIndex] & ENCRYPT_4) ? 4
306✔
UNCOV
342
                                                              : 0);
×
343
}
344

345
//*** DecryptSize()
346
// This function returns the size of the decrypt size field. This function returns
347
// 0 if decryption is not allowed
348
//  Return Type: int
349
//  0       encryption not allowed
350
//  2       size field is two bytes
351
//  4       size field is four bytes
352
int DecryptSize(COMMAND_INDEX commandIndex  // IN: command index
322✔
353
)
354
{
355
    return ((s_commandAttributes[commandIndex] & DECRYPT_2)   ? 2
322✔
356
            : (s_commandAttributes[commandIndex] & DECRYPT_4) ? 4
322✔
UNCOV
357
                                                              : 0);
×
358
}
359

360
//*** IsSessionAllowed()
361
//
362
// This function indicates if the command is allowed to have sessions.
363
//
364
// This function must not be called if the command is not known to be implemented.
365
//
366
//  Return Type: BOOL
367
//      TRUE(1)         session is allowed with this command
368
//      FALSE(0)        session is not allowed with this command
369
BOOL IsSessionAllowed(COMMAND_INDEX commandIndex  // IN: the command to be checked
20,861✔
370
)
371
{
372
    return ((s_commandAttributes[commandIndex] & NO_SESSIONS) == 0);
20,861✔
373
}
374

375
//*** IsHandleInResponse()
376
// This function determines if a command has a handle in the response
377
BOOL IsHandleInResponse(COMMAND_INDEX commandIndex)
16,518✔
378
{
379
    return ((s_commandAttributes[commandIndex] & R_HANDLE) != 0);
16,518✔
380
}
381

382

383
//*** IsDisallowedInReadOnlyMode()
384
// This function determines if a command is disallowed when operating in Read-Only mode
NEW
385
BOOL IsDisallowedInReadOnlyMode(COMMAND_INDEX commandIndex)
×
386
{
NEW
387
    return ((s_commandAttributes[commandIndex] & RO_DISALLOW) != 0);
×
388
}
389

390
//*** IsWriteOperation()
391
// Checks to see if an operation will write to an NV Index and is subject to being
392
// blocked by read-lock
393
BOOL IsWriteOperation(COMMAND_INDEX commandIndex  // IN: Command to check
533✔
394
)
395
{
396
#ifdef WRITE_LOCK
397
    return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0);
398
#else
399
    if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
533✔
400
    {
401
        switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex))
533✔
402
        {
403
            case TPM_CC_NV_Write:
243✔
404
#  if CC_NV_Increment
405
            case TPM_CC_NV_Increment:
406
#  endif
407
#  if CC_NV_SetBits
408
            case TPM_CC_NV_SetBits:
409
#  endif
410
#  if CC_NV_Extend
411
            case TPM_CC_NV_Extend:
412
#  endif
413
#  if CC_AC_Send
414
            case TPM_CC_AC_Send:
415
#  endif
416
            // NV write lock counts as a write operation for authorization purposes.
417
            // We check to see if the NV is write locked before we do the
418
            // authorization. If it is locked, we fail the command early.
419
            case TPM_CC_NV_WriteLock:
420
                return TRUE;
243✔
421
            default:
422
                break;
423
        }
424
    }
425
    return FALSE;
426
#endif
427
}
428

429
//*** IsReadOperation()
430
// Checks to see if an operation will write to an NV Index and is
431
// subject to being blocked by write-lock.
UNCOV
432
BOOL IsReadOperation(COMMAND_INDEX commandIndex  // IN: Command to check
×
433
)
434
{
435
#ifdef READ_LOCK
436
    return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0);
437
#else
438

UNCOV
439
    if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
×
440
    {
UNCOV
441
        switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex))
×
442
        {
UNCOV
443
            case TPM_CC_NV_Read:
×
444
            case TPM_CC_PolicyNV:
445
            case TPM_CC_NV_Certify:
446
            // NV read lock counts as a read operation for authorization purposes.
447
            // We check to see if the NV is read locked before we do the
448
            // authorization. If it is locked, we fail the command early.
449
            case TPM_CC_NV_ReadLock:
UNCOV
450
                return TRUE;
×
451
            default:
452
                break;
453
        }
454
    }
455
    return FALSE;
456
#endif
457
}
458

459
//*** CommandCapGetCCList()
460
// This function returns a list of implemented commands and command attributes
461
// starting from the command in 'commandCode'.
462
//  Return Type: TPMI_YES_NO
463
//      YES         more command attributes are available
464
//      NO          no more command attributes are available
465
TPMI_YES_NO
466
CommandCapGetCCList(TPM_CC commandCode,  // IN: start command code
46✔
467
                    UINT32 count,        // IN: maximum count for number of entries in
468
                                         //     'commandList'
469
                    TPML_CCA* commandList  // OUT: list of TPMA_CC
470
)
471
{
472
    TPMI_YES_NO   more = NO;
46✔
473
    COMMAND_INDEX commandIndex;
46✔
474

475
    // initialize output handle list count
476
    commandList->count = 0;
46✔
477

478
    for(commandIndex = GetClosestCommandIndex(commandCode);
46✔
479
        commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
1,296✔
480
        commandIndex = GetNextCommandIndex(commandIndex))
1,250✔
481
    {
482
        if (!RuntimeCommandsCheckEnabled(&g_RuntimeProfile.RuntimeCommands,                // libtpms added begin
1,283✔
483
                                         GET_ATTRIBUTE(s_ccAttr[commandIndex],
1,283✔
484
                                                       TPMA_CC, commandIndex)))
NEW
485
             continue;                                                                        // libtpms added end
×
486
        if(commandList->count < count)
1,283✔
487
        {
488
            // If the list is not full, add the attributes for this command.
489
            commandList->commandAttributes[commandList->count] =
1,250✔
490
                s_ccAttr[commandIndex];
491
            commandList->count++;
1,250✔
492
        }
493
        else
494
        {
495
            // If the list is full but there are more commands to report,
496
            // indicate this and return.
497
            more = YES;
498
            break;
499
        }
500
    }
501
    return more;
46✔
502
}
503

504
//*** CommandCapGetOneCC()
505
// This function checks whether a command is implemented, and returns its
506
// attributes if so.
UNCOV
507
BOOL CommandCapGetOneCC(TPM_CC   commandCode,       // IN: command code
×
508
                        TPMA_CC* commandAttributes  // OUT: command attributes
509
)
510
{
UNCOV
511
    COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode);
×
UNCOV
512
    if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX)
×
513
    {
UNCOV
514
        *commandAttributes = s_ccAttr[commandIndex];
×
UNCOV
515
        return TRUE;
×
516
    }
517
    return FALSE;
518
}
519
#if 0 /* libtpms added */
520

521
//*** IsVendorCommand()
522
// Function indicates if a command index references a vendor command.
523
//  Return Type: BOOL
524
//      TRUE(1)         command is a vendor command
525
//      FALSE(0)        command is not a vendor command
526
BOOL IsVendorCommand(COMMAND_INDEX commandIndex  // IN: command index to check
527
)
528
{
529
    return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V));
530
}
531
#endif /* libtpms added */
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