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