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#ifdef ANDROID
31#include <stddef.h>
32#endif
33
34#include <stdlib.h>
35#include <string.h>
36
37#define SST_EXPORTS
38#define EXCLUDE_SERVICE_SYSTEM_SST_BASIC_TYPES
39#include "sst.h"
40
41/* Included for the TEE management */
42#include "pkcs11_internal.h"
43
44
45static TEEC_Session g_SSTSession;
46static bool g_bSSTInitialized = false;
47
48
49/* ------------------------------------------------------------------------
50            TEEC -> SST error code translation
51  ------------------------------------------------------------------------- */
52static SST_ERROR static_SSTConvertErrorCode(TEEC_Result nError)
53{
54   switch (nError)
55   {
56      case TEEC_SUCCESS:
57         return SST_SUCCESS;
58      case SST_ERROR_BAD_PARAMETERS:
59      case SST_ERROR_ACCESS_DENIED:
60      case SST_ERROR_ACCESS_CONFLICT:
61      case SST_ERROR_CORRUPTED:
62      case SST_ERROR_NO_SPACE:
63      case SST_ERROR_ITEM_NOT_FOUND:
64      case SST_ERROR_OUT_OF_MEMORY:
65      case SST_ERROR_OVERFLOW:
66         return nError;
67      default:
68         return SST_ERROR_GENERIC;
69   }
70}
71
72static TEEC_Session* static_SSTGetSession(void)
73{
74   if (g_bSSTInitialized)
75   {
76      return &g_SSTSession;
77   }
78
79   return NULL;
80}
81
82SST_ERROR SST_EXPORT_API SSTInit(void)
83{
84   TEEC_Result          nTeeError = TEEC_SUCCESS;
85   TEEC_Operation       sOperation;
86   uint8_t              nParamType3 = TEEC_NONE;
87   void*                pSignatureFile = NULL;
88   uint32_t             nSignatureFileLen = 0;
89   uint32_t             nLoginType;
90
91   stubMutexLock();
92   if (g_bSSTInitialized)
93   {
94      /* SST library already initialized */
95      nTeeError = TEEC_SUCCESS;
96      goto end;
97   }
98
99   nTeeError = stubInitializeContext();
100   if (nTeeError != TEEC_SUCCESS)
101   {
102      goto end;
103   }
104
105   /* Check if there is a signature file.
106    * If yes, send it in param3, otherwise use LOGIN_APPLICATION
107    */
108   nTeeError =  TEEC_ReadSignatureFile(&pSignatureFile, &nSignatureFileLen);
109   if (nTeeError == TEEC_ERROR_ITEM_NOT_FOUND)
110   {
111      nLoginType = TEEC_LOGIN_USER_APPLICATION;
112   }
113   else
114   {
115       if (nTeeError != TEEC_SUCCESS)
116       {
117           goto end;
118       }
119       sOperation.params[3].tmpref.buffer = pSignatureFile;
120       sOperation.params[3].tmpref.size   = nSignatureFileLen;
121       nParamType3 = TEEC_MEMREF_TEMP_INPUT;
122       nLoginType = TEEC_LOGIN_AUTHENTICATION;
123   }
124
125   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3);
126   nTeeError = TEEC_OpenSession(&g_sContext,
127                             &g_SSTSession,              /* OUT session */
128                             &SERVICE_UUID,              /* destination UUID */
129                             nLoginType,                 /* connectionMethod */
130                             NULL,                       /* connectionData */
131                             &sOperation,                /* IN OUT operation */
132                             NULL                        /* OUT returnOrigin, optional */
133                             );
134   if (nTeeError != TEEC_SUCCESS)
135   {
136      goto end_finalize_context;
137   }
138
139   g_bSSTInitialized = true;
140   stubMutexUnlock();
141   return SST_SUCCESS;
142
143end_finalize_context:
144   stubFinalizeContext();
145end:
146   stubMutexUnlock();
147   return static_SSTConvertErrorCode(nTeeError);
148}
149
150SST_ERROR SST_EXPORT_API SSTTerminate(void)
151{
152   stubMutexLock();
153   if (g_bSSTInitialized)
154   {
155      TEEC_CloseSession(&g_SSTSession);
156      stubFinalizeContext();
157      g_bSSTInitialized = false;
158   }
159   /* else if not intialized => success too */
160   stubMutexUnlock();
161   return SST_SUCCESS;
162}
163
164
165/* ------------------------------------------------------------------------
166                           Other API Functions
167------------------------------------------------------------------------- */
168
169
170/* Check that the input filename is well-formed */
171static SST_ERROR static_SSTCheckFileName(const char* pName)
172{
173   uint32_t i;
174   char     c;
175
176   if (pName == NULL)
177   {
178      return SST_ERROR_BAD_PARAMETERS;
179   }
180
181   for (i = 0; i <= SST_MAX_FILENAME; i++)
182   {
183      c = pName[i];
184      if (c == 0)
185      {
186         /* End of the string */
187         return SST_SUCCESS;
188      }
189
190      if (c == '/' || c == '\\')
191      {
192         /* Invalid character */
193         return SST_ERROR_BAD_PARAMETERS;
194      }
195
196      if (c < 0x20 || c >= 0x7F)
197      {
198         /* Filename contains illegal characters */
199         return SST_ERROR_BAD_PARAMETERS;
200      }
201   }
202   /* Filename is too long. Zero terminator not found */
203   return SST_ERROR_BAD_PARAMETERS;
204}
205
206static SST_ERROR static_SSTCheckPattern(
207      const char* pFilenamePattern)
208{
209   uint32_t i;
210   if(pFilenamePattern == NULL)
211   {
212      return S_SUCCESS;
213   }
214
215   /**
216    * Check Forbidden characters.
217    */
218   for (i = 0; pFilenamePattern[i] != 0; i++)
219   {
220      if(pFilenamePattern[i] < 0x20 )
221      {
222         return S_ERROR_BAD_PARAMETERS;
223      }
224      else if(pFilenamePattern[i] == 0x2F ) /* '/' */
225      {
226         return S_ERROR_BAD_PARAMETERS;
227      }
228      else if(pFilenamePattern[i] == 0x5C ) /* '\' */
229      {
230         /**
231          * Must be directly followed by asterisk character or question-mark
232          * character.
233          */
234         if (! ((pFilenamePattern[i+1] == '*' ||
235                   pFilenamePattern[i+1] == '?')))
236         {
237            return S_ERROR_BAD_PARAMETERS;
238         }
239      }
240      else if(pFilenamePattern[i] >= 0x7F )
241      {
242         return S_ERROR_BAD_PARAMETERS;
243      }
244   }
245
246   return S_SUCCESS;
247}
248
249
250
251SST_ERROR SST_EXPORT_API SSTOpen(const char* pFilename,
252                                 uint32_t    nFlags,
253                                 uint32_t    nReserved,
254                                 SST_HANDLE* phFile)
255{
256   TEEC_Session*     pSession;
257   TEEC_Result       nError;
258   TEEC_Operation    sOperation;
259   uint32_t          nReturnOrigin;
260   SST_ERROR         nErrorCode = SST_SUCCESS;
261
262   if (phFile == NULL || nReserved != 0)
263   {
264      return SST_ERROR_BAD_PARAMETERS;
265   }
266
267   *phFile = SST_HANDLE_INVALID;
268
269   nErrorCode = static_SSTCheckFileName(pFilename);
270   if (nErrorCode != SST_SUCCESS)
271   {
272      return nErrorCode;
273   }
274
275   pSession = static_SSTGetSession();
276   if (pSession == NULL)
277   {
278      return SST_ERROR_GENERIC;
279   }
280
281   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
282   sOperation.params[0].value.a = 1;      /* Private storage */
283   sOperation.params[0].value.b = nFlags; /* Access flags */
284   sOperation.params[1].tmpref.buffer = (void*)pFilename;
285   sOperation.params[1].tmpref.size   = strlen(pFilename);
286   nError = TEEC_InvokeCommand(pSession,
287                               SERVICE_SYSTEM_SST_OPEN_COMMAND_ID,   /* commandID */
288                               &sOperation,                 /* IN OUT operation */
289                               &nReturnOrigin               /* OUT returnOrigin, optional */
290                              );
291   if (nError == TEEC_SUCCESS)
292   {
293      *phFile = (SST_HANDLE)sOperation.params[0].value.a;
294   }
295
296   return static_SSTConvertErrorCode(nError);
297}
298
299SST_ERROR SST_EXPORT_API SSTCloseHandle(SST_HANDLE  hFile)
300{
301   TEEC_Session*     pSession;
302   TEEC_Result        nError;
303   TEEC_Operation    sOperation;
304   uint32_t          nReturnOrigin;
305
306   if (hFile == S_HANDLE_NULL)
307   {
308      return SST_SUCCESS;
309   }
310
311   pSession = static_SSTGetSession();
312   if (pSession == NULL)
313   {
314      return SST_ERROR_GENERIC;
315   }
316
317   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
318   sOperation.params[0].value.a = hFile;
319   nError = TEEC_InvokeCommand(pSession,
320                               SERVICE_SYSTEM_SST_CLOSE_COMMAND_ID, /* commandID */
321                               &sOperation,                  /* IN OUT operation */
322                               &nReturnOrigin            /* OUT returnOrigin, optional */
323                              );
324
325   return static_SSTConvertErrorCode(nError);
326}
327
328SST_ERROR SST_EXPORT_API SSTWrite(SST_HANDLE       hFile,
329                                  const uint8_t*   pBuffer,
330                                  uint32_t         nSize)
331{
332   TEEC_Session*     pSession;
333   TEEC_Result       nError;
334   TEEC_Operation    sOperation;
335   uint32_t          nReturnOrigin;
336
337   if (pBuffer == NULL)
338   {
339      return SST_ERROR_BAD_PARAMETERS;
340   }
341
342   if (nSize == 0)
343   {
344      return SST_SUCCESS;
345   }
346
347   pSession = static_SSTGetSession();
348   if (pSession == NULL)
349   {
350      return SST_ERROR_GENERIC;
351   }
352
353   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
354   sOperation.params[0].value.a       = hFile;
355   sOperation.params[1].tmpref.buffer = (void*)pBuffer;
356   sOperation.params[1].tmpref.size   = nSize;
357
358   nError = TEEC_InvokeCommand(pSession,
359                               SERVICE_SYSTEM_SST_WRITE_COMMAND_ID, /* commandID */
360                               &sOperation,                  /* IN OUT operation */
361                               &nReturnOrigin            /* OUT returnOrigin, optional */
362                              );
363
364   return static_SSTConvertErrorCode(nError);
365}
366
367
368SST_ERROR SST_EXPORT_API SSTRead(SST_HANDLE   hFile,
369                                 uint8_t*     pBuffer,
370                                 uint32_t     nSize,
371                                 uint32_t*    pnCount)
372{
373   TEEC_Session*     pSession;
374   TEEC_Result       nError;
375   TEEC_Operation    sOperation;
376   uint32_t          nReturnOrigin;
377
378   if ((pBuffer == NULL) || (pnCount == NULL))
379   {
380      return SST_ERROR_BAD_PARAMETERS;
381   }
382   *pnCount = 0;
383
384   pSession = static_SSTGetSession();
385   if (pSession == NULL)
386   {
387      return SST_ERROR_GENERIC;
388   }
389
390   if (nSize == 0)
391   {
392      return SST_SUCCESS;
393   }
394
395   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
396   sOperation.params[0].value.a       = hFile;
397   sOperation.params[1].tmpref.buffer = pBuffer;
398   sOperation.params[1].tmpref.size   = nSize;
399
400   nError = TEEC_InvokeCommand(pSession,
401                               SERVICE_SYSTEM_SST_READ_COMMAND_ID, /* commandID */
402                               &sOperation,                  /* IN OUT operation */
403                               &nReturnOrigin            /* OUT returnOrigin, optional */
404                              );
405
406   *pnCount = sOperation.params[1].tmpref.size; /* The returned buffer size */
407   return static_SSTConvertErrorCode(nError);
408}
409
410SST_ERROR SST_EXPORT_API SSTSeek(SST_HANDLE   hFile,
411                                 int32_t     nOffset,
412                                 SST_WHENCE   whence)
413{
414   TEEC_Session*     pSession;
415   TEEC_Result       nError;
416   TEEC_Operation    sOperation;
417   uint32_t          nReturnOrigin;
418
419   switch(whence)
420   {
421   case SST_SEEK_SET:
422   case SST_SEEK_CUR:
423   case SST_SEEK_END:
424      break;
425   default:
426      return SST_ERROR_BAD_PARAMETERS;
427   }
428
429   pSession = static_SSTGetSession();
430   if (pSession == NULL)
431   {
432      return SST_ERROR_GENERIC;
433   }
434
435   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE);
436   sOperation.params[0].value.a = hFile;
437   sOperation.params[1].value.a = nOffset;
438   sOperation.params[1].value.b = (uint32_t)whence;
439
440   nError = TEEC_InvokeCommand(pSession,
441                               SERVICE_SYSTEM_SST_SEEK_COMMAND_ID, /* commandID */
442                               &sOperation,                  /* IN OUT operation */
443                               &nReturnOrigin            /* OUT returnOrigin, optional */
444                              );
445   return static_SSTConvertErrorCode(nError);
446
447}
448
449static SST_ERROR SSTGetOffsetAndSize(SST_HANDLE   hFile, uint32_t* pnOffset, uint32_t* pnSize)
450{
451   TEEC_Session*     pSession;
452   TEEC_Result       nError;
453   TEEC_Operation    sOperation;
454   uint32_t          nReturnOrigin;
455
456   pSession = static_SSTGetSession();
457   if (pSession == NULL)
458   {
459      return SST_ERROR_GENERIC;
460   }
461
462   if (pnOffset == NULL)
463   {
464      return SST_ERROR_BAD_PARAMETERS;
465   }
466
467   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
468   sOperation.params[0].value.a = (uint32_t)hFile;
469
470   nError = TEEC_InvokeCommand(pSession,
471                               SERVICE_SYSTEM_SST_GET_OFFSET_AND_SIZE_COMMAND_ID, /* commandID */
472                               &sOperation,                  /* IN OUT operation */
473                               &nReturnOrigin            /* OUT returnOrigin, optional */
474                              );
475
476   if (pnOffset != NULL)
477   {
478      *pnOffset = sOperation.params[0].value.a;
479   }
480   if (pnSize != NULL)
481   {
482      *pnSize = sOperation.params[0].value.b;
483   }
484   return static_SSTConvertErrorCode(nError);
485
486}
487
488SST_ERROR SST_EXPORT_API SSTTell(SST_HANDLE   hFile,
489                                 uint32_t*    pnPos)
490{
491   return SSTGetOffsetAndSize(hFile, pnPos, NULL);
492}
493
494SST_ERROR SST_EXPORT_API SSTGetSize(const char*  pFilename,
495                                    uint32_t*    pnSize)
496{
497   TEEC_Session*     pSession;
498   TEEC_Result       nError;
499   TEEC_Operation    sOperation;
500   uint32_t          nReturnOrigin;
501
502   if ((pFilename == NULL) || (pnSize == NULL))
503   {
504      return SST_ERROR_BAD_PARAMETERS;
505   }
506
507   nError = static_SSTCheckFileName(pFilename);
508   if (nError != SST_SUCCESS)
509   {
510      return nError;
511   }
512
513   pSession = static_SSTGetSession();
514   if (pSession == NULL)
515   {
516      return SST_ERROR_GENERIC;
517   }
518
519   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
520   sOperation.params[0].value.a = 1; /* private storage */
521   sOperation.params[0].value.b = 0;
522   sOperation.params[1].tmpref.buffer = (void*)pFilename;
523   sOperation.params[1].tmpref.size   = strlen(pFilename);
524
525   nError = TEEC_InvokeCommand(pSession,
526                               SERVICE_SYSTEM_SST_GET_SIZE_COMMAND_ID, /* commandID */
527                               &sOperation,                  /* IN OUT operation */
528                               &nReturnOrigin            /* OUT returnOrigin, optional */
529                              );
530
531   *pnSize = sOperation.params[0].value.a;
532   return static_SSTConvertErrorCode(nError);
533}
534
535
536SST_ERROR SST_EXPORT_API SSTEof( SST_HANDLE   hFile,
537                                 bool*        pbEof)
538{
539   uint32_t nOffset;
540   uint32_t nSize;
541   SST_ERROR nError;
542   if (pbEof == NULL)
543      return SST_ERROR_BAD_PARAMETERS;
544   nError = SSTGetOffsetAndSize(hFile, &nOffset, &nSize);
545   if (nError == SST_SUCCESS)
546   {
547      if (nOffset >= nSize)
548      {
549         *pbEof = true;
550      }
551      else
552      {
553         *pbEof = false;
554      }
555   }
556   return nError;
557}
558
559SST_ERROR SST_EXPORT_API SSTCloseAndDelete(SST_HANDLE  hFile)
560{
561   TEEC_Session*     pSession;
562   TEEC_Result       nError;
563   TEEC_Operation    sOperation;
564   uint32_t          nReturnOrigin;
565
566   pSession = static_SSTGetSession();
567   if (pSession == NULL)
568   {
569      return SST_ERROR_GENERIC;
570   }
571
572   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
573   sOperation.params[0].value.a = hFile;
574
575   nError = TEEC_InvokeCommand(pSession,
576                               SERVICE_SYSTEM_SST_CLOSE_DELETE_COMMAND_ID, /* commandID */
577                               &sOperation,                  /* IN OUT operation */
578                               &nReturnOrigin            /* OUT returnOrigin, optional */
579                              );
580   return static_SSTConvertErrorCode(nError);
581}
582
583SST_ERROR SST_EXPORT_API SSTTruncate(SST_HANDLE hFile, uint32_t nLength)
584{
585   TEEC_Session*     pSession;
586   TEEC_Result       nError;
587   TEEC_Operation    sOperation;
588   uint32_t          nReturnOrigin;
589
590   pSession = static_SSTGetSession();
591   if (pSession == NULL)
592   {
593      return SST_ERROR_GENERIC;
594   }
595
596   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
597   sOperation.params[0].value.a = hFile;
598   sOperation.params[0].value.b = nLength;
599
600   nError = TEEC_InvokeCommand(pSession,
601                               SERVICE_SYSTEM_SST_TRUNCATE_COMMAND_ID, /* commandID */
602                               &sOperation,                  /* IN OUT operation */
603                               &nReturnOrigin            /* OUT returnOrigin, optional */
604                              );
605   return static_SSTConvertErrorCode(nError);
606}
607
608SST_ERROR SST_EXPORT_API SSTRename(SST_HANDLE hFile,
609                                   const char* pNewFilename)
610{
611   TEEC_Session*     pSession;
612   TEEC_Result       nError;
613   TEEC_Operation    sOperation;
614   uint32_t          nReturnOrigin;
615
616   pSession = static_SSTGetSession();
617   if (pSession == NULL)
618   {
619      return SST_ERROR_GENERIC;
620   }
621
622   if (pNewFilename == NULL)
623   {
624      return SST_ERROR_BAD_PARAMETERS;
625   }
626
627   nError = static_SSTCheckFileName(pNewFilename);
628   if (nError != SST_SUCCESS)
629   {
630      return nError;
631   }
632
633   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
634   sOperation.params[0].value.a = hFile;
635   sOperation.params[1].tmpref.buffer = (void*)pNewFilename;
636   sOperation.params[1].tmpref.size   = strlen(pNewFilename);
637
638   nError = TEEC_InvokeCommand(pSession,
639                               SERVICE_SYSTEM_SST_RENAME_COMMAND_ID, /* commandID */
640                               &sOperation,                  /* IN OUT operation */
641                               &nReturnOrigin            /* OUT returnOrigin, optional */
642                              );
643      return static_SSTConvertErrorCode(nError);
644}
645
646SST_ERROR SST_EXPORT_API SSTEnumerationStart(const char* pFilenamePattern,
647                                             uint32_t  nReserved1,
648                                             uint32_t  nReserved2,
649                                             SST_HANDLE* phFileEnumeration)
650{
651   TEEC_Session*     pSession;
652   TEEC_Result       nError;
653   TEEC_Operation    sOperation;
654   uint32_t          nReturnOrigin;
655
656   if (nReserved1!=0 || nReserved2!=0)
657   {
658      return SST_ERROR_BAD_PARAMETERS;
659   }
660   if (phFileEnumeration==NULL)
661   {
662      return SST_ERROR_BAD_PARAMETERS;
663   }
664   *phFileEnumeration = SST_HANDLE_INVALID;
665
666   nError = static_SSTCheckPattern(pFilenamePattern);
667   if (nError != SST_SUCCESS)
668   {
669      return nError;
670   }
671
672   pSession = static_SSTGetSession();
673   if (pSession == NULL)
674   {
675      return SST_ERROR_GENERIC;
676   }
677
678   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
679   sOperation.params[0].value.a = 1;      /* Private storage */
680   sOperation.params[1].tmpref.buffer = (void*)pFilenamePattern;
681   if (pFilenamePattern != NULL)
682   {
683      sOperation.params[1].tmpref.size   = strlen(pFilenamePattern);
684   }
685   else
686   {
687      sOperation.params[1].tmpref.size   = 0;
688   }
689
690   nError = TEEC_InvokeCommand(pSession,
691                               SERVICE_SYSTEM_SST_ENUM_START_COMMAND_ID, /* commandID */
692                               &sOperation,                  /* IN OUT operation */
693                               &nReturnOrigin            /* OUT returnOrigin, optional */
694                              );
695
696   *phFileEnumeration = (SST_HANDLE)sOperation.params[0].value.a;
697   return static_SSTConvertErrorCode(nError);
698}
699
700SST_ERROR SST_EXPORT_API SSTEnumerationCloseHandle(SST_HANDLE hFileEnumeration)
701{
702   TEEC_Session*     pSession;
703   TEEC_Result       nError;
704   TEEC_Operation    sOperation;
705   uint32_t          nReturnOrigin;
706
707   pSession = static_SSTGetSession();
708   if (pSession == NULL)
709   {
710      return SST_ERROR_GENERIC;
711   }
712
713   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
714   sOperation.params[0].value.a = hFileEnumeration;
715
716   nError = TEEC_InvokeCommand(pSession,
717                               SERVICE_SYSTEM_SST_ENUM_CLOSE_COMMAND_ID, /* commandID */
718                               &sOperation,                  /* IN OUT operation */
719                               &nReturnOrigin                /* OUT returnOrigin, optional */
720                              );
721
722   return static_SSTConvertErrorCode(nError);
723}
724
725SST_ERROR SST_EXPORT_API SSTEnumerationGetNext(SST_HANDLE      hFileEnumeration,
726                                               SST_FILE_INFO**   ppFileInfo)
727
728{
729   TEEC_Session*     pSession;
730   TEEC_Result       nError;
731   TEEC_Operation    sOperation;
732   uint32_t          nReturnOrigin;
733   SST_FILE_INFO*    pInfo = NULL;
734   char              sFilename[SST_MAX_FILENAME];
735
736   if (ppFileInfo==NULL)
737   {
738      return SST_ERROR_BAD_PARAMETERS;
739   }
740
741   pSession = static_SSTGetSession();
742   if (pSession == NULL)
743   {
744      return SST_ERROR_GENERIC;
745   }
746
747   sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
748   sOperation.params[0].value.a = hFileEnumeration;
749   sOperation.params[1].tmpref.buffer = sFilename;
750   sOperation.params[1].tmpref.size   = SST_MAX_FILENAME;
751
752   nError = TEEC_InvokeCommand(pSession,
753                               SERVICE_SYSTEM_SST_ENUM_GETNEXT_COMMAND_ID, /* commandID */
754                               &sOperation,                  /* IN OUT operation */
755                               &nReturnOrigin            /* OUT returnOrigin, optional */
756                              );
757
758   if (nError == TEEC_SUCCESS)
759   {
760      if (sOperation.params[1].tmpref.size <= SST_MAX_FILENAME)
761      {
762         pInfo = (SST_FILE_INFO*)malloc(sizeof(SST_FILE_INFO));
763         if (pInfo == NULL)
764         {
765            return SST_ERROR_OUT_OF_MEMORY;
766         }
767         pInfo->pName = (char*)malloc(sOperation.params[1].tmpref.size+1);
768         if (pInfo->pName == NULL)
769         {
770            free(pInfo);
771            return SST_ERROR_OUT_OF_MEMORY;
772         }
773         memcpy(pInfo->pName, sFilename, sOperation.params[1].tmpref.size);
774         /* Add zero terminator */
775         pInfo->pName[sOperation.params[1].tmpref.size] = 0;
776         pInfo->nSize = sOperation.params[0].value.b;
777      }
778   }
779  *ppFileInfo = pInfo;
780   return static_SSTConvertErrorCode(nError);
781 }
782
783SST_ERROR SST_EXPORT_API SSTDestroyFileInfo(SST_FILE_INFO*   pFileInfo)
784{
785   TEEC_Session*  pSession;
786
787   pSession = static_SSTGetSession();
788   if (pSession == NULL)
789   {
790      return SST_ERROR_GENERIC;
791   }
792
793   if (pFileInfo != NULL)
794   {
795      free(pFileInfo->pName);
796      free(pFileInfo);
797   }
798   return SST_SUCCESS;
799}
800