blob: 8a6661f597a08e17c5425c7078a1a6b910dbd591 [file] [log] [blame]
Balint Dobszayefd67b32024-11-14 17:44:02 +01001From 0e4b2fe3e03d0c5e7e64592d853fb7aa2df74759 Mon Sep 17 00:00:00 2001
2From: Balint Dobszay <balint.dobszay@arm.com>
3Date: Wed, 13 Nov 2024 17:17:00 +0100
4Subject: [PATCH 2/3] Add PSA platform port
5
6Modify the default platform port to use PSA Storage API for non-volatile
7storage operations and PSA Crypto API for random number generation.
8
9Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
10Change-Id: I219f5ec47825f863a50c7f806cc3ab6aa1ca3e85
11---
12 TPMCmd/Platform/src/Clock.c | 28 ++---
13 TPMCmd/Platform/src/Entropy.c | 55 ++--------
14 TPMCmd/Platform/src/NVMem.c | 178 +++++--------------------------
15 TPMCmd/Platform/src/RunCommand.c | 13 ++-
16 4 files changed, 57 insertions(+), 217 deletions(-)
17
18diff --git a/TPMCmd/Platform/src/Clock.c b/TPMCmd/Platform/src/Clock.c
19index 89260f1..142f4a3 100644
20--- a/TPMCmd/Platform/src/Clock.c
21+++ b/TPMCmd/Platform/src/Clock.c
22@@ -6,6 +6,7 @@
23 * under this license.
24 *
25 * Copyright (c) Microsoft Corporation
26+ * Copyright (c) 2024, Arm Limited
27 *
28 * All rights reserved.
29 *
30@@ -79,30 +80,18 @@ LIB_EXPORT void _plat__TimerRestart(void)
31 // appropriated hardware functions.
32
33 #include <time.h>
34-clock_t debugTime;
35+// TODO
36+// clock_t debugTime;
37+
38+// TODO: add timer implementation
39+static uint64_t fake_timer = 1;
40
41 //*** _plat__RealTime()
42 // This is another, probably futile, attempt to define a portable function
43 // that will return a 64-bit clock value that has mSec resolution.
44 LIB_EXPORT uint64_t _plat__RealTime(void)
45 {
46- clock64_t time;
47-#ifdef _MSC_VER
48- struct _timeb sysTime;
49- //
50- _ftime_s(&sysTime);
51- time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm;
52- // set the time back by one hour if daylight savings
53- if(sysTime.dstflag)
54- time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour
55-#else
56- // hopefully, this will work with most UNIX systems
57- struct timespec systime;
58- //
59- clock_gettime(CLOCK_MONOTONIC, &systime);
60- time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000);
61-#endif
62- return time;
63+ return fake_timer++;
64 }
65
66 //***_plat__TimerRead()
67@@ -136,7 +125,8 @@ LIB_EXPORT uint64_t _plat__TimerRead(void)
68 if(s_lastSystemTime == 0)
69 {
70 s_lastSystemTime = timeNow;
71- debugTime = clock();
72+ // TODO
73+ // debugTime = clock();
74 s_lastReportedTime = 0;
75 s_realTimePrevious = 0;
76 }
77diff --git a/TPMCmd/Platform/src/Entropy.c b/TPMCmd/Platform/src/Entropy.c
78index af7a0c4..98e9a46 100644
79--- a/TPMCmd/Platform/src/Entropy.c
80+++ b/TPMCmd/Platform/src/Entropy.c
81@@ -6,6 +6,7 @@
82 * under this license.
83 *
84 * Copyright (c) Microsoft Corporation
85+ * Copyright (c) 2024, Arm Limited
86 *
87 * All rights reserved.
88 *
89@@ -35,17 +36,9 @@
90 //** Includes and Local Values
91
92 #define _CRT_RAND_S
93-#include <stdlib.h>
94-#include <memory.h>
95-#include <time.h>
96+#include <string.h>
97 #include "Platform.h"
98-
99-#ifdef _MSC_VER
100-# include <process.h>
101-#else
102-# include <unistd.h>
103-#endif
104-
105+#include "psa/crypto.h"
106 // This is the last 32-bits of hardware entropy produced. We have to check to
107 // see that two consecutive 32-bit values are not the same because
108 // according to FIPS 140-2, annex C:
109@@ -64,21 +57,14 @@ extern uint32_t lastEntropy;
110 // Local function to get a 32-bit random number
111 static uint32_t rand32(void)
112 {
113- uint32_t rndNum = rand();
114-#if RAND_MAX < UINT16_MAX
115- // If the maximum value of the random number is a 15-bit number, then shift it up
116- // 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get
117- // a full 32 bits.
118- rndNum = (rndNum << 15) ^ rand();
119- rndNum = (rndNum << 2) ^ rand();
120-#elif RAND_MAX == UINT16_MAX
121- // If the maximum size is 16-bits, shift it and add another 16 bits
122- rndNum = (rndNum << 16) ^ rand();
123-#elif RAND_MAX < UINT32_MAX
124- // If 31 bits, then shift 1 and include another random value to get the extra bit
125- rndNum = (rndNum << 1) ^ rand();
126-#endif
127- return rndNum;
128+ uint32_t num = 0;
129+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
130+
131+ status = psa_generate_random((uint8_t *)&num, sizeof(num));
132+ if (status != PSA_SUCCESS)
133+ return 0;
134+
135+ return num;
136 }
137
138 //*** _plat__GetEntropy()
139@@ -98,25 +84,6 @@ LIB_EXPORT int32_t _plat__GetEntropy(unsigned char* entropy, // output buffer
140 //
141 if(amount == 0)
142 {
143- // Seed the platform entropy source if the entropy source is software. There
144- // is no reason to put a guard macro (#if or #ifdef) around this code because
145- // this code would not be here if someone was changing it for a system with
146- // actual hardware.
147- //
148- // NOTE 1: The following command does not provide proper cryptographic
149- // entropy. Its primary purpose to make sure that different instances of the
150- // simulator, possibly started by a script on the same machine, are seeded
151- // differently. Vendors of the actual TPMs need to ensure availability of
152- // proper entropy using their platform-specific means.
153- //
154- // NOTE 2: In debug builds by default the reference implementation will seed
155- // its RNG deterministically (without using any platform provided randomness).
156- // See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function.
157-#ifdef _MSC_VER
158- srand((unsigned)_plat__RealTime() ^ _getpid());
159-#else
160- srand((unsigned)_plat__RealTime() ^ getpid());
161-#endif
162 lastEntropy = rand32();
163 ret = 0;
164 }
165diff --git a/TPMCmd/Platform/src/NVMem.c b/TPMCmd/Platform/src/NVMem.c
166index 29d9213..b4f2dc0 100644
167--- a/TPMCmd/Platform/src/NVMem.c
168+++ b/TPMCmd/Platform/src/NVMem.c
169@@ -6,6 +6,7 @@
170 * under this license.
171 *
172 * Copyright (c) Microsoft Corporation
173+ * Copyright (c) 2024, Arm Limited
174 *
175 * All rights reserved.
176 *
177@@ -40,99 +41,18 @@
178 //
179
180 //** Includes and Local
181-#include <memory.h>
182 #include <string.h>
183 #include <assert.h>
184 #include "Platform.h"
185-#if FILE_BACKED_NV
186-# include <stdio.h>
187-static FILE* s_NvFile = NULL;
188-static int s_NeedsManufacture = FALSE;
189+#include "psa/protected_storage.h"
190+
191+#ifndef TPM_NV_UID
192+#define TPM_NV_UID 0x123
193 #endif
194
195+static const psa_storage_uid_t tpm_nv_uid = TPM_NV_UID;
196 //**Functions
197
198-#if FILE_BACKED_NV
199-
200-//*** NvFileOpen()
201-// This function opens the file used to hold the NV image.
202-// Return Type: int
203-// >= 0 success
204-// -1 error
205-static int NvFileOpen(const char* mode)
206-{
207-# if defined(NV_FILE_PATH)
208-# define TO_STRING(s) TO_STRING_IMPL(s)
209-# define TO_STRING_IMPL(s) #s
210- const char* s_NvFilePath = TO_STRING(NV_FILE_PATH);
211-# undef TO_STRING
212-# undef TO_STRING_IMPL
213-# else
214- const char* s_NvFilePath = "NVChip";
215-# endif
216-
217- // Try to open an exist NVChip file for read/write
218-# if defined _MSC_VER && 1
219- if(fopen_s(&s_NvFile, s_NvFilePath, mode) != 0)
220- s_NvFile = NULL;
221-# else
222- s_NvFile = fopen(s_NvFilePath, mode);
223-# endif
224- return (s_NvFile == NULL) ? -1 : 0;
225-}
226-
227-//*** NvFileCommit()
228-// Write all of the contents of the NV image to a file.
229-// Return Type: int
230-// TRUE(1) success
231-// FALSE(0) failure
232-static int NvFileCommit(void)
233-{
234- int OK;
235- // If NV file is not available, return failure
236- if(s_NvFile == NULL)
237- return 1;
238- // Write RAM data to NV
239- fseek(s_NvFile, 0, SEEK_SET);
240- OK = (NV_MEMORY_SIZE == fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NvFile));
241- OK = OK && (0 == fflush(s_NvFile));
242- assert(OK);
243- return OK;
244-}
245-
246-//*** NvFileSize()
247-// This function gets the size of the NV file and puts the file pointer where desired
248-// using the seek method values. SEEK_SET => beginning; SEEK_CUR => current position
249-// and SEEK_END => to the end of the file.
250-static long NvFileSize(int leaveAt)
251-{
252- long fileSize;
253- long filePos = ftell(s_NvFile);
254- //
255- assert(NULL != s_NvFile);
256-
257- int fseek_result = fseek(s_NvFile, 0, SEEK_END);
258- NOT_REFERENCED(fseek_result); // Fix compiler warning for NDEBUG
259- assert(fseek_result == 0);
260- fileSize = ftell(s_NvFile);
261- assert(fileSize >= 0);
262- switch(leaveAt)
263- {
264- case SEEK_SET:
265- filePos = 0;
266- case SEEK_CUR:
267- fseek(s_NvFile, filePos, SEEK_SET);
268- break;
269- case SEEK_END:
270- break;
271- default:
272- assert(FALSE);
273- break;
274- }
275- return fileSize;
276-}
277-#endif
278-
279 //*** _plat__NvErrors()
280 // This function is used by the simulator to set the error flags in the NV
281 // subsystem to simulate an error in the NV loading process
282@@ -161,48 +81,33 @@ LIB_EXPORT int _plat__NVEnable(
283 void* platParameter // IN: platform specific parameters
284 )
285 {
286+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
287+ size_t data_length = 0;
288+
289 NOT_REFERENCED(platParameter); // to keep compiler quiet
290- //
291 // Start assuming everything is OK
292 s_NV_unrecoverable = FALSE;
293 s_NV_recoverable = FALSE;
294-#if FILE_BACKED_NV
295- if(s_NvFile != NULL)
296- return 0;
297+
298 // Initialize all the bytes in the ram copy of the NV
299 _plat__NvMemoryClear(0, NV_MEMORY_SIZE);
300
301- // If the file exists
302- if(NvFileOpen("r+b") >= 0)
303- {
304- long fileSize = NvFileSize(SEEK_SET); // get the file size and leave the
305- // file pointer at the start
306- //
307- // If the size is right, read the data
308- if(NV_MEMORY_SIZE == fileSize)
309- {
310- s_NeedsManufacture = fread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile)
311- != NV_MEMORY_SIZE;
312- }
313- else
314- {
315- NvFileCommit(); // for any other size, initialize it
316- s_NeedsManufacture = TRUE;
317- }
318- }
319- // If NVChip file does not exist, try to create it for read/write.
320- else if(NvFileOpen("w+b") >= 0)
321- {
322- NvFileCommit(); // Initialize the file
323- s_NeedsManufacture = TRUE;
324+ status = psa_ps_get(tpm_nv_uid, 0, NV_MEMORY_SIZE, s_NV, &data_length);
325+ if (status == PSA_ERROR_DOES_NOT_EXIST) {
326+ /* Add entry if it doesn't exist */
327+ status = psa_ps_create(tpm_nv_uid, NV_MEMORY_SIZE, 0);
328+ if (status != PSA_SUCCESS)
329+ s_NV_unrecoverable = TRUE;
330+ } else if (status != PSA_SUCCESS || data_length != NV_MEMORY_SIZE) {
331+ s_NV_unrecoverable = TRUE;
332 }
333- assert(NULL != s_NvFile); // Just in case we are broken for some reason.
334-#endif
335+
336 // NV contents have been initialized and the error checks have been performed. For
337 // simulation purposes, use the signaling interface to indicate if an error is
338 // to be simulated and the type of the error.
339 if(s_NV_unrecoverable)
340 return -1;
341+
342 return s_NV_recoverable;
343 }
344
345@@ -211,24 +116,9 @@ LIB_EXPORT int _plat__NVEnable(
346 LIB_EXPORT void _plat__NVDisable(int delete // IN: If TRUE, delete the NV contents.
347 )
348 {
349-#if FILE_BACKED_NV
350- if(NULL != s_NvFile)
351- {
352- fclose(s_NvFile); // Close NV file
353- // Alternative to deleting the file is to set its size to 0. This will not
354- // match the NV size so the TPM will need to be remanufactured.
355- if(delete)
356- {
357- // Open for writing at the start. Sets the size to zero.
358- if(NvFileOpen("w") >= 0)
359- {
360- fflush(s_NvFile);
361- fclose(s_NvFile);
362- }
363- }
364- }
365- s_NvFile = NULL; // Set file handle to NULL
366-#endif
367+ if (delete)
368+ psa_ps_remove(tpm_nv_uid);
369+
370 return;
371 }
372
373@@ -240,15 +130,7 @@ LIB_EXPORT void _plat__NVDisable(int delete // IN: If TRUE, delete the NV conte
374 // 2 NV is not available due to rate limit
375 LIB_EXPORT int _plat__IsNvAvailable(void)
376 {
377- int retVal = 0;
378- // NV is not available if the TPM is in failure mode
379- if(!s_NvIsAvailable)
380- retVal = 1;
381-#if FILE_BACKED_NV
382- else
383- retVal = (s_NvFile == NULL);
384-#endif
385- return retVal;
386+ return !s_NvIsAvailable;
387 }
388
389 //***_plat__NvMemoryRead()
390@@ -334,11 +216,7 @@ LIB_EXPORT void _plat__NvMemoryMove(
391 // non-0 NV write fail
392 LIB_EXPORT int _plat__NvCommit(void)
393 {
394-#if FILE_BACKED_NV
395- return (NvFileCommit() ? 0 : 1);
396-#else
397- return 0;
398-#endif
399+ return (psa_ps_set(tpm_nv_uid, NV_MEMORY_SIZE, s_NV, 0) != PSA_SUCCESS);
400 }
401
402 //***_plat__SetNvAvail()
403@@ -364,9 +242,5 @@ LIB_EXPORT void _plat__ClearNvAvail(void)
404 // needs to be manufactured.
405 LIB_EXPORT int _plat__NVNeedsManufacture(void)
406 {
407-#if FILE_BACKED_NV
408- return s_NeedsManufacture;
409-#else
410- return FALSE;
411-#endif
412+ return 0;
413 }
414diff --git a/TPMCmd/Platform/src/RunCommand.c b/TPMCmd/Platform/src/RunCommand.c
415index 114421e..749a9f0 100644
416--- a/TPMCmd/Platform/src/RunCommand.c
417+++ b/TPMCmd/Platform/src/RunCommand.c
418@@ -6,6 +6,7 @@
419 * under this license.
420 *
421 * Copyright (c) Microsoft Corporation
422+ * Copyright (c) 2024, Arm Limited
423 *
424 * All rights reserved.
425 *
426@@ -50,6 +51,7 @@
427 #include "Platform.h"
428 #include <setjmp.h>
429 #include "ExecCommand_fp.h"
430+#include "trace.h"
431
432 jmp_buf s_jumpBuffer;
433
434@@ -69,13 +71,20 @@ LIB_EXPORT void _plat__RunCommand(
435 unsigned char** response // IN/OUT: response buffer
436 )
437 {
438- setjmp(s_jumpBuffer);
439+ // TODO: add setjmp to libc
440+ // setjmp(s_jumpBuffer);
441 ExecuteCommand(requestSize, request, responseSize, response);
442 }
443
444+EXTERN UINT32 s_failFunction;
445+EXTERN UINT32 s_failLine;
446+
447 //***_plat__Fail()
448 // This is the platform depended failure exit for the TPM.
449 LIB_EXPORT NORETURN void _plat__Fail(void)
450 {
451- longjmp(&s_jumpBuffer[0], 1);
452+ // TODO: add longjmp to libc
453+ // longjmp(&s_jumpBuffer[0], 1);
454+ EMSG("TPM fail: %s:%d", (const char *)(uintptr_t)s_failFunction, s_failLine);
455+ for (;;) {}
456 }
457\ No newline at end of file
458--
4592.34.1
460