1/**
2 * @file   tlcTeeKeymaster_if.c
3 * @brief  Contains trustlet connector interface implementations to
4 * handle key operations with TEE Keymaster trustlet
5 *
6 * Copyright Giesecke & Devrient GmbH 2012
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote
17 *    products derived from this software without specific prior
18 *    written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <stdlib.h>
34
35#include "MobiCoreDriverApi.h"
36#include "tlTeeKeymaster_Api.h"
37#include "tlcTeeKeymaster_log.h"
38#include "tlcTeeKeymaster_if.h"
39
40
41/* Global definitions */
42static const uint32_t DEVICE_ID = MC_DEVICE_ID_DEFAULT;
43static const mcUuid_t uuid = TEE_KEYMASTER_TL_UUID;
44
45/**
46 * TEE_Open
47 *
48 * Open session to the TEE Keymaster trustlet
49 *
50 * @param  pSessionHandle  [out] Return pointer to the session handle
51 */
52static tciMessage_ptr TEE_Open(
53    mcSessionHandle_t *pSessionHandle
54){
55    tciMessage_ptr pTci = NULL;
56    mcResult_t     mcRet;
57
58    do
59    {
60
61        /* Validate session handle */
62        if (!pSessionHandle)
63        {
64            LOG_E("TEE_Open(): Invalid session handle\n");
65            break;
66        }
67
68        /* Initialize session handle data */
69        bzero(pSessionHandle, sizeof(mcSessionHandle_t));
70
71        /* Open MobiCore device */
72        mcRet = mcOpenDevice(DEVICE_ID);
73        if (MC_DRV_OK != mcRet)
74        {
75            LOG_E("TEE_Open(): mcOpenDevice returned: %d\n", mcRet);
76            break;
77        }
78
79        /* Allocating WSM for TCI */
80        mcRet = mcMallocWsm(DEVICE_ID, 0, sizeof(tciMessage_t), (uint8_t **) &pTci, 0);
81        if (MC_DRV_OK != mcRet)
82        {
83            LOG_E("TEE_Open(): mcMallocWsm returned: %d\n", mcRet);
84            break;
85        }
86
87        /* Open session the TEE Keymaster trustlet */
88        pSessionHandle->deviceId = DEVICE_ID;
89        mcRet = mcOpenSession(pSessionHandle,
90                              &uuid,
91                              (uint8_t *) pTci,
92                              (uint32_t) sizeof(tciMessage_t));
93        if (MC_DRV_OK != mcRet)
94        {
95            LOG_E("TEE_Open(): mcOpenSession returned: %d\n", mcRet);
96            break;
97        }
98
99    } while (false);
100
101    return pTci;
102}
103
104
105/**
106 * TEE_Close
107 *
108 * Close session to the TEE Keymaster trustlet
109 *
110 * @param  sessionHandle  [in] Session handle
111 */
112static void TEE_Close(
113    mcSessionHandle_t sessionHandle
114){
115    teeResult_t   ret = TEE_ERR_NONE;
116    mcResult_t    mcRet;
117
118    do {
119
120        /* Close session */
121        mcRet = mcCloseSession(&sessionHandle);
122        if (MC_DRV_OK != mcRet)
123        {
124            LOG_E("TEE_Close(): mcCloseSession returned: %d\n", mcRet);
125            ret = TEE_ERR_SESSION;
126            break;
127        }
128
129        /* Close MobiCore device */
130        mcRet = mcCloseDevice(DEVICE_ID);
131        if (MC_DRV_OK != mcRet)
132        {
133            LOG_E("TEE_Close(): mcCloseDevice returned: %d\n", mcRet);
134            ret = TEE_ERR_MC_DEVICE;
135        }
136
137    } while (false);
138}
139
140
141/**
142 * TEE_RSAGenerateKeyPair
143 *
144 * Generates RSA key pair and returns key pair data as wrapped object
145 *
146 * @param  keyType        [in]  Key pair type. RSA or RSACRT
147 * @param  keyData        [in]  Pointer to the key data buffer
148 * @param  keyDataLength  [in]  Key data buffer length
149 * @param  keySize        [in]  Key size
150 * @param  exponent       [in]  Exponent number
151 * @param  soLen          [out] Key data secure object length
152 */
153teeResult_t TEE_RSAGenerateKeyPair(
154    teeRsaKeyPairType_t keyType,
155    uint8_t*            keyData,
156    uint32_t            keyDataLength,
157    uint32_t            keySize,
158    uint32_t            exponent,
159    uint32_t*           soLen
160){
161    teeResult_t         ret = TEE_ERR_NONE;
162    tciMessage_ptr      pTci = NULL;
163    mcSessionHandle_t   sessionHandle;
164    mcBulkMap_t         mapInfo;
165    mcResult_t          mcRet;
166
167    do {
168
169        /* Open session to the trustlet */
170        pTci = TEE_Open(&sessionHandle);
171        if (!pTci) {
172            ret = TEE_ERR_MEMORY;
173            break;
174        }
175
176        /* Map memory to the secure world */
177        mcRet = mcMap(&sessionHandle, keyData, keyDataLength, &mapInfo);
178        if (MC_DRV_OK != mcRet) {
179            ret = TEE_ERR_MAP;
180            break;
181        }
182
183        /* Update TCI buffer */
184        pTci->command.header.commandId = CMD_ID_TEE_RSA_GEN_KEY_PAIR;
185        pTci->rsagenkey.type        = keyType;
186        pTci->rsagenkey.keysize     = keySize;
187        pTci->rsagenkey.keydata     = (uint32_t)mapInfo.sVirtualAddr;
188        pTci->rsagenkey.keydatalen  = keyDataLength;
189        pTci->rsagenkey.exponent    = exponent;
190
191        /* Notify the trustlet */
192        mcRet = mcNotify(&sessionHandle);
193        if (MC_DRV_OK != mcRet)
194        {
195            ret = TEE_ERR_NOTIFICATION;
196            break;
197        }
198
199        /* Wait for response from the trustlet */
200        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
201        {
202            ret = TEE_ERR_NOTIFICATION;
203            break;
204        }
205
206        /* Unmap memory */
207        mcRet = mcUnmap(&sessionHandle, keyData, &mapInfo);
208        if (MC_DRV_OK != mcRet)
209        {
210            ret = TEE_ERR_MAP;
211            break;
212        }
213
214        if (RET_OK != pTci->response.header.returnCode)
215        {
216            LOG_E("TEE_RSAGenerateKeyPair(): TEE Keymaster trustlet returned: 0x%.8x\n",
217                        pTci->response.header.returnCode);
218            ret = TEE_ERR_FAIL;
219            break;
220        }
221
222        /* Update secure object length */
223        *soLen =  pTci->rsagenkey.solen;
224
225    } while (false);
226
227    /* Close session to the trustlet */
228    TEE_Close(sessionHandle);
229
230    return ret;
231}
232
233
234/**
235 * TEE_RSASign
236 *
237 * Signs given plain data and returns signature data
238 *
239 * @param  keyData          [in]  Pointer to key data buffer
240 * @param  keyDataLength    [in]  Key data buffer length
241 * @param  plainData        [in]  Pointer to plain data to be signed
242 * @param  plainDataLength  [in]  Plain data length
243 * @param  signatureData    [out] Pointer to signature data
244 * @param  signatureDataLength  [out] Signature data length
245 * @param  algorithm        [in]  RSA signature algorithm
246 */
247teeResult_t TEE_RSASign(
248    const uint8_t*  keyData,
249    const uint32_t  keyDataLength,
250    const uint8_t*  plainData,
251    const uint32_t  plainDataLength,
252    uint8_t*        signatureData,
253    uint32_t*       signatureDataLength,
254    teeRsaSigAlg_t  algorithm
255){
256    teeResult_t        ret = TEE_ERR_NONE;
257    tciMessage_ptr     pTci = NULL;
258    mcSessionHandle_t  sessionHandle;
259    mcBulkMap_t        keyMapInfo;
260    mcBulkMap_t        plainMapInfo;
261    mcBulkMap_t        signatureMapInfo;
262    mcResult_t         mcRet;
263
264    do {
265
266        /* Open session to the trustlet */
267        pTci = TEE_Open(&sessionHandle);
268        if (!pTci) {
269            ret = TEE_ERR_MEMORY;
270            break;
271        }
272
273        /* Map memory to the secure world */
274        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
275        if (MC_DRV_OK != mcRet) {
276            ret = TEE_ERR_MAP;
277            break;
278        }
279
280        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
281        if (MC_DRV_OK != mcRet) {
282            ret = TEE_ERR_MAP;
283            break;
284        }
285
286        mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo);
287        if (MC_DRV_OK != mcRet) {
288            ret = TEE_ERR_MAP;
289            break;
290        }
291
292        /* Update TCI buffer */
293        pTci->command.header.commandId = CMD_ID_TEE_RSA_SIGN;
294        pTci->rsasign.keydata = (uint32_t)keyMapInfo.sVirtualAddr;
295        pTci->rsasign.keydatalen = keyDataLength;
296
297        pTci->rsasign.plaindata = (uint32_t)plainMapInfo.sVirtualAddr;
298        pTci->rsasign.plaindatalen = plainDataLength;
299
300        pTci->rsasign.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr;
301        pTci->rsasign.signaturedatalen = *signatureDataLength;
302
303        pTci->rsasign.algorithm = algorithm;
304
305        /* Notify the trustlet */
306        mcRet = mcNotify(&sessionHandle);
307        if (MC_DRV_OK != mcRet)
308        {
309            ret = TEE_ERR_NOTIFICATION;
310            break;
311        }
312
313        /* Wait for response from the trustlet */
314        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
315        {
316            ret = TEE_ERR_NOTIFICATION;
317            break;
318        }
319
320        /* Unmap memory */
321        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
322        if (MC_DRV_OK != mcRet)
323        {
324            ret = TEE_ERR_MAP;
325            break;
326        }
327
328        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
329        if (MC_DRV_OK != mcRet)
330        {
331            ret = TEE_ERR_MAP;
332            break;
333        }
334
335        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
336        if (MC_DRV_OK != mcRet)
337        {
338            ret = TEE_ERR_MAP;
339            break;
340        }
341
342        if (RET_OK != pTci->response.header.returnCode)
343        {
344            LOG_E("TEE_RSASign(): TEE Keymaster trustlet returned: 0x%.8x\n",
345                        pTci->response.header.returnCode);
346            ret = TEE_ERR_FAIL;
347            break;
348        }
349
350        /* Retrieve signature data length */
351        *signatureDataLength = pTci->rsasign.signaturedatalen;
352
353    } while (false);
354
355    /* Close session to the trustlet */
356    TEE_Close(sessionHandle);
357
358    return ret;
359}
360
361
362/**
363 * TEE_RSAVerify
364 *
365 * Verifies given data with RSA public key and return status
366 *
367 * @param  keyData          [in]  Pointer to key data buffer
368 * @param  keyDataLength    [in]  Key data buffer length
369 * @param  plainData        [in]  Pointer to plain data to be signed
370 * @param  plainDataLength  [in]  Plain data length
371 * @param  signatureData    [in]  Pointer to signed data
372 * @param  signatureData    [in]  Plain  data length
373 * @param  algorithm        [in]  RSA signature algorithm
374 * @param  validity         [out] Signature validity
375 */
376teeResult_t TEE_RSAVerify(
377    const uint8_t*  keyData,
378    const uint32_t  keyDataLength,
379    const uint8_t*  plainData,
380    const uint32_t  plainDataLength,
381    const uint8_t*  signatureData,
382    const uint32_t  signatureDataLength,
383    teeRsaSigAlg_t  algorithm,
384    bool            *validity
385){
386    teeResult_t        ret = TEE_ERR_NONE;
387    tciMessage_ptr     pTci = NULL;
388    mcSessionHandle_t  sessionHandle;
389    mcBulkMap_t        keyMapInfo;
390    mcBulkMap_t        plainMapInfo;
391    mcBulkMap_t        signatureMapInfo;
392    mcResult_t         mcRet;
393
394    do {
395
396        /* Open session to the trustlet */
397        pTci = TEE_Open(&sessionHandle);
398        if (!pTci) {
399            ret = TEE_ERR_MEMORY;
400            break;
401        }
402
403        /* Map memory to the secure world */
404        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
405        if (MC_DRV_OK != mcRet) {
406            ret = TEE_ERR_MAP;
407            break;
408        }
409
410        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
411        if (MC_DRV_OK != mcRet) {
412            ret = TEE_ERR_MAP;
413            break;
414        }
415
416        mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo);
417        if (MC_DRV_OK != mcRet) {
418            ret = TEE_ERR_MAP;
419            break;
420        }
421
422        /* Update TCI buffer */
423        pTci->command.header.commandId = CMD_ID_TEE_RSA_VERIFY;
424        pTci->rsaverify.keydata = (uint32_t)keyMapInfo.sVirtualAddr;
425        pTci->rsaverify.keydatalen = keyDataLength;
426
427        pTci->rsaverify.plaindata = (uint32_t)plainMapInfo.sVirtualAddr;
428        pTci->rsaverify.plaindatalen = plainDataLength;
429
430        pTci->rsaverify.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr;
431        pTci->rsaverify.signaturedatalen = signatureDataLength;
432
433        pTci->rsaverify.algorithm = algorithm;
434        pTci->rsaverify.validity = false;
435
436        /* Notify the trustlet */
437        mcRet = mcNotify(&sessionHandle);
438        if (MC_DRV_OK != mcRet)
439        {
440            ret = TEE_ERR_NOTIFICATION;
441            break;
442        }
443
444        /* Wait for response from the trustlet */
445        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
446        {
447            ret = TEE_ERR_NOTIFICATION;
448            break;
449        }
450
451        /* Unmap memory */
452        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
453        if (MC_DRV_OK != mcRet)
454        {
455            ret = TEE_ERR_MAP;
456            break;
457        }
458
459        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
460        if (MC_DRV_OK != mcRet)
461        {
462            ret = TEE_ERR_MAP;
463            break;
464        }
465
466        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
467        if (MC_DRV_OK != mcRet)
468        {
469            ret = TEE_ERR_MAP;
470            break;
471        }
472
473        if (RET_OK != pTci->response.header.returnCode)
474        {
475            LOG_E("TEE_RSAVerify(): TEE Keymaster trustlet returned: 0x%.8x\n",
476                        pTci->response.header.returnCode);
477            ret = TEE_ERR_FAIL;
478            break;
479        }
480
481        *validity =  pTci->rsaverify.validity;
482
483    } while (false);
484
485    /* Close session to the trustlet */
486    TEE_Close(sessionHandle);
487
488    return ret;
489}
490
491
492/**
493 * TEE_HMACKeyGenerate
494 *
495 * Generates random key for HMAC calculation and returns key data as wrapped object
496 * (key is encrypted)
497 *
498 * @param  keyData        [out] Pointer to key data
499 * @param  keyDataLength  [in]  Key data buffer length
500 * @param  soLen          [out] Key data secure object length
501 */
502teeResult_t TEE_HMACKeyGenerate(
503    uint8_t*  keyData,
504    uint32_t  keyDataLength,
505    uint32_t* soLen
506){
507    teeResult_t        ret = TEE_ERR_NONE;
508    tciMessage_ptr     pTci = NULL;
509    mcSessionHandle_t  sessionHandle;
510    mcBulkMap_t        keyMapInfo;
511    mcResult_t         mcRet;
512
513    do {
514
515        /* Open session to the trustlet */
516        pTci = TEE_Open(&sessionHandle);
517        if (!pTci) {
518            ret = TEE_ERR_MEMORY;
519            break;
520        }
521
522        /* Map memory to the secure world */
523        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
524        if (MC_DRV_OK != mcRet) {
525            ret = TEE_ERR_MAP;
526            break;
527        }
528
529        /* Update TCI buffer */
530        pTci->command.header.commandId = CMD_ID_TEE_HMAC_GEN_KEY;
531        pTci->hmacgenkey.keydata = (uint32_t)keyMapInfo.sVirtualAddr;
532        pTci->hmacgenkey.keydatalen = keyDataLength;
533
534        /* Notify the trustlet */
535        mcRet = mcNotify(&sessionHandle);
536        if (MC_DRV_OK != mcRet)
537        {
538            ret = TEE_ERR_NOTIFICATION;
539            break;
540        }
541
542        /* Wait for response from the trustlet */
543        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
544        {
545            ret = TEE_ERR_NOTIFICATION;
546            break;
547        }
548
549        /* Unmap memory */
550        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
551        if (MC_DRV_OK != mcRet)
552        {
553            ret = TEE_ERR_MAP;
554            break;
555        }
556
557        if (RET_OK != pTci->response.header.returnCode)
558        {
559            LOG_E("TEE_RSAVerify(): TEE Keymaster trustlet returned: 0x%.8x\n",
560                        pTci->response.header.returnCode);
561            ret = TEE_ERR_FAIL;
562        }
563
564        /* Update secure object length */
565        *soLen =  pTci->hmacgenkey.solen;
566
567    }while (false);
568
569    /* Close session to the trustlet */
570    TEE_Close(sessionHandle);
571
572    return ret;
573}
574
575/**
576 * TEE_HMACSign
577 *
578 * Signs given plain data and returns HMAC signature data
579 *
580 * @param  keyData          [in]  Pointer to key data buffer
581 * @param  keyDataLength    [in]  Key data buffer length
582 * @param  plainData        [in]  Pointer to plain data to be signed
583 * @param  plainDataLength  [in]  Plain data length
584 * @param  signatureData    [out] Pointer to signature data
585 * @param  signatureDataLength  [out] Signature data length
586 * @param  digest           [in]  Digest type
587 */
588teeResult_t TEE_HMACSign(
589    const uint8_t*  keyData,
590    const uint32_t  keyDataLength,
591    const uint8_t*  plainData,
592    const uint32_t  plainDataLength,
593    uint8_t*        signatureData,
594    uint32_t*       signatureDataLength,
595    teeDigest_t     digest
596){
597    teeResult_t        ret = TEE_ERR_NONE;
598    tciMessage_ptr     pTci = NULL;
599    mcSessionHandle_t  sessionHandle;
600    mcBulkMap_t        keyMapInfo;
601    mcBulkMap_t        plainMapInfo;
602    mcBulkMap_t        signatureMapInfo;
603    mcResult_t         mcRet;
604
605    do {
606
607        /* Open session to the trustlet */
608        pTci = TEE_Open(&sessionHandle);
609        if (!pTci) {
610            ret = TEE_ERR_MEMORY;
611            break;
612        }
613
614        /* Map memory to the secure world */
615        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
616        if (MC_DRV_OK != mcRet) {
617            ret = TEE_ERR_MAP;
618            break;
619        }
620
621        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
622        if (MC_DRV_OK != mcRet) {
623            ret = TEE_ERR_MAP;
624            break;
625        }
626
627        mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo);
628        if (MC_DRV_OK != mcRet) {
629            ret = TEE_ERR_MAP;
630            break;
631        }
632
633        /* Update TCI buffer */
634        pTci->command.header.commandId = CMD_ID_TEE_HMAC_SIGN;
635        pTci->hmacsign.keydata = (uint32_t)keyMapInfo.sVirtualAddr;
636        pTci->hmacsign.keydatalen = keyDataLength;
637
638        pTci->hmacsign.plaindata = (uint32_t)plainMapInfo.sVirtualAddr;
639        pTci->hmacsign.plaindatalen = plainDataLength;
640
641        pTci->hmacsign.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr;
642        pTci->hmacsign.signaturedatalen = *signatureDataLength;
643
644        pTci->hmacsign.digest = digest;
645
646        /* Notify the trustlet */
647        mcRet = mcNotify(&sessionHandle);
648        if (MC_DRV_OK != mcRet)
649        {
650            ret = TEE_ERR_NOTIFICATION;
651            break;
652        }
653
654        /* Wait for response from the trustlet */
655        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
656        {
657            ret = TEE_ERR_NOTIFICATION;
658            break;
659        }
660
661        /* Unmap memory */
662        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
663        if (MC_DRV_OK != mcRet)
664        {
665            ret = TEE_ERR_MAP;
666            break;
667        }
668
669        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
670        if (MC_DRV_OK != mcRet)
671        {
672            ret = TEE_ERR_MAP;
673            break;
674        }
675
676        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
677        if (MC_DRV_OK != mcRet)
678        {
679            ret = TEE_ERR_MAP;
680            break;
681        }
682
683        if (RET_OK != pTci->response.header.returnCode)
684        {
685            LOG_E("TEE_HMACSign(): TEE Keymaster trustlet returned: 0x%.8x\n",
686                        pTci->response.header.returnCode);
687            ret = TEE_ERR_FAIL;
688            break;
689        }
690
691        /* Retrieve signature data length */
692        *signatureDataLength = pTci->hmacsign.signaturedatalen;
693
694    } while (false);
695
696    /* Close session to the trustlet */
697    TEE_Close(sessionHandle);
698
699    return ret;
700}
701
702
703/**
704 * TEE_HMACVerify
705 *
706 * Verifies given data HMAC key data and return status
707 *
708 * @param  plainData        [in]  Pointer to plain data to be signed
709 * @param  plainDataLength  [in]  Plain data length
710 * @param  signatureData    [in]  Pointer to signed data
711 * @param  signatureData    [in]  Plain  data length
712 * @param  digest           [in]  Digest type
713 * @param  validity         [out] Signature validity
714 */
715teeResult_t TEE_HMACVerify(
716    const uint8_t*  keyData,
717    const uint32_t  keyDataLength,
718    const uint8_t*  plainData,
719    const uint32_t  plainDataLength,
720    const uint8_t*  signatureData,
721    const uint32_t  signatureDataLength,
722    teeDigest_t     digest,
723    bool            *validity
724){
725    teeResult_t        ret = TEE_ERR_NONE;
726    tciMessage_ptr     pTci = NULL;
727    mcSessionHandle_t  sessionHandle;
728    mcBulkMap_t        keyMapInfo;
729    mcBulkMap_t        plainMapInfo;
730    mcBulkMap_t        signatureMapInfo;
731    mcResult_t         mcRet;
732
733    do {
734
735        /* Open session to the trustlet */
736        pTci = TEE_Open(&sessionHandle);
737        if (!pTci) {
738            ret = TEE_ERR_MEMORY;
739            break;
740        }
741
742        /* Map memory to the secure world */
743        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
744        if (MC_DRV_OK != mcRet) {
745            ret = TEE_ERR_MAP;
746            break;
747        }
748
749        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
750        if (MC_DRV_OK != mcRet) {
751            ret = TEE_ERR_MAP;
752            break;
753        }
754
755        mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo);
756        if (MC_DRV_OK != mcRet) {
757            ret = TEE_ERR_MAP;
758            break;
759        }
760
761        /* Update TCI buffer */
762        pTci->command.header.commandId = CMD_ID_TEE_HMAC_VERIFY;
763        pTci->hmacverify.keydata = (uint32_t)keyMapInfo.sVirtualAddr;
764        pTci->hmacverify.keydatalen = keyDataLength;
765
766        pTci->hmacverify.plaindata = (uint32_t)plainMapInfo.sVirtualAddr;
767        pTci->hmacverify.plaindatalen = plainDataLength;
768
769        pTci->hmacverify.signaturedata = (uint32_t)signatureMapInfo.sVirtualAddr;
770        pTci->hmacverify.signaturedatalen = signatureDataLength;
771
772        pTci->hmacverify.digest = digest;
773        pTci->hmacverify.validity = false;
774
775        /* Notify the trustlet */
776        mcRet = mcNotify(&sessionHandle);
777        if (MC_DRV_OK != mcRet)
778        {
779            ret = TEE_ERR_NOTIFICATION;
780            break;
781        }
782
783        /* Wait for response from the trustlet */
784        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
785        {
786            ret = TEE_ERR_NOTIFICATION;
787            break;
788        }
789
790        /* Unmap memory */
791        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
792        if (MC_DRV_OK != mcRet)
793        {
794            ret = TEE_ERR_MAP;
795            break;
796        }
797
798        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
799        if (MC_DRV_OK != mcRet)
800        {
801            ret = TEE_ERR_MAP;
802            break;
803        }
804
805        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
806        if (MC_DRV_OK != mcRet)
807        {
808            ret = TEE_ERR_MAP;
809            break;
810        }
811
812        if (RET_OK != pTci->response.header.returnCode)
813        {
814            LOG_E("TEE_HMACVerify(): TEE Keymaster trustlet returned: 0x%.8x\n",
815                        pTci->response.header.returnCode);
816            ret = TEE_ERR_FAIL;
817            break;
818        }
819
820        *validity =  pTci->hmacverify.validity;
821
822    } while (false);
823
824    /* Close session to the trustlet */
825    TEE_Close(sessionHandle);
826
827    return ret;
828}
829
830
831/**
832 * TEE_KeyImport
833 *
834 * Imports key data and returns key data as secure object
835 *
836 * Key data needs to be in the following format
837 *
838 * RSA key data:
839 * |--key metadata--|--public modulus--|--public exponent--|--private exponent--|
840 *
841 * RSA CRT key data:
842 * |--key metadata--|--public modulus--|--public exponent--|--P--|--Q--|--DP--|--DQ--|--Qinv--|
843 *
844 * Where:
845 * P:     secret prime factor
846 * Q:     secret prime factor
847 * DP:    d mod (p-1)
848 * DQ:    d mod (q-1)
849 * Qinv:  q^-1 mod p
850 *
851 * @param  keyData          [in]  Pointer to key data
852 * @param  keyDataLength    [in]  Key data length
853 * @param  soData           [out] Pointer to wrapped key data
854 * @param  soDataLength     [out] Wrapped key data length
855 */
856teeResult_t TEE_KeyImport(
857    const uint8_t*  keyData,
858    const uint32_t  keyDataLength,
859    uint8_t*        soData,
860    uint32_t*       soDataLength
861){
862    teeResult_t         ret = TEE_ERR_NONE;
863    tciMessage_ptr      pTci = NULL;
864    mcSessionHandle_t   sessionHandle;
865    mcBulkMap_t         keyMapInfo;
866    mcBulkMap_t         soMapInfo;
867    mcResult_t          mcRet;
868
869    do {
870
871        /* Open session to the trustlet */
872        pTci = TEE_Open(&sessionHandle);
873        if (!pTci) {
874            ret = TEE_ERR_MEMORY;
875            break;
876        }
877
878        /* Map memory to the secure world */
879        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
880        if (MC_DRV_OK != mcRet) {
881            ret = TEE_ERR_MAP;
882            break;
883        }
884
885        mcRet = mcMap(&sessionHandle, (void*)soData, *soDataLength, &soMapInfo);
886        if (MC_DRV_OK != mcRet) {
887            ret = TEE_ERR_MAP;
888            break;
889        }
890
891        /* Update TCI buffer */
892        pTci->command.header.commandId = CMD_ID_TEE_KEY_IMPORT;
893        pTci->keyimport.keydata        = (uint32_t)keyMapInfo.sVirtualAddr;
894        pTci->keyimport.keydatalen     = keyDataLength;
895        pTci->keyimport.sodata         = (uint32_t)soMapInfo.sVirtualAddr;
896        pTci->keyimport.sodatalen      = *soDataLength;
897
898        /* Notify the trustlet */
899        mcRet = mcNotify(&sessionHandle);
900        if (MC_DRV_OK != mcRet)
901        {
902            ret = TEE_ERR_NOTIFICATION;
903            break;
904        }
905
906        /* Wait for response from the trustlet */
907        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
908        {
909            ret = TEE_ERR_NOTIFICATION;
910            break;
911        }
912
913        /* Unmap memory */
914        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
915        if (MC_DRV_OK != mcRet)
916        {
917            ret = TEE_ERR_MAP;
918            break;
919        }
920
921        mcRet = mcUnmap(&sessionHandle, (void*)soData, &soMapInfo);
922        if (MC_DRV_OK != mcRet)
923        {
924            ret = TEE_ERR_MAP;
925            break;
926        }
927
928        if (RET_OK != pTci->response.header.returnCode)
929        {
930            LOG_E("TEE_KeyWrap(): TEE Keymaster trustlet returned: 0x%.8x\n",
931                        pTci->response.header.returnCode);
932            ret = TEE_ERR_FAIL;
933            break;
934        }
935
936        /* Update secure object length */
937        *soDataLength =  pTci->keyimport.sodatalen;
938
939    } while (false);
940
941    /* Close session to the trustlet */
942    TEE_Close(sessionHandle);
943
944    return ret;
945}
946
947
948/** * TEE_GetPubKey
949 *
950 * Retrieves public key daya (modulus and exponent) from wrapped key data
951 *
952 * @param  keyData          [in]  Pointer to key data
953 * @param  keyDataLength    [in]  Key data length
954 * @param  modulus          [out] Pointer to public key modulus data
955 * @param  modulusLength    [out] Modulus data length
956 * @param  exponent         [out] Pointer to public key exponent data
957 * @param  exponentLength   [out] Exponent data length
958 */
959teeResult_t TEE_GetPubKey(
960    const uint8_t*  keyData,
961    const uint32_t  keyDataLength,
962    uint8_t*        modulus,
963    uint32_t*       modulusLength,
964    uint8_t*        exponent,
965    uint32_t*       exponentLength
966){
967    teeResult_t         ret = TEE_ERR_NONE;
968    tciMessage_ptr      pTci = NULL;
969    mcSessionHandle_t   sessionHandle;
970    mcBulkMap_t         keyMapInfo;
971    mcBulkMap_t         modMapInfo;
972    mcBulkMap_t         expMapInfo;
973    mcResult_t          mcRet;
974
975    do {
976
977        /* Open session to the trustlet */
978        pTci = TEE_Open(&sessionHandle);
979        if (!pTci) {
980            ret = TEE_ERR_MEMORY;
981            break;
982        }
983
984        /* Map memory to the secure world */
985        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
986        if (MC_DRV_OK != mcRet) {
987            ret = TEE_ERR_MAP;
988            break;
989        }
990
991        mcRet = mcMap(&sessionHandle, (void*)modulus, *modulusLength, &modMapInfo);
992        if (MC_DRV_OK != mcRet) {
993            ret = TEE_ERR_MAP;
994            break;
995        }
996
997        mcRet = mcMap(&sessionHandle, (void*)exponent, *exponentLength, &expMapInfo);
998        if (MC_DRV_OK != mcRet) {
999            ret = TEE_ERR_MAP;
1000            break;
1001        }
1002
1003        /* Update TCI buffer */
1004        pTci->command.header.commandId = CMD_ID_TEE_GET_PUB_KEY;
1005        pTci->getpubkey.keydata        = (uint32_t)keyMapInfo.sVirtualAddr;
1006        pTci->getpubkey.keydatalen     = keyDataLength;
1007        pTci->getpubkey.modulus        = (uint32_t)modMapInfo.sVirtualAddr;
1008        pTci->getpubkey.moduluslen     = *modulusLength;
1009        pTci->getpubkey.exponent       = (uint32_t)expMapInfo.sVirtualAddr;
1010        pTci->getpubkey.exponentlen    = *exponentLength;
1011
1012        /* Notify the trustlet */
1013        mcRet = mcNotify(&sessionHandle);
1014        if (MC_DRV_OK != mcRet)
1015        {
1016            ret = TEE_ERR_NOTIFICATION;
1017            break;
1018        }
1019
1020        /* Wait for response from the trustlet */
1021        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
1022        {
1023            ret = TEE_ERR_NOTIFICATION;
1024            break;
1025        }
1026
1027        /* Unmap memory */
1028        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
1029        if (MC_DRV_OK != mcRet)
1030        {
1031            ret = TEE_ERR_MAP;
1032            break;
1033        }
1034
1035        mcRet = mcUnmap(&sessionHandle, (void*)modulus, &modMapInfo);
1036        if (MC_DRV_OK != mcRet)
1037        {
1038            ret = TEE_ERR_MAP;
1039            break;
1040        }
1041
1042        mcRet = mcUnmap(&sessionHandle, (void*)exponent, &expMapInfo);
1043        if (MC_DRV_OK != mcRet)
1044        {
1045            ret = TEE_ERR_MAP;
1046            break;
1047        }
1048
1049        if (RET_OK != pTci->response.header.returnCode)
1050        {
1051            LOG_E("TEE_GetPubKey(): TEE Keymaster trustlet returned: 0x%.8x\n",
1052                        pTci->response.header.returnCode);
1053            ret = TEE_ERR_FAIL;
1054            break;
1055        }
1056
1057        /* Update  modulus and exponent lengths */
1058        *modulusLength =   pTci->getpubkey.moduluslen;
1059        *exponentLength =   pTci->getpubkey.exponentlen;
1060
1061    } while (false);
1062
1063    /* Close session to the trustlet */
1064    TEE_Close(sessionHandle);
1065
1066    return ret;
1067}
1068