]> git.proxmox.com Git - libtpms.git/blame - src/tpm12/tpm_nvfile.c
tpm2: Use EC_POINT_set/get_affine_coordinates on OpenSSL >= 1.1
[libtpms.git] / src / tpm12 / tpm_nvfile.c
CommitLineData
a0098eda
CB
1/********************************************************************************/
2/* */
3/* NVRAM File Abstraction Layer */
4/* Written by Ken Goldman */
5/* IBM Thomas J. Watson Research Center */
6/* $Id: tpm_nvfile.c 4664 2012-01-03 22:15:08Z kgoldman $ */
7/* */
8/* (c) Copyright IBM Corporation 2006, 2010. */
9/* */
10/* All rights reserved. */
11/* */
12/* Redistribution and use in source and binary forms, with or without */
13/* modification, are permitted provided that the following conditions are */
14/* met: */
15/* */
16/* Redistributions of source code must retain the above copyright notice, */
17/* this list of conditions and the following disclaimer. */
18/* */
19/* Redistributions in binary form must reproduce the above copyright */
20/* notice, this list of conditions and the following disclaimer in the */
21/* documentation and/or other materials provided with the distribution. */
22/* */
23/* Neither the names of the IBM Corporation nor the names of its */
24/* contributors may be used to endorse or promote products derived from */
25/* this software without specific prior written permission. */
26/* */
27/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
28/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
29/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
30/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
31/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
33/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
34/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
35/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
36/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
37/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38/********************************************************************************/
39
40/* This module abstracts out all NVRAM read and write operations.
41
42 This implementation uses standard, portable C files.
43
44 The basic high level abstractions are:
45
46 TPM_NVRAM_LoadData();
47 TPM_NVRAM_StoreData();
48 TPM_NVRAM_DeleteName();
49
50 They take a 'name' that is mapped to a rooted file name.
51*/
52
53#include <stdio.h>
54#include <string.h>
55#include <stdlib.h>
56#include <errno.h>
57
58#include "tpm_debug.h"
59#include "tpm_error.h"
60#include "tpm_memory.h"
61#include "tpm_nvram.h"
62
63#include "tpm_nvfile.h"
64
65#ifdef TPM_LIBTPMS_CALLBACKS
66#include "tpm_library_intern.h"
7bbb41a1 67#include "tpm_library.h"
a0098eda
CB
68#endif
69
70
71/* local prototypes */
72
7bd2fb0d
SB
73static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename,
74 size_t filename_len,
a0098eda
CB
75 uint32_t tpm_number,
76 const char *name);
77
78
79/* A file name in NVRAM is composed of 3 parts:
80
81 1 - 'state_directory' is the rooted path to the TPM state home directory
82 2 = 'tpm_number' is the TPM instance, 00 for a single TPM
83 2 - the file name
84
85 For the IBM cryptographic coprocessor version, the root path is hard coded.
86
87 For the Linux and Windows versions, the path comes from an environment variable. This variable is
88 used once in TPM_NVRAM_Init().
89
90 One root path is used for all virtual TPM's, so it can be a static variable.
91*/
92
93char state_directory[FILENAME_MAX];
94
95/* TPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization.
96
97 This function sets some static variables that are used by all TPM's.
98*/
99
100TPM_RESULT TPM_NVRAM_Init(void)
101{
102 TPM_RESULT rc = 0;
103 char *tpm_state_path;
104 size_t length;
105
106#ifdef TPM_LIBTPMS_CALLBACKS
107 struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
108
109 /* call user-provided function if available, otherwise execute
110 default behavior */
111 if (cbs->tpm_nvram_init) {
112 rc = cbs->tpm_nvram_init();
113 return rc;
114 }
115#endif
116
117 printf(" TPM_NVRAM_Init:\n");
118#ifdef TPM_NV_DISK
119 /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */
120 if (rc == 0) {
121 tpm_state_path = getenv("TPM_PATH");
122 if (tpm_state_path == NULL) {
123 printf("TPM_NVRAM_Init: Error (fatal), TPM_PATH environment variable not set\n");
124 rc = TPM_FAIL;
125 }
126 }
127#endif
128 /* check that the directory name plus a file name will not overflow FILENAME_MAX */
129 if (rc == 0) {
130 length = strlen(tpm_state_path);
131 if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) {
132 printf("TPM_NVRAM_Init: Error (fatal), TPM state path name %s too large\n",
133 tpm_state_path);
134 rc = TPM_FAIL;
135 }
136 }
137 if (rc == 0) {
048e207b 138 strcpy(state_directory, tpm_state_path);
a0098eda
CB
139 printf("TPM_NVRAM_Init: Rooted state path %s\n", state_directory);
140 }
141 return rc;
142}
143
144/* Load 'data' of 'length' from the 'name'.
145
146 'data' must be freed after use.
147
148 Returns
149 0 on success.
150 TPM_RETRY and NULL,0 on non-existent file (non-fatal, first time start up)
151 TPM_FAIL on failure to load (fatal), since it should never occur
152*/
153
154TPM_RESULT TPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */
155 uint32_t *length,
156 uint32_t tpm_number,
157 const char *name)
158{
159 TPM_RESULT rc = 0;
160 long lrc;
161 size_t src;
162 int irc;
163 FILE *file = NULL;
164 char filename[FILENAME_MAX]; /* rooted file name from name */
165
166#ifdef TPM_LIBTPMS_CALLBACKS
7bbb41a1
SB
167 struct libtpms_callbacks *cbs;
168 bool is_empty_buffer;
169
170 /* try to get state blob set with TPMLIB_SetState() */
171 GetCachedState(TPMLIB_NameToStateType(name), data, length, &is_empty_buffer);
172 if (is_empty_buffer)
173 return TPM_RETRY;
174 if (*data)
175 return TPM_SUCCESS;
176
177 cbs = TPMLIB_GetCallbacks();
a0098eda
CB
178
179 /* call user-provided function if available, otherwise execute
180 default behavior */
181 if (cbs->tpm_nvram_loaddata) {
182 rc = cbs->tpm_nvram_loaddata(data, length, tpm_number, name);
183 return rc;
184 }
185#endif
186
187 printf(" TPM_NVRAM_LoadData: From file %s\n", name);
188 *data = NULL;
189 *length = 0;
190 /* open the file */
191 if (rc == 0) {
192 /* map name to the rooted filename */
7bd2fb0d
SB
193 rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
194 tpm_number, name);
195 }
196 if (rc == 0) {
a0098eda
CB
197 printf(" TPM_NVRAM_LoadData: Opening file %s\n", filename);
198 file = fopen(filename, "rb"); /* closed @1 */
199 if (file == NULL) { /* if failure, determine cause */
200 if (errno == ENOENT) {
201 printf("TPM_NVRAM_LoadData: No such file %s\n", filename);
202 rc = TPM_RETRY; /* first time start up */
203 }
204 else {
205 printf("TPM_NVRAM_LoadData: Error (fatal) opening %s for read, %s\n",
206 filename, strerror(errno));
207 rc = TPM_FAIL;
208 }
209 }
210 }
211 /* determine the file length */
212 if (rc == 0) {
213 irc = fseek(file, 0L, SEEK_END); /* seek to end of file */
214 if (irc == -1L) {
215 printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n",
216 filename, strerror(errno));
217 rc = TPM_FAIL;
218 }
219 }
220 if (rc == 0) {
221 lrc = ftell(file); /* get position in the stream */
222 if (lrc == -1L) {
223 printf("TPM_NVRAM_LoadData: Error (fatal) ftell'ing %s, %s\n",
224 filename, strerror(errno));
225 rc = TPM_FAIL;
226 }
227 else {
228 *length = (uint32_t)lrc; /* save the length */
229 }
230 }
231 if (rc == 0) {
232 irc = fseek(file, 0L, SEEK_SET); /* seek back to the beginning of the file */
233 if (irc == -1L) {
234 printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n",
235 filename, strerror(errno));
236 rc = TPM_FAIL;
237 }
238 }
239 /* allocate a buffer for the actual data */
240 if ((rc == 0) && *length != 0) {
241 printf(" TPM_NVRAM_LoadData: Reading %u bytes of data\n", *length);
242 rc = TPM_Malloc(data, *length);
243 if (rc != 0) {
244 printf("TPM_NVRAM_LoadData: Error (fatal) allocating %u bytes\n", *length);
245 rc = TPM_FAIL;
246 }
247 }
248 /* read the contents of the file into the data buffer */
249 if ((rc == 0) && *length != 0) {
250 src = fread(*data, 1, *length, file);
251 if (src != *length) {
252 printf("TPM_NVRAM_LoadData: Error (fatal), data read of %u only read %lu\n",
253 *length, (unsigned long)src);
254 rc = TPM_FAIL;
255 }
256 }
257 /* close the file */
258 if (file != NULL) {
259 printf(" TPM_NVRAM_LoadData: Closing file %s\n", filename);
260 irc = fclose(file); /* @1 */
261 if (irc != 0) {
262 printf("TPM_NVRAM_LoadData: Error (fatal) closing file %s\n", filename);
263 rc = TPM_FAIL;
264 }
265 else {
266 printf(" TPM_NVRAM_LoadData: Closed file %s\n", filename);
267 }
268 }
269 return rc;
270}
271
272/* TPM_NVRAM_StoreData stores 'data' of 'length' to the rooted 'filename'
273
274 Returns
275 0 on success
276 TPM_FAIL for other fatal errors
277*/
278
279TPM_RESULT TPM_NVRAM_StoreData(const unsigned char *data,
280 uint32_t length,
281 uint32_t tpm_number,
282 const char *name)
283{
284 TPM_RESULT rc = 0;
285 uint32_t lrc;
286 int irc;
287 FILE *file = NULL;
288 char filename[FILENAME_MAX]; /* rooted file name from name */
289
290#ifdef TPM_LIBTPMS_CALLBACKS
291 struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
292
293 /* call user-provided function if available, otherwise execute
294 default behavior */
295 if (cbs->tpm_nvram_storedata) {
296 rc = cbs->tpm_nvram_storedata(data, length, tpm_number, name);
297 return rc;
298 }
299#endif
300
301 printf(" TPM_NVRAM_StoreData: To name %s\n", name);
302 if (rc == 0) {
303 /* map name to the rooted filename */
7bd2fb0d
SB
304 rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
305 tpm_number, name);
306 }
307 if (rc == 0) {
a0098eda
CB
308 /* open the file */
309 printf(" TPM_NVRAM_StoreData: Opening file %s\n", filename);
310 file = fopen(filename, "wb"); /* closed @1 */
311 if (file == NULL) {
312 printf("TPM_NVRAM_StoreData: Error (fatal) opening %s for write failed, %s\n",
313 filename, strerror(errno));
314 rc = TPM_FAIL;
315 }
316 }
317 /* write the data to the file */
318 if (rc == 0) {
319 printf(" TPM_NVRAM_StoreData: Writing %u bytes of data\n", length);
320 lrc = fwrite(data, 1, length, file);
321 if (lrc != length) {
322 printf("TPM_NVRAM_StoreData: Error (fatal), data write of %u only wrote %u\n",
323 length, lrc);
324 rc = TPM_FAIL;
325 }
326 }
327 if (file != NULL) {
328 printf(" TPM_NVRAM_StoreData: Closing file %s\n", filename);
329 irc = fclose(file); /* @1 */
330 if (irc != 0) {
331 printf("TPM_NVRAM_StoreData: Error (fatal) closing file\n");
332 rc = TPM_FAIL;
333 }
334 else {
335 printf(" TPM_NVRAM_StoreData: Closed file %s\n", filename);
336 }
337 }
338 return rc;
339}
340
341
342/* TPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name.
343
344 The filename is of the form:
345
346 state_directory/tpm_number.name
347*/
348
7bd2fb0d
SB
349static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */
350 size_t filename_len,
351 uint32_t tpm_number,
352 const char *name) /* input: abstract name */
a0098eda 353{
7bd2fb0d
SB
354 int n;
355 TPM_RESULT rc = TPM_FAIL;
356
a0098eda 357 printf(" TPM_NVRAM_GetFilenameForName: For name %s\n", name);
7bd2fb0d
SB
358 n = snprintf(filename, filename_len,
359 "%s/%02lx.%s", state_directory, (unsigned long)tpm_number,
360 name);
361 if (n < 0) {
362 printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), snprintf failed\n");
363 } else if ((size_t)n >= filename_len) {
364 printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), buffer too small\n");
365 } else {
366 printf(" TPM_NVRAM_GetFilenameForName: File name %s\n", filename);
367 rc = TPM_SUCCESS;
368 }
369 return rc;
a0098eda
CB
370}
371
372/* TPM_NVRAM_DeleteName() deletes the 'name' from NVRAM
373
374 Returns:
375 0 on success, or if the file does not exist and mustExist is FALSE
376 TPM_FAIL if the file could not be removed, since this should never occur and there is
377 no recovery
378
379 NOTE: Not portable code, but supported by Linux and Windows
380*/
381
382TPM_RESULT TPM_NVRAM_DeleteName(uint32_t tpm_number,
383 const char *name,
384 TPM_BOOL mustExist)
385{
386 TPM_RESULT rc = 0;
387 int irc;
388 char filename[FILENAME_MAX]; /* rooted file name from name */
389
390#ifdef TPM_LIBTPMS_CALLBACKS
391 struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks();
392
393 /* call user-provided function if available, otherwise execute
394 default behavior */
395 if (cbs->tpm_nvram_deletename) {
396 rc = cbs->tpm_nvram_deletename(tpm_number, name, mustExist);
397 return rc;
398 }
399#endif
400
401 printf(" TPM_NVRAM_DeleteName: Name %s\n", name);
402 /* map name to the rooted filename */
7bd2fb0d
SB
403 if (rc == 0) {
404 rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
405 tpm_number, name);
406 }
a0098eda
CB
407 if (rc == 0) {
408 irc = remove(filename);
409 if ((irc != 0) && /* if the remove failed */
410 (mustExist || /* if any error is a failure, or */
411 (errno != ENOENT))) { /* if error other than no such file */
412 printf("TPM_NVRAM_DeleteName: Error, (fatal) file remove failed, errno %d\n",
413 errno);
414 rc = TPM_FAIL;
415 }
416 }
417 return rc;
418}
419