/** * @file tlcTeeKeymaster_if.c * @brief Contains trustlet connector interface implementations to * handle key operations with TEE Keymaster trustlet * * Copyright Giesecke & Devrient GmbH 2012 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdlib.h> #include "MobiCoreDriverApi.h" #include "tlTeeKeymaster_Api.h" #include "tlcTeeKeymaster_log.h" #include "tlcTeeKeymaster_if.h" /* Global definitions */ static const uint32_t DEVICE_ID = MC_DEVICE_ID_DEFAULT; static const mcUuid_t uuid = TEE_KEYMASTER_TL_UUID; /** * TEE_Open * * Open session to the TEE Keymaster trustlet * * @param pSessionHandle [out] Return pointer to the session handle */ static tciMessage_ptr TEE_Open( mcSessionHandle_t *pSessionHandle ){ tciMessage_ptr pTci = NULL; mcResult_t mcRet; do { /* Validate session handle */ if (!pSessionHandle) { LOG_E("TEE_Open(): Invalid session handle\n"); break; } /* Initialize session handle data */ bzero(pSessionHandle, sizeof(mcSessionHandle_t)); /* Open MobiCore device */ mcRet = mcOpenDevice(DEVICE_ID); if (MC_DRV_OK != mcRet) { LOG_E("TEE_Open(): mcOpenDevice returned: %d\n", mcRet); break; } /* Allocating WSM for TCI */ mcRet = mcMallocWsm(DEVICE_ID, 0, sizeof(tciMessage_t), (uint8_t **) &pTci, 0); if (MC_DRV_OK != mcRet) { LOG_E("TEE_Open(): mcMallocWsm returned: %d\n", mcRet); break; } /* Open session the TEE Keymaster trustlet */ pSessionHandle->deviceId = DEVICE_ID; mcRet = mcOpenSession(pSessionHandle, &uuid, (uint8_t *) pTci, (uint32_t) sizeof(tciMessage_t)); if (MC_DRV_OK != mcRet) { LOG_E("TEE_Open(): mcOpenSession returned: %d\n", mcRet); break; } } while (false); return pTci; } /** * TEE_Close * * Close session to the TEE Keymaster trustlet * * @param sessionHandle [in] Session handle */ static void TEE_Close( mcSessionHandle_t sessionHandle ){ teeResult_t ret = TEE_ERR_NONE; mcResult_t mcRet; do { /* Close session */ mcRet = mcCloseSession(&sessionHandle); if (MC_DRV_OK != mcRet) { LOG_E("TEE_Close(): mcCloseSession returned: %d\n", mcRet); ret = TEE_ERR_SESSION; break; } /* Close MobiCore device */ mcRet = mcCloseDevice(DEVICE_ID); if (MC_DRV_OK != mcRet) { LOG_E("TEE_Close(): mcCloseDevice returned: %d\n", mcRet); ret = TEE_ERR_MC_DEVICE; } } while (false); } /** * TEE_RSAGenerateKeyPair * * Generates RSA key pair and returns key pair data as wrapped object * * @param keyType [in] Key pair type. RSA or RSACRT * @param keyData [in] Pointer to the key data buffer * @param keyDataLength [in] Key data buffer length * @param keySize [in] Key size * @param exponent [in] Exponent number * @param soLen [out] Key data secure object length */ teeResult_t TEE_RSAGenerateKeyPair( teeRsaKeyPairType_t keyType, uint8_t* keyData, uint32_t keyDataLength, uint32_t keySize, uint32_t exponent, uint32_t* soLen ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t mapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, keyData, keyDataLength, &mapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_RSA_GEN_KEY_PAIR; pTci->rsagenkey.type = keyType; pTci->rsagenkey.keysize = keySize; pTci->rsagenkey.keydata = (uint32_t)mapInfo.sVirtualAddr; pTci->rsagenkey.keydatalen = keyDataLength; pTci->rsagenkey.exponent = exponent; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, keyData, &mapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_RSAGenerateKeyPair(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } /* Update secure object length */ *soLen = pTci->rsagenkey.solen; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_RSASign * * Signs given plain data and returns signature data * * @param keyData [in] Pointer to key data buffer * @param keyDataLength [in] Key data buffer length * @param plainData [in] Pointer to plain data to be signed * @param plainDataLength [in] Plain data length * @param signatureData [out] Pointer to signature data * @param signatureDataLength [out] Signature data length * @param algorithm [in] RSA signature algorithm */ teeResult_t TEE_RSASign( const uint8_t* keyData, const uint32_t keyDataLength, const uint8_t* plainData, const uint32_t plainDataLength, uint8_t* signatureData, uint32_t* signatureDataLength, teeRsaSigAlg_t algorithm ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t plainMapInfo; mcBulkMap_t signatureMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_RSA_SIGN; pTci->rsasign.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->rsasign.keydatalen = keyDataLength; pTci->rsasign.plaindata = (uint32_t)plainMapInfo.sVirtualAddr; pTci->rsasign.plaindatalen = plainDataLength; pTci->rsasign.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr; pTci->rsasign.signaturedatalen = *signatureDataLength; pTci->rsasign.algorithm = algorithm; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_RSASign(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } /* Retrieve signature data length */ *signatureDataLength = pTci->rsasign.signaturedatalen; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_RSAVerify * * Verifies given data with RSA public key and return status * * @param keyData [in] Pointer to key data buffer * @param keyDataLength [in] Key data buffer length * @param plainData [in] Pointer to plain data to be signed * @param plainDataLength [in] Plain data length * @param signatureData [in] Pointer to signed data * @param signatureData [in] Plain data length * @param algorithm [in] RSA signature algorithm * @param validity [out] Signature validity */ teeResult_t TEE_RSAVerify( const uint8_t* keyData, const uint32_t keyDataLength, const uint8_t* plainData, const uint32_t plainDataLength, const uint8_t* signatureData, const uint32_t signatureDataLength, teeRsaSigAlg_t algorithm, bool *validity ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t plainMapInfo; mcBulkMap_t signatureMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_RSA_VERIFY; pTci->rsaverify.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->rsaverify.keydatalen = keyDataLength; pTci->rsaverify.plaindata = (uint32_t)plainMapInfo.sVirtualAddr; pTci->rsaverify.plaindatalen = plainDataLength; pTci->rsaverify.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr; pTci->rsaverify.signaturedatalen = signatureDataLength; pTci->rsaverify.algorithm = algorithm; pTci->rsaverify.validity = false; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_RSAVerify(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } *validity = pTci->rsaverify.validity; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_HMACKeyGenerate * * Generates random key for HMAC calculation and returns key data as wrapped object * (key is encrypted) * * @param keyData [out] Pointer to key data * @param keyDataLength [in] Key data buffer length * @param soLen [out] Key data secure object length */ teeResult_t TEE_HMACKeyGenerate( uint8_t* keyData, uint32_t keyDataLength, uint32_t* soLen ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_HMAC_GEN_KEY; pTci->hmacgenkey.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->hmacgenkey.keydatalen = keyDataLength; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_RSAVerify(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; } /* Update secure object length */ *soLen = pTci->hmacgenkey.solen; }while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_HMACSign * * Signs given plain data and returns HMAC signature data * * @param keyData [in] Pointer to key data buffer * @param keyDataLength [in] Key data buffer length * @param plainData [in] Pointer to plain data to be signed * @param plainDataLength [in] Plain data length * @param signatureData [out] Pointer to signature data * @param signatureDataLength [out] Signature data length * @param digest [in] Digest type */ teeResult_t TEE_HMACSign( const uint8_t* keyData, const uint32_t keyDataLength, const uint8_t* plainData, const uint32_t plainDataLength, uint8_t* signatureData, uint32_t* signatureDataLength, teeDigest_t digest ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t plainMapInfo; mcBulkMap_t signatureMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_HMAC_SIGN; pTci->hmacsign.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->hmacsign.keydatalen = keyDataLength; pTci->hmacsign.plaindata = (uint32_t)plainMapInfo.sVirtualAddr; pTci->hmacsign.plaindatalen = plainDataLength; pTci->hmacsign.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr; pTci->hmacsign.signaturedatalen = *signatureDataLength; pTci->hmacsign.digest = digest; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_HMACSign(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } /* Retrieve signature data length */ *signatureDataLength = pTci->hmacsign.signaturedatalen; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_HMACVerify * * Verifies given data HMAC key data and return status * * @param plainData [in] Pointer to plain data to be signed * @param plainDataLength [in] Plain data length * @param signatureData [in] Pointer to signed data * @param signatureData [in] Plain data length * @param digest [in] Digest type * @param validity [out] Signature validity */ teeResult_t TEE_HMACVerify( const uint8_t* keyData, const uint32_t keyDataLength, const uint8_t* plainData, const uint32_t plainDataLength, const uint8_t* signatureData, const uint32_t signatureDataLength, teeDigest_t digest, bool *validity ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t plainMapInfo; mcBulkMap_t signatureMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_HMAC_VERIFY; pTci->hmacverify.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->hmacverify.keydatalen = keyDataLength; pTci->hmacverify.plaindata = (uint32_t)plainMapInfo.sVirtualAddr; pTci->hmacverify.plaindatalen = plainDataLength; pTci->hmacverify.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr; pTci->hmacverify.signaturedatalen = signatureDataLength; pTci->hmacverify.digest = digest; pTci->hmacverify.validity = false; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_HMACVerify(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } *validity = pTci->hmacverify.validity; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_KeyImport * * Imports key data and returns key data as secure object * * Key data needs to be in the following format * * RSA key data: * |--key metadata--|--public modulus--|--public exponent--|--private exponent--| * * RSA CRT key data: * |--key metadata--|--public modulus--|--public exponent--|--P--|--Q--|--DP--|--DQ--|--Qinv--| * * Where: * P: secret prime factor * Q: secret prime factor * DP: d mod (p-1) * DQ: d mod (q-1) * Qinv: q^-1 mod p * * @param keyData [in] Pointer to key data * @param keyDataLength [in] Key data length * @param soData [out] Pointer to wrapped key data * @param soDataLength [out] Wrapped key data length */ teeResult_t TEE_KeyImport( const uint8_t* keyData, const uint32_t keyDataLength, uint8_t* soData, uint32_t* soDataLength ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t soMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)soData, *soDataLength, &soMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_KEY_IMPORT; pTci->keyimport.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->keyimport.keydatalen = keyDataLength; pTci->keyimport.sodata = (uint32_t)soMapInfo.sVirtualAddr; pTci->keyimport.sodatalen = *soDataLength; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)soData, &soMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_KeyWrap(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } /* Update secure object length */ *soDataLength = pTci->keyimport.sodatalen; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; } /** * TEE_GetPubKey * * Retrieves public key daya (modulus and exponent) from wrapped key data * * @param keyData [in] Pointer to key data * @param keyDataLength [in] Key data length * @param modulus [out] Pointer to public key modulus data * @param modulusLength [out] Modulus data length * @param exponent [out] Pointer to public key exponent data * @param exponentLength [out] Exponent data length */ teeResult_t TEE_GetPubKey( const uint8_t* keyData, const uint32_t keyDataLength, uint8_t* modulus, uint32_t* modulusLength, uint8_t* exponent, uint32_t* exponentLength ){ teeResult_t ret = TEE_ERR_NONE; tciMessage_ptr pTci = NULL; mcSessionHandle_t sessionHandle; mcBulkMap_t keyMapInfo; mcBulkMap_t modMapInfo; mcBulkMap_t expMapInfo; mcResult_t mcRet; do { /* Open session to the trustlet */ pTci = TEE_Open(&sessionHandle); if (!pTci) { ret = TEE_ERR_MEMORY; break; } /* Map memory to the secure world */ mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)modulus, *modulusLength, &modMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcMap(&sessionHandle, (void*)exponent, *exponentLength, &expMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } /* Update TCI buffer */ pTci->command.header.commandId = CMD_ID_TEE_GET_PUB_KEY; pTci->getpubkey.keydata = (uint32_t)keyMapInfo.sVirtualAddr; pTci->getpubkey.keydatalen = keyDataLength; pTci->getpubkey.modulus = (uint32_t)modMapInfo.sVirtualAddr; pTci->getpubkey.moduluslen = *modulusLength; pTci->getpubkey.exponent = (uint32_t)expMapInfo.sVirtualAddr; pTci->getpubkey.exponentlen = *exponentLength; /* Notify the trustlet */ mcRet = mcNotify(&sessionHandle); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_NOTIFICATION; break; } /* Wait for response from the trustlet */ if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) { ret = TEE_ERR_NOTIFICATION; break; } /* Unmap memory */ mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)modulus, &modMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } mcRet = mcUnmap(&sessionHandle, (void*)exponent, &expMapInfo); if (MC_DRV_OK != mcRet) { ret = TEE_ERR_MAP; break; } if (RET_OK != pTci->response.header.returnCode) { LOG_E("TEE_GetPubKey(): TEE Keymaster trustlet returned: 0x%.8x\n", pTci->response.header.returnCode); ret = TEE_ERR_FAIL; break; } /* Update modulus and exponent lengths */ *modulusLength = pTci->getpubkey.moduluslen; *exponentLength = pTci->getpubkey.exponentlen; } while (false); /* Close session to the trustlet */ TEE_Close(sessionHandle); return ret; }