1 /**
2 * Copyright(c) 2011 Trusted Logic. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name Trusted Logic nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #if defined(ANDROID)
32 #include <stddef.h>
33 #endif
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /*
39 * When porting to a new OS, insert here the appropriate include files
40 */
41 #include <sys/stat.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <fcntl.h>
45
46 #if defined(LINUX) || defined(ANDROID)
47 #include <unistd.h>
48 #include <sys/resource.h>
49
50
51 #if defined(ANDROID)
52 /* fdatasync does not exist on Android */
53 #define fdatasync fsync
54 #else
55 /*
56 * http://linux.die.net/man/2/fsync
57 * The function fdatasync seems to be absent of the header file
58 * in some distributions
59 */
60 int fdatasync(int fd);
61 #endif /* ANDROID */
62 #include <syslog.h>
63 #include <sys/types.h>
64 #include <sys/stat.h>
65 #include <pthread.h>
66 #include <semaphore.h>
67 #define PATH_SEPARATOR '/'
68 #endif /* LINUX || ANDROID */
69
70 #ifdef WIN32
71 #include <windows.h>
72 #include <io.h>
73 #define PATH_SEPARATOR '\\'
74 #endif
75
76 #ifdef __SYMBIAN32__
77 #include <unistd.h>
78 #include "os_symbian.h"
79 #define PATH_SEPARATOR '\\'
80 #endif
81
82 #include <stdarg.h>
83 #include <assert.h>
84
85 #include "service_delegation_protocol.h"
86
87 #include "s_version.h"
88 #include "s_error.h"
89 #include "tee_client_api.h"
90
91 /* You can define the preprocessor constant SUPPORT_DELEGATION_EXTENSION
92 if you want to pass extended options in a configuration file (option '-c').
93 It is up to you to define the format of this configuration file and the
94 extended option in the source file delegation_client_extension.c. You can
95 use extended options, e.g., to control the name of each partition file. */
96 #ifdef SUPPORT_DELEGATION_EXTENSION
97 #include "delegation_client_extension.h"
98 #endif
99
100 #ifdef TFSW_FDM_ANDROID
101 #include <android/log.h>
102 #endif
103
104 /*----------------------------------------------------------------------------
105 * Design notes
106 * ============
107 *
108 * This implementation of the delegation daemon supports the protocol
109 * specified in the Product Reference Manual ("Built-in Services Protocols Specification")
110 *
111 *----------------------------------------------------------------------------*/
112
113 /*----------------------------------------------------------------------------
114 * Defines and structures
115 *----------------------------------------------------------------------------*/
116 #define ECHANGE_BUFFER_INSTRUCTIONS_NB 1000
117
118 #define DEFAULT_WORKSPACE_SIZE (128*1024)
119
120 /* A single shared memory block is used to contain the administrative data, the
121 instruction buffer and the workspace. The size of the instruction buffer is
122 fixed, but the size of workspace can be configured using the "-workspaceSize"
123 command-line option. */
124 typedef struct
125 {
126 DELEGATION_ADMINISTRATIVE_DATA sAdministrativeData;
127 uint32_t sInstructions[ECHANGE_BUFFER_INSTRUCTIONS_NB];
128 uint8_t sWorkspace[1/*g_nWorkspaceSize*/];
129 } DELEGATION_EXCHANGE_BUFFER;
130
131 #ifdef SUPPORT_RPMB_PARTITION
132 typedef struct
133 {
134 uint8_t pDummy[196];
135 uint8_t pMAC[32];
136 uint8_t pData[256];
137 uint8_t pNonce[16];
138 uint32_t nMC;
139 uint16_t nAddr;
140 uint16_t nBlockCount;
141 uint16_t nResult;
142 uint16_t nReqOrResp;
143 } DELEGATION_RPMB_MESSAGE;
144 #endif
145
146 #define MD_VAR_NOT_USED(variable) do{(void)(variable);}while(0);
147
148 #define MD_INLINE __inline
149
150 /* ----------------------------------------------
151 Traces and logs
152
153 On Linux, traces and logs go either to the console (stderr) or to the syslog.
154 When the daemon is started, the logs go to the console. Once and if the daemon
155 is detached, the logs go to syslog.
156
157 On other systems, traces and logs go systematically to stderr
158
159 The difference between traces and logs is that traces are compiled out
160 in release builds whereas logs are visible to the customer.
161
162 -----------------------------------------------*/
163 #if defined(LINUX) || (defined ANDROID)
164
165 static bool bDetached = false;
166
LogError(const char * format,...)167 static MD_INLINE void LogError(const char* format, ...)
168 {
169 va_list ap;
170 va_start(ap, format);
171 if (bDetached)
172 {
173 vsyslog(LOG_ERR, format, ap);
174 }
175 else
176 {
177 #ifdef TFSW_FDM_ANDROID
178 __android_log_vprint(ANDROID_LOG_ERROR , "TF Daemon", format, ap);
179 #else
180 fprintf(stderr, "ERROR: ");
181 vfprintf(stderr, format, ap);
182 fprintf(stderr, "\n");
183 #endif
184 }
185 va_end(ap);
186 }
187
LogWarning(const char * format,...)188 static MD_INLINE void LogWarning(const char* format, ...)
189 {
190 va_list ap;
191 va_start(ap, format);
192 if (bDetached)
193 {
194 vsyslog(LOG_WARNING, format, ap);
195 }
196 else
197 {
198 #ifdef TFSW_FDM_ANDROID
199 __android_log_vprint(ANDROID_LOG_WARN , "TF Daemon", format, ap);
200 #else
201 fprintf(stderr, "WARNING: ");
202 vfprintf(stderr, format, ap);
203 fprintf(stderr, "\n");
204 #endif
205 }
206 va_end(ap);
207 }
LogInfo(const char * format,...)208 static MD_INLINE void LogInfo(const char* format, ...)
209 {
210 va_list ap;
211 va_start(ap, format);
212 if (bDetached)
213 {
214 vsyslog(LOG_INFO, format, ap);
215 }
216 else
217 {
218 #ifdef TFSW_FDM_ANDROID
219 __android_log_vprint(ANDROID_LOG_INFO , "TF Daemon", format, ap);
220 #else
221 vfprintf(stderr, format, ap);
222 fprintf(stderr, "\n");
223 #endif
224 }
225 va_end(ap);
226 }
227
TRACE_ERROR(const char * format,...)228 static MD_INLINE void TRACE_ERROR(const char* format, ...)
229 {
230 #ifndef NDEBUG
231 va_list ap;
232 va_start(ap, format);
233 if (bDetached)
234 {
235 vsyslog(LOG_ERR, format, ap);
236 }
237 else
238 {
239 #ifdef TFSW_FDM_ANDROID
240 __android_log_vprint(ANDROID_LOG_ERROR , "TF Daemon", format, ap);
241 #else
242 fprintf(stderr, "TRACE: ERROR: ");
243 vfprintf(stderr, format, ap);
244 fprintf(stderr, "\n");
245 #endif
246 }
247 va_end(ap);
248 #else
249 MD_VAR_NOT_USED(format);
250 #endif /* NDEBUG */
251 }
252
TRACE_WARNING(const char * format,...)253 static MD_INLINE void TRACE_WARNING(const char* format, ...)
254 {
255 #ifndef NDEBUG
256 va_list ap;
257 va_start(ap, format);
258 if (bDetached)
259 {
260 vsyslog(LOG_WARNING, format, ap);
261 }
262 else
263 {
264 #ifdef TFSW_FDM_ANDROID
265 __android_log_vprint(ANDROID_LOG_WARN , "TF Daemon", format, ap);
266 #else
267 fprintf(stderr, "TRACE: WARNING: ");
268 vfprintf(stderr, format, ap);
269 fprintf(stderr, "\n");
270 #endif
271 }
272 va_end(ap);
273 #else
274 MD_VAR_NOT_USED(format);
275 #endif /* NDEBUG */
276 }
277
TRACE_INFO(const char * format,...)278 static MD_INLINE void TRACE_INFO(const char* format, ...)
279 {
280 #ifndef NDEBUG
281 va_list ap;
282 va_start(ap, format);
283 if (bDetached)
284 {
285 vsyslog(LOG_DEBUG, format, ap);
286 }
287 else
288 {
289 #ifdef TFSW_FDM_ANDROID
290 __android_log_vprint(ANDROID_LOG_INFO , "TF Daemon", format, ap);
291 #else
292 fprintf(stderr, "TRACE: ");
293 vfprintf(stderr, format, ap);
294 fprintf(stderr, "\n");
295 #endif
296 }
297 va_end(ap);
298 #else
299 MD_VAR_NOT_USED(format);
300 #endif /* NDEBUG */
301 }
302 #elif defined __SYMBIAN32__
303 /* defined in os_symbian.h */
304
305 #elif defined NO_LOG_NO_TRACE
LogError(const char * format,...)306 static MD_INLINE void LogError(const char* format, ...)
307 {
308 MD_VAR_NOT_USED(format);
309 }
LogWarning(const char * format,...)310 static MD_INLINE void LogWarning(const char* format, ...)
311 {
312 MD_VAR_NOT_USED(format);
313 }
LogInfo(const char * format,...)314 static MD_INLINE void LogInfo(const char* format, ...)
315 {
316 MD_VAR_NOT_USED(format);
317 }
318
TRACE_ERROR(const char * format,...)319 static MD_INLINE void TRACE_ERROR(const char* format, ...)
320 {
321 MD_VAR_NOT_USED(format);
322 }
323
TRACE_WARNING(const char * format,...)324 static MD_INLINE void TRACE_WARNING(const char* format, ...)
325 {
326 MD_VAR_NOT_USED(format);
327 }
328
TRACE_INFO(const char * format,...)329 static MD_INLINE void TRACE_INFO(const char* format, ...)
330 {
331 MD_VAR_NOT_USED(format);
332 }
333
334 #else
335 /* !defined(LINUX) || !defined(ANDROID) */
336
LogError(const char * format,...)337 static MD_INLINE void LogError(const char* format, ...)
338 {
339 va_list ap;
340 va_start(ap, format);
341 fprintf(stderr, "ERROR: ");
342 vfprintf(stderr, format, ap);
343 fprintf(stderr, "\n");
344 va_end(ap);
345 }
LogWarning(const char * format,...)346 static MD_INLINE void LogWarning(const char* format, ...)
347 {
348 va_list ap;
349 va_start(ap, format);
350 fprintf(stderr, "WARNING: ");
351 vfprintf(stderr, format, ap);
352 fprintf(stderr, "\n");
353 va_end(ap);
354 }
LogInfo(const char * format,...)355 static MD_INLINE void LogInfo(const char* format, ...)
356 {
357 va_list ap;
358 va_start(ap, format);
359 vfprintf(stderr, format, ap);
360 fprintf(stderr, "\n");
361 va_end(ap);
362 }
363
TRACE_ERROR(const char * format,...)364 static MD_INLINE void TRACE_ERROR(const char* format, ...)
365 {
366 #ifndef NDEBUG
367 va_list ap;
368 va_start(ap, format);
369 fprintf(stderr, "TRACE: ERROR: ");
370 vfprintf(stderr, format, ap);
371 fprintf(stderr, "\n");
372 va_end(ap);
373 #else
374 MD_VAR_NOT_USED(format);
375 #endif /* NDEBUG */
376 }
377
TRACE_WARNING(const char * format,...)378 static MD_INLINE void TRACE_WARNING(const char* format, ...)
379 {
380 #ifndef NDEBUG
381 va_list ap;
382 va_start(ap, format);
383 fprintf(stderr, "TRACE: WARNING: ");
384 vfprintf(stderr, format, ap);
385 fprintf(stderr, "\n");
386 va_end(ap);
387 #else
388 MD_VAR_NOT_USED(format);
389 #endif /* NDEBUG */
390 }
391
TRACE_INFO(const char * format,...)392 static MD_INLINE void TRACE_INFO(const char* format, ...)
393 {
394 #ifndef NDEBUG
395 va_list ap;
396 va_start(ap, format);
397 fprintf(stderr, "TRACE: ");
398 vfprintf(stderr, format, ap);
399 fprintf(stderr, "\n");
400 va_end(ap);
401 #else
402 MD_VAR_NOT_USED(format);
403 #endif /* NDEBUG */
404 }
405 #endif /* defined(LINUX) || defined(ANDROID) */
406
407 /*----------------------------------------------------------------------------
408 * Globals
409 *----------------------------------------------------------------------------*/
410 /* The sector size */
411 static uint32_t g_nSectorSize;
412
413 /* The workspace size */
414 static uint32_t g_nWorkspaceSize = DEFAULT_WORKSPACE_SIZE;
415
416 /* UUID of the delegation service */
417 static const TEEC_UUID g_sServiceId = SERVICE_DELEGATION_UUID;
418
419 /* pWorkspaceBuffer points to the workspace buffer shared with the secure
420 world to transfer the sectors in the READ and WRITE instructions */
421 static uint8_t* g_pWorkspaceBuffer;
422 static DELEGATION_EXCHANGE_BUFFER * g_pExchangeBuffer;
423 TEEC_SharedMemory sExchangeSharedMem;
424 /*
425 The absolute path name for each of the 16 possible partitions.
426 */
427 static char* g_pPartitionNames[16];
428
429 /* The file context for each of the 16 possible partitions. An entry
430 in this array is NULL if the corresponding partition is currently not opened
431 */
432 static FILE* g_pPartitionFiles[16];
433
434 /*----------------------------------------------------------------------------
435 * Utilities functions
436 *----------------------------------------------------------------------------*/
printUsage(void)437 static void printUsage(void)
438 {
439 LogInfo("usage : tf_daemon [options]");
440 LogInfo("where [options] are:");
441 LogInfo("-h --help Display help.");
442 #ifdef SUPPORT_DELEGATION_EXTENSION
443 LogInfo("-c <conf> Configuration file path.");
444 #else
445 /* If the compilation parameter SUPPORT_DELEGATION_EXTENSION is not set, each
446 partition is stored as a file within the base dir */
447 LogInfo("-storageDir <baseDir> Set the directory where the data will be stored; this directory");
448 LogInfo(" must be writable and executable (this parameter is mandatory)");
449 #endif
450 LogInfo("-d Turns on debug mode. If not specified, the daemon will fork itself");
451 LogInfo(" and get detached from the console.");
452 #ifndef SUPPORT_DELEGATION_EXTENSION
453 LogInfo("-workspaceSize <integer> Set the size in bytes of the workspace. Must be greater or equal to 8 sectors.");
454 LogInfo(" (default is 128KB)");
455 #endif
456 }
457
errno2serror(void)458 static TEEC_Result errno2serror(void)
459 {
460 switch (errno)
461 {
462 case EINVAL:
463 return S_ERROR_BAD_PARAMETERS;
464 case EMFILE:
465 return S_ERROR_NO_MORE_HANDLES;
466 case ENOENT:
467 return S_ERROR_ITEM_NOT_FOUND;
468 case EEXIST:
469 return S_ERROR_ITEM_EXISTS;
470 case ENOSPC:
471 return S_ERROR_STORAGE_NO_SPACE;
472 case ENOMEM:
473 return S_ERROR_OUT_OF_MEMORY;
474 case EBADF:
475 case EACCES:
476 default:
477 return S_ERROR_STORAGE_UNREACHABLE;
478 }
479 }
480
481 /*
482 * Check if the directory in parameter exists with Read/Write access
483 * Return 0 in case of success and 1 otherwise.
484 */
static_checkStorageDirAndAccessRights(char * directoryName)485 int static_checkStorageDirAndAccessRights(char * directoryName)
486 {
487 #ifdef __SYMBIAN32__
488 /* it looks like stat is not working properly on Symbian
489 Create and remove dummy file to check access rights */
490 FILE *stream;
491 char *checkAccess = NULL;
492
493 if (directoryName == NULL)
494 {
495 LogError("Directory Name is NULL");
496 return 1;
497 }
498
499 checkAccess = malloc(strlen(directoryName)+1/* \ */ +1 /* a */ + 1 /* 0 */);
500 if (!checkAccess)
501 {
502 LogError("storageDir '%s' allocation error", directoryName);
503 return 1;
504 }
505 sprintf(checkAccess,"%s\\a",directoryName);
506 stream = fopen(checkAccess, "w+b");
507 if (!stream)
508 {
509 LogError("storageDir '%s' is incorrect or cannot be reached", directoryName);
510 return 1;
511 }
512 fclose(stream);
513 unlink(checkAccess);
514 #else
515 /* Non-Symbian OS: use stat */
516 struct stat buf;
517 int result = 0;
518
519 if (directoryName == NULL)
520 {
521 LogError("Directory Name is NULL");
522 return 1;
523 }
524
525 result = stat(directoryName, &buf);
526 if (result == 0)
527 {
528 /* Storage dir exists. Check access rights */
529 #if defined(LINUX) || (defined ANDROID)
530 if ((buf.st_mode & (S_IXUSR | S_IWUSR)) != (S_IXUSR | S_IWUSR))
531 {
532 LogError("storageDir '%s' does not have read-write access", directoryName);
533 return 1;
534 }
535 #endif
536 }
537 else if (errno == ENOENT)
538 {
539 LogError("storageDir '%s' does not exist", directoryName);
540 return 1;
541 }
542 else
543 {
544 /* Another error */
545 LogError("storageDir '%s' is incorrect or cannot be reached", directoryName);
546 return 1;
547 }
548 #endif
549 return 0;
550 }
551
552
553
554 /*----------------------------------------------------------------------------
555 * Instructions
556 *----------------------------------------------------------------------------*/
557
558 /**
559 * This function executes the DESTROY_PARTITION instruction
560 *
561 * @param nPartitionID: the partition identifier
562 **/
partitionDestroy(uint32_t nPartitionID)563 static TEEC_Result partitionDestroy(uint32_t nPartitionID)
564 {
565 TEEC_Result nError = S_SUCCESS;
566
567 if (g_pPartitionFiles[nPartitionID] != NULL)
568 {
569 /* The partition must not be currently opened */
570 LogError("g_pPartitionFiles not NULL");
571 return S_ERROR_BAD_STATE;
572 }
573
574 /* Try to erase the file */
575 #if defined(LINUX) || (defined ANDROID) || defined (__SYMBIAN32__)
576 if (unlink(g_pPartitionNames[nPartitionID]) != 0)
577 #endif
578 #ifdef WIN32
579 if (_unlink(g_pPartitionNames[nPartitionID]) != 0)
580 #endif
581 {
582 /* File in use or OS didn't allow the operation */
583 nError = errno2serror();
584 }
585
586 return nError;
587 }
588
589 /**
590 * This function executes the CREATE_PARTITION instruction. When successful,
591 * it fills the g_pPartitionFiles[nPartitionID] slot.
592 *
593 * @param nPartitionID: the partition identifier
594 **/
partitionCreate(uint32_t nPartitionID)595 static TEEC_Result partitionCreate(uint32_t nPartitionID)
596 {
597 uint32_t nError = S_SUCCESS;
598
599 if (g_pPartitionFiles[nPartitionID] != NULL)
600 {
601 /* The partition is already opened */
602 LogError("g_pPartitionFiles not NULL");
603 return S_ERROR_BAD_STATE;
604 }
605
606 /* Create the file unconditionnally */
607 LogInfo("Create storage file \"%s\"", g_pPartitionNames[nPartitionID]);
608 g_pPartitionFiles[nPartitionID] = fopen(g_pPartitionNames[nPartitionID], "w+b");
609
610 if (g_pPartitionFiles[nPartitionID] == NULL)
611 {
612 LogError("Cannot create storage file \"%s\"", g_pPartitionNames[nPartitionID]);
613 nError = errno2serror();
614 return nError;
615 }
616
617 return nError;
618 }
619
620 /**
621 * This function executes the OPEN_PARTITION instruction. When successful,
622 * it fills the g_pPartitionFiles[nPartitionID] slot and writes the partition
623 * size in hResultEncoder
624 *
625 * @param nPartitionID: the partition identifier
626 * @param pnPartitionSize: filled with the number of sectors in the partition
627 **/
partitionOpen(uint32_t nPartitionID,uint32_t * pnPartitionSize)628 static TEEC_Result partitionOpen(uint32_t nPartitionID, uint32_t* pnPartitionSize)
629 {
630 uint32_t nError = S_SUCCESS;
631
632 if (g_pPartitionFiles[nPartitionID] != NULL)
633 {
634 /* No partition must be currently opened in the session */
635 LogError("g_pPartitionFiles not NULL");
636 return S_ERROR_BAD_STATE;
637 }
638
639 /* Open the file */
640 g_pPartitionFiles[nPartitionID] = fopen(g_pPartitionNames[nPartitionID], "r+b");
641 if (g_pPartitionFiles[nPartitionID] == NULL)
642 {
643 if (errno == ENOENT)
644 {
645 /* File does not exist */
646 LogError("Storage file \"%s\" does not exist", g_pPartitionNames[nPartitionID]);
647 nError = S_ERROR_ITEM_NOT_FOUND;
648 return nError;
649 }
650 else
651 {
652 LogError("cannot open storage file \"%s\"", g_pPartitionNames[nPartitionID]);
653 nError = errno2serror();
654 return nError;
655 }
656 }
657 /* Determine the current number of sectors */
658 fseek(g_pPartitionFiles[nPartitionID], 0L, SEEK_END);
659 *pnPartitionSize = ftell(g_pPartitionFiles[nPartitionID]) / g_nSectorSize;
660
661 LogInfo("storage file \"%s\" successfully opened (size = %d KB (%d bytes))",
662 g_pPartitionNames[nPartitionID],
663 ((*pnPartitionSize) * g_nSectorSize) / 1024,
664 ((*pnPartitionSize) * g_nSectorSize));
665
666 return nError;
667 }
668
669
670 /**
671 * This function executes the CLOSE_PARTITION instruction.
672 * It closes the partition file.
673 *
674 * @param nPartitionID: the partition identifier
675 **/
partitionClose(uint32_t nPartitionID)676 static TEEC_Result partitionClose(uint32_t nPartitionID)
677 {
678 if (g_pPartitionFiles[nPartitionID] == NULL)
679 {
680 /* The partition is currently not opened */
681 return S_ERROR_BAD_STATE;
682 }
683 fclose(g_pPartitionFiles[nPartitionID]);
684 g_pPartitionFiles[nPartitionID] = NULL;
685 return S_SUCCESS;
686 }
687
688 /**
689 * This function executes the READ instruction.
690 *
691 * @param nPartitionID: the partition identifier
692 * @param nSectorIndex: the index of the sector to read
693 * @param nWorkspaceOffset: the offset in the workspace where the sector must be written
694 **/
partitionRead(uint32_t nPartitionID,uint32_t nSectorIndex,uint32_t nWorkspaceOffset)695 static TEEC_Result partitionRead(uint32_t nPartitionID, uint32_t nSectorIndex, uint32_t nWorkspaceOffset)
696 {
697 FILE* pFile;
698
699 TRACE_INFO(">Partition %1X: read sector 0x%08X into workspace at offset 0x%08X",
700 nPartitionID, nSectorIndex, nWorkspaceOffset);
701
702 pFile = g_pPartitionFiles[nPartitionID];
703
704 if (pFile == NULL)
705 {
706 /* The partition is not opened */
707 return S_ERROR_BAD_STATE;
708 }
709
710 if (fseek(pFile, nSectorIndex*g_nSectorSize, SEEK_SET) != 0)
711 {
712 LogError("fseek error: %s", strerror(errno));
713 return errno2serror();
714 }
715
716 if (fread(g_pWorkspaceBuffer + nWorkspaceOffset,
717 g_nSectorSize, 1,
718 pFile) != 1)
719 {
720 if (feof(pFile))
721 {
722 LogError("fread error: End-Of-File detected");
723 return S_ERROR_ITEM_NOT_FOUND;
724 }
725 LogError("fread error: %s", strerror(errno));
726 return errno2serror();
727 }
728
729 return S_SUCCESS;
730 }
731
732 #ifdef SUPPORT_RPMB_PARTITION
rpmbRead(DELEGATION_RPMB_INSTRUCTION * pInstruction)733 static TEEC_Result rpmbRead(DELEGATION_RPMB_INSTRUCTION *pInstruction)
734 {
735 DELEGATION_RPMB_MESSAGE* pMessages;
736 uint32_t nNbMsg, nIndex;
737
738 nNbMsg = g_nSectorSize >> 8;
739 pMessages = (DELEGATION_RPMB_MESSAGE*)malloc(nNbMsg * sizeof(DELEGATION_RPMB_MESSAGE));
740 if (pMessages == NULL)
741 {
742 return S_ERROR_OUT_OF_MEMORY;
743 }
744 memset(pMessages,0,nNbMsg * sizeof(DELEGATION_RPMB_MESSAGE));
745
746 for (nIndex=0;nIndex<nNbMsg;nIndex++)
747 {
748 memcpy(pMessages[nIndex].pNonce , pInstruction->pNonce, 16);
749 pMessages[nIndex].nAddr = pInstruction->nAddr;
750 pMessages[nIndex].nBlockCount = pInstruction->nBlockCount;
751 pMessages[nIndex].nReqOrResp = 0x0004;
752 }
753 memcpy(pMessages[nNbMsg-1].pMAC,pInstruction->nMAC,32);
754
755 /* TODO: send to the RPMB driver */
756
757 memcpy(pInstruction->pNonce,pMessages[0].pNonce , 16);
758 pInstruction->nAddr = pMessages[0].nAddr;
759 pInstruction->nBlockCount = pMessages[0].nBlockCount;
760 for (nIndex=0;nIndex<nNbMsg;nIndex++)
761 {
762 memcpy(g_pWorkspaceBuffer + pInstruction->nWorkspaceOffset[nIndex],pMessages[nIndex].pData,256);
763 }
764 memcpy(pInstruction->nMAC, pMessages[nNbMsg-1].pMAC,32);
765 pInstruction->nResult=pMessages[nNbMsg-1].nResult;
766
767 free(pMessages);
768
769 return S_SUCCESS;
770 }
771 #endif
772 /**
773 * This function executes the WRITE instruction.
774 *
775 * @param nPartitionID: the partition identifier
776 * @param nSectorIndex: the index of the sector to read
777 * @param nWorkspaceOffset: the offset in the workspace where the sector must be read
778 **/
partitionWrite(uint32_t nPartitionID,uint32_t nSectorIndex,uint32_t nWorkspaceOffset)779 static TEEC_Result partitionWrite(uint32_t nPartitionID, uint32_t nSectorIndex, uint32_t nWorkspaceOffset)
780 {
781 FILE* pFile;
782
783 TRACE_INFO(">Partition %1X: write sector 0x%X from workspace at offset 0x%X",
784 nPartitionID, nSectorIndex, nWorkspaceOffset);
785
786 pFile = g_pPartitionFiles[nPartitionID];
787
788 if (pFile == NULL)
789 {
790 /* The partition is not opened */
791 return S_ERROR_BAD_STATE;
792 }
793
794 if (fseek(pFile, nSectorIndex*g_nSectorSize, SEEK_SET) != 0)
795 {
796 LogError("fseek error: %s", strerror(errno));
797 return errno2serror();
798 }
799
800 if (fwrite(g_pWorkspaceBuffer + nWorkspaceOffset,
801 g_nSectorSize, 1,
802 pFile) != 1)
803 {
804 LogError("fread error: %s", strerror(errno));
805 return errno2serror();
806 }
807 return S_SUCCESS;
808 }
809
810 #ifdef SUPPORT_RPMB_PARTITION
rpmbWrite(DELEGATION_RPMB_INSTRUCTION * pInstruction)811 static TEEC_Result rpmbWrite(DELEGATION_RPMB_INSTRUCTION *pInstruction)
812 {
813 DELEGATION_RPMB_MESSAGE* pMessages;
814 uint32_t nNbMsg, nIndex;
815
816 nNbMsg = g_nSectorSize >> 8;
817 pMessages = (DELEGATION_RPMB_MESSAGE*)malloc(nNbMsg * sizeof(DELEGATION_RPMB_MESSAGE));
818 if (pMessages == NULL)
819 {
820 return S_ERROR_OUT_OF_MEMORY;
821 }
822 memset(pMessages,0,nNbMsg * sizeof(DELEGATION_RPMB_MESSAGE));
823
824 for (nIndex=0;nIndex<nNbMsg;nIndex++)
825 {
826 memcpy(pMessages[nIndex].pData,g_pWorkspaceBuffer + pInstruction->nWorkspaceOffset[nIndex],256);
827 pMessages[nIndex].nMC = pInstruction->nMC;
828 pMessages[nIndex].nAddr = pInstruction->nAddr;
829 pMessages[nIndex].nBlockCount = pInstruction->nBlockCount;
830 pMessages[nIndex].nReqOrResp = 0x0003;
831 }
832 memcpy(pMessages[nNbMsg-1].pMAC,pInstruction->nMAC,32);
833
834 /* TODO: send to the RPMB driver */
835
836 pInstruction->nAddr = pMessages[0].nAddr;
837 pInstruction->nMC = pMessages[0].nMC;
838 memcpy(pInstruction->nMAC, pMessages[nNbMsg-1].pMAC,32);
839 pInstruction->nResult=pMessages[nNbMsg-1].nResult;
840
841 free(pMessages);
842
843 return S_SUCCESS;
844 }
845 #endif
846 /**
847 * This function executes the SET_SIZE instruction.
848 *
849 * @param nPartitionID: the partition identifier
850 * @param nNewSectorCount: the new sector count
851 **/
partitionSetSize(uint32_t nPartitionID,uint32_t nNewSectorCount)852 static TEEC_Result partitionSetSize(uint32_t nPartitionID, uint32_t nNewSectorCount)
853 {
854 FILE* pFile;
855 uint32_t nCurrentSectorCount;
856
857 pFile = g_pPartitionFiles[nPartitionID];
858
859 if (pFile==NULL)
860 {
861 /* The partition is not opened */
862 return S_ERROR_BAD_STATE;
863 }
864
865 /* Determine the current size of the partition */
866 if (fseek(pFile, 0, SEEK_END) != 0)
867 {
868 LogError("fseek error: %s", strerror(errno));
869 return errno2serror();
870 }
871 nCurrentSectorCount = ftell(pFile) / g_nSectorSize;
872
873 if (nNewSectorCount > nCurrentSectorCount)
874 {
875 uint32_t nAddedBytesCount;
876 /* Enlarge the partition file. Make sure we actually write
877 some non-zero data into the new sectors. Otherwise, some file-system
878 might not really reserve the storage space but use a
879 sparse representation. In this case, a subsequent write instruction
880 could fail due to out-of-space, which we want to avoid. */
881 nAddedBytesCount = (nNewSectorCount-nCurrentSectorCount)*g_nSectorSize;
882 while (nAddedBytesCount)
883 {
884 if (fputc(0xA5, pFile)!=0xA5)
885 {
886 return errno2serror();
887 }
888 nAddedBytesCount--;
889 }
890 }
891 else if (nNewSectorCount < nCurrentSectorCount)
892 {
893 int result = 0;
894 /* Truncate the partition file */
895 #if defined(LINUX) || (defined ANDROID)
896 result = ftruncate(fileno(pFile),nNewSectorCount * g_nSectorSize);
897 #endif
898 #if defined (__SYMBIAN32__)
899 LogError("No truncate available in Symbian C API");
900 #endif
901 #ifdef WIN32
902 result = _chsize(_fileno(pFile),nNewSectorCount * g_nSectorSize);
903 #endif
904 if (result)
905 {
906 return errno2serror();
907 }
908 }
909 return S_SUCCESS;
910 }
911
912 /**
913 * This function executes the SYNC instruction.
914 *
915 * @param pPartitionID: the partition identifier
916 **/
partitionSync(uint32_t nPartitionID)917 static TEEC_Result partitionSync(uint32_t nPartitionID)
918 {
919 TEEC_Result nError = S_SUCCESS;
920 int result;
921
922 FILE* pFile = g_pPartitionFiles[nPartitionID];
923
924 if (pFile == NULL)
925 {
926 /* The partition is not currently opened */
927 return S_ERROR_BAD_STATE;
928 }
929
930 /* First make sure that the data in the stdio buffers
931 is flushed to the file descriptor */
932 result=fflush(pFile);
933 if (result)
934 {
935 nError=errno2serror();
936 goto end;
937 }
938 /* Then synchronize the file descriptor with the file-system */
939
940 #if defined(LINUX) || (defined ANDROID)
941 result=fdatasync(fileno(pFile));
942 #endif
943 #if defined (__SYMBIAN32__)
944 result=fsync(fileno(pFile));
945 #endif
946 #ifdef WIN32
947 result=_commit(_fileno(pFile));
948 #endif
949 if (result)
950 {
951 nError=errno2serror();
952 }
953
954 end:
955 return nError;
956 }
957
958 /**
959 * This function executes the NOTIFY instruction.
960 *
961 * @param pMessage the message string
962 * @param nMessageType the type of messages
963 **/
notify(const wchar_t * pMessage,uint32_t nMessageType)964 static void notify(const wchar_t* pMessage, uint32_t nMessageType)
965 {
966 switch (nMessageType)
967 {
968 case DELEGATION_NOTIFY_TYPE_ERROR:
969 LogError("%ls", pMessage);
970 break;
971 case DELEGATION_NOTIFY_TYPE_WARNING:
972 LogWarning("%ls", pMessage);
973 break;
974 case DELEGATION_NOTIFY_TYPE_DEBUG:
975 LogInfo("DEBUG: %ls", pMessage);
976 break;
977 case DELEGATION_NOTIFY_TYPE_INFO:
978 default:
979 LogInfo("%ls", pMessage);
980 break;
981 }
982 }
983
984 /*----------------------------------------------------------------------------
985 * Session main function
986 *----------------------------------------------------------------------------*/
987
988 /*
989 * This function runs a session opened on the delegation service. It fetches
990 * instructions and execute them in a loop. It never returns, but may call
991 * exit when instructed to shutdown by the service
992 */
runSession(TEEC_Context * pContext,TEEC_Session * pSession,TEEC_Operation * pOperation)993 static int runSession(TEEC_Context* pContext, TEEC_Session* pSession, TEEC_Operation* pOperation)
994 {
995 memset(&g_pExchangeBuffer->sAdministrativeData, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData));
996
997 while (true)
998 {
999 S_RESULT nError;
1000 TEEC_Result nTeeError;
1001 uint32_t nInstructionsIndex;
1002 uint32_t nInstructionsBufferSize = sizeof(g_pExchangeBuffer->sInstructions);
1003
1004 pOperation->paramTypes = TEEC_PARAM_TYPES(
1005 TEEC_MEMREF_PARTIAL_INPUT,
1006 TEEC_MEMREF_PARTIAL_OUTPUT,
1007 TEEC_MEMREF_PARTIAL_INOUT,
1008 TEEC_NONE);
1009 pOperation->params[0].memref.parent = &sExchangeSharedMem;
1010 pOperation->params[0].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sAdministrativeData);
1011 pOperation->params[0].memref.size = sizeof(g_pExchangeBuffer->sAdministrativeData);
1012
1013 pOperation->params[1].memref.parent = &sExchangeSharedMem;
1014 pOperation->params[1].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sInstructions);
1015 pOperation->params[1].memref.size = sizeof(g_pExchangeBuffer->sInstructions);
1016
1017 pOperation->params[2].memref.parent = &sExchangeSharedMem;
1018 pOperation->params[2].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sWorkspace);
1019 pOperation->params[2].memref.size = g_nWorkspaceSize;
1020
1021 nTeeError = TEEC_InvokeCommand(pSession,
1022 SERVICE_DELEGATION_GET_INSTRUCTIONS, /* commandID */
1023 pOperation, /* IN OUT operation */
1024 NULL /* OUT errorOrigin, optional */
1025 );
1026
1027 if (nTeeError != TEEC_SUCCESS)
1028 {
1029 LogError("TEEC_InvokeCommand error: 0x%08X", nTeeError);
1030 LogError("Daemon exits");
1031 exit(2);
1032 }
1033
1034 if (pOperation->params[1].tmpref.size > nInstructionsBufferSize)
1035 {
1036 /* Should not happen, probably an error from the service */
1037 pOperation->params[1].tmpref.size = 0;
1038 }
1039
1040 /* Reset the operation results */
1041 nError = TEEC_SUCCESS;
1042 g_pExchangeBuffer->sAdministrativeData.nSyncExecuted = 0;
1043 memset(g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates));
1044 memset(g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes));
1045
1046 /* Execute the instructions */
1047 nInstructionsIndex = 0;
1048 nInstructionsBufferSize = pOperation->params[1].tmpref.size;
1049 while (true)
1050 {
1051 DELEGATION_INSTRUCTION * pInstruction;
1052 uint32_t nInstructionID;
1053 pInstruction = (DELEGATION_INSTRUCTION *)(&g_pExchangeBuffer->sInstructions[nInstructionsIndex/4]);
1054 if (nInstructionsIndex + 4 <= nInstructionsBufferSize)
1055 {
1056 nInstructionID = pInstruction->sGeneric.nInstructionID;
1057 nInstructionsIndex+=4;
1058 }
1059 else
1060 {
1061 goto instruction_parse_end;
1062 }
1063 if ((nInstructionID & 0x0F) == 0)
1064 {
1065 /* Partition-independent instruction */
1066 switch (nInstructionID)
1067 {
1068 case DELEGATION_INSTRUCTION_SHUTDOWN:
1069 {
1070 exit(0);
1071 /* The implementation of the TF Client API will automatically
1072 destroy the context and release any associated resource */
1073 }
1074 case DELEGATION_INSTRUCTION_NOTIFY:
1075 {
1076 /* Parse the instruction parameters */
1077 wchar_t pMessage[100];
1078 uint32_t nMessageType;
1079 uint32_t nMessageSize;
1080 memset(pMessage, 0, 100*sizeof(wchar_t));
1081
1082 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
1083 {
1084 nMessageType = pInstruction->sNotify.nMessageType;
1085 nMessageSize = pInstruction->sNotify.nMessageSize;
1086 nInstructionsIndex+=8;
1087 }
1088 else
1089 {
1090 goto instruction_parse_end;
1091 }
1092 if (nMessageSize > (99)*sizeof(wchar_t))
1093 {
1094 /* How to handle the error correctly in this case ? */
1095 goto instruction_parse_end;
1096 }
1097 if (nInstructionsIndex + nMessageSize <= nInstructionsBufferSize)
1098 {
1099 memcpy(pMessage, &pInstruction->sNotify.nMessage[0], nMessageSize);
1100 nInstructionsIndex+=nMessageSize;
1101 }
1102 else
1103 {
1104 goto instruction_parse_end;
1105 }
1106 /* Align the pInstructionsIndex on 4 bytes */
1107 nInstructionsIndex = (nInstructionsIndex+3)&~3;
1108 notify(pMessage, nMessageType);
1109 break;
1110 }
1111 default:
1112 LogError("Unknown instruction identifier: %02X", nInstructionID);
1113 nError = S_ERROR_BAD_PARAMETERS;
1114 break;
1115 }
1116 }
1117 else
1118 {
1119 /* Partition-specific instruction */
1120 uint32_t nPartitionID = (nInstructionID & 0xF0) >> 4;
1121 if (g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates[nPartitionID] == S_SUCCESS)
1122 {
1123 /* Execute the instruction only if there is currently no
1124 error on the partition */
1125 switch (nInstructionID & 0x0F)
1126 {
1127 case DELEGATION_INSTRUCTION_PARTITION_CREATE:
1128 nError = partitionCreate(nPartitionID);
1129 #ifdef SUPPORT_RPMB_PARTITION
1130 if (nPartitionID == RPMB_PARTITION_ID)
1131 {
1132 /* TODO: get the Write counter */
1133 pInstruction->sAuthRW.nMC = 0;
1134 }
1135 #endif
1136 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1137 break;
1138 case DELEGATION_INSTRUCTION_PARTITION_OPEN:
1139 {
1140 uint32_t nPartitionSize = 0;
1141 nError = partitionOpen(nPartitionID, &nPartitionSize);
1142 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d pSize=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nPartitionSize, nError);
1143 if (nError == S_SUCCESS)
1144 {
1145 g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes[nPartitionID] = nPartitionSize;
1146 }
1147 #ifdef SUPPORT_RPMB_PARTITION
1148 if (nPartitionID == RPMB_PARTITION_ID)
1149 {
1150 /* TODO: get the Write counter */
1151 pInstruction->sAuthRW.nMC = 0;
1152 }
1153 #endif
1154 break;
1155 }
1156 case DELEGATION_INSTRUCTION_PARTITION_READ:
1157 #ifdef SUPPORT_RPMB_PARTITION
1158 if (nPartitionID == RPMB_PARTITION_ID)
1159 {
1160 if (nInstructionsIndex + sizeof(DELEGATION_RPMB_INSTRUCTION)-sizeof(uint32_t) <= nInstructionsBufferSize)
1161 {
1162 nInstructionsIndex+=sizeof(DELEGATION_RPMB_INSTRUCTION)-sizeof(uint32_t);
1163 }
1164 else
1165 {
1166 goto instruction_parse_end;
1167 }
1168 nError = rpmbRead(&pInstruction->sAuthRW);
1169 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1170 break;
1171 }
1172 else
1173 #endif
1174 {
1175 /* Parse parameters */
1176 uint32_t nSectorID;
1177 uint32_t nWorkspaceOffset;
1178 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
1179 {
1180 nSectorID = pInstruction->sReadWrite.nSectorID;
1181 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
1182 nInstructionsIndex+=8;
1183 }
1184 else
1185 {
1186 goto instruction_parse_end;
1187 }
1188 nError = partitionRead(nPartitionID, nSectorID, nWorkspaceOffset);
1189 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
1190 break;
1191 }
1192 case DELEGATION_INSTRUCTION_PARTITION_WRITE:
1193 #ifdef SUPPORT_RPMB_PARTITION
1194 if (nPartitionID == RPMB_PARTITION_ID)
1195 {
1196 if (nInstructionsIndex + sizeof(DELEGATION_RPMB_INSTRUCTION)-sizeof(uint32_t) <= nInstructionsBufferSize)
1197 {
1198 nInstructionsIndex+=sizeof(DELEGATION_RPMB_INSTRUCTION)-sizeof(uint32_t);
1199 }
1200 else
1201 {
1202 goto instruction_parse_end;
1203 }
1204 nError = rpmbWrite(&pInstruction->sAuthRW);
1205 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1206 break;
1207 }
1208 else
1209 #endif
1210 {
1211 /* Parse parameters */
1212 uint32_t nSectorID;
1213 uint32_t nWorkspaceOffset;
1214 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
1215 {
1216 nSectorID = pInstruction->sReadWrite.nSectorID;
1217 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
1218 nInstructionsIndex+=8;
1219 }
1220 else
1221 {
1222 goto instruction_parse_end;
1223 }
1224 nError = partitionWrite(nPartitionID, nSectorID, nWorkspaceOffset);
1225 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
1226 break;
1227 }
1228 case DELEGATION_INSTRUCTION_PARTITION_SYNC:
1229 nError = partitionSync(nPartitionID);
1230 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1231 if (nError == S_SUCCESS)
1232 {
1233 g_pExchangeBuffer->sAdministrativeData.nSyncExecuted++;
1234 }
1235 break;
1236 case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE:
1237 {
1238 uint32_t nNewSize;
1239 if (nInstructionsIndex + 4 <= nInstructionsBufferSize)
1240 {
1241 nNewSize = pInstruction->sSetSize.nNewSize;
1242 nInstructionsIndex+=4;
1243 }
1244 else
1245 {
1246 goto instruction_parse_end;
1247 }
1248 nError = partitionSetSize(nPartitionID, nNewSize);
1249 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d nNewSize=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nNewSize, nError);
1250 break;
1251 }
1252 case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
1253 nError = partitionClose(nPartitionID);
1254 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1255 break;
1256 case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
1257 nError = partitionDestroy(nPartitionID);
1258 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1259 break;
1260 }
1261 g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates[nPartitionID] = nError;
1262 }
1263 }
1264 }
1265 instruction_parse_end:
1266 memset(pOperation, 0, sizeof(TEEC_Operation));
1267 }
1268 }
1269
1270 /**
1271 * This function opens a new session to the delegation service.
1272 **/
createSession(TEEC_Context * pContext,TEEC_Session * pSession,TEEC_Operation * pOperation)1273 static int createSession(TEEC_Context* pContext, TEEC_Session* pSession, TEEC_Operation* pOperation)
1274 {
1275 TEEC_Result nError;
1276 uint32_t nExchangeBufferSize;
1277
1278 memset(pOperation, 0, sizeof(TEEC_Operation));
1279 pOperation->paramTypes = TEEC_PARAM_TYPES(
1280 TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1281 nError = TEEC_OpenSession(pContext,
1282 pSession, /* OUT session */
1283 &g_sServiceId, /* destination UUID */
1284 TEEC_LOGIN_PRIVILEGED, /* connectionMethod */
1285 NULL, /* connectionData */
1286 pOperation, /* IN OUT operation */
1287 NULL /* OUT errorOrigin, optional */
1288 );
1289 if (nError != TEEC_SUCCESS)
1290 {
1291 LogError("Error on TEEC_OpenSession : 0x%x", nError);
1292 exit(2);
1293 }
1294 /* Read sector size */
1295 g_nSectorSize = pOperation->params[0].value.a;
1296 LogInfo("Sector Size: %d bytes", g_nSectorSize);
1297
1298 /* Check sector size */
1299 if (!(g_nSectorSize == 512 || g_nSectorSize == 1024 || g_nSectorSize == 2048 || g_nSectorSize == 4096))
1300 {
1301 LogError("Incorrect sector size: terminating...");
1302 exit(2);
1303 }
1304
1305 /* Check workspace size */
1306 if (g_nWorkspaceSize < 8 * g_nSectorSize)
1307 {
1308 g_nWorkspaceSize = 8 * g_nSectorSize;
1309 LogWarning("Workspace size too small, automatically set to %d bytes", g_nWorkspaceSize);
1310 }
1311 /* Compute the size of the exchange buffer */
1312 nExchangeBufferSize = sizeof(DELEGATION_EXCHANGE_BUFFER)-1+g_nWorkspaceSize;
1313 g_pExchangeBuffer = (DELEGATION_EXCHANGE_BUFFER*)malloc(nExchangeBufferSize);
1314 if (g_pExchangeBuffer == NULL)
1315 {
1316 LogError("Cannot allocate exchange buffer of %d bytes", nExchangeBufferSize);
1317 LogError("Now exiting...");
1318 exit(2);
1319 }
1320 g_pWorkspaceBuffer = (uint8_t*)g_pExchangeBuffer->sWorkspace;
1321 memset(g_pExchangeBuffer, 0x00, nExchangeBufferSize);
1322 memset(g_pPartitionFiles,0,16*sizeof(FILE*));
1323
1324 /* Register the exchange buffer as a shared memory block */
1325 sExchangeSharedMem.buffer = g_pExchangeBuffer;
1326 sExchangeSharedMem.size = nExchangeBufferSize;
1327 sExchangeSharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
1328 nError = TEEC_RegisterSharedMemory(pContext, &sExchangeSharedMem);
1329 if (nError != TEEC_SUCCESS)
1330 {
1331 LogError("Error on TEEC_RegisterSharedMemory : 0x%x", nError);
1332 free(g_pExchangeBuffer);
1333 exit(2);
1334 }
1335 LogInfo("Daemon now connected");
1336 return 0;
1337 }
1338
1339
1340 /*----------------------------------------------------------------------------
1341 * Main
1342 *----------------------------------------------------------------------------*/
1343
1344 #ifdef INCLUDE_CLIENT_DELEGATION
delegation_main(int argc,char * argv[])1345 int delegation_main(int argc, char* argv[])
1346 #else
1347 int main(int argc, char* argv[])
1348 #endif
1349 {
1350 TEEC_Result nError;
1351 TEEC_Context sContext;
1352 TEEC_Session sSession;
1353 TEEC_Operation sOperation;
1354 bool debug = false;
1355
1356 #ifndef SUPPORT_DELEGATION_EXTENSION
1357 char * baseDir = NULL;
1358
1359 LogInfo("TFSW Normal-World Daemon");
1360 #else
1361 LogInfo("TFSW Normal-World Ext Daemon");
1362 #endif
1363 LogInfo(S_VERSION_STRING);
1364 LogInfo("");
1365
1366 /* Skip program name */
1367 argv++;
1368 argc--;
1369
1370 while (argc != 0)
1371 {
1372 if (strcmp(argv[0], "-d") == 0)
1373 {
1374 debug = true;
1375 }
1376 #ifdef SUPPORT_DELEGATION_EXTENSION
1377 else if (strcmp(argv[0], "-c") == 0)
1378 {
1379 int error;
1380 argc--;
1381 argv++;
1382 if (argc == 0)
1383 {
1384 printUsage();
1385 return 1;
1386 }
1387 /* Note that the function parseCommandLineExtension can modify the
1388 content of the g_partitionNames array */
1389 error = parseCommandLineExtension(argv[0], g_pPartitionNames);
1390 if ( error != 0 )
1391 {
1392 printUsage();
1393 return error;
1394 }
1395 }
1396 #else
1397 else if (strcmp(argv[0], "-storageDir") == 0)
1398 {
1399 uint32_t i = 0;
1400 argc--;
1401 argv++;
1402 if (argc == 0)
1403 {
1404 printUsage();
1405 return 1;
1406 }
1407 if (baseDir != NULL)
1408 {
1409 LogError("Only one storage directory may be specified");
1410 return 1;
1411 }
1412 baseDir = malloc(strlen(argv[0])+1); /* Zero-terminated string */
1413 if (baseDir == NULL)
1414 {
1415 LogError("Out of memory");
1416 return 2;
1417 }
1418
1419 strcpy(baseDir, argv[0]);
1420
1421 /* Set default names to the partitions */
1422 for ( i=0; i<16 ;i++ )
1423 {
1424 g_pPartitionNames[i] = NULL;
1425 g_pPartitionNames[i] = malloc(strlen(baseDir) + 1 /* separator */ + sizeof("Store_X.tf"));
1426 if (g_pPartitionNames[i] != NULL)
1427 {
1428 sprintf(g_pPartitionNames[i], "%s%cStore_%1X.tf", baseDir, PATH_SEPARATOR, i);
1429 }
1430 else
1431 {
1432 free(baseDir);
1433 i=0;
1434 while(g_pPartitionNames[i] != NULL) free(g_pPartitionNames[i++]);
1435 LogError("Out of memory");
1436 return 2;
1437 }
1438 }
1439 }
1440 else if (strcmp(argv[0], "-workspaceSize") == 0)
1441 {
1442 argc--;
1443 argv++;
1444 if (argc == 0)
1445 {
1446 printUsage();
1447 return 1;
1448 }
1449 g_nWorkspaceSize=atol(argv[0]);
1450 }
1451 #endif /* ! SUPPORT_DELEGATION_EXTENSION */
1452 /*****************************************/
1453 else if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "-h") == 0)
1454 {
1455 printUsage();
1456 return 0;
1457 }
1458 else
1459 {
1460 printUsage();
1461 return 1;
1462 }
1463 argc--;
1464 argv++;
1465 }
1466
1467 #ifndef SUPPORT_DELEGATION_EXTENSION
1468 if (baseDir == NULL)
1469 {
1470 LogError("-storageDir option is mandatory");
1471 return 1;
1472 }
1473 else
1474 {
1475 if (static_checkStorageDirAndAccessRights(baseDir) != 0)
1476 {
1477 return 1;
1478 }
1479 }
1480 #endif /* #ifndef SUPPORT_DELEGATION_EXTENSION */
1481
1482 /*
1483 * Detach the daemon from the console
1484 */
1485
1486 #if defined(LINUX) || (defined ANDROID)
1487 {
1488 /*
1489 * Turns this application into a daemon => fork off parent process, setup logging, ...
1490 */
1491
1492 /* Our process ID and Session ID */
1493 pid_t pid, sid;
1494
1495 if (!debug)
1496 {
1497 LogInfo("tf_daemon is detaching from console... Further traces go to syslog");
1498 /* Fork off the parent process */
1499 pid = fork();
1500 if (pid < 0)
1501 {
1502 LogError("daemon forking failed");
1503 return 1;
1504 }
1505
1506 if (pid > 0)
1507 {
1508 /* parent */
1509 return 0;
1510 }
1511 bDetached = true;
1512 }
1513
1514 /* Change the file mode mask */
1515 umask(0077);
1516
1517 if (!debug)
1518 {
1519 /* Open any logs here */
1520 openlog("tf_daemon", 0, LOG_DAEMON);
1521
1522 /* Detach from the console */
1523 sid = setsid();
1524 if (sid < 0)
1525 {
1526 /* Log the failure */
1527 LogError("daemon group creation failed");
1528 return 1;
1529 }
1530 /* Close out the standard file descriptors */
1531 close(STDIN_FILENO);
1532 close(STDOUT_FILENO);
1533 close(STDERR_FILENO);
1534 }
1535 }
1536 /* Change priority so that tf_driver.ko with no polling thread is faster */
1537 if (setpriority(PRIO_PROCESS, 0, 19)!=0)
1538 {
1539 LogError("Daemon cannot change priority");
1540 return 1;
1541 }
1542
1543 #endif
1544
1545 TRACE_INFO("Sector size is %d", g_nSectorSize);
1546
1547 LogInfo("tf_daemon - started");
1548
1549 nError = TEEC_InitializeContext(NULL, /* const char * name */
1550 &sContext); /* TEEC_Context* context */
1551 if (nError != TEEC_SUCCESS)
1552 {
1553 LogError("TEEC_InitializeContext error: 0x%08X", nError);
1554 LogError("Now exiting...");
1555 exit(2);
1556 }
1557
1558 /* Open a session */
1559 if(createSession(&sContext, &sSession, &sOperation) == 0)
1560 {
1561 /* Run the session. This should never return */
1562 runSession(&sContext, &sSession, &sOperation);
1563 }
1564 TEEC_FinalizeContext(&sContext);
1565
1566 return 3;
1567 }
1568