Coverage Report

Created: 2024-08-10 06:15

/src/ms-tpm-20-ref/TPMCmd/fuzzer/tpm_cmd.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2024 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "TpmBuildSwitches.h"
16
#include <stdlib.h>
17
#include <stdio.h>
18
#include <stdint.h>
19
#include <stdbool.h>
20
#include <ctype.h>
21
#include <string.h>
22
#include <sys/types.h>
23
#include <unistd.h>
24
25
#include "Manufacture_fp.h"
26
#include "Platform_fp.h"
27
28
5.46k
#define TPM_ST_NO_SESSIONS 0x8001
29
3.83k
#define TPM_ST_SESSIONS 0x8002
30
31
enum tpm_cc {
32
    TPM_CC_NV_UndefineSpaceSpecial,
33
    TPM_CC_EvictControl,
34
    TPM_CC_HierarchyControl,
35
    TPM_CC_NV_UndefineSpace,
36
    TPM_CC_ChangeEPS,
37
    TPM_CC_ChangePPS,
38
    TPM_CC_Clear,
39
    TPM_CC_ClearControl,
40
    TPM_CC_ClockSet,
41
    TPM_CC_HierarchyChangeAuth,
42
    TPM_CC_NV_DefineSpace,
43
    TPM_CC_PCR_Allocate,
44
    TPM_CC_PCR_SetAuthPolicy,
45
    TPM_CC_PP_Commands,
46
    TPM_CC_SetPrimaryPolicy,
47
    TPM_CC_FieldUpgradeStart,
48
    TPM_CC_ClockRateAdjust,
49
    TPM_CC_CreatePrimary,
50
    TPM_CC_NV_GlobalWriteLock,
51
    TPM_CC_GetCommandAuditDigest,
52
    TPM_CC_NV_Increment,
53
    TPM_CC_NV_SetBits,
54
    TPM_CC_NV_Extend,
55
    TPM_CC_NV_Write,
56
    TPM_CC_NV_WriteLock,
57
    TPM_CC_DictionaryAttackLockReset,
58
    TPM_CC_DictionaryAttackParameters,
59
    TPM_CC_NV_ChangeAuth,
60
    TPM_CC_PCR_Event,
61
    TPM_CC_PCR_Reset,
62
    TPM_CC_SequenceComplete,
63
    TPM_CC_SetAlgorithmSet,
64
    TPM_CC_SetCommandCodeAuditStatus,
65
    TPM_CC_FieldUpgradeData,
66
    TPM_CC_IncrementalSelfTest,
67
    TPM_CC_SelfTest,
68
    TPM_CC_Startup,
69
    TPM_CC_Shutdown,
70
    TPM_CC_StirRandom,
71
    TPM_CC_ActivateCredential,
72
    TPM_CC_Certify,
73
    TPM_CC_PolicyNV,
74
    TPM_CC_CertifyCreation,
75
    TPM_CC_Duplicate,
76
    TPM_CC_GetTime,
77
    TPM_CC_GetSessionAuditDigest,
78
    TPM_CC_NV_Read,
79
    TPM_CC_NV_ReadLock,
80
    TPM_CC_ObjectChangeAuth,
81
    TPM_CC_PolicySecret,
82
    TPM_CC_Rewrap,
83
    TPM_CC_Create,
84
    TPM_CC_ECDH_ZGen,
85
    TPM_CC_HMAC,
86
    TPM_CC_MAC,
87
    TPM_CC_Import,
88
    TPM_CC_Load,
89
    TPM_CC_Quote,
90
    TPM_CC_RSA_Decrypt,
91
    TPM_CC_HMAC_Start,
92
    TPM_CC_MAC_Start,
93
    TPM_CC_SequenceUpdate,
94
    TPM_CC_Sign,
95
    TPM_CC_Unseal,
96
    TPM_CC_PolicySigned,
97
    TPM_CC_ContextLoad,
98
    TPM_CC_ContextSave,
99
    TPM_CC_ECDH_KeyGen,
100
    TPM_CC_EncryptDecrypt,
101
    TPM_CC_FlushContext,
102
    TPM_CC_LoadExternal,
103
    TPM_CC_MakeCredential,
104
    TPM_CC_NV_ReadPublic,
105
    TPM_CC_PolicyAuthorize,
106
    TPM_CC_PolicyAuthValue,
107
    TPM_CC_PolicyCommandCode,
108
    TPM_CC_PolicyCounterTimer,
109
    TPM_CC_PolicyCpHash,
110
    TPM_CC_PolicyLocality,
111
    TPM_CC_PolicyNameHash,
112
    TPM_CC_PolicyOR,
113
    TPM_CC_PolicyTicket,
114
    TPM_CC_ReadPublic,
115
    TPM_CC_RSA_Encrypt,
116
    TPM_CC_StartAuthSession,
117
    TPM_CC_VerifySignature,
118
    TPM_CC_ECC_Parameters,
119
    TPM_CC_FirmwareRead,
120
    TPM_CC_GetCapability,
121
    TPM_CC_GetRandom,
122
    TPM_CC_GetTestResult,
123
    TPM_CC_Hash,
124
    TPM_CC_PCR_Read,
125
    TPM_CC_PolicyPCR,
126
    TPM_CC_PolicyRestart,
127
    TPM_CC_ReadClock,
128
    TPM_CC_PCR_Extend,
129
    TPM_CC_PCR_SetAuthValue,
130
    TPM_CC_NV_Certify,
131
    TPM_CC_EventSequenceComplete,
132
    TPM_CC_HashSequenceStart,
133
    TPM_CC_PolicyPhysicalPresence,
134
    TPM_CC_PolicyDuplicationSelect,
135
    TPM_CC_PolicyGetDigest,
136
    TPM_CC_TestParms,
137
    TPM_CC_Commit,
138
    TPM_CC_PolicyPassword,
139
    TPM_CC_ZGen_2Phase,
140
    TPM_CC_EC_Ephemeral,
141
    TPM_CC_PolicyNvWritten,
142
    TPM_CC_PolicyTemplate,
143
    TPM_CC_CreateLoaded,
144
    TPM_CC_PolicyAuthorizeNV,
145
    TPM_CC_EncryptDecrypt2,
146
    TPM_CC_AC_GetCapability,
147
    TPM_CC_AC_Send,
148
    TPM_CC_Policy_AC_SendSelect,
149
    TPM_CC_CertifyX509,
150
    TPM_CC_ACT_SetTimeout,
151
    TPM_CC_ECC_Encrypt,
152
    TPM_CC_ECC_Decrypt,
153
154
    __TPM_CC_MAX
155
};
156
157
uint32_t tpm_cc_lookup[__TPM_CC_MAX] = {
158
    [TPM_CC_NV_UndefineSpaceSpecial   ] = 0x0000011F,
159
    [TPM_CC_EvictControl              ] = 0x00000120,
160
    [TPM_CC_HierarchyControl          ] = 0x00000121,
161
    [TPM_CC_NV_UndefineSpace          ] = 0x00000122,
162
    [TPM_CC_ChangeEPS                 ] = 0x00000124,
163
    [TPM_CC_ChangePPS                 ] = 0x00000125,
164
    [TPM_CC_Clear                     ] = 0x00000126,
165
    [TPM_CC_ClearControl              ] = 0x00000127,
166
    [TPM_CC_ClockSet                  ] = 0x00000128,
167
    [TPM_CC_HierarchyChangeAuth       ] = 0x00000129,
168
    [TPM_CC_NV_DefineSpace            ] = 0x0000012A,
169
    [TPM_CC_PCR_Allocate              ] = 0x0000012B,
170
    [TPM_CC_PCR_SetAuthPolicy         ] = 0x0000012C,
171
    [TPM_CC_PP_Commands               ] = 0x0000012D,
172
    [TPM_CC_SetPrimaryPolicy          ] = 0x0000012E,
173
    [TPM_CC_FieldUpgradeStart         ] = 0x0000012F,
174
    [TPM_CC_ClockRateAdjust           ] = 0x00000130,
175
    [TPM_CC_CreatePrimary             ] = 0x00000131,
176
    [TPM_CC_NV_GlobalWriteLock        ] = 0x00000132,
177
    [TPM_CC_GetCommandAuditDigest     ] = 0x00000133,
178
    [TPM_CC_NV_Increment              ] = 0x00000134,
179
    [TPM_CC_NV_SetBits                ] = 0x00000135,
180
    [TPM_CC_NV_Extend                 ] = 0x00000136,
181
    [TPM_CC_NV_Write                  ] = 0x00000137,
182
    [TPM_CC_NV_WriteLock              ] = 0x00000138,
183
    [TPM_CC_DictionaryAttackLockReset ] = 0x00000139,
184
    [TPM_CC_DictionaryAttackParameters] = 0x0000013A,
185
    [TPM_CC_NV_ChangeAuth             ] = 0x0000013B,
186
    [TPM_CC_PCR_Event                 ] = 0x0000013C,
187
    [TPM_CC_PCR_Reset                 ] = 0x0000013D,
188
    [TPM_CC_SequenceComplete          ] = 0x0000013E,
189
    [TPM_CC_SetAlgorithmSet           ] = 0x0000013F,
190
    [TPM_CC_SetCommandCodeAuditStatus ] = 0x00000140,
191
    [TPM_CC_FieldUpgradeData          ] = 0x00000141,
192
    [TPM_CC_IncrementalSelfTest       ] = 0x00000142,
193
    [TPM_CC_SelfTest                  ] = 0x00000143,
194
    [TPM_CC_Startup                   ] = 0x00000144,
195
    [TPM_CC_Shutdown                  ] = 0x00000145,
196
    [TPM_CC_StirRandom                ] = 0x00000146,
197
    [TPM_CC_ActivateCredential        ] = 0x00000147,
198
    [TPM_CC_Certify                   ] = 0x00000148,
199
    [TPM_CC_PolicyNV                  ] = 0x00000149,
200
    [TPM_CC_CertifyCreation           ] = 0x0000014A,
201
    [TPM_CC_Duplicate                 ] = 0x0000014B,
202
    [TPM_CC_GetTime                   ] = 0x0000014C,
203
    [TPM_CC_GetSessionAuditDigest     ] = 0x0000014D,
204
    [TPM_CC_NV_Read                   ] = 0x0000014E,
205
    [TPM_CC_NV_ReadLock               ] = 0x0000014F,
206
    [TPM_CC_ObjectChangeAuth          ] = 0x00000150,
207
    [TPM_CC_PolicySecret              ] = 0x00000151,
208
    [TPM_CC_Rewrap                    ] = 0x00000152,
209
    [TPM_CC_Create                    ] = 0x00000153,
210
    [TPM_CC_ECDH_ZGen                 ] = 0x00000154,
211
    [TPM_CC_HMAC                      ] = 0x00000155,
212
    [TPM_CC_MAC                       ] = 0x00000155,
213
    [TPM_CC_Import                    ] = 0x00000156,
214
    [TPM_CC_Load                      ] = 0x00000157,
215
    [TPM_CC_Quote                     ] = 0x00000158,
216
    [TPM_CC_RSA_Decrypt               ] = 0x00000159,
217
    [TPM_CC_HMAC_Start                ] = 0x0000015B,
218
    [TPM_CC_MAC_Start                 ] = 0x0000015B,
219
    [TPM_CC_SequenceUpdate            ] = 0x0000015C,
220
    [TPM_CC_Sign                      ] = 0x0000015D,
221
    [TPM_CC_Unseal                    ] = 0x0000015E,
222
    [TPM_CC_PolicySigned              ] = 0x00000160,
223
    [TPM_CC_ContextLoad               ] = 0x00000161,
224
    [TPM_CC_ContextSave               ] = 0x00000162,
225
    [TPM_CC_ECDH_KeyGen               ] = 0x00000163,
226
    [TPM_CC_EncryptDecrypt            ] = 0x00000164,
227
    [TPM_CC_FlushContext              ] = 0x00000165,
228
    [TPM_CC_LoadExternal              ] = 0x00000167,
229
    [TPM_CC_MakeCredential            ] = 0x00000168,
230
    [TPM_CC_NV_ReadPublic             ] = 0x00000169,
231
    [TPM_CC_PolicyAuthorize           ] = 0x0000016A,
232
    [TPM_CC_PolicyAuthValue           ] = 0x0000016B,
233
    [TPM_CC_PolicyCommandCode         ] = 0x0000016C,
234
    [TPM_CC_PolicyCounterTimer        ] = 0x0000016D,
235
    [TPM_CC_PolicyCpHash              ] = 0x0000016E,
236
    [TPM_CC_PolicyLocality            ] = 0x0000016F,
237
    [TPM_CC_PolicyNameHash            ] = 0x00000170,
238
    [TPM_CC_PolicyOR                  ] = 0x00000171,
239
    [TPM_CC_PolicyTicket              ] = 0x00000172,
240
    [TPM_CC_ReadPublic                ] = 0x00000173,
241
    [TPM_CC_RSA_Encrypt               ] = 0x00000174,
242
    [TPM_CC_StartAuthSession          ] = 0x00000176,
243
    [TPM_CC_VerifySignature           ] = 0x00000177,
244
    [TPM_CC_ECC_Parameters            ] = 0x00000178,
245
    [TPM_CC_FirmwareRead              ] = 0x00000179,
246
    [TPM_CC_GetCapability             ] = 0x0000017A,
247
    [TPM_CC_GetRandom                 ] = 0x0000017B,
248
    [TPM_CC_GetTestResult             ] = 0x0000017C,
249
    [TPM_CC_Hash                      ] = 0x0000017D,
250
    [TPM_CC_PCR_Read                  ] = 0x0000017E,
251
    [TPM_CC_PolicyPCR                 ] = 0x0000017F,
252
    [TPM_CC_PolicyRestart             ] = 0x00000180,
253
    [TPM_CC_ReadClock                 ] = 0x00000181,
254
    [TPM_CC_PCR_Extend                ] = 0x00000182,
255
    [TPM_CC_PCR_SetAuthValue          ] = 0x00000183,
256
    [TPM_CC_NV_Certify                ] = 0x00000184,
257
    [TPM_CC_EventSequenceComplete     ] = 0x00000185,
258
    [TPM_CC_HashSequenceStart         ] = 0x00000186,
259
    [TPM_CC_PolicyPhysicalPresence    ] = 0x00000187,
260
    [TPM_CC_PolicyDuplicationSelect   ] = 0x00000188,
261
    [TPM_CC_PolicyGetDigest           ] = 0x00000189,
262
    [TPM_CC_TestParms                 ] = 0x0000018A,
263
    [TPM_CC_Commit                    ] = 0x0000018B,
264
    [TPM_CC_PolicyPassword            ] = 0x0000018C,
265
    [TPM_CC_ZGen_2Phase               ] = 0x0000018D,
266
    [TPM_CC_EC_Ephemeral              ] = 0x0000018E,
267
    [TPM_CC_PolicyNvWritten           ] = 0x0000018F,
268
    [TPM_CC_PolicyTemplate            ] = 0x00000190,
269
    [TPM_CC_CreateLoaded              ] = 0x00000191,
270
    [TPM_CC_PolicyAuthorizeNV         ] = 0x00000192,
271
    [TPM_CC_EncryptDecrypt2           ] = 0x00000193,
272
    [TPM_CC_AC_GetCapability          ] = 0x00000194,
273
    [TPM_CC_AC_Send                   ] = 0x00000195,
274
    [TPM_CC_Policy_AC_SendSelect      ] = 0x00000196,
275
    [TPM_CC_CertifyX509               ] = 0x00000197,
276
    [TPM_CC_ACT_SetTimeout            ] = 0x00000198,
277
    [TPM_CC_ECC_Encrypt               ] = 0x00000199,
278
    [TPM_CC_ECC_Decrypt               ] = 0x0000019A,
279
};
280
281
struct __attribute__((__packed__)) tpm2_cmd {
282
  uint16_t tag;
283
  uint32_t size; // sizeof(struct tpm2_cmd) + sizeof(buf)
284
  uint32_t command_code; // tpm_cc
285
  uint32_t buf[];
286
};
287
288
18.5k
static inline uint16_t reverse2(uint16_t _in) {
289
18.5k
    uint8_t *in = (uint8_t*)&_in;
290
18.5k
    return (in[0] << 8) | in[1];
291
18.5k
}
292
293
55.0k
static inline uint32_t reverse4(uint32_t _in) {
294
55.0k
    uint8_t *in = (uint8_t*)&_in;
295
55.0k
    return ((uint32_t)in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
296
55.0k
}
297
298
// tpm2_startup -c
299
unsigned char tpm2_startup[] = {
300
    0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x01
301
};
302
unsigned char tpm2_startup_c[] = {
303
    0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00
304
};
305
unsigned char tpm2_shutdown[] = {
306
    0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x01
307
};
308
unsigned char tpm2_shutdown_c[] = {
309
    0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00
310
};
311
312
uint32_t responseSize = 4096;
313
unsigned char response[4096];
314
unsigned char cmd_buffer[4096];
315
unsigned char cmd2_buffer[4096];
316
317
int LLVMFuzzerInitialize(int *argc, char ***argv)
318
2
{
319
2
    _plat__NVEnable(NULL);
320
2
    TPM_Manufacture(1);
321
2
    _plat__Signal_PowerOn();
322
2
    _plat__LocalitySet(3);
323
2
    fprintf(stderr, "TPM initialized, let the fuzzing COMMENCE!\n");
324
2
    return 0;
325
2
}
326
327
static inline void fixup_tag(struct tpm2_cmd *cmd)
328
9.29k
{
329
9.29k
    if ( reverse2(cmd->tag) % 2 )
330
5.46k
        cmd->tag = reverse2(TPM_ST_NO_SESSIONS);
331
3.83k
    else
332
3.83k
        cmd->tag = reverse2(TPM_ST_SESSIONS);
333
9.29k
}
334
335
static inline void fixup_size(struct tpm2_cmd *cmd, uint32_t size)
336
9.29k
{
337
9.29k
    cmd->size = reverse4(size);
338
9.29k
}
339
340
static inline void fixup_cc(struct tpm2_cmd *cmd)
341
9.29k
{
342
9.29k
    uint32_t cc = reverse4(cmd->command_code);
343
9.29k
    if ( cc < tpm_cc_lookup[0] || cc >= tpm_cc_lookup[__TPM_CC_MAX-1] )
344
8.51k
    {
345
8.51k
        uint8_t selector = cc % __TPM_CC_MAX;
346
8.51k
        cc = tpm_cc_lookup[selector];
347
8.51k
        cmd->command_code = reverse4(cc);
348
8.51k
    }
349
9.29k
}
350
351
8.45k
int LLVMFuzzerTestOneInput(const uint8_t *const Data, size_t Size) {
352
8.45k
    if (Data == NULL || Size < sizeof(struct tpm2_cmd)) {
353
6
        return 0;
354
6
    }
355
356
8.44k
    unsigned char *r = &response[0];
357
8.44k
    unsigned char **_response = &r;
358
359
8.44k
    struct tpm2_cmd *cmd = NULL;
360
8.44k
    struct tpm2_cmd *cmd2 = NULL;
361
362
8.44k
    if ( Size > 4096 )
363
853
    {
364
853
        if ( Size > 4096 + sizeof(struct tpm2_cmd) )
365
852
        {
366
852
            size_t size2 = Size - 4096;
367
852
            if ( size2 > 4096 )
368
0
                size2 = 4096;
369
370
852
            memcpy(&cmd2_buffer, Data + 4096, size2);
371
372
852
            cmd2 = (struct tpm2_cmd *)&cmd2_buffer;
373
852
            fixup_tag(cmd2);
374
852
            fixup_size(cmd2, size2);
375
852
            fixup_cc(cmd2);
376
852
        }
377
378
853
        Size = 4096;
379
853
    }
380
381
8.44k
    memcpy(&cmd_buffer, Data, Size);
382
8.44k
    cmd = (struct tpm2_cmd *)&cmd_buffer;
383
384
    // Fixups
385
8.44k
    fixup_tag(cmd);
386
8.44k
    fixup_size(cmd, Size);
387
8.44k
    fixup_cc(cmd);
388
389
8.44k
    _plat__Signal_Reset();
390
8.44k
    _plat__SetNvAvail();
391
392
    // Start the TPM
393
8.44k
    _plat__RunCommand(12, (unsigned char*)&tpm2_startup_c, &responseSize, _response);
394
395
    // Run the command(s)
396
8.44k
    _plat__RunCommand(reverse4(cmd->size), (unsigned char*)cmd, &responseSize, _response);
397
8.44k
    if ( cmd2 )
398
852
        _plat__RunCommand(reverse4(cmd2->size), (unsigned char*)cmd2, &responseSize, _response);
399
400
    // Restart the TPM with state saved */
401
8.44k
    _plat__RunCommand(12, (unsigned char*)&tpm2_shutdown, &responseSize, _response);
402
8.44k
    _plat__RunCommand(12, (unsigned char*)&tpm2_startup, &responseSize, _response);
403
404
    // Re-run the commands
405
8.44k
    _plat__RunCommand(reverse4(cmd->size), (unsigned char*)cmd, &responseSize, _response);
406
8.44k
    if ( cmd2 )
407
852
        _plat__RunCommand(reverse4(cmd2->size), (unsigned char*)cmd2, &responseSize, _response);
408
409
    // Shut down the TPM
410
8.44k
    _plat__RunCommand(12, (unsigned char*)&tpm2_shutdown_c, &responseSize, _response);
411
412
    // Try running the commands on the shutdown TPM
413
8.44k
    _plat__RunCommand(reverse4(cmd->size), (unsigned char*)cmd, &responseSize, _response);
414
8.44k
    if ( cmd2 )
415
852
        _plat__RunCommand(reverse4(cmd2->size), (unsigned char*)cmd2, &responseSize, _response);
416
417
8.44k
    _plat__ClearNvAvail();
418
419
8.44k
    return 0;
420
8.45k
}
421
422
#ifdef COVERAGE
423
int main(int argc, char **argv)
424
{
425
    if ( argc != 2 )
426
        return 0;
427
428
    FILE *f = fopen(argv[1], "rb");
429
    fseek(f, 0, SEEK_END);
430
    long fsize = ftell(f);
431
    fseek(f, 0, SEEK_SET);
432
433
    char *buf = malloc(fsize);
434
    fread(buf, fsize, 1, f);
435
    fclose(f);
436
437
    LLVMFuzzerInitialize(0,NULL);
438
    LLVMFuzzerTestOneInput((uint8_t*)buf, fsize);
439
440
    free(buf);
441
}
442
#endif