summaryrefslogtreecommitdiff
path: root/security/tf_crypto_sst
diff options
context:
space:
mode:
Diffstat (limited to 'security/tf_crypto_sst')
-rw-r--r--security/tf_crypto_sst/Android.mk32
-rw-r--r--security/tf_crypto_sst/lib_mutex.h97
-rw-r--r--security/tf_crypto_sst/lib_mutex_linux.c56
-rw-r--r--security/tf_crypto_sst/lib_object.c418
-rw-r--r--security/tf_crypto_sst/lib_object.h348
-rw-r--r--security/tf_crypto_sst/mtc.c274
-rw-r--r--security/tf_crypto_sst/pkcs11_global.c275
-rw-r--r--security/tf_crypto_sst/pkcs11_internal.h137
-rw-r--r--security/tf_crypto_sst/pkcs11_object.c1637
-rw-r--r--security/tf_crypto_sst/pkcs11_session.c420
-rw-r--r--security/tf_crypto_sst/service_system_protocol.h116
-rw-r--r--security/tf_crypto_sst/sst_stub.c800
12 files changed, 4610 insertions, 0 deletions
diff --git a/security/tf_crypto_sst/Android.mk b/security/tf_crypto_sst/Android.mk
new file mode 100644
index 00000000..6d3a9d8c
--- /dev/null
+++ b/security/tf_crypto_sst/Android.mk
@@ -0,0 +1,32 @@
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES := \
+ lib_object.c \
+ lib_mutex_linux.c \
+ sst_stub.c \
+ mtc.c \
+ pkcs11_global.c \
+ pkcs11_object.c \
+ pkcs11_session.c
+
+LOCAL_CFLAGS += -DLINUX
+LOCAL_CFLAGS += -D__ANDROID32__
+
+ifdef S_VERSION_BUILD
+LOCAL_CFLAGS += -DS_VERSION_BUILD=$(S_VERSION_BUILD)
+endif
+
+LOCAL_CFLAGS += -I $(LOCAL_PATH)/../tf_sdk/include/
+
+LOCAL_MODULE:= libtf_crypto_sst
+LOCAL_STATIC_LIBRARIES := libtee_client_api_driver
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/security/tf_crypto_sst/lib_mutex.h b/security/tf_crypto_sst/lib_mutex.h
new file mode 100644
index 00000000..6f4bed1b
--- /dev/null
+++ b/security/tf_crypto_sst/lib_mutex.h
@@ -0,0 +1,97 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LIB_MUTEX_H__
+#define __LIB_MUTEX_H__
+
+/**
+ * This libray defines a type of simple non-recursive mutex that can
+ * be statically initialized. The interface is very similar to pthread
+ * mutexes.
+ **/
+
+#ifdef WIN32
+
+#include <windows.h>
+#include "s_type.h"
+
+/* Windows API: use a critical section with a state describing
+ whether it has been initialized or not or is being initialized.
+ We use interlocked operations on the state to synchronize between
+ multiple threads competing to initialize the critical section */
+typedef struct
+{
+ volatile uint32_t nInitState;
+ CRITICAL_SECTION sCriticalSection;
+}
+LIB_MUTEX;
+
+#define LIB_MUTEX_WIN32_STATE_UNINITIALIZED 0
+#define LIB_MUTEX_WIN32_STATE_INITIALIZING 1
+#define LIB_MUTEX_WIN32_STATE_INITIALIZED 2
+
+#define LIB_MUTEX_INITIALIZER { 0 }
+
+#endif /* WIN32 */
+
+#ifdef LINUX
+
+#include <pthread.h>
+#include "s_type.h"
+
+/* Linux: directly use a pthread mutex. */
+typedef pthread_mutex_t LIB_MUTEX;
+#define LIB_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#endif /* LINUX */
+
+/**
+ * Initialize a mutex. Note that thie function cannot fail. If there
+ * is not enough resource to initialize the mutex, the implementation
+ * resort to active-wait
+ **/
+void libMutexInit(LIB_MUTEX* pMutex);
+
+/**
+ * Lock the mutex
+ */
+void libMutexLock(LIB_MUTEX* pMutex);
+
+/**
+ * Unlock the mutex
+ */
+void libMutexUnlock(LIB_MUTEX* pMutex);
+
+/**
+ * Destroy the mutex
+ */
+void libMutexDestroy(LIB_MUTEX* pMutex);
+
+#endif /* __LIB_MUTEX_H__ */
diff --git a/security/tf_crypto_sst/lib_mutex_linux.c b/security/tf_crypto_sst/lib_mutex_linux.c
new file mode 100644
index 00000000..da8c9e00
--- /dev/null
+++ b/security/tf_crypto_sst/lib_mutex_linux.c
@@ -0,0 +1,56 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Implementation of the mutex library over the Linux API
+ **/
+#include <pthread.h>
+#include "lib_mutex.h"
+
+void libMutexInit(LIB_MUTEX* pMutex)
+{
+ pthread_mutex_init(pMutex, NULL);
+ /* Error ignored. Is that OK? */
+}
+
+void libMutexLock(LIB_MUTEX* pMutex)
+{
+ pthread_mutex_lock(pMutex);
+}
+
+void libMutexUnlock(LIB_MUTEX* pMutex)
+{
+ pthread_mutex_unlock(pMutex);
+}
+
+void libMutexDestroy(LIB_MUTEX* pMutex)
+{
+ pthread_mutex_destroy(pMutex);
+}
diff --git a/security/tf_crypto_sst/lib_object.c b/security/tf_crypto_sst/lib_object.c
new file mode 100644
index 00000000..a07a66f2
--- /dev/null
+++ b/security/tf_crypto_sst/lib_object.c
@@ -0,0 +1,418 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** Simple implementation of lib_object using doubly-linked lists. This
+ implementation should outperform more sophisticated data structures
+ like blanced binary trees when the tables have fewer than 10 to 20
+ elements. */
+
+#include <string.h>
+#include "s_type.h"
+
+#include "lib_object.h"
+
+/* Generic node */
+typedef struct LIB_OBJECT_NODE
+{
+ struct LIB_OBJECT_NODE* pPrevious;
+ struct LIB_OBJECT_NODE* pNext;
+ union
+ {
+ uint16_t nHandle;
+
+ S_STORAGE_NAME sStorageName;
+
+ struct
+ {
+ /* Public fields */
+ uint8_t sFilename[64];
+ uint8_t nFilenameLength;
+ }
+ f;
+ }
+ key;
+}
+LIB_OBJECT_NODE;
+
+typedef enum
+{
+ LIB_OBJECT_NODE_TYPE_HANDLE16,
+ LIB_OBJECT_NODE_TYPE_STORAGE_NAME,
+ LIB_OBJECT_NODE_TYPE_FILENAME,
+ LIB_OBJECT_NODE_TYPE_UNINDEXED
+}
+LIB_OBJECT_NODE_TYPE;
+
+/* -----------------------------------------------------------------------
+ Search functions
+ -----------------------------------------------------------------------*/
+static bool libObjectKeyEqualNode(
+ LIB_OBJECT_NODE* pNode,
+ uint32_t nKey1,
+ void* pKey2,
+ LIB_OBJECT_NODE_TYPE eNodeType)
+{
+ switch (eNodeType)
+ {
+ default:
+ case LIB_OBJECT_NODE_TYPE_HANDLE16:
+ return
+ nKey1 == pNode->key.nHandle;
+ case LIB_OBJECT_NODE_TYPE_STORAGE_NAME:
+ return
+ memcmp(
+ (S_STORAGE_NAME*)pKey2,
+ &pNode->key.sStorageName,
+ sizeof(S_STORAGE_NAME)) == 0;
+ case LIB_OBJECT_NODE_TYPE_FILENAME:
+ {
+ uint32_t nLength1 = nKey1;
+ uint32_t nLength2 = pNode->key.f.nFilenameLength;
+ return
+ nLength1 == nLength2
+ &&
+ memcmp(
+ pKey2,
+ &pNode->key.f.sFilename,
+ nLength1) == 0;
+ }
+ }
+}
+
+/* Polymorphic search function */
+static LIB_OBJECT_NODE* libObjectSearch(
+ LIB_OBJECT_NODE* pRoot,
+ uint32_t nKey1,
+ void* pKey2,
+ LIB_OBJECT_NODE_TYPE eNodeType)
+{
+ if (pRoot != NULL)
+ {
+ LIB_OBJECT_NODE* pNode = pRoot;
+ do
+ {
+ if (libObjectKeyEqualNode(pNode, nKey1, pKey2, eNodeType))
+ {
+ /* Match found */
+ return pNode;
+ }
+ pNode = pNode->pNext;
+ }
+ while (pNode != pRoot);
+ }
+ return NULL;
+}
+
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16Search(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ uint32_t nHandle)
+{
+ return (LIB_OBJECT_NODE_HANDLE16*)libObjectSearch(
+ (LIB_OBJECT_NODE*)pTable->pRoot, nHandle, NULL, LIB_OBJECT_NODE_TYPE_HANDLE16);
+}
+
+
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameSearch(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ S_STORAGE_NAME* pStorageName)
+{
+ return (LIB_OBJECT_NODE_STORAGE_NAME*)libObjectSearch(
+ (LIB_OBJECT_NODE*)pTable->pRoot, 0, pStorageName, LIB_OBJECT_NODE_TYPE_STORAGE_NAME);
+}
+
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameSearch(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ uint8_t* pFilename,
+ uint32_t nFilenameLength)
+{
+ return (LIB_OBJECT_NODE_FILENAME*)libObjectSearch(
+ (LIB_OBJECT_NODE*)pTable->pRoot, nFilenameLength, pFilename, LIB_OBJECT_NODE_TYPE_FILENAME);
+}
+
+/* -----------------------------------------------------------------------
+ Add functions
+ -----------------------------------------------------------------------*/
+
+/* Polymorphic add function. Add the node at the end of the linked list */
+static bool libObjectAdd(
+ LIB_OBJECT_NODE** ppRoot,
+ LIB_OBJECT_NODE* pNew,
+ LIB_OBJECT_NODE_TYPE eNodeType)
+{
+ LIB_OBJECT_NODE* pRoot;
+ LIB_OBJECT_NODE* pLast;
+ if (*ppRoot == NULL)
+ {
+ *ppRoot = pNew;
+ pNew->pNext = pNew;
+ pNew->pPrevious = pNew;
+ if (eNodeType == LIB_OBJECT_NODE_TYPE_HANDLE16)
+ {
+ pNew->key.nHandle = 1;
+ }
+ return true;
+ }
+ else
+ {
+ pRoot = *ppRoot;
+ pLast = pRoot->pPrevious;
+ if (eNodeType == LIB_OBJECT_NODE_TYPE_HANDLE16)
+ {
+ if (pLast->key.nHandle == LIB_OBJECT_HANDLE16_MAX)
+ {
+ /* We cannot just assign last handle + 1 because it will
+ overflow. So, scan the whole list */
+ goto scan_list;
+ }
+ pNew->key.nHandle = pLast->key.nHandle + 1;
+ }
+ pLast->pNext = pNew;
+ pNew->pPrevious = pLast;
+ pNew->pNext = pRoot;
+ pRoot->pPrevious = pNew;
+ return true;
+ }
+scan_list:
+ {
+ LIB_OBJECT_NODE* pNode = pRoot;
+ uint32_t nFreeHandle = 1;
+ do
+ {
+ if (pNode->key.nHandle > nFreeHandle)
+ {
+ /* nMaxHandle+1 is not allocated. Insert pNew just before pNode */
+ pNew->key.nHandle = nFreeHandle;
+ pNew->pNext = pNode;
+ pNew->pPrevious = pNode->pPrevious;
+ pNode->pPrevious->pNext = pNew;
+ pNode->pPrevious = pNew;
+ if (pNode == pRoot)
+ {
+ /* Special case, pNew is the new root */
+ *ppRoot = pNew;
+ }
+ return true;
+ }
+ pNode = pNode->pNext;
+ nFreeHandle++;
+ }
+ while (pNode != pRoot);
+ /* No free handle */
+ return false;
+ }
+}
+
+bool libObjectHandle16Add(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject)
+{
+ return libObjectAdd(
+ (LIB_OBJECT_NODE**)&pTable->pRoot,
+ (LIB_OBJECT_NODE*)pObject,
+ LIB_OBJECT_NODE_TYPE_HANDLE16);
+}
+
+
+void libObjectStorageNameAdd(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject)
+{
+ libObjectAdd(
+ (LIB_OBJECT_NODE**)&pTable->pRoot,
+ (LIB_OBJECT_NODE*)pObject,
+ LIB_OBJECT_NODE_TYPE_STORAGE_NAME);
+}
+
+
+void libObjectFilenameAdd(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject)
+{
+ libObjectAdd(
+ (LIB_OBJECT_NODE**)&pTable->pRoot,
+ (LIB_OBJECT_NODE*)pObject,
+ LIB_OBJECT_NODE_TYPE_FILENAME);
+}
+
+
+void libObjectUnindexedAdd(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject)
+{
+ libObjectAdd(
+ (LIB_OBJECT_NODE**)&pTable->pRoot,
+ (LIB_OBJECT_NODE*)pObject,
+ LIB_OBJECT_NODE_TYPE_UNINDEXED);
+}
+
+
+/* -----------------------------------------------------------------------
+ Remove functions
+ -----------------------------------------------------------------------*/
+static void libObjectRemove(LIB_OBJECT_NODE** ppRoot, LIB_OBJECT_NODE* pObject)
+{
+ LIB_OBJECT_NODE* pPrevious = pObject->pPrevious;
+ LIB_OBJECT_NODE* pNext = pObject->pNext;
+
+ pPrevious->pNext = pNext;
+ pNext->pPrevious = pPrevious;
+
+ if (pPrevious == pObject)
+ {
+ /* Removed the last object in the table */
+ *ppRoot = NULL;
+ }
+ else if (pObject == *ppRoot)
+ {
+ /* Removed the first object in the list */
+ *ppRoot = pNext;
+ }
+}
+
+static LIB_OBJECT_NODE* libObjectRemoveOne(LIB_OBJECT_NODE** ppRoot)
+{
+ if (*ppRoot == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ LIB_OBJECT_NODE* pObject = *ppRoot;
+ libObjectRemove(ppRoot, pObject);
+ return pObject;
+ }
+}
+
+void libObjectHandle16Remove(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject)
+{
+ libObjectRemove((LIB_OBJECT_NODE**)&pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+ pObject->nHandle = 0;
+}
+
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16RemoveOne(
+ LIB_OBJECT_TABLE_HANDLE16* pTable)
+{
+ LIB_OBJECT_NODE_HANDLE16* pObject = (LIB_OBJECT_NODE_HANDLE16*)libObjectRemoveOne((LIB_OBJECT_NODE**)&pTable->pRoot);
+ if (pObject != NULL)
+ {
+ pObject->nHandle = 0;
+ }
+ return pObject;
+}
+
+void libObjectStorageNameRemove(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject)
+{
+ libObjectRemove((LIB_OBJECT_NODE**)&pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameRemoveOne(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable)
+{
+ return (LIB_OBJECT_NODE_STORAGE_NAME*)libObjectRemoveOne((LIB_OBJECT_NODE**)&pTable->pRoot);
+}
+
+void libObjectFilenameRemove(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject)
+{
+ libObjectRemove((LIB_OBJECT_NODE**)&pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameRemoveOne(
+ LIB_OBJECT_TABLE_FILENAME* pTable)
+{
+ return (LIB_OBJECT_NODE_FILENAME*)libObjectRemoveOne((LIB_OBJECT_NODE**)&pTable->pRoot);
+}
+
+void libObjectUnindexedRemove(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject)
+{
+ libObjectRemove((LIB_OBJECT_NODE**)&pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_UNINDEXED* libObjectUnindexedRemoveOne(LIB_OBJECT_TABLE_UNINDEXED* pTable)
+{
+ return (LIB_OBJECT_NODE_UNINDEXED*)libObjectRemoveOne((LIB_OBJECT_NODE**)&pTable->pRoot);
+}
+
+
+/* -----------------------------------------------------------------------
+ Get-next functions
+ -----------------------------------------------------------------------*/
+
+static LIB_OBJECT_NODE* libObjectNext(LIB_OBJECT_NODE* pRoot, LIB_OBJECT_NODE* pObject)
+{
+ if (pObject == NULL)
+ {
+ return pRoot;
+ }
+ else if (pObject == pRoot->pPrevious)
+ {
+ return NULL;
+ }
+ else
+ {
+ return pObject->pNext;
+ }
+}
+
+
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16Next(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject)
+{
+ return (LIB_OBJECT_NODE_HANDLE16*)libObjectNext((LIB_OBJECT_NODE*)pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameNext(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject)
+{
+ return (LIB_OBJECT_NODE_STORAGE_NAME*)libObjectNext((LIB_OBJECT_NODE*)pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameNext(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject)
+{
+ return (LIB_OBJECT_NODE_FILENAME*)libObjectNext((LIB_OBJECT_NODE*)pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
+
+LIB_OBJECT_NODE_UNINDEXED* libObjectUnindexedNext(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject)
+{
+ return (LIB_OBJECT_NODE_UNINDEXED*)libObjectNext((LIB_OBJECT_NODE*)pTable->pRoot, (LIB_OBJECT_NODE*)pObject);
+}
diff --git a/security/tf_crypto_sst/lib_object.h b/security/tf_crypto_sst/lib_object.h
new file mode 100644
index 00000000..5abb8346
--- /dev/null
+++ b/security/tf_crypto_sst/lib_object.h
@@ -0,0 +1,348 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LIB_OBJECT_H__
+#define __LIB_OBJECT_H__
+
+#include "s_type.h"
+
+typedef struct
+{
+ /* Type of storage: See S_STORAGE_TYPE_XXX */
+ uint32_t nStorageType;
+
+ /* Login type of the client: See S_LOGIN_XXX */
+ uint32_t nLoginType;
+
+ /* Identifier of the client (secure or non-secure client) */
+ S_UUID sClientUUID;
+}
+S_STORAGE_NAME;
+
+
+/**
+ * This library defines three types of objects and keys:
+ * - objects identified by a 16-bit handle
+ * - objects identified by a S_STORAGE_NAME
+ * - objects identified by a filename, which is a variable-size up-to-64 bytes byte array
+ * - unindexed objects
+ **/
+
+/* -------------------------------------------------------------------------
+ Useful macro to get a structure from a pointer to one of its fields.
+
+ Typical usage:
+ typedef struct
+ {
+ LIB_OBJECT_NODE_HANDLE16 sNodeInHandleTable;
+ LIB_OBJECT_NODE_UNINDEXED sNodeInList;
+ }
+ CONTEXT;
+
+ LIB_OBJECT_CONTAINER_OF(libObjectUnindexedNext(pList, pObject), CONTEXT, sNodeInList)
+
+
+ -------------------------------------------------------------------------*/
+#define LIB_OBJECT_CONTAINER_OF(ptr, type, member) (((type*)(((char*)(ptr)) - offsetof(type, member))))
+
+
+/* -------------------------------------------------------------------------
+ Table of objects indexed by 16-bit handles
+ -------------------------------------------------------------------------*/
+
+#define LIB_OBJECT_HANDLE16_MAX ((uint16_t)0xFFFF)
+
+/**
+ * NODE of an object in a table indexed by 16-bit handles
+ **/
+typedef struct
+{
+ /* Implementation-defined fields */
+ uint32_t _l[2];
+
+ /* Public field */
+ uint16_t nHandle;
+}
+LIB_OBJECT_NODE_HANDLE16;
+
+/**
+ * A table of objects indexed by 16-bit handles
+ **/
+typedef struct
+{
+ LIB_OBJECT_NODE_HANDLE16* pRoot;
+}
+LIB_OBJECT_TABLE_HANDLE16;
+
+/**
+ * Add an object in a handle table. This function also
+ * assigns a new handle value to the object. The handle
+ * is guaranteed to be unique among all the objects
+ * in the table and non-zero.
+ *
+ * Returns false if the maximum number of handles has been reached
+ * (i.e., there are already 65535 objects in the table)
+ **/
+bool libObjectHandle16Add(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject);
+
+/**
+ * Search an object by its handle. Return NULL if the
+ * object is not found
+ **/
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16Search(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ uint32_t nHandle);
+
+/**
+ * Remove an object from a handle table.
+ *
+ * The object must be part of the table
+ **/
+void libObjectHandle16Remove(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject);
+
+/**
+ * Remove one object from the table. This is useful when
+ * you want to destroy all the objects in the table.
+ *
+ * Returns NULL if the table is empty
+ **/
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16RemoveOne(
+ LIB_OBJECT_TABLE_HANDLE16* pTable);
+
+/**
+ * Get the object following pObject in the handle table.
+ * If pObject is NULL, return the first object in the list
+ * Return NULL if the object is the last in the table
+ **/
+LIB_OBJECT_NODE_HANDLE16* libObjectHandle16Next(
+ LIB_OBJECT_TABLE_HANDLE16* pTable,
+ LIB_OBJECT_NODE_HANDLE16* pObject);
+
+/* -------------------------------------------------------------------------
+ Table of objects indexed by storage name
+ -------------------------------------------------------------------------*/
+
+/**
+ * NODE of an object in a table indexed by storage name
+ **/
+typedef struct
+{
+ /* Implementation-defined fields */
+ uint32_t _l[2];
+
+ /* Public fields */
+ S_STORAGE_NAME sStorageName;
+}
+LIB_OBJECT_NODE_STORAGE_NAME;
+
+/**
+ * A table of objects indexed by storage name
+ **/
+typedef struct
+{
+ LIB_OBJECT_NODE_STORAGE_NAME* pRoot;
+}
+LIB_OBJECT_TABLE_STORAGE_NAME;
+
+/**
+ * Add an object in a storage name table.
+ *
+ * The object must not be part of the table yet. The caller
+ * must have set pObject->sStorageName with the storage name
+ **/
+void libObjectStorageNameAdd(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject);
+
+/**
+ * Search an object by its storage name. Return NULL if the
+ * object is not found
+ **/
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameSearch(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ S_STORAGE_NAME* pStorageName);
+
+/**
+ * Remove an object from a storage name table.
+ *
+ * The object must be part of the table
+ **/
+void libObjectStorageNameRemove(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject);
+
+/**
+ * Remove one object from the table. This is useful when
+ * you want to destroy all the objects in the table
+ * Returns NULL if the table is empty
+ **/
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameRemoveOne(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable);
+
+/**
+ * Get the object following pObject in the storage name table.
+ * If pObject is NULL, return the first object
+ * Return NULL if the object is the last in the table
+ **/
+LIB_OBJECT_NODE_STORAGE_NAME* libObjectStorageNameNext(
+ LIB_OBJECT_TABLE_STORAGE_NAME* pTable,
+ LIB_OBJECT_NODE_STORAGE_NAME* pObject);
+
+/* -------------------------------------------------------------------------
+ Table of objects indexed by filenames
+ -------------------------------------------------------------------------*/
+
+/**
+ * NODE of an object in a table indexed by filenames (varsize up-to-64 bytes)
+ **/
+typedef struct
+{
+ /* Implementation-defined fields */
+ uint32_t _l[2];
+
+ /* Public fields */
+ uint8_t sFilename[64];
+ uint8_t nFilenameLength;
+}
+LIB_OBJECT_NODE_FILENAME;
+
+/**
+ * A table of objects indexed by filenames
+ **/
+typedef struct
+{
+ LIB_OBJECT_NODE_FILENAME* pRoot;
+}
+LIB_OBJECT_TABLE_FILENAME;
+
+/**
+ * Add an object in a filename table.
+ *
+ * The object must not be part of the table yet. The caller
+ * must have set pObject->sFilename and pObject->nFilenameLength
+ * with the object filename
+ **/
+void libObjectFilenameAdd(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject);
+
+/**
+ * Search an object by its filename. Return NULL if the
+ * object is not found
+ **/
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameSearch(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ uint8_t* pFilename,
+ uint32_t nFilenameLength);
+
+/**
+ * Remove an object from a filename table.
+ *
+ * The object must be part of the table
+ **/
+void libObjectFilenameRemove(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject);
+
+/**
+ * Remove one element from the table and return it. This is useful when
+ * you want to destroy all the objects in the table
+ * Returns NULL if the table is empty
+ **/
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameRemoveOne(
+ LIB_OBJECT_TABLE_FILENAME* pTable);
+
+/**
+ * Get the object following pObject in the filename table.
+ * If pObject is NULL, return the first object
+ * Return NULL if the object is the last in the table
+ **/
+LIB_OBJECT_NODE_FILENAME* libObjectFilenameNext(
+ LIB_OBJECT_TABLE_FILENAME* pTable,
+ LIB_OBJECT_NODE_FILENAME* pObject);
+
+/* -------------------------------------------------------------------------
+ Unindexed table of objects
+ -------------------------------------------------------------------------*/
+/**
+ * NODE of an unindexed object
+ **/
+typedef struct
+{
+ /* Implementation-defined fields */
+ uint32_t _l[2];
+}
+LIB_OBJECT_NODE_UNINDEXED;
+
+/**
+ * A table of unindexed objects
+ **/
+typedef struct
+{
+ LIB_OBJECT_NODE_UNINDEXED* pRoot;
+}
+LIB_OBJECT_TABLE_UNINDEXED;
+
+
+/**
+ * Add an object in an unindexed table. The object must not be part of the table yet.
+ **/
+void libObjectUnindexedAdd(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject);
+
+/**
+ * Remove an object from an unindexed table. The object must be part of the table.
+ **/
+void libObjectUnindexedRemove(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject);
+
+/**
+ * Remove one object in the table. This is useful when you want to destroy all objects
+ * in the table.
+ * Returns NULL if the table is empty
+ **/
+LIB_OBJECT_NODE_UNINDEXED* libObjectUnindexedRemoveOne(LIB_OBJECT_TABLE_UNINDEXED* pTable);
+
+/**
+ * Get the object following pObject in the table.
+ * If pObject is NULL, return the first object
+ * Return NULL if the object is the last in the table
+ **/
+LIB_OBJECT_NODE_UNINDEXED* libObjectUnindexedNext(
+ LIB_OBJECT_TABLE_UNINDEXED* pTable,
+ LIB_OBJECT_NODE_UNINDEXED* pObject);
+
+#endif /* __LIB_OBJECT_H__ */
diff --git a/security/tf_crypto_sst/mtc.c b/security/tf_crypto_sst/mtc.c
new file mode 100644
index 00000000..2be48705
--- /dev/null
+++ b/security/tf_crypto_sst/mtc.c
@@ -0,0 +1,274 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MTC_EXPORTS
+#include "mtc.h"
+
+/* Included for the TEE management */
+#include "pkcs11_internal.h"
+
+
+/*------------------------------------------------------------------------------
+ Defines
+------------------------------------------------------------------------------*/
+
+/**
+ * The magic word.
+ */
+#define MTC_SESSION_MAGIC ( (uint32_t)0x4D544300 ) /* "MTC\0" */
+
+/**
+ * The MTC session context
+ */
+typedef struct
+{
+ /* Magic word, must be set to {MTC_SESSION_MAGIC}. */
+ uint32_t nMagicWord;
+
+ /* MTC Identifier */
+ uint32_t nCounterIdentifier;
+
+ /* TEEC session and cryptoki session */
+ TEEC_Session sSession;
+ uint32_t hCryptoSession;
+
+} MTC_SESSION_CONTEXT;
+
+
+static bool g_bMTCInitialized = false;
+
+
+/*------------------------------------------------------------------------------
+ Static functions
+------------------------------------------------------------------------------*/
+
+static S_RESULT static_getMonotonicCounter(S_HANDLE hCounter,
+ S_MONOTONIC_COUNTER_VALUE* psValue,
+ bool bIncrement)
+{
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ MTC_SESSION_CONTEXT* pSession = NULL;
+ uint32_t nCommandID;
+
+ if (!g_bMTCInitialized)
+ {
+ return S_ERROR_BAD_STATE;
+ }
+
+ pSession = (MTC_SESSION_CONTEXT *)hCounter;
+ if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC))
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+
+ if (bIncrement)
+ {
+ nCommandID = SERVICE_SYSTEM_PKCS11_INCREMENT_MTC_COMMAND_ID;
+ }
+ else
+ {
+ nCommandID = SERVICE_SYSTEM_PKCS11_GET_MTC_COMMAND_ID;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = pSession->nCounterIdentifier;
+ sOperation.params[0].value.b = 0;
+ nError = TEEC_InvokeCommand(&pSession->sSession,
+ (pSession->hCryptoSession << 16 ) |
+ (nCommandID & 0x00007FFF),
+ &sOperation,
+ NULL);
+
+ psValue->nLow = sOperation.params[0].value.a;
+ psValue->nHigh = sOperation.params[0].value.b;
+
+ return nError;
+}
+
+/*------------------------------------------------------------------------------
+ API
+------------------------------------------------------------------------------*/
+
+MTC_EXPORT S_RESULT SMonotonicCounterInit(void)
+{
+ TEEC_Result nTeeError;
+
+ stubMutexLock();
+ if (g_bMTCInitialized)
+ {
+ nTeeError = TEEC_SUCCESS;
+ }
+ else
+ {
+ nTeeError = stubInitializeContext();
+ if (nTeeError == TEEC_SUCCESS)
+ {
+ g_bMTCInitialized = true;
+ }
+ }
+ stubMutexUnlock();
+
+ return nTeeError;
+}
+
+MTC_EXPORT void SMonotonicCounterTerminate(void)
+{
+ stubMutexLock();
+ if (g_bMTCInitialized)
+ {
+ stubFinalizeContext();
+ g_bMTCInitialized = false;
+ }
+ stubMutexUnlock();
+}
+
+MTC_EXPORT S_RESULT SMonotonicCounterOpen(
+ uint32_t nCounterIdentifier,
+ OUT S_HANDLE* phCounter)
+{
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ MTC_SESSION_CONTEXT* pSession = NULL;
+ S_MONOTONIC_COUNTER_VALUE nCounterValue;
+
+ if (phCounter == NULL)
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+
+ *phCounter = S_HANDLE_NULL;
+
+ if (!g_bMTCInitialized)
+ {
+ return S_ERROR_BAD_STATE;
+ }
+
+ if (nCounterIdentifier != S_MONOTONIC_COUNTER_GLOBAL)
+ {
+ return S_ERROR_ITEM_NOT_FOUND;
+ }
+
+ pSession = (MTC_SESSION_CONTEXT*)malloc(sizeof(MTC_SESSION_CONTEXT));
+ if (pSession == NULL)
+ {
+ return S_ERROR_OUT_OF_MEMORY;
+ }
+ memset(pSession, 0, sizeof(MTC_SESSION_CONTEXT));
+ pSession->nMagicWord = MTC_SESSION_MAGIC;
+
+ /* Open a TEE session with the system service */
+ nError = TEEC_OpenSession(&g_sContext,
+ &pSession->sSession,
+ &SERVICE_UUID,
+ TEEC_LOGIN_PUBLIC,
+ NULL,
+ NULL, /* No operation parameters */
+ NULL);
+ if (nError != TEEC_SUCCESS)
+ {
+ goto error;
+ }
+
+ /* Open a cryptoki session */
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = CKV_TOKEN_SYSTEM_SHARED;
+ sOperation.params[0].value.b = CKF_RW_SESSION | CKF_SERIAL_SESSION;
+ nError = TEEC_InvokeCommand(&pSession->sSession,
+ SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF,
+ &sOperation,
+ NULL);
+ if (nError != TEEC_SUCCESS)
+ {
+ TEEC_CloseSession(&pSession->sSession);
+ goto error;
+ }
+
+ pSession->hCryptoSession = sOperation.params[0].value.a;
+ pSession->nCounterIdentifier = nCounterIdentifier;
+
+ nError = SMonotonicCounterGet((S_HANDLE)pSession, &nCounterValue);
+ if (nError != TEEC_SUCCESS)
+ {
+ SMonotonicCounterClose((S_HANDLE)pSession);
+ return nError;
+ }
+
+ *phCounter = (S_HANDLE)pSession;
+
+ return TEEC_SUCCESS;
+
+error:
+ free(pSession);
+ return nError;
+}
+
+MTC_EXPORT void SMonotonicCounterClose(S_HANDLE hCounter)
+{
+ MTC_SESSION_CONTEXT* pSession;
+
+ if (!g_bMTCInitialized)
+ {
+ return;
+ }
+
+ pSession = (MTC_SESSION_CONTEXT *)hCounter;
+ if ((pSession == NULL) || (pSession->nMagicWord != MTC_SESSION_MAGIC))
+ {
+ return;
+ }
+
+ (void)TEEC_InvokeCommand(&pSession->sSession,
+ (pSession->hCryptoSession << 16 ) |
+ (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF),
+ NULL, /* No operation parameters */
+ NULL);
+
+ TEEC_CloseSession(&pSession->sSession);
+ free(pSession);
+}
+
+MTC_EXPORT S_RESULT SMonotonicCounterGet(
+ S_HANDLE hCounter,
+ S_MONOTONIC_COUNTER_VALUE* psCurrentValue)
+{
+ return static_getMonotonicCounter(hCounter, psCurrentValue, false);
+}
+
+MTC_EXPORT S_RESULT SMonotonicCounterIncrement(
+ S_HANDLE hCounter,
+ S_MONOTONIC_COUNTER_VALUE* psNewValue)
+{
+ return static_getMonotonicCounter(hCounter, psNewValue, true);
+}
diff --git a/security/tf_crypto_sst/pkcs11_global.c b/security/tf_crypto_sst/pkcs11_global.c
new file mode 100644
index 00000000..f7c491d7
--- /dev/null
+++ b/security/tf_crypto_sst/pkcs11_global.c
@@ -0,0 +1,275 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Implementation Notes:
+ *
+ * This API is NOT thread-safe. Indeed this Cryptoki implementation
+ * only supports option 1 defined in PKCS#11, section 6.5.2:
+ * "The application can specify that it will not be accessing the library concurrently
+ * from multiple threads, and so the library need not worry about performing any type
+ * of locking for the sake of thread-safety."
+ */
+
+#include "pkcs11_internal.h"
+
+/* ------------------------------------------------------------------------
+ System Service UUID
+------------------------------------------------------------------------- */
+const TEEC_UUID SERVICE_UUID = SERVICE_SYSTEM_UUID;
+
+/* ------------------------------------------------------------------------
+ Definition of the global TEE Context
+------------------------------------------------------------------------- */
+TEEC_Context g_sContext;
+/* A mutex that protects the access to the global context and to the
+ g_bContextRefCounter flag */
+LIB_MUTEX g_sContextMutex = LIB_MUTEX_INITIALIZER;
+/* Whether the context has already been initialized or not */
+uint32_t g_nContextRefCounter = 0;
+
+bool g_bCryptokiInitialized = false;
+
+/* ------------------------------------------------------------------------
+ Internal global TEE context management
+------------------------------------------------------------------------- */
+
+void stubMutexLock(void)
+{
+ libMutexLock(&g_sContextMutex);
+}
+
+void stubMutexUnlock(void)
+{
+ libMutexUnlock(&g_sContextMutex);
+}
+
+/* This API must be protected by stubMutexLock/Unlock */
+TEEC_Result stubInitializeContext(void)
+{
+ TEEC_Result nTeeError;
+
+ if (g_nContextRefCounter)
+ {
+ g_nContextRefCounter ++;
+ return TEEC_SUCCESS;
+ }
+
+ nTeeError = TEEC_InitializeContext(NULL, &g_sContext);
+ if (nTeeError == TEEC_SUCCESS)
+ {
+ g_nContextRefCounter = 1;
+ }
+
+ return nTeeError;
+}
+
+/* This API must be protected by stubMutexLock/Unlock */
+void stubFinalizeContext(void)
+{
+ if (g_nContextRefCounter > 0)
+ {
+ g_nContextRefCounter --;
+ }
+
+ if (g_nContextRefCounter == 0)
+ {
+ TEEC_FinalizeContext(&g_sContext);
+ memset(&g_sContext, 0, sizeof(TEEC_Context));
+ }
+}
+
+
+/* ------------------------------------------------------------------------
+ Internal monitor management
+------------------------------------------------------------------------- */
+/**
+* Check that hSession is a valid primary session,
+* or a valid secondary session attached to a valid primary session.
+*
+* input:
+* S_HANDLE hSession: the session handle to check
+* output:
+* bool* pBoolIsPrimarySession: a boolean set to true if the session is primary,
+* set to false if the session if the session is secondary
+* returned boolean: set to true iff :
+* - either hSession is a valid primary session
+* - or hSession is a valid secondary session attached to a valid primary session
+**/
+bool ckInternalSessionIsOpenedEx(S_HANDLE hSession, bool* pBoolIsPrimarySession)
+{
+ PPKCS11_SESSION_CONTEXT_HEADER pHeader = (PPKCS11_SESSION_CONTEXT_HEADER)hSession;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession = NULL;
+
+ if ((pHeader == NULL) || (pHeader->nMagicWord != PKCS11_SESSION_MAGIC))
+ {
+ return FALSE;
+ }
+ if (pHeader->nSessionTag == PKCS11_PRIMARY_SESSION_TAG) /* primary session */
+ {
+ pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)pHeader;
+
+ *pBoolIsPrimarySession = true;
+
+ /* check that primary session is valid */
+ return (pSession->hCryptoSession != CK_INVALID_HANDLE);
+ }
+ else if (pHeader->nSessionTag == PKCS11_SECONDARY_SESSION_TAG) /*secondary session */
+ {
+ PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)pHeader;
+
+ *pBoolIsPrimarySession = false;
+
+ /* check that primary session is still valid */
+ pSession = pSecSession->pPrimarySession;
+ if ( (pSession == NULL) ||
+ (pSession->sHeader.nMagicWord != PKCS11_SESSION_MAGIC) ||
+ (pSession->sHeader.nSessionTag != PKCS11_PRIMARY_SESSION_TAG))
+ {
+ return FALSE;
+ }
+
+ if (pSession->hCryptoSession == CK_INVALID_HANDLE)
+ {
+ return FALSE;
+ }
+
+ /* check that secondary session is valid */
+ return (pSecSession->hSecondaryCryptoSession != CK_INVALID_HANDLE);
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+/* ------------------------------------------------------------------------
+ Internal error management
+------------------------------------------------------------------------- */
+
+CK_RV ckInternalTeeErrorToCKError(TEEC_Result nError)
+{
+ switch (nError)
+ {
+ case TEEC_SUCCESS:
+ return CKR_OK;
+
+ case TEEC_ERROR_BAD_PARAMETERS:
+ case TEEC_ERROR_BAD_FORMAT:
+ return CKR_ARGUMENTS_BAD;
+ case TEEC_ERROR_OUT_OF_MEMORY:
+ return CKR_HOST_MEMORY;
+ case TEEC_ERROR_ACCESS_DENIED:
+ return CKR_TOKEN_NOT_PRESENT;
+ default:
+ return CKR_DEVICE_ERROR;
+ }
+}
+
+/* ------------------------------------------------------------------------
+ Public Functions
+------------------------------------------------------------------------- */
+CK_RV PKCS11_EXPORT C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ CK_RV nErrorCode;
+ TEEC_Result nTeeError;
+
+ if (pInitArgs != NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ stubMutexLock();
+ if (g_bCryptokiInitialized)
+ {
+ nErrorCode = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ }
+ else
+ {
+ nTeeError = stubInitializeContext();
+ if (nTeeError == TEEC_SUCCESS)
+ {
+ g_bCryptokiInitialized = true;
+ }
+ nErrorCode = ckInternalTeeErrorToCKError(nTeeError);
+ }
+ stubMutexUnlock();
+
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_Finalize(CK_VOID_PTR pReserved)
+{
+ CK_RV nErrorCode;
+
+ if (pReserved != NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ stubMutexLock();
+ if (g_bCryptokiInitialized)
+ {
+ stubFinalizeContext();
+ g_bCryptokiInitialized = false;
+ nErrorCode = CKR_OK;
+ }
+ else
+ {
+ nErrorCode = CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ stubMutexUnlock();
+
+ return nErrorCode;
+}
+
+static const CK_INFO sImplementationInfo =
+{
+ {2, 20}, /* cryptokiVersion, spec 2.20 */
+ "Trusted Logic", /* manufacturerID */
+ 0, /* flags */
+ "PKCS#11", /* libraryDescription */
+ {3, 0} /* libraryVersion */
+};
+
+CK_RV PKCS11_EXPORT C_GetInfo(CK_INFO_PTR pInfo)
+{
+ if (!g_bCryptokiInitialized)
+ {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ if (pInfo == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ memcpy(pInfo, &sImplementationInfo, sizeof(CK_INFO));
+ return CKR_OK;
+}
diff --git a/security/tf_crypto_sst/pkcs11_internal.h b/security/tf_crypto_sst/pkcs11_internal.h
new file mode 100644
index 00000000..14ecf834
--- /dev/null
+++ b/security/tf_crypto_sst/pkcs11_internal.h
@@ -0,0 +1,137 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PKCS11_INTERNAL_H__
+#define __PKCS11_INTERNAL_H__
+
+#define CRYPTOKI_EXPORTS
+#include "cryptoki.h"
+#include "service_system_protocol.h"
+
+#include "lib_object.h"
+#include "lib_mutex.h"
+#include "tee_client_api.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/**
+ * The magic word.
+ */
+#define PKCS11_SESSION_MAGIC ( (uint32_t)0x45EF683B )
+
+/**
+ * Computes required size to fit in a 4-bytes aligned buffer (at the end)
+ * If the size is a multiple of 4, just returns the size
+ * Otherwise, return the size so that the (end of the buffer)+1 is 4-bytes aligned.
+ */
+#define PKCS11_GET_SIZE_WITH_ALIGNMENT(a) (uint32_t)(((uint32_t)a+3) & ~3)
+
+
+/**
+ * The System Service UUID used by the library
+ */
+extern const TEEC_UUID SERVICE_UUID;
+
+/**
+ * g_sContext: the global TEEC context used by the library
+ */
+extern TEEC_Context g_sContext;
+
+void stubMutexLock(void);
+void stubMutexUnlock(void);
+TEEC_Result stubInitializeContext(void);
+void stubFinalizeContext(void);
+
+/** Whether the cryptoki library is initialized or not */
+extern bool g_bCryptokiInitialized;
+
+CK_RV ckInternalTeeErrorToCKError(TEEC_Result nError);
+
+#define PKCS11_PRIMARY_SESSION_TAG 1
+#define PKCS11_SECONDARY_SESSION_TAG 2
+
+typedef struct
+{
+ /*
+ * Magic word, must be set to {PKCS11_SESSION_MAGIC}.
+ */
+ uint32_t nMagicWord;
+
+ /* nSessionTag must be set to {PKCS11_PRIMARY_SESSION_TAG} for primary session
+ * to {PKCS11_SECONDARY_SESSION_TAG} for secondary session */
+ uint32_t nSessionTag;
+
+}PKCS11_SESSION_CONTEXT_HEADER, * PPKCS11_SESSION_CONTEXT_HEADER;
+
+/**
+ * The PKCS11 Primary session context
+ */
+typedef struct
+{
+ /* sHeader must be the first field of this structure */
+ PKCS11_SESSION_CONTEXT_HEADER sHeader;
+
+ /* TEEC session used for this cryptoki primary session.
+ Each primary session has its own TEEC session */
+ TEEC_Session sSession;
+ uint32_t hCryptoSession;
+
+ /* Mutex to protect the table of secondary sessions */
+ LIB_MUTEX sSecondarySessionTableMutex;
+
+ /* Table of secondary sessions */
+ LIB_OBJECT_TABLE_HANDLE16 sSecondarySessionTable;
+
+} PKCS11_PRIMARY_SESSION_CONTEXT, * PPKCS11_PRIMARY_SESSION_CONTEXT;
+
+/**
+ * The PKCS11 Secondary session context
+ */
+typedef struct
+{
+ /* sHeader must be the first field of this structure */
+ PKCS11_SESSION_CONTEXT_HEADER sHeader;
+
+ /* Secondary session handle as returned by pkcs11 */
+ uint32_t hSecondaryCryptoSession;
+
+ /* A node of the table of secondary sessions */
+ LIB_OBJECT_NODE_HANDLE16 sSecondarySessionNode;
+
+ /* pointer to the primary session */
+ PKCS11_PRIMARY_SESSION_CONTEXT* pPrimarySession;
+
+} PKCS11_SECONDARY_SESSION_CONTEXT, *PPKCS11_SECONDARY_SESSION_CONTEXT;
+
+bool ckInternalSessionIsOpenedEx(S_HANDLE hSession, bool* pBoolIsPrimarySession);
+
+#endif /* __PKCS11_INTERNAL_H__ */
diff --git a/security/tf_crypto_sst/pkcs11_object.c b/security/tf_crypto_sst/pkcs11_object.c
new file mode 100644
index 00000000..53caadcc
--- /dev/null
+++ b/security/tf_crypto_sst/pkcs11_object.c
@@ -0,0 +1,1637 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pkcs11_internal.h"
+
+/* ------------------------------------------------------------------------
+Internal Functions
+------------------------------------------------------------------------- */
+/**
+* Checks the following pre-conditions:
+* - cryptoki is initialized,
+* - hSession is valid (primary and/or secondary),
+* - the user is logged in.
+*
+* And updates handle values:
+* IN/OUT : phSession
+* IN = Cryptoki external handle
+* OUT = TFAPI handle = primary cryptoki session handle
+* OUT : phSecSession16Msb
+* OUT = 0 for a primary session or
+* the secondary cryptoki session handle in the 16 MSB bits
+*/
+static CK_RV static_checkPreConditionsAndUpdateHandles(
+ CK_SESSION_HANDLE* phSession,
+ uint32_t* phCommandIDAndSession,
+ PPKCS11_PRIMARY_SESSION_CONTEXT* ppSession)
+{
+ bool bIsPrimarySession;
+
+ /* Check Cryptoki is initialized */
+ if (!g_bCryptokiInitialized)
+ {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+
+ if (phSession == NULL)
+ {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+
+ /* Check that the session is valid */
+ if (!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession))
+ {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+ /* previous check is fine, then update session handles */
+ if (bIsPrimarySession)
+ {
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession =
+ (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession);
+
+ *phSession = pSession->hCryptoSession;
+ *phCommandIDAndSession = (pSession->hCryptoSession<<16)|(*phCommandIDAndSession&0x00007FFF);
+ *ppSession = pSession;
+ }
+ else
+ {
+ PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession =
+ (PPKCS11_SECONDARY_SESSION_CONTEXT)(*phSession);
+
+ *phSession = pSecSession->pPrimarySession->hCryptoSession;
+ *phCommandIDAndSession = (pSecSession->hSecondaryCryptoSession<<16)|(1<<15)|(*phCommandIDAndSession&0x00007FFF);
+ *ppSession = pSecSession->pPrimarySession;
+ }
+
+ return CKR_OK;
+}
+
+/******************************************/
+/* The buffer must be freed by the caller */
+/******************************************/
+static CK_RV static_encodeTwoTemplates(
+ uint8_t** ppBuffer,
+ uint32_t * pBufferSize,
+ const uint32_t nParamIndex,
+ CK_ATTRIBUTE* pTemplate1,
+ CK_ULONG ulCount1,
+ CK_ATTRIBUTE* pTemplate2,
+ CK_ULONG ulCount2)
+{
+ INPUT_TEMPLATE_ITEM sItem;
+
+ uint32_t i;
+ uint32_t nDataOffset = 0;
+ uint32_t nBufferIndex = 0;
+ uint32_t nBufferSize = 0;
+ uint8_t* pBuffer = NULL;
+ CK_RV nErrorCode = CKR_OK;
+
+ if (ulCount1 == 0)
+ {
+ /* Nothing to do */
+ return CKR_OK;
+ }
+ if (pTemplate1 == NULL)
+ {
+ /* Nothing to do */
+ return CKR_OK;
+ }
+
+ /* First compute the total required buffer size that
+ * will contain the full templates (for the template 1 AND 2)
+ */
+ nBufferSize = 4 + /* Nb Attributes */
+ sizeof(INPUT_TEMPLATE_ITEM)*ulCount1; /* The attributes items */
+ if (pTemplate2 != NULL)
+ {
+ nBufferSize += 4 + /* Nb Attributes */
+ sizeof(INPUT_TEMPLATE_ITEM)*ulCount2; /* The attributes items */
+ }
+
+ /* First data (attribute values) on either template 1 or 2 will just be after the last item */
+ nDataOffset = nBufferSize;
+
+ for (i = 0; i < ulCount1; i++)
+ {
+ /* Each value will be aligned on 4 bytes.
+ This computation includes the spare bytes. */
+ nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen);
+ }
+ if (pTemplate2 != NULL)
+ {
+ for (i = 0; i < ulCount2; i++)
+ {
+ /* Each value will be aligned on 4 bytes.
+ This computation includes the spare bytes. */
+ nBufferSize += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen);
+ }
+ }
+
+ pBuffer = (uint8_t*)malloc(nBufferSize);
+ if (pBuffer == NULL)
+ {
+ /* Not enough memory */
+ return CKR_DEVICE_MEMORY;
+ }
+
+ memset(pBuffer, 0, nBufferSize);
+
+ /*
+ * First template
+ */
+ *(uint32_t*)(pBuffer + nBufferIndex) = ulCount1;
+ nBufferIndex += 4;
+ for (i = 0; i < ulCount1; i++)
+ {
+ sItem.attributeType = (uint32_t)pTemplate1[i].type;
+ /* dataOffset = 0 means NULL buffer */
+ sItem.dataOffset = ((pTemplate1[i].pValue == NULL) ? 0 : nDataOffset);
+ sItem.dataParamIndex = nParamIndex; /* The parameter where we store the data (0 to 3) */
+ sItem.dataValueLen = (uint32_t)pTemplate1[i].ulValueLen;
+ /* Copy the item */
+ memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM));
+ nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM);
+ if (pTemplate1[i].pValue != NULL)
+ {
+ /* Copy the data */
+ memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate1[i].pValue, (uint32_t)pTemplate1[i].ulValueLen);
+ /* Next data will be stored just after the previous one but aligned on 4 bytes */
+ nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate1[i].ulValueLen);
+ if ((nDataOffset & 0xC0000000) != 0)
+ {
+ /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */
+ nErrorCode = CKR_DEVICE_ERROR;
+ goto error;
+ }
+ }
+ }
+
+ /*
+ * Second template
+ */
+ if (pTemplate2 != NULL)
+ {
+ *(uint32_t*)(pBuffer + nBufferIndex) = ulCount2;
+ nBufferIndex += 4;
+ for (i = 0; i < ulCount2; i++)
+ {
+ sItem.attributeType = (uint32_t)pTemplate2[i].type;
+ /* dataOffset = 0 means NULL buffer */
+ sItem.dataOffset = ((pTemplate2[i].pValue == NULL) ? 0 : nDataOffset);
+ sItem.dataParamIndex = nParamIndex; /* The parameter where we store the data (0..3) */
+ sItem.dataValueLen = (uint32_t)pTemplate2[i].ulValueLen;
+ /* Copy the item */
+ memcpy(pBuffer + nBufferIndex, &sItem, sizeof(INPUT_TEMPLATE_ITEM));
+ nBufferIndex += sizeof(INPUT_TEMPLATE_ITEM);
+ if (pTemplate2[i].pValue != NULL)
+ {
+ /* Copy the data */
+ memcpy(pBuffer + nDataOffset, (uint8_t*)pTemplate2[i].pValue, (uint32_t)pTemplate2[i].ulValueLen);
+ /* Next data will be stored just after the previous one but aligned on 4 bytes */
+ nDataOffset += PKCS11_GET_SIZE_WITH_ALIGNMENT(pTemplate2[i].ulValueLen);
+ if ((nDataOffset & 0xC0000000) != 0)
+ {
+ /* We whould never go in this case, that means the dataOffset will not be able to store the offset correctly */
+ nErrorCode = CKR_DEVICE_ERROR;
+ goto error;
+ }
+ }
+ }
+ }
+
+ *ppBuffer = pBuffer;
+ *pBufferSize = nBufferSize;
+
+ return CKR_OK;
+
+error:
+ free(pBuffer);
+ return nErrorCode;
+}
+
+/******************************************/
+/* The buffer must be freed by the caller */
+/******************************************/
+static CK_RV static_encodeTemplate(
+ uint8_t** ppBuffer,
+ uint32_t* pBufferSize,
+ const uint32_t nParamIndex,
+ CK_ATTRIBUTE* pTemplate,
+ CK_ULONG ulCount)
+{
+ return static_encodeTwoTemplates(ppBuffer, pBufferSize, nParamIndex, pTemplate, ulCount, NULL, 0);
+}
+/* ----------------------------------------------------------------------- */
+
+static CK_RV static_C_CallInit(
+ uint32_t nCommandID,
+ CK_SESSION_HANDLE hSession,
+ const CK_MECHANISM* pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = nCommandID;
+ uint32_t nParamType2 = TEEC_NONE;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+ if (pMechanism == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
+ if (nCommandID != SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID)
+ {
+ sOperation.params[0].value.b = (uint32_t)hKey;
+
+ }
+ sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
+ sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
+
+ /* Specific case of RSA OAEP */
+ if (((nCommandID == SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID)
+ ||(nCommandID == SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID))
+ && (pMechanism->mechanism == CKM_RSA_PKCS_OAEP)
+ && (pMechanism->pParameter != NULL))
+ {
+ /* Add the source buffer of the RSA OAEP mechanism parameters */
+ nParamType2 = TEEC_MEMREF_TEMP_INPUT;
+ sOperation.params[2].tmpref.buffer = (uint8_t*)((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->pSourceData;
+ sOperation.params[2].tmpref.size = (uint32_t) ((CK_RSA_PKCS_OAEP_PARAMS_PTR)(pMechanism->pParameter))->ulSourceDataLen;
+ }
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, nParamType2, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+
+ return nErrorCode;
+}
+
+/* ----------------------------------------------------------------------- */
+/**
+* If bSend, the pData buffer is sent to the service.
+* If bResult, a buffer is received, the convention described in
+* PKCS11 Section 11.2 applies for pResult and pulResultLen.
+* Specific function used for single operation
+*/
+static CK_RV static_C_CallForSingle(
+ uint32_t nCommandID,
+ CK_SESSION_HANDLE hSession,
+ const CK_BYTE* pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE* pResult,
+ CK_ULONG* pulResultLen,
+ bool bSend,
+ bool bReceive)
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = nCommandID;
+ uint32_t nParamType0 = TEEC_NONE;
+ uint32_t nParamType1 = TEEC_NONE;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+
+ if (bSend)
+ {
+ nParamType0 = TEEC_MEMREF_TEMP_INPUT;
+ sOperation.params[0].tmpref.buffer = (uint8_t*)pData;
+ sOperation.params[0].tmpref.size = (uint32_t)ulDataLen;
+ }
+
+ if (bReceive)
+ {
+ if (pulResultLen == NULL)
+ {
+ /* The P11 API Spec states that, in this case, the operation must be
+ aborted and the error code CKR_ARGUMENTS_BAD must be returned. We
+ achieve this result by sending an invalid parameter type */
+ nParamType1 = TEEC_NONE;
+ }
+ else if (pResult == NULL)
+ {
+ /* If pResult is NULL, the caller only wants the buffer length.
+ Send a NULL output memref */
+ nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
+ sOperation.params[1].tmpref.buffer = (uint8_t*)NULL;
+ }
+ else
+ {
+ /* send the result buffer information */
+ nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
+ sOperation.params[1].tmpref.buffer = (uint8_t*)pResult;
+ sOperation.params[1].tmpref.size = (uint32_t)*pulResultLen;
+ }
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand(&pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ goto end;
+ }
+
+ /* Success */
+ nErrorCode = CKR_OK;
+
+ end:
+ if (bReceive)
+ {
+ if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL))
+ {
+ /* The service has returned the actual result */
+ /* The data is already in pResult, we get the returned length */
+ *pulResultLen = sOperation.params[1].tmpref.size;
+ }
+ }
+
+ return nErrorCode;
+}
+
+/* ----------------------------------------------------------------------- */
+/**
+* If bSend, the pData buffer is sent to the service.
+* If bResult, a buffer is received, the convention described in
+* PKCS11 Section 11.2 applies for pResult and pulResultLen.
+* Specific function only used for update operations
+*/
+static CK_RV static_C_CallUpdate(
+ uint32_t nCommandID,
+ CK_SESSION_HANDLE hSession,
+ const CK_BYTE* pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE* pResult,
+ CK_ULONG* pulResultLen,
+ bool bSend,
+ bool bReceive)
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nResultLen = 0;
+ uint32_t nCommandIDAndSession = nCommandID;
+ uint32_t nParamType0 = TEEC_NONE;
+ uint32_t nParamType1 = TEEC_NONE;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ if (pulResultLen != NULL)
+ {
+ nResultLen = *pulResultLen;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+
+ if (bSend)
+ {
+ nParamType0 = TEEC_MEMREF_TEMP_INPUT;
+ sOperation.params[0].tmpref.buffer = (void*)pData;
+ sOperation.params[0].tmpref.size = ulDataLen;
+ }
+
+ if (bReceive)
+ {
+ if (pulResultLen == NULL)
+ {
+ /* The P11 API Spec states that, in this case, the operation must be
+ aborted and the error code CKR_ARGUMENTS_BAD must be returned. We
+ achieve this result by setting an invalid parameter type */
+ nParamType1 = TEEC_NONE;
+ }
+ else if (pResult == NULL)
+ {
+ /* If pResult is NULL, the caller only wants the output buffer length.
+ Pass a NULL output ref */
+ nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
+ sOperation.params[1].tmpref.buffer = NULL;
+ }
+ else
+ {
+ /* send the result buffer information */
+ nParamType1 = TEEC_MEMREF_TEMP_OUTPUT;
+ sOperation.params[1].tmpref.buffer = pResult;
+ sOperation.params[1].tmpref.size = (uint32_t)*pulResultLen;
+ }
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(nParamType0, nParamType1, TEEC_NONE, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ goto end;
+ }
+
+ /* Success */
+ nErrorCode = CKR_OK;
+
+ end:
+ if (bReceive)
+ {
+ if ((nErrorCode == CKR_OK) || (nErrorCode == CKR_BUFFER_TOO_SMALL))
+ {
+ /* The service has returned the actual result */
+ /* The data is already in pResult, we get the returned length */
+ *pulResultLen = sOperation.params[1].tmpref.size;
+ }
+ }
+
+ return nErrorCode;
+}
+
+/* Splits the buffer pData in chunks of nChunkSize size
+ * and calls static_C_CallUpdate for each chunk
+ */
+static CK_RV static_C_CallSplitUpdate(
+ uint32_t nCommandID,
+ CK_SESSION_HANDLE hSession,
+ const CK_BYTE* pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE* pResult,
+ CK_ULONG* pulResultLen,
+ bool bSend,
+ bool bReceive,
+ uint32_t nChunkSize)
+{
+ CK_RV nErrorCode;
+ CK_ULONG nPartDataLen;
+ CK_ULONG nPartResultLen = 0;
+ CK_ULONG ulResultLen = 0;
+ bool bIsSymOperation = false;
+
+ if (pulResultLen != NULL)
+ {
+ ulResultLen = *pulResultLen;
+ /* Check wether the operation is a symetrical or asymetrical */
+ if (*pulResultLen == ulDataLen)
+ {
+ bIsSymOperation = true;
+ }
+ *pulResultLen = 0;
+ }
+
+ while (ulDataLen > 0)
+ {
+ nPartDataLen = (ulDataLen <= nChunkSize ?
+ ulDataLen : nChunkSize);
+ if (bIsSymOperation)
+ {
+ /* update the result only if it is a symetric operation */
+ nPartResultLen = (ulResultLen <= nChunkSize ?
+ ulResultLen : nChunkSize);
+ }
+ else
+ {
+ nPartResultLen = ulResultLen;
+ }
+
+ nErrorCode = static_C_CallUpdate(
+ nCommandID,
+ hSession,
+ pData,
+ nPartDataLen,
+ pResult,
+ &nPartResultLen,
+ bSend,
+ bReceive);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ ulDataLen -= nPartDataLen;
+ pData += nPartDataLen;
+
+ if (pResult != NULL)
+ {
+ ulResultLen -= nPartResultLen;
+ pResult += nPartResultLen;
+ }
+
+ if ((pulResultLen != NULL) && (bIsSymOperation))
+ {
+ *pulResultLen += nPartResultLen;
+ }
+ }
+ return CKR_OK;
+}
+
+/* Decides whether to split or not the inout/output buffer into chunks
+*/
+static CK_RV static_C_Call_CallForUpdate(
+ uint32_t nCommandID,
+ CK_SESSION_HANDLE hSession,
+ const CK_BYTE* pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE* pResult,
+ CK_ULONG* pulResultLen,
+ bool bSend,
+ bool bReceive)
+{
+ CK_RV nErrorCode;
+ uint32_t nChunkSize;
+
+ TEEC_ImplementationLimits limits;
+
+ if (!g_bCryptokiInitialized)
+ {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+
+ TEEC_GetImplementationLimits(&limits);
+
+ /* We can split the buffer in chunks of fixed size.
+ No matter of the start address of the buffer,
+ a safe size would be TotalNumberOfPages - 1
+ */
+ nChunkSize = limits.tmprefMaxSize - limits.pageSize;
+
+ if (ulDataLen > nChunkSize)
+ {
+ /* inoutMaxSize = 0 means unlimited size */
+ nErrorCode = static_C_CallSplitUpdate(nCommandID,
+ hSession,
+ pData,
+ ulDataLen,
+ pResult,
+ pulResultLen,
+ bSend,
+ bReceive,
+ nChunkSize);
+ }
+ else
+ {
+ nErrorCode = static_C_CallUpdate(nCommandID,
+ hSession,
+ pData,
+ ulDataLen,
+ pResult,
+ pulResultLen,
+ bSend,
+ bReceive);
+ }
+ return nErrorCode;
+
+}
+
+/* ------------------------------------------------------------------------
+Public Functions
+------------------------------------------------------------------------- */
+
+CK_RV PKCS11_EXPORT C_CreateObject(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_ATTRIBUTE* pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE* phObject) /* receives new object's handle. */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CREATEOBJECT_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+
+ if ( pTemplate == NULL || phObject == NULL )
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].tmpref.buffer = pBuffer;
+ sOperation.params[0].tmpref.size = nBufferSize;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ goto end;
+ }
+
+ *phObject = sOperation.params[1].value.a;
+
+ /* Success */
+ nErrorCode = CKR_OK;
+
+end:
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_DestroyObject(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject) /* the object's handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DESTROYOBJECT_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = (uint32_t)hObject;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_GetAttributeValue(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE* pTemplate, /* specifies attributes, gets values */
+ CK_ULONG ulCount) /* attributes in template */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ CK_RV nFinalErrorCode = CKR_OK;
+ uint32_t i = 0;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GETATTRIBUTEVALUE_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ if (pTemplate == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (ulCount == 0)
+ {
+ return CKR_OK;
+ }
+
+ for (i = 0; i < ulCount; i++)
+ {
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = (uint32_t)hObject;
+ sOperation.params[0].value.b = (uint32_t)pTemplate[i].type;
+ sOperation.params[1].tmpref.buffer = pTemplate[i].pValue;
+ sOperation.params[1].tmpref.size = pTemplate[i].ulValueLen;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ if (nErrorCode != CKR_OK)
+ {
+ if ( (nErrorCode == CKR_ATTRIBUTE_SENSITIVE) ||
+ (nErrorCode == CKR_ATTRIBUTE_TYPE_INVALID) ||
+ (nErrorCode == CKR_BUFFER_TOO_SMALL))
+ {
+ nFinalErrorCode = nErrorCode;
+ }
+ else
+ {
+ /* Not some of the special error codes: this is fatal */
+ return nErrorCode;
+ }
+ }
+
+ pTemplate[i].ulValueLen = sOperation.params[1].tmpref.size;
+ }
+
+ return nFinalErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_FindObjectsInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_ATTRIBUTE* pTemplate, /* attribute values to match */
+ CK_ULONG ulCount) /* attributes in search template */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSINIT_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 0, (CK_ATTRIBUTE*)pTemplate, ulCount); /* Sets the template on the param 0 */
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].tmpref.buffer = pBuffer;
+ sOperation.params[0].tmpref.size = nBufferSize;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+
+CK_RV PKCS11_EXPORT C_FindObjects(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE* phObject, /* receives object handle array */
+ CK_ULONG ulMaxObjectCount, /* max handles to be returned */
+ CK_ULONG* pulObjectCount) /* actual number returned */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTS_COMMAND_ID;
+
+ if ( (phObject == NULL) || (pulObjectCount == NULL))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ *pulObjectCount = 0;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].tmpref.buffer = (uint8_t*)phObject;
+ sOperation.params[0].tmpref.size = (uint32_t)ulMaxObjectCount * sizeof(uint32_t);
+
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ *pulObjectCount = sOperation.params[0].tmpref.size / sizeof(uint32_t);
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSFINAL_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+
+CK_RV PKCS11_EXPORT C_DigestInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism) /* the digesting mechanism */
+{
+ return static_C_CallInit(
+ SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID,
+ hSession,
+ pMechanism,
+ CK_INVALID_HANDLE);
+}
+
+CK_RV PKCS11_EXPORT C_Digest(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to be digested */
+ CK_BYTE* pDigest, /* receives the message digest */
+ CK_ULONG* pulDigestLen) /* receives byte length of digest */
+{
+ return static_C_CallForSingle(
+ SERVICE_SYSTEM_PKCS11_C_DIGEST_COMMAND_ID,
+ hSession,
+ pData,
+ ulDataLen,
+ pDigest,
+ pulDigestLen,
+ TRUE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_DigestUpdate(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pPart, /* data to be digested */
+ CK_ULONG ulPartLen) /* bytes of data to be digested */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_DIGESTUPDATE_COMMAND_ID,
+ hSession,
+ pPart,
+ ulPartLen,
+ NULL,
+ NULL,
+ TRUE,
+ FALSE);
+}
+
+CK_RV PKCS11_EXPORT C_DigestFinal(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE* pDigest, /* receives the message digest */
+ CK_ULONG* pulDigestLen) /* receives byte count of digest */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_DIGESTFINAL_COMMAND_ID,
+ hSession,
+ NULL,
+ 0,
+ pDigest,
+ pulDigestLen,
+ FALSE,
+ TRUE);
+}
+
+
+CK_RV PKCS11_EXPORT C_SignInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey) /* handle of the signature key */
+{
+ return static_C_CallInit(
+ SERVICE_SYSTEM_PKCS11_C_SIGNINIT_COMMAND_ID,
+ hSession,
+ pMechanism,
+ hKey);
+}
+
+CK_RV PKCS11_EXPORT C_Sign(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pData, /* the data (digest) to be signed */
+ CK_ULONG ulDataLen, /* count of bytes to be signed */
+ CK_BYTE* pSignature, /* receives the signature */
+ CK_ULONG* pulSignatureLen) /* receives byte count of signature */
+{
+ return static_C_CallForSingle(
+ SERVICE_SYSTEM_PKCS11_C_SIGN_COMMAND_ID,
+ hSession,
+ pData,
+ ulDataLen,
+ pSignature,
+ pulSignatureLen,
+ TRUE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_SignUpdate(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pPart, /* the data (digest) to be signed */
+ CK_ULONG ulPartLen) /* count of bytes to be signed */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_SIGNUPDATE_COMMAND_ID,
+ hSession,
+ pPart,
+ ulPartLen,
+ NULL,
+ NULL,
+ TRUE,
+ FALSE);
+}
+
+CK_RV PKCS11_EXPORT C_SignFinal(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE* pSignature, /* receives the signature */
+ CK_ULONG* pulSignatureLen) /* receives byte count of signature */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_SIGNFINAL_COMMAND_ID,
+ hSession,
+ NULL,
+ 0,
+ pSignature,
+ pulSignatureLen,
+ FALSE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_EncryptInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey) /* handle of encryption key */
+{
+ return static_C_CallInit(
+ SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID,
+ hSession,
+ pMechanism,
+ hKey);
+}
+
+CK_RV PKCS11_EXPORT C_Encrypt(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext data */
+ CK_BYTE* pEncryptedData, /* receives encrypted data */
+ CK_ULONG* pulEncryptedDataLen) /* receives encrypted byte count */
+{
+
+ return static_C_CallForSingle(
+ SERVICE_SYSTEM_PKCS11_C_ENCRYPT_COMMAND_ID,
+ hSession,
+ pData,
+ ulDataLen,
+ pEncryptedData,
+ pulEncryptedDataLen,
+ TRUE,
+ TRUE);
+}
+
+
+
+CK_RV PKCS11_EXPORT C_EncryptUpdate(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* bytes of plaintext data */
+ CK_BYTE* pEncryptedPart, /* receives encrypted data */
+ CK_ULONG* pulEncryptedPartLen)/* receives encrypted byte count */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_ENCRYPTUPDATE_COMMAND_ID,
+ hSession,
+ pPart,
+ ulPartLen,
+ pEncryptedPart,
+ pulEncryptedPartLen,
+ TRUE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_EncryptFinal(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE* pLastEncryptedPart, /* receives encrypted last part */
+ CK_ULONG* pulLastEncryptedPartLen) /* receives byte count */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_ENCRYPTFINAL_COMMAND_ID,
+ hSession,
+ NULL,
+ 0,
+ pLastEncryptedPart,
+ pulLastEncryptedPartLen,
+ FALSE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_DecryptInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey) /* handle of the decryption key */
+{
+ return static_C_CallInit(
+ SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID,
+ hSession,
+ pMechanism,
+ hKey);
+}
+
+CK_RV PKCS11_EXPORT C_Decrypt(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pEncryptedData, /* input encrypted data */
+ CK_ULONG ulEncryptedDataLen, /* count of bytes of input */
+ CK_BYTE* pData, /* receives decrypted output */
+ CK_ULONG* pulDataLen) /* receives decrypted byte count */
+{
+
+ return static_C_CallForSingle(
+ SERVICE_SYSTEM_PKCS11_C_DECRYPT_COMMAND_ID,
+ hSession,
+ pEncryptedData,
+ ulEncryptedDataLen,
+ pData,
+ pulDataLen,
+ TRUE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_DecryptUpdate(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pEncryptedPart, /* input encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* count of bytes of input */
+ CK_BYTE* pPart, /* receives decrypted output */
+ CK_ULONG* pulPartLen) /* receives decrypted byte count */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_DECRYPTUPDATE_COMMAND_ID,
+ hSession,
+ pEncryptedPart,
+ ulEncryptedPartLen,
+ pPart,
+ pulPartLen,
+ TRUE,
+ TRUE);
+}
+
+CK_RV PKCS11_EXPORT C_DecryptFinal(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE* pLastPart, /* receives decrypted output */
+ CK_ULONG* pulLastPartLen) /* receives decrypted byte count */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_DECRYPTFINAL_COMMAND_ID,
+ hSession,
+ NULL,
+ 0,
+ pLastPart,
+ pulLastPartLen,
+ FALSE,
+ TRUE);
+}
+
+
+CK_RV PKCS11_EXPORT C_GenerateKey(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the key generation mechanism */
+ const CK_ATTRIBUTE* pTemplate, /* template for the new key */
+ CK_ULONG ulCount, /* number of attributes in template */
+ CK_OBJECT_HANDLE* phKey) /* receives handle of new key */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEY_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ if ((pMechanism == NULL) || (phKey == NULL) || (pTemplate == NULL))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulCount);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
+ sOperation.params[0].value.b = 0;
+ sOperation.params[1].tmpref.buffer = pMechanism->pParameter;
+ sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
+ sOperation.params[2].tmpref.buffer = pBuffer;
+ sOperation.params[2].tmpref.size = nBufferSize;
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ *phKey = sOperation.params[0].value.a;
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_GenerateKeyPair(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the key gen. mech. */
+ const CK_ATTRIBUTE* pPublicKeyTemplate, /* pub. attr. template */
+ CK_ULONG ulPublicKeyAttributeCount, /* # of pub. attrs. */
+ const CK_ATTRIBUTE* pPrivateKeyTemplate, /* priv. attr. template */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # of priv. attrs. */
+ CK_OBJECT_HANDLE* phPublicKey, /* gets pub. key handle */
+ CK_OBJECT_HANDLE* phPrivateKey) /* gets priv. key handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATEKEYPAIR_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ if ( (pMechanism == NULL) ||
+ (pPublicKeyTemplate == NULL) || (pPrivateKeyTemplate == NULL) ||
+ (phPublicKey== NULL) || (phPrivateKey== NULL))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTwoTemplates(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pPublicKeyTemplate, ulPublicKeyAttributeCount, (CK_ATTRIBUTE*)pPrivateKeyTemplate, ulPrivateKeyAttributeCount);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
+ sOperation.params[0].value.b = 0;
+ sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
+ sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
+ sOperation.params[2].tmpref.buffer = pBuffer;
+ sOperation.params[2].tmpref.size = nBufferSize;
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ *phPublicKey = sOperation.params[0].value.a;
+ *phPrivateKey = sOperation.params[0].value.b;
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_DeriveKey(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ const CK_MECHANISM* pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ const CK_ATTRIBUTE* pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE* phKey) /* gets new handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_DERIVEKEY_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ if ((pMechanism == NULL) || (pTemplate == NULL) || (phKey == NULL))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 2, (CK_ATTRIBUTE*)pTemplate, ulAttributeCount);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = (uint32_t)pMechanism->mechanism;
+ sOperation.params[0].value.b = (uint32_t)hBaseKey;
+ sOperation.params[1].tmpref.buffer = (uint8_t*)pMechanism->pParameter;
+ sOperation.params[1].tmpref.size = (uint32_t)pMechanism->ulParameterLen;
+ sOperation.params[2].tmpref.buffer = pBuffer;
+ sOperation.params[2].tmpref.size = nBufferSize;
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ *phKey = sOperation.params[0].value.a;
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_SeedRandom(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pSeed, /* the seed material */
+ CK_ULONG ulSeedLen) /* count of bytes of seed material */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_SEEDRANDOM_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].tmpref.buffer = (uint8_t*)pSeed;
+ sOperation.params[0].tmpref.size = (uint32_t)ulSeedLen;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_GenerateRandom(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE* pRandomData, /* receives the random data */
+ CK_ULONG ulRandomLen) /* number of bytes to be generated */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_GENERATERANDOM_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ do
+ {
+ CK_ULONG nArrayLength;
+ nArrayLength = 1024;
+ if (ulRandomLen < nArrayLength)
+ {
+ nArrayLength = ulRandomLen;
+ }
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].tmpref.buffer = (uint8_t*)pRandomData;
+ sOperation.params[0].tmpref.size = (uint32_t)nArrayLength;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ ulRandomLen -= nArrayLength;
+ pRandomData += nArrayLength;
+ if (ulRandomLen == 0)
+ {
+ break;
+ }
+ }
+ while(1);
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_VerifyInit(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_MECHANISM* pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey) /* handle of the verification key */
+{
+ return static_C_CallInit(
+ SERVICE_SYSTEM_PKCS11_C_VERIFYINIT_COMMAND_ID,
+ hSession,
+ pMechanism,
+ hKey);
+}
+
+CK_RV PKCS11_EXPORT C_Verify(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pData, /* plaintext data (digest) to compare */
+ CK_ULONG ulDataLen, /* length of data (digest) in bytes */
+ CK_BYTE* pSignature, /* the signature to be verified */
+ CK_ULONG ulSignatureLen) /* count of bytes of signature */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_VERIFY_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].tmpref.buffer = (uint8_t*)pData;
+ sOperation.params[0].tmpref.size = (uint32_t)ulDataLen;
+ sOperation.params[1].tmpref.buffer = (uint8_t*)pSignature;
+ sOperation.params[1].tmpref.size = (uint32_t)ulSignatureLen;
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_VerifyUpdate(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pPart, /* plaintext data (digest) to compare */
+ CK_ULONG ulPartLen) /* length of data (digest) in bytes */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_VERIFYUPDATE_COMMAND_ID,
+ hSession,
+ pPart,
+ ulPartLen,
+ NULL,
+ NULL,
+ TRUE,
+ FALSE);
+}
+
+CK_RV PKCS11_EXPORT C_VerifyFinal(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ const CK_BYTE* pSignature, /* the signature to be verified */
+ CK_ULONG ulSignatureLen) /* count of bytes of signature */
+{
+ return static_C_Call_CallForUpdate(
+ SERVICE_SYSTEM_PKCS11_C_VERIFYFINAL_COMMAND_ID,
+ hSession,
+ pSignature,
+ ulSignatureLen,
+ NULL,
+ NULL,
+ TRUE,
+ FALSE);
+}
+
+CK_RV PKCS11_EXPORT C_CloseObjectHandle(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject) /* the object's handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_CLOSEOBJECTHANDLE_COMMAND_ID;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = (uint32_t)hObject;
+ sOperation.params[0].value.b = 0;
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_CopyObject(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the source object's handle */
+ const CK_ATTRIBUTE* pTemplate, /* the template of the copied object */
+ CK_ULONG ulCount, /* the number of attributes of the template*/
+ CK_OBJECT_HANDLE* phNewObject) /* the copied object's handle */
+{
+ TEEC_Result teeErr;
+ uint32_t nErrorOrigin;
+ TEEC_Operation sOperation;
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nCommandIDAndSession = SERVICE_SYSTEM_PKCS11_C_COPYOBJECT_COMMAND_ID;
+ uint8_t* pBuffer = NULL;
+ uint32_t nBufferSize = 0;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ if ((pTemplate == NULL) || (phNewObject == NULL))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ nErrorCode = static_checkPreConditionsAndUpdateHandles(&hSession, &nCommandIDAndSession, &pSession);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ nErrorCode = static_encodeTemplate(&pBuffer, &nBufferSize, 1, (CK_ATTRIBUTE*)pTemplate, ulCount);
+ if (nErrorCode != CKR_OK)
+ {
+ return nErrorCode;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = (uint32_t)hObject;
+ sOperation.params[0].value.b = 0;
+ sOperation.params[1].tmpref.buffer = pBuffer;
+ sOperation.params[1].tmpref.size = nBufferSize;
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ teeErr = TEEC_InvokeCommand( &pSession->sSession,
+ nCommandIDAndSession, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ free(pBuffer);
+
+ if (teeErr != TEEC_SUCCESS)
+ {
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ teeErr :
+ ckInternalTeeErrorToCKError(teeErr));
+ return nErrorCode;
+ }
+
+ *phNewObject = sOperation.params[0].value.a;
+
+ return CKR_OK;
+}
diff --git a/security/tf_crypto_sst/pkcs11_session.c b/security/tf_crypto_sst/pkcs11_session.c
new file mode 100644
index 00000000..bc845c7e
--- /dev/null
+++ b/security/tf_crypto_sst/pkcs11_session.c
@@ -0,0 +1,420 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Implementation Notes:
+ *
+ * The PKCS11 session handle is directly mapped on the
+ * Trusted Foundations Software session handle (S_HANDLE).
+ */
+
+#include "pkcs11_internal.h"
+
+
+/* ------------------------------------------------------------------------
+ Public Functions
+------------------------------------------------------------------------- */
+
+
+CK_RV PKCS11_EXPORT C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* defined in CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* pointer passed to callback */
+ CK_NOTIFY Notify, /* notification callback function */
+ CK_SESSION_HANDLE* phSession) /* receives new session handle */
+{
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nErrorOrigin = TEEC_ORIGIN_API;
+ TEEC_Result nTeeError;
+ TEEC_Operation sOperation;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession = NULL;
+ PPKCS11_SECONDARY_SESSION_CONTEXT pSecondarySession = NULL;
+ uint32_t nLoginType;
+ uint32_t nLoginData = 0;
+ void* pLoginData = NULL;
+ bool bIsPrimarySession;
+ char* pSignatureFile = NULL;
+ uint32_t nSignatureFileLen = 0;
+ uint8_t nParamType3 = TEEC_NONE;
+
+ /* Prevent the compiler from complaining about unused parameters */
+ do{(void)pApplication;}while(0);
+ do{(void)Notify;}while(0);
+
+ if (phSession == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ /* Check Cryptoki is initialized */
+ if (!g_bCryptokiInitialized)
+ {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+
+ if ((flags & CKVF_OPEN_SUB_SESSION) == 0)
+ {
+ *phSession = CK_INVALID_HANDLE;
+
+ /*
+ * Allocate the session context
+ */
+ pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)malloc(sizeof(PKCS11_PRIMARY_SESSION_CONTEXT));
+ if (pSession == NULL)
+ {
+ return CKR_DEVICE_MEMORY;
+ }
+
+ pSession->sHeader.nMagicWord = PKCS11_SESSION_MAGIC;
+ pSession->sHeader.nSessionTag = PKCS11_PRIMARY_SESSION_TAG;
+ memset(&pSession->sSession, 0, sizeof(TEEC_Session));
+ pSession->sSecondarySessionTable.pRoot = NULL_PTR;
+
+ /* The structure must be initialized first (in a portable manner)
+ to make it work on Win32 */
+ memset(&pSession->sSecondarySessionTableMutex, 0,
+ sizeof(pSession->sSecondarySessionTableMutex));
+ libMutexInit(&pSession->sSecondarySessionTableMutex);
+
+ switch (slotID)
+ {
+ case CKV_TOKEN_SYSTEM_SHARED:
+ case CKV_TOKEN_USER_SHARED:
+ nLoginType = TEEC_LOGIN_PUBLIC;
+ break;
+
+ case CKV_TOKEN_SYSTEM:
+ case CKV_TOKEN_USER:
+ default:
+ nLoginType = TEEC_LOGIN_AUTHENTICATION;
+ break;
+ }
+
+ /* Group tokens */
+ if ((slotID >= 0x00010000) && (slotID <= 0x0002FFFF))
+ {
+ nLoginType = TEEC_LOGIN_GROUP;
+
+ /* The 16 lower-order bits encode the group identifier */
+ nLoginData = (uint32_t)slotID & 0x0000FFFF;
+ pLoginData = (void*)&nLoginData;
+
+ /* Update the slotID for the system / PKCS11 service */
+ if ((slotID >= 0x00010000) && (slotID <= 0x0001FFFF))
+ {
+ /* System group token */
+ slotID = 3; /* CKV_TOKEN_SYSTEM_GROUP */
+ }
+ else /* ((slotID >= 0x00020000) && (slotID <= 0x0002FFFF)) */
+ {
+ /* User group token */
+ slotID = 0x4014; /* CKV_TOKEN_USER_GROUP */
+ }
+ }
+
+retry:
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+
+ if (nLoginType == TEEC_LOGIN_AUTHENTICATION)
+ {
+ nTeeError = TEEC_ReadSignatureFile((void **)&pSignatureFile, &nSignatureFileLen);
+ if (nTeeError != TEEC_ERROR_ITEM_NOT_FOUND)
+ {
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto error;
+ }
+
+ sOperation.params[3].tmpref.buffer = pSignatureFile;
+ sOperation.params[3].tmpref.size = nSignatureFileLen;
+ nParamType3 = TEEC_MEMREF_TEMP_INPUT;
+ }
+ else
+ {
+ /* No signature file found.
+ * Should use LOGIN_APPLICATION for now
+ * Can not use TEEC_LOGIN_AUTHENTICATION as this means that all .exe wil need a signature file
+ * - a bit annoying for when passing the tests
+ */
+ nLoginType = TEEC_LOGIN_USER_APPLICATION;
+ }
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3);
+ nTeeError = TEEC_OpenSession(&g_sContext,
+ &pSession->sSession, /* OUT session */
+ &SERVICE_UUID, /* destination UUID */
+ nLoginType, /* connectionMethod */
+ pLoginData, /* connectionData */
+ &sOperation, /* IN OUT operation */
+ NULL /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ /* No need of the returnOrigin as this is not specific to P11 */
+
+ if ( (nTeeError == TEEC_ERROR_NOT_SUPPORTED) &&
+ (nLoginType == TEEC_LOGIN_AUTHENTICATION))
+ {
+ /* We could not open a session with the login TEEC_LOGIN_AUTHENTICATION */
+ /* If it is not supported by the product, */
+ /* retry with fallback to TEEC_LOGIN_USER_APPLICATION */
+ nLoginType = TEEC_LOGIN_USER_APPLICATION;
+ goto retry;
+ }
+
+ /* The ERROR_ACCESS_DENIED, if returned, will be converted into CKR_TOKEN_NOT_PRESENT
+ * For the External Cryptographic API, this means that the authentication
+ * of the calling application fails.
+ */
+ goto error;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.params[0].value.a = slotID;
+ sOperation.params[0].value.b = flags; /* access flags */
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ nTeeError = TEEC_InvokeCommand(&pSession->sSession,
+ SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF,
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto error;
+ }
+
+ *phSession = (CK_SESSION_HANDLE)pSession;
+ pSession->hCryptoSession = sOperation.params[0].value.a;
+
+ return CKR_OK;
+ }
+ else
+ {
+ bool bResult;
+
+ /* Check that {*phSession} is a valid primary session handle */
+ if ((!ckInternalSessionIsOpenedEx(*phSession, &bIsPrimarySession)) ||
+ (!bIsPrimarySession))
+ {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+
+ pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(*phSession);
+
+ /* allocate the secondary session context */
+ pSecondarySession = (PKCS11_SECONDARY_SESSION_CONTEXT*)malloc(sizeof(PKCS11_SECONDARY_SESSION_CONTEXT));
+ if (pSecondarySession == NULL)
+ {
+ return CKR_DEVICE_MEMORY;
+ }
+ pSecondarySession->sHeader.nMagicWord = PKCS11_SESSION_MAGIC;
+ pSecondarySession->sHeader.nSessionTag = PKCS11_SECONDARY_SESSION_TAG;
+ pSecondarySession->pPrimarySession = pSession;
+
+ libMutexLock(&pSession->sSecondarySessionTableMutex);
+ bResult = libObjectHandle16Add(&pSession->sSecondarySessionTable,
+ &pSecondarySession->sSecondarySessionNode);
+ libMutexUnlock(&pSession->sSecondarySessionTableMutex);
+ if (bResult == false)
+ {
+ free(pSecondarySession);
+ return CKR_DEVICE_MEMORY;
+ }
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ nTeeError = TEEC_InvokeCommand(&pSession->sSession,
+ (pSession->hCryptoSession << 16) |
+ (1 << 15) |
+ (SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID & 0x00007FFF),
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto error;
+ }
+
+ *phSession = (CK_SESSION_HANDLE)pSecondarySession;
+ pSecondarySession->hSecondaryCryptoSession = sOperation.params[0].value.a;
+
+ return CKR_OK;
+ }
+
+error:
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ nTeeError :
+ ckInternalTeeErrorToCKError(nTeeError));
+
+ if ((flags & CKVF_OPEN_SUB_SESSION) == 0)
+ {
+ libMutexDestroy(&pSession->sSecondarySessionTableMutex);
+ free(pSession);
+ }
+ else
+ {
+ libMutexLock(&pSession->sSecondarySessionTableMutex);
+ libObjectHandle16Remove(&pSession->sSecondarySessionTable,&pSecondarySession->sSecondarySessionNode);
+ libMutexUnlock(&pSession->sSecondarySessionTableMutex);
+ free(pSecondarySession);
+ }
+
+ return nErrorCode;
+}
+
+CK_RV PKCS11_EXPORT C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
+{
+ CK_RV nErrorCode = CKR_OK;
+ uint32_t nErrorOrigin = TEEC_ORIGIN_API;
+ TEEC_Result nTeeError;
+ TEEC_Operation sOperation;
+ bool bIsPrimarySession;
+
+ /* Check Cryptoki is initialized */
+ if (!g_bCryptokiInitialized)
+ {
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+
+ if (!ckInternalSessionIsOpenedEx(hSession, &bIsPrimarySession))
+ {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+
+ if (bIsPrimarySession)
+ {
+ LIB_OBJECT_NODE_HANDLE16* pObject;
+ PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)hSession;
+
+ hSession = pSession->hCryptoSession;
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ nTeeError = TEEC_InvokeCommand(&pSession->sSession,
+ (pSession->hCryptoSession << 16 ) |
+ (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF),
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto end;
+ }
+
+ TEEC_CloseSession(&pSession->sSession);
+ memset(&pSession->sSession, 0, sizeof(TEEC_Session));
+
+ /* Free all secondary session contexts */
+ libMutexLock(&pSession->sSecondarySessionTableMutex);
+ pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable);
+ while (pObject != NULL)
+ {
+ /* find all secondary session contexts,
+ and release associated resources */
+
+ pSecSession = LIB_OBJECT_CONTAINER_OF(pObject, //ptr
+ PKCS11_SECONDARY_SESSION_CONTEXT,//type
+ sSecondarySessionNode);//member
+
+ /* free secondary session context */
+ free(pSecSession);
+
+ pObject = libObjectHandle16RemoveOne(&pSession->sSecondarySessionTable);
+ }
+ libMutexUnlock(&pSession->sSecondarySessionTableMutex);
+
+ libMutexDestroy(&pSession->sSecondarySessionTableMutex);
+
+ /* free primary session context */
+ free(pSession);
+ }
+ else
+ {
+ PPKCS11_SECONDARY_SESSION_CONTEXT pSecSession = (PPKCS11_SECONDARY_SESSION_CONTEXT)hSession;
+ PPKCS11_PRIMARY_SESSION_CONTEXT pSession;
+
+ uint32_t nCommandID = ( (pSecSession->hSecondaryCryptoSession & 0xFFFF) << 16 ) |
+ (1 << 15) |
+ (SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID & 0x00007FFF);
+
+ /* every pre-check are fine, then, update the local handles */
+ hSession = pSecSession->pPrimarySession->hCryptoSession;
+ pSession = (PPKCS11_PRIMARY_SESSION_CONTEXT)(pSecSession->pPrimarySession);
+
+ memset(&sOperation, 0, sizeof(TEEC_Operation));
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ nTeeError = TEEC_InvokeCommand(&pSession->sSession,
+ nCommandID,
+ &sOperation, /* IN OUT operation */
+ &nErrorOrigin /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto end;
+ }
+
+ /* remove the object from the table */
+ libMutexLock(&pSession->sSecondarySessionTableMutex);
+ libObjectHandle16Remove(&pSecSession->pPrimarySession->sSecondarySessionTable, &pSecSession->sSecondarySessionNode);
+ libMutexUnlock(&pSession->sSecondarySessionTableMutex);
+
+ /* free secondary session context */
+ free(pSecSession);
+ }
+
+end:
+ nErrorCode = (nErrorOrigin == TEEC_ORIGIN_TRUSTED_APP ?
+ nTeeError :
+ ckInternalTeeErrorToCKError(nTeeError));
+ return nErrorCode;
+}
+
+
+CK_RV PKCS11_EXPORT C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ const CK_UTF8CHAR* pPin, /* the user's PIN */
+ CK_ULONG ulPinLen) /* the length of the PIN */
+{
+ /* Prevent the compiler from complaining about unused variables */
+ do{(void)hSession;}while(0);
+ do{(void)userType;}while(0);
+ do{(void)pPin;}while(0);
+ do{(void)ulPinLen;}while(0);
+
+ return CKR_OK;
+}
+
+CK_RV PKCS11_EXPORT C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
+{
+ do{(void)hSession;}while(0);
+
+ return CKR_OK;
+}
diff --git a/security/tf_crypto_sst/service_system_protocol.h b/security/tf_crypto_sst/service_system_protocol.h
new file mode 100644
index 00000000..560ec40c
--- /dev/null
+++ b/security/tf_crypto_sst/service_system_protocol.h
@@ -0,0 +1,116 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SERVICE_SYSTEM_PROTOCOL_H__
+#define __SERVICE_SYSTEM_PROTOCOL_H__
+
+#include "s_type.h"
+
+/* -----------------------------------------------------------------------------
+ UUID and Name
+----------------------------------------------------------------------------- */
+
+/** Service Identifier */
+/* {56304b83-5c4e-4428-b99e-605c96ae58d6} */
+#define SERVICE_SYSTEM_UUID { 0x56304b83, 0x5c4e, 0x4428, { 0xb9, 0x9e, 0x60, 0x5c, 0x96, 0xae, 0x58, 0xd6 } }
+
+/** Generic type for error codes in the system service */
+#define SERVICE_SYSTEM_NAME_ASCII "SYSTEM"
+
+
+/* -----------------------------------------------------------------------------
+ SST Command identifiers
+----------------------------------------------------------------------------- */
+
+#define SERVICE_SYSTEM_SST_OPEN_COMMAND_ID 0x00000001
+#define SERVICE_SYSTEM_SST_CLOSE_COMMAND_ID 0x00000002
+#define SERVICE_SYSTEM_SST_READ_COMMAND_ID 0x00000003
+#define SERVICE_SYSTEM_SST_WRITE_COMMAND_ID 0x00000004
+#define SERVICE_SYSTEM_SST_SEEK_COMMAND_ID 0x00000005
+#define SERVICE_SYSTEM_SST_GET_OFFSET_AND_SIZE_COMMAND_ID 0x00000007
+#define SERVICE_SYSTEM_SST_GET_SIZE_COMMAND_ID 0x00000008
+#define SERVICE_SYSTEM_SST_CLOSE_DELETE_COMMAND_ID 0x00000009
+#define SERVICE_SYSTEM_SST_TRUNCATE_COMMAND_ID 0x0000000A
+#define SERVICE_SYSTEM_SST_ENUM_START_COMMAND_ID 0x0000000B
+#define SERVICE_SYSTEM_SST_ENUM_GETNEXT_COMMAND_ID 0x0000000C
+#define SERVICE_SYSTEM_SST_ENUM_CLOSE_COMMAND_ID 0x0000000D
+#define SERVICE_SYSTEM_SST_RENAME_COMMAND_ID 0x0000000E
+
+/* -----------------------------------------------------------------------------
+ PKCS11/MTC Command identifiers
+----------------------------------------------------------------------------- */
+#define SERVICE_SYSTEM_PKCS11_C_CREATEOBJECT_COMMAND_ID 0x00000020
+#define SERVICE_SYSTEM_PKCS11_C_DESTROYOBJECT_COMMAND_ID 0x00000021
+#define SERVICE_SYSTEM_PKCS11_C_GETATTRIBUTEVALUE_COMMAND_ID 0x00000022
+#define SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSINIT_COMMAND_ID 0x00000023
+#define SERVICE_SYSTEM_PKCS11_C_FINDOBJECTS_COMMAND_ID 0x00000024
+#define SERVICE_SYSTEM_PKCS11_C_FINDOBJECTSFINAL_COMMAND_ID 0x00000025
+#define SERVICE_SYSTEM_PKCS11_C_DIGESTINIT_COMMAND_ID 0x00000026
+#define SERVICE_SYSTEM_PKCS11_C_DIGEST_COMMAND_ID 0x00000027
+#define SERVICE_SYSTEM_PKCS11_C_DIGESTUPDATE_COMMAND_ID 0x00000028
+#define SERVICE_SYSTEM_PKCS11_C_DIGESTFINAL_COMMAND_ID 0x00000029
+#define SERVICE_SYSTEM_PKCS11_C_SIGNINIT_COMMAND_ID 0x0000002A
+#define SERVICE_SYSTEM_PKCS11_C_SIGN_COMMAND_ID 0x0000002B
+#define SERVICE_SYSTEM_PKCS11_C_SIGNUPDATE_COMMAND_ID 0x0000002C
+#define SERVICE_SYSTEM_PKCS11_C_SIGNFINAL_COMMAND_ID 0x0000002D
+#define SERVICE_SYSTEM_PKCS11_C_ENCRYPTINIT_COMMAND_ID 0x0000002E
+#define SERVICE_SYSTEM_PKCS11_C_ENCRYPT_COMMAND_ID 0x0000002F
+#define SERVICE_SYSTEM_PKCS11_C_ENCRYPTUPDATE_COMMAND_ID 0x00000030
+#define SERVICE_SYSTEM_PKCS11_C_ENCRYPTFINAL_COMMAND_ID 0x00000031
+#define SERVICE_SYSTEM_PKCS11_C_DECRYPTINIT_COMMAND_ID 0x00000032
+#define SERVICE_SYSTEM_PKCS11_C_DECRYPT_COMMAND_ID 0x00000033
+#define SERVICE_SYSTEM_PKCS11_C_DECRYPTUPDATE_COMMAND_ID 0x00000034
+#define SERVICE_SYSTEM_PKCS11_C_DECRYPTFINAL_COMMAND_ID 0x00000035
+#define SERVICE_SYSTEM_PKCS11_C_GENERATEKEY_COMMAND_ID 0x00000036
+#define SERVICE_SYSTEM_PKCS11_C_GENERATEKEYPAIR_COMMAND_ID 0x00000037
+#define SERVICE_SYSTEM_PKCS11_C_SEEDRANDOM_COMMAND_ID 0x00000038
+#define SERVICE_SYSTEM_PKCS11_C_GENERATERANDOM_COMMAND_ID 0x00000039
+#define SERVICE_SYSTEM_PKCS11_C_VERIFYINIT_COMMAND_ID 0x0000003A
+#define SERVICE_SYSTEM_PKCS11_C_VERIFY_COMMAND_ID 0x0000003B
+#define SERVICE_SYSTEM_PKCS11_C_VERIFYUPDATE_COMMAND_ID 0x0000003C
+#define SERVICE_SYSTEM_PKCS11_C_VERIFYFINAL_COMMAND_ID 0x0000003D
+#define SERVICE_SYSTEM_PKCS11_C_DERIVEKEY_COMMAND_ID 0x0000003E
+#define SERVICE_SYSTEM_PKCS11_C_ABORTOPERATION_COMMAND_ID 0x0000003F
+#define SERVICE_SYSTEM_PKCS11_C_COPYOBJECT_COMMAND_ID 0x00000040
+#define SERVICE_SYSTEM_PKCS11_C_CLOSEOBJECTHANDLE_COMMAND_ID 0x00000041
+#define SERVICE_SYSTEM_PKCS11_C_OPEN_SESSION_COMMAND_ID 0x00000042
+#define SERVICE_SYSTEM_PKCS11_C_CLOSE_SESSION_COMMAND_ID 0x00000043
+#define SERVICE_SYSTEM_PKCS11_INCREMENT_MTC_COMMAND_ID 0x00000044
+#define SERVICE_SYSTEM_PKCS11_GET_MTC_COMMAND_ID 0x00000045
+
+typedef struct
+{
+ uint32_t attributeType;
+ uint32_t dataOffset : 30;
+ uint32_t dataParamIndex : 2;
+ uint32_t dataValueLen;
+} INPUT_TEMPLATE_ITEM;
+
+#endif /* __SERVICE_SYSTEM_PROTOCOL_H__ */
diff --git a/security/tf_crypto_sst/sst_stub.c b/security/tf_crypto_sst/sst_stub.c
new file mode 100644
index 00000000..e8a78bcf
--- /dev/null
+++ b/security/tf_crypto_sst/sst_stub.c
@@ -0,0 +1,800 @@
+/**
+ * Copyright(c) 2011 Trusted Logic. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Trusted Logic nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __ANDROID32__
+#include <stddef.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#define SST_EXPORTS
+#define EXCLUDE_SERVICE_SYSTEM_SST_BASIC_TYPES
+#include "sst.h"
+
+/* Included for the TEE management */
+#include "pkcs11_internal.h"
+
+
+static TEEC_Session g_SSTSession;
+static bool g_bSSTInitialized = false;
+
+
+/* ------------------------------------------------------------------------
+ TEEC -> SST error code translation
+ ------------------------------------------------------------------------- */
+static SST_ERROR static_SSTConvertErrorCode(TEEC_Result nError)
+{
+ switch (nError)
+ {
+ case TEEC_SUCCESS:
+ return SST_SUCCESS;
+ case SST_ERROR_BAD_PARAMETERS:
+ case SST_ERROR_ACCESS_DENIED:
+ case SST_ERROR_ACCESS_CONFLICT:
+ case SST_ERROR_CORRUPTED:
+ case SST_ERROR_NO_SPACE:
+ case SST_ERROR_ITEM_NOT_FOUND:
+ case SST_ERROR_OUT_OF_MEMORY:
+ case SST_ERROR_OVERFLOW:
+ return nError;
+ default:
+ return SST_ERROR_GENERIC;
+ }
+}
+
+static TEEC_Session* static_SSTGetSession(void)
+{
+ if (g_bSSTInitialized)
+ {
+ return &g_SSTSession;
+ }
+
+ return NULL;
+}
+
+SST_ERROR SST_EXPORT_API SSTInit(void)
+{
+ TEEC_Result nTeeError = TEEC_SUCCESS;
+ TEEC_Operation sOperation;
+ uint8_t nParamType3 = TEEC_NONE;
+ void* pSignatureFile = NULL;
+ uint32_t nSignatureFileLen = 0;
+ uint32_t nLoginType;
+
+ stubMutexLock();
+ if (g_bSSTInitialized)
+ {
+ /* SST library already initialized */
+ nTeeError = TEEC_SUCCESS;
+ goto end;
+ }
+
+ nTeeError = stubInitializeContext();
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto end;
+ }
+
+ /* Check if there is a signature file.
+ * If yes, send it in param3, otherwise use LOGIN_APPLICATION
+ */
+ nTeeError = TEEC_ReadSignatureFile(&pSignatureFile, &nSignatureFileLen);
+ if (nTeeError == TEEC_ERROR_ITEM_NOT_FOUND)
+ {
+ nLoginType = TEEC_LOGIN_USER_APPLICATION;
+ }
+ else
+ {
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto end;
+ }
+ sOperation.params[3].tmpref.buffer = pSignatureFile;
+ sOperation.params[3].tmpref.size = nSignatureFileLen;
+ nParamType3 = TEEC_MEMREF_TEMP_INPUT;
+ nLoginType = TEEC_LOGIN_AUTHENTICATION;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, nParamType3);
+ nTeeError = TEEC_OpenSession(&g_sContext,
+ &g_SSTSession, /* OUT session */
+ &SERVICE_UUID, /* destination UUID */
+ nLoginType, /* connectionMethod */
+ NULL, /* connectionData */
+ &sOperation, /* IN OUT operation */
+ NULL /* OUT returnOrigin, optional */
+ );
+ if (nTeeError != TEEC_SUCCESS)
+ {
+ goto end_finalize_context;
+ }
+
+ g_bSSTInitialized = true;
+ stubMutexUnlock();
+ return SST_SUCCESS;
+
+end_finalize_context:
+ stubFinalizeContext();
+end:
+ stubMutexUnlock();
+ return static_SSTConvertErrorCode(nTeeError);
+}
+
+SST_ERROR SST_EXPORT_API SSTTerminate(void)
+{
+ stubMutexLock();
+ if (g_bSSTInitialized)
+ {
+ TEEC_CloseSession(&g_SSTSession);
+ stubFinalizeContext();
+ g_bSSTInitialized = false;
+ }
+ /* else if not intialized => success too */
+ stubMutexUnlock();
+ return SST_SUCCESS;
+}
+
+
+/* ------------------------------------------------------------------------
+ Other API Functions
+------------------------------------------------------------------------- */
+
+
+/* Check that the input filename is well-formed */
+static SST_ERROR static_SSTCheckFileName(const char* pName)
+{
+ uint32_t i;
+ char c;
+
+ if (pName == NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ for (i = 0; i <= SST_MAX_FILENAME; i++)
+ {
+ c = pName[i];
+ if (c == 0)
+ {
+ /* End of the string */
+ return SST_SUCCESS;
+ }
+
+ if (c == '/' || c == '\\')
+ {
+ /* Invalid character */
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ if (c < 0x20 || c >= 0x7F)
+ {
+ /* Filename contains illegal characters */
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+ }
+ /* Filename is too long. Zero terminator not found */
+ return SST_ERROR_BAD_PARAMETERS;
+}
+
+static SST_ERROR static_SSTCheckPattern(
+ const char* pFilenamePattern)
+{
+ uint32_t i;
+ if(pFilenamePattern == NULL)
+ {
+ return S_SUCCESS;
+ }
+
+ /**
+ * Check Forbidden characters.
+ */
+ for (i = 0; pFilenamePattern[i] != 0; i++)
+ {
+ if(pFilenamePattern[i] < 0x20 )
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+ else if(pFilenamePattern[i] == 0x2F ) /* '/' */
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+ else if(pFilenamePattern[i] == 0x5C ) /* '\' */
+ {
+ /**
+ * Must be directly followed by asterisk character or question-mark
+ * character.
+ */
+ if (! ((pFilenamePattern[i+1] == '*' ||
+ pFilenamePattern[i+1] == '?')))
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+ }
+ else if(pFilenamePattern[i] >= 0x7F )
+ {
+ return S_ERROR_BAD_PARAMETERS;
+ }
+ }
+
+ return S_SUCCESS;
+}
+
+
+
+SST_ERROR SST_EXPORT_API SSTOpen(const char* pFilename,
+ uint32_t nFlags,
+ uint32_t nReserved,
+ SST_HANDLE* phFile)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+ SST_ERROR nErrorCode = SST_SUCCESS;
+
+ if (phFile == NULL || nReserved != 0)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ *phFile = SST_HANDLE_INVALID;
+
+ nErrorCode = static_SSTCheckFileName(pFilename);
+ if (nErrorCode != SST_SUCCESS)
+ {
+ return nErrorCode;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = 1; /* Private storage */
+ sOperation.params[0].value.b = nFlags; /* Access flags */
+ sOperation.params[1].tmpref.buffer = (void*)pFilename;
+ sOperation.params[1].tmpref.size = strlen(pFilename);
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_OPEN_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+ if (nError == TEEC_SUCCESS)
+ {
+ *phFile = (SST_HANDLE)sOperation.params[0].value.a;
+ }
+
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTCloseHandle(SST_HANDLE hFile)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ if (hFile == S_HANDLE_NULL)
+ {
+ return SST_SUCCESS;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_CLOSE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTWrite(SST_HANDLE hFile,
+ const uint8_t* pBuffer,
+ uint32_t nSize)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ if (pBuffer == NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ if (nSize == 0)
+ {
+ return SST_SUCCESS;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ sOperation.params[1].tmpref.buffer = (void*)pBuffer;
+ sOperation.params[1].tmpref.size = nSize;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_WRITE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ return static_SSTConvertErrorCode(nError);
+}
+
+
+SST_ERROR SST_EXPORT_API SSTRead(SST_HANDLE hFile,
+ uint8_t* pBuffer,
+ uint32_t nSize,
+ uint32_t* pnCount)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ if ((pBuffer == NULL) || (pnCount == NULL))
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+ *pnCount = 0;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ if (nSize == 0)
+ {
+ return SST_SUCCESS;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ sOperation.params[1].tmpref.buffer = pBuffer;
+ sOperation.params[1].tmpref.size = nSize;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_READ_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ *pnCount = sOperation.params[1].tmpref.size; /* The returned buffer size */
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTSeek(SST_HANDLE hFile,
+ int32_t nOffset,
+ SST_WHENCE whence)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ switch(whence)
+ {
+ case SST_SEEK_SET:
+ case SST_SEEK_CUR:
+ case SST_SEEK_END:
+ break;
+ default:
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ sOperation.params[1].value.a = nOffset;
+ sOperation.params[1].value.b = (uint32_t)whence;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_SEEK_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+ return static_SSTConvertErrorCode(nError);
+
+}
+
+static SST_ERROR SSTGetOffsetAndSize(SST_HANDLE hFile, uint32_t* pnOffset, uint32_t* pnSize)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ if (pnOffset == NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = (uint32_t)hFile;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_GET_OFFSET_AND_SIZE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ if (pnOffset != NULL)
+ {
+ *pnOffset = sOperation.params[0].value.a;
+ }
+ if (pnSize != NULL)
+ {
+ *pnSize = sOperation.params[0].value.b;
+ }
+ return static_SSTConvertErrorCode(nError);
+
+}
+
+SST_ERROR SST_EXPORT_API SSTTell(SST_HANDLE hFile,
+ uint32_t* pnPos)
+{
+ return SSTGetOffsetAndSize(hFile, pnPos, NULL);
+}
+
+SST_ERROR SST_EXPORT_API SSTGetSize(const char* pFilename,
+ uint32_t* pnSize)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ if ((pFilename == NULL) || (pnSize == NULL))
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ nError = static_SSTCheckFileName(pFilename);
+ if (nError != SST_SUCCESS)
+ {
+ return nError;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = 1; /* private storage */
+ sOperation.params[0].value.b = 0;
+ sOperation.params[1].tmpref.buffer = (void*)pFilename;
+ sOperation.params[1].tmpref.size = strlen(pFilename);
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_GET_SIZE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ *pnSize = sOperation.params[0].value.a;
+ return static_SSTConvertErrorCode(nError);
+}
+
+
+SST_ERROR SST_EXPORT_API SSTEof( SST_HANDLE hFile,
+ bool* pbEof)
+{
+ uint32_t nOffset;
+ uint32_t nSize;
+ SST_ERROR nError;
+ if (pbEof == NULL)
+ return SST_ERROR_BAD_PARAMETERS;
+ nError = SSTGetOffsetAndSize(hFile, &nOffset, &nSize);
+ if (nError == SST_SUCCESS)
+ {
+ if (nOffset >= nSize)
+ {
+ *pbEof = true;
+ }
+ else
+ {
+ *pbEof = false;
+ }
+ }
+ return nError;
+}
+
+SST_ERROR SST_EXPORT_API SSTCloseAndDelete(SST_HANDLE hFile)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_CLOSE_DELETE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTTruncate(SST_HANDLE hFile, uint32_t nLength)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ sOperation.params[0].value.b = nLength;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_TRUNCATE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTRename(SST_HANDLE hFile,
+ const char* pNewFilename)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ if (pNewFilename == NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ nError = static_SSTCheckFileName(pNewFilename);
+ if (nError != SST_SUCCESS)
+ {
+ return nError;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFile;
+ sOperation.params[1].tmpref.buffer = (void*)pNewFilename;
+ sOperation.params[1].tmpref.size = strlen(pNewFilename);
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_RENAME_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTEnumerationStart(const char* pFilenamePattern,
+ uint32_t nReserved1,
+ uint32_t nReserved2,
+ SST_HANDLE* phFileEnumeration)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ if (nReserved1!=0 || nReserved2!=0)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+ if (phFileEnumeration==NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+ *phFileEnumeration = SST_HANDLE_INVALID;
+
+ nError = static_SSTCheckPattern(pFilenamePattern);
+ if (nError != SST_SUCCESS)
+ {
+ return nError;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = 1; /* Private storage */
+ sOperation.params[1].tmpref.buffer = (void*)pFilenamePattern;
+ if (pFilenamePattern != NULL)
+ {
+ sOperation.params[1].tmpref.size = strlen(pFilenamePattern);
+ }
+ else
+ {
+ sOperation.params[1].tmpref.size = 0;
+ }
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_ENUM_START_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ *phFileEnumeration = (SST_HANDLE)sOperation.params[0].value.a;
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTEnumerationCloseHandle(SST_HANDLE hFileEnumeration)
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFileEnumeration;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_ENUM_CLOSE_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ return static_SSTConvertErrorCode(nError);
+}
+
+SST_ERROR SST_EXPORT_API SSTEnumerationGetNext(SST_HANDLE hFileEnumeration,
+ SST_FILE_INFO** ppFileInfo)
+
+{
+ TEEC_Session* pSession;
+ TEEC_Result nError;
+ TEEC_Operation sOperation;
+ uint32_t nReturnOrigin;
+ SST_FILE_INFO* pInfo = NULL;
+ char sFilename[SST_MAX_FILENAME];
+
+ if (ppFileInfo==NULL)
+ {
+ return SST_ERROR_BAD_PARAMETERS;
+ }
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, TEEC_NONE);
+ sOperation.params[0].value.a = hFileEnumeration;
+ sOperation.params[1].tmpref.buffer = sFilename;
+ sOperation.params[1].tmpref.size = SST_MAX_FILENAME;
+
+ nError = TEEC_InvokeCommand(pSession,
+ SERVICE_SYSTEM_SST_ENUM_GETNEXT_COMMAND_ID, /* commandID */
+ &sOperation, /* IN OUT operation */
+ &nReturnOrigin /* OUT returnOrigin, optional */
+ );
+
+ if (nError == TEEC_SUCCESS)
+ {
+ if (sOperation.params[1].tmpref.size <= SST_MAX_FILENAME)
+ {
+ pInfo = (SST_FILE_INFO*)malloc(sizeof(SST_FILE_INFO));
+ if (pInfo == NULL)
+ {
+ return SST_ERROR_OUT_OF_MEMORY;
+ }
+ pInfo->pName = (char*)malloc(sOperation.params[1].tmpref.size+1);
+ if (pInfo->pName == NULL)
+ {
+ free(pInfo);
+ return SST_ERROR_OUT_OF_MEMORY;
+ }
+ memcpy(pInfo->pName, sFilename, sOperation.params[1].tmpref.size);
+ /* Add zero terminator */
+ pInfo->pName[sOperation.params[1].tmpref.size] = 0;
+ pInfo->nSize = sOperation.params[0].value.b;
+ }
+ }
+ *ppFileInfo = pInfo;
+ return static_SSTConvertErrorCode(nError);
+ }
+
+SST_ERROR SST_EXPORT_API SSTDestroyFileInfo(SST_FILE_INFO* pFileInfo)
+{
+ TEEC_Session* pSession;
+
+ pSession = static_SSTGetSession();
+ if (pSession == NULL)
+ {
+ return SST_ERROR_GENERIC;
+ }
+
+ if (pFileInfo != NULL)
+ {
+ free(pFileInfo->pName);
+ free(pFileInfo);
+ }
+ return SST_SUCCESS;
+}