1 /** Mobicore Driver Registry.
3 * Implements the MobiCore driver registry which maintains trustlets.
6 * @ingroup MCD_MCDIMPL_DAEMON_REG
10 * Copyright (c) 2013 TRUSTONIC LIMITED
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
31 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 #include "mcLoadFormat.h"
56 #include "mcVersionHelper.h"
58 #include "PrivateRegistry.h"
59 #include "MobiCoreRegistry.h"
61 #include "uuid_attestation.h"
65 /** Maximum size of a trustlet in bytes. */
66 #define MAX_TL_SIZE (1 * 1024 * 1024)
67 /** Maximum size of a shared object container in bytes. */
68 #define MAX_SO_CONT_SIZE (512)
70 // Asserts expression at compile-time (to be used within a function body).
71 #define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0)
73 #define MC_REGISTRY_CONTAINER_PATH "/data/app/mcRegistry"
74 #define MC_REGISTRY_DEFAULT_PATH "/system/app/mcRegistry"
75 #define MC_REGISTRY_FALLBACK_PATH "/data/app/mcRegistry"
76 #define AUTH_TOKEN_FILE_NAME "00000000.authtokcont"
77 #define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH"
78 #define ROOT_FILE_NAME "00000000.rootcont"
79 #define SP_CONT_FILE_EXT ".spcont"
80 #define TL_CONT_FILE_EXT ".tlcont"
81 #define DATA_CONT_FILE_EXT ".datacont"
82 #define TL_BIN_FILE_EXT ".tlbin"
83 #define GP_TA_BIN_FILE_EXT ".tabin"
84 #define GP_TA_SPID_FILE_EXT ".spid"
88 //------------------------------------------------------------------------------
89 static string
byteArrayToString(const void *bytes
, size_t elems
)
91 char hx
[elems
* 2 + 1];
93 for (size_t i
= 0; i
< elems
; i
++) {
94 sprintf(&hx
[i
* 2], "%02x", ((uint8_t *)bytes
)[i
]);
99 //------------------------------------------------------------------------------
100 static string
uint32ToString(uint32_t value
)
103 snprintf(hx
, sizeof(hx
), "%08X", value
);
105 return string(str
.rbegin(), str
.rend());
108 //------------------------------------------------------------------------------
109 static bool doesDirExist(const char *path
)
112 if (path
!= NULL
&& stat(path
, &ss
) == 0 && S_ISDIR(ss
.st_mode
)) {
118 //------------------------------------------------------------------------------
119 static string
getRegistryPath()
123 // use the default registry path.
124 registryPath
= MC_REGISTRY_CONTAINER_PATH
;
125 LOG_I(" Using default registry path %s", registryPath
.c_str());
127 assert(registryPath
.length() != 0);
132 //------------------------------------------------------------------------------
133 string
getTlRegistryPath()
137 // First, attempt to use regular registry environment variable.
138 if (doesDirExist(MC_REGISTRY_DEFAULT_PATH
)) {
139 registryPath
= MC_REGISTRY_DEFAULT_PATH
;
140 LOG_I(" Using MC_REGISTRY_PATH %s", registryPath
.c_str());
141 } else if (doesDirExist(MC_REGISTRY_FALLBACK_PATH
)) {
142 // Second, attempt to use fallback registry environment variable.
143 registryPath
= MC_REGISTRY_FALLBACK_PATH
;
144 LOG_I(" Using MC_REGISTRY_FALLBACK_PATH %s", registryPath
.c_str());
147 // As a last resort, use the default registry path.
148 if (registryPath
.length() == 0) {
149 registryPath
= MC_REGISTRY_CONTAINER_PATH
;
150 LOG_I(" Using default registry path %s", registryPath
.c_str());
153 assert(registryPath
.length() != 0);
158 //------------------------------------------------------------------------------
159 static string
getAuthTokenFilePath()
162 string authTokenPath
;
164 // First, attempt to use regular auth token path environment variable.
165 path
= getenv(ENV_MC_AUTH_TOKEN_PATH
);
166 if (doesDirExist(path
)) {
167 LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path
);
168 authTokenPath
= path
;
170 authTokenPath
= getRegistryPath();
171 LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath
.c_str());
174 return authTokenPath
+ "/" + AUTH_TOKEN_FILE_NAME
;
177 //------------------------------------------------------------------------------
178 static string
getRootContFilePath()
180 return getRegistryPath() + "/" + ROOT_FILE_NAME
;
183 //------------------------------------------------------------------------------
184 static string
getSpDataPath(mcSpid_t spid
)
186 return getRegistryPath() + "/" + uint32ToString(spid
);
189 //------------------------------------------------------------------------------
190 static string
getSpContFilePath(mcSpid_t spid
)
192 return getRegistryPath() + "/" + uint32ToString(spid
) + SP_CONT_FILE_EXT
;
195 //------------------------------------------------------------------------------
196 static string
getTlContFilePath(const mcUuid_t
*uuid
, const mcSpid_t spid
)
198 return getRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
))
199 + "." + uint32ToString(spid
) + TL_CONT_FILE_EXT
;
202 //------------------------------------------------------------------------------
203 static string
getTlDataPath(const mcUuid_t
*uuid
)
205 return getRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
));
208 //------------------------------------------------------------------------------
209 static string
getTlDataFilePath(const mcUuid_t
*uuid
, mcPid_t pid
)
211 return getTlDataPath(uuid
) + "/" + uint32ToString(pid
.data
) + DATA_CONT_FILE_EXT
;
214 //------------------------------------------------------------------------------
215 static string
getTlBinFilePath(const mcUuid_t
*uuid
)
217 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + TL_BIN_FILE_EXT
;
220 //------------------------------------------------------------------------------
221 static string
getTABinFilePath(const mcUuid_t
*uuid
)
223 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + GP_TA_BIN_FILE_EXT
;
226 //------------------------------------------------------------------------------
227 static string
getTASpidFilePath(const mcUuid_t
*uuid
)
229 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + GP_TA_SPID_FILE_EXT
;
232 //------------------------------------------------------------------------------
233 mcResult_t
mcRegistryStoreAuthToken(void *so
, uint32_t size
)
235 if (so
== NULL
|| size
> 3 * MAX_SO_CONT_SIZE
) {
236 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
237 return MC_DRV_ERR_INVALID_PARAMETER
;
239 const string
&authTokenFilePath
= getAuthTokenFilePath();
240 LOG_I("store AuthToken: %s", authTokenFilePath
.c_str());
242 FILE *fs
= fopen(authTokenFilePath
.c_str(), "wb");
244 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
245 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
247 fseek(fs
, 0, SEEK_SET
);
248 fwrite((char *)so
, 1, size
, fs
);
256 //------------------------------------------------------------------------------
257 mcResult_t
mcRegistryReadAuthToken(mcSoAuthTokenCont_t
*so
)
260 LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
261 return MC_DRV_ERR_INVALID_PARAMETER
;
263 const string
&authTokenFilePath
= getAuthTokenFilePath();
264 LOG_I("read AuthToken: %s", authTokenFilePath
.c_str());
266 FILE *fs
= fopen(authTokenFilePath
.c_str(), "rb");
268 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
269 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
271 fseek(fs
, 0, SEEK_END
);
272 int32_t filesize
= ftell(fs
);
273 if (sizeof(mcSoAuthTokenCont_t
) != filesize
) {
275 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES
);
276 return MC_DRV_ERR_OUT_OF_RESOURCES
;
278 fseek(fs
, 0, SEEK_SET
);
279 if (fread((char *)so
, 1, sizeof(mcSoAuthTokenCont_t
), fs
) !=
280 sizeof(mcSoAuthTokenCont_t
))
283 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
284 return MC_DRV_ERR_INVALID_PARAMETER
;
291 //------------------------------------------------------------------------------
292 mcResult_t
mcRegistryDeleteAuthToken(void)
294 if (remove(getAuthTokenFilePath().c_str())) {
295 LOG_ERRNO("Delete Auth token file!");
296 return MC_DRV_ERR_UNKNOWN
;
302 //------------------------------------------------------------------------------
303 mcResult_t
mcRegistryStoreRoot(void *so
, uint32_t size
)
305 if (so
== NULL
|| size
> 3 * MAX_SO_CONT_SIZE
) {
306 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
307 return MC_DRV_ERR_INVALID_PARAMETER
;
310 const string
&rootContFilePath
= getRootContFilePath();
311 LOG_I("store Root: %s", rootContFilePath
.c_str());
313 FILE *fs
= fopen(rootContFilePath
.c_str(), "wb");
315 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
316 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
318 fseek(fs
, 0, SEEK_SET
);
319 fwrite((char *)so
, 1, size
, fs
);
327 //------------------------------------------------------------------------------
328 mcResult_t
mcRegistryReadRoot(void *so
, uint32_t *size
)
330 const string
&rootContFilePath
= getRootContFilePath();
334 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
335 return MC_DRV_ERR_INVALID_PARAMETER
;
337 LOG_I(" Opening %s", rootContFilePath
.c_str());
339 FILE *fs
= fopen(rootContFilePath
.c_str(), "rb");
341 LOG_W("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
342 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
344 readBytes
= fread((char *)so
, 1, *size
, fs
);
351 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
352 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
357 //------------------------------------------------------------------------------
358 mcResult_t
mcRegistryStoreSp(mcSpid_t spid
, void *so
, uint32_t size
)
360 if ((spid
== 0) || (so
== NULL
) || size
> 3 * MAX_SO_CONT_SIZE
) {
361 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
362 return MC_DRV_ERR_INVALID_PARAMETER
;
365 const string
&spContFilePath
= getSpContFilePath(spid
);
366 LOG_I("store SP: %s", spContFilePath
.c_str());
368 FILE *fs
= fopen(spContFilePath
.c_str(), "wb");
370 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
371 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
373 fseek(fs
, 0, SEEK_SET
);
374 fwrite((char *)so
, 1, size
, fs
);
382 //------------------------------------------------------------------------------
383 mcResult_t
mcRegistryReadSp(mcSpid_t spid
, void *so
, uint32_t *size
)
385 const string
&spContFilePath
= getSpContFilePath(spid
);
387 if ((spid
== 0) || (so
== NULL
)) {
388 LOG_E("mcRegistry read So.Sp(SpId=0x%x) failed", spid
);
389 return MC_DRV_ERR_INVALID_PARAMETER
;
391 LOG_I(" Reading %s", spContFilePath
.c_str());
393 FILE *fs
= fopen(spContFilePath
.c_str(), "rb");
395 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
396 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
398 readBytes
= fread((char *)so
, 1, *size
, fs
);
405 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
406 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
411 //------------------------------------------------------------------------------
412 mcResult_t
mcRegistryStoreTrustletCon(const mcUuid_t
*uuid
, const mcSpid_t spid
, void *so
, uint32_t size
)
414 if ((uuid
== NULL
) || (so
== NULL
) || size
> 3 * MAX_SO_CONT_SIZE
) {
415 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
416 return MC_DRV_ERR_INVALID_PARAMETER
;
419 const string
&tlContFilePath
= getTlContFilePath(uuid
, spid
);
420 LOG_I("store TLc: %s", tlContFilePath
.c_str());
422 FILE *fs
= fopen(tlContFilePath
.c_str(), "wb");
424 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
425 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
427 fseek(fs
, 0, SEEK_SET
);
428 fwrite((char *)so
, 1, size
, fs
);
435 static uint32_t getAsUint32BE(
436 void *pValueUnaligned
439 uint8_t *p
= (uint8_t *)pValueUnaligned
;
440 uint32_t val
= p
[3] | (p
[2] << 8) | (p
[1] << 16) | (p
[0] << 24);
444 mcResult_t
mcRegistryStoreTABlob(mcSpid_t spid
, void *blob
, uint32_t size
)
447 LOG_I("mcRegistryStoreTABlob started");
450 if (size
< sizeof(mclfHeaderV24_t
)) {
451 LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size");
452 return MC_DRV_ERR_INVALID_PARAMETER
;
455 mclfHeaderV24_t
*header24
= (mclfHeaderV24_t
*)blob
;
456 mclfHeaderV2_t
*header20
= (mclfHeaderV2_t
*)blob
;
458 // Check header version
459 if (header20
->intro
.version
< MC_MAKE_VERSION(2, 4)) {
460 LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4");
461 return MC_DRV_ERR_TA_HEADER_ERROR
;
465 if (header24
->gp_level
!= 1) {
466 LOG_E("RegistryStoreTABlob failed - TA blob header gp_level is not equal to 1");
467 return MC_DRV_ERR_TA_HEADER_ERROR
;
471 switch (header20
->serviceType
) {
472 case SERVICE_TYPE_SYSTEM_TRUSTLET
: {
474 if (spid
!= MC_SPID_SYSTEM
) {
475 LOG_E("RegistryStoreTABlob failed - SPID is not equal to %d for System TA", spid
);
476 return MC_DRV_ERR_INVALID_PARAMETER
;
478 memcpy(&uuid
, &header20
->uuid
, sizeof(mcUuid_t
));
481 case SERVICE_TYPE_SP_TRUSTLET
: {
483 if (spid
>= MC_SPID_SYSTEM
) {
484 LOG_E("RegistryStoreTABlob failed - SPID is equal to %u ", spid
);
485 return MC_DRV_ERR_INVALID_PARAMETER
;
488 uuid_attestation
*pUa
= (uuid_attestation
*) & ((uint8_t *)blob
)[header24
->attestationOffset
];
489 // Check attestation size
490 if ((header24
->attestationOffset
> size
) && (header24
->attestationOffset
+ getAsUint32BE(&pUa
->size
) > size
)) {
491 LOG_E("RegistryStoreTABlob failed - Attestation size is not correct");
492 return MC_DRV_ERR_TA_HEADER_ERROR
;
495 // Check attestation size
496 if (getAsUint32BE(&pUa
->size
) < sizeof(uuid_attestation
)) {
497 LOG_E("RegistryStoreTABlob failed - Attestation size is equal to %d and is less then %d", getAsUint32BE(&pUa
->size
), sizeof(uuid_attestation
));
498 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
502 if (memcmp(pUa
->magic
, MAGIC
, AT_MAGIC_SIZE
)) {
503 LOG_E("RegistryStoreTABlob failed - Attestation magic word is not correct");
504 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
508 if (getAsUint32BE(&pUa
->version
) != AT_VERSION
) {
509 LOG_E("RegistryStoreTABlob failed - Attestation version is equal to %08X. It has to be equal to %08X", getAsUint32BE(&pUa
->version
), AT_VERSION
);
510 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
513 memcpy(&uuid
, &pUa
->uuid
, sizeof(mcUuid_t
));
517 return MC_DRV_ERR_INVALID_PARAMETER
;
520 const string tlBinFilePath
= getTABinFilePath((mcUuid_t
*)&uuid
);
522 LOG_I("Store TA blob at: %s", tlBinFilePath
.c_str());
524 FILE *fs
= fopen(tlBinFilePath
.c_str(), "wb");
526 LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
527 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
529 fseek(fs
, 0, SEEK_SET
);
530 fwrite(blob
, 1, size
, fs
);
534 if (header20
->serviceType
== SERVICE_TYPE_SP_TRUSTLET
) {
535 const string taspidFilePath
= getTASpidFilePath((mcUuid_t
*)&uuid
);
537 LOG_I("Store spid file at: %s", taspidFilePath
.c_str());
539 FILE *fs
= fopen(taspidFilePath
.c_str(), "wb");
541 //TODO: shouldn't we delete TA blob file ?
542 LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
543 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
545 fseek(fs
, 0, SEEK_SET
);
546 fwrite(&spid
, 1, sizeof(mcSpid_t
), fs
);
553 //------------------------------------------------------------------------------
554 mcResult_t
mcRegistryReadTrustletCon(const mcUuid_t
*uuid
, const mcSpid_t spid
, void *so
, uint32_t *size
)
556 if ((uuid
== NULL
) || (so
== NULL
)) {
557 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
558 return MC_DRV_ERR_INVALID_PARAMETER
;
561 const string
&tlContFilePath
= getTlContFilePath(uuid
, spid
);
562 LOG_I("read TLc: %s", tlContFilePath
.c_str());
564 FILE *fs
= fopen(tlContFilePath
.c_str(), "rb");
566 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
567 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
569 fseek(fs
, 0, SEEK_SET
);
570 readBytes
= fread((char *)so
, 1, *size
, fs
);
577 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
578 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
583 //------------------------------------------------------------------------------
584 mcResult_t
mcRegistryStoreData(void *so
, uint32_t size
)
586 mcSoDataCont_t
*dataCont
= (mcSoDataCont_t
*)so
;
588 if (dataCont
== NULL
|| size
!= sizeof(mcSoDataCont_t
)) {
589 LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
590 return MC_DRV_ERR_INVALID_PARAMETER
;
592 string pathname
, filename
;
594 switch (dataCont
->cont
.type
) {
595 case CONT_TYPE_SPDATA
:
596 LOG_E("SPDATA not supported");
597 return MC_DRV_ERR_INVALID_PARAMETER
;
599 case CONT_TYPE_TLDATA
:
600 pathname
= getTlDataPath(&dataCont
->cont
.uuid
);
601 filename
= getTlDataFilePath(&dataCont
->cont
.uuid
, dataCont
->cont
.pid
);
604 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
605 return MC_DRV_ERR_INVALID_PARAMETER
;
607 if (mkdir(pathname
.c_str(), 0777) < 0)
609 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
610 return MC_DRV_ERR_INVALID_PARAMETER
;
613 LOG_I("store DT: %s", filename
.c_str());
615 FILE *fs
= fopen(filename
.c_str(), "wb");
617 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
618 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
620 fseek(fs
, 0, SEEK_SET
);
621 fwrite((char *)dataCont
, 1, MC_SO_SIZE(dataCont
->soHeader
.plainLen
, dataCont
->soHeader
.encryptedLen
), fs
);
629 //------------------------------------------------------------------------------
630 mcResult_t
mcRegistryReadData(uint32_t context
, const mcCid_t
*cid
, mcPid_t pid __unused
,
631 mcSoDataCont_t
*so
, uint32_t maxLen
)
634 if ((NULL
== cid
) || (NULL
== so
)) {
635 LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
636 return MC_DRV_ERR_INVALID_PARAMETER
;
641 LOG_E("SPDATA not supported");
642 return MC_DRV_ERR_INVALID_PARAMETER
;
645 filename
= getTlDataFilePath(&so
->cont
.uuid
, so
->cont
.pid
);
648 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
649 return MC_DRV_ERR_INVALID_PARAMETER
;
651 LOG_I("read DT: %s", filename
.c_str());
653 FILE *fs
= fopen(filename
.c_str(), "rb");
655 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
656 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
658 fseek(fs
, 0, SEEK_END
);
659 uint32_t filesize
= ftell(fs
);
660 if (maxLen
< filesize
) {
662 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES
);
663 return MC_DRV_ERR_OUT_OF_RESOURCES
;
665 fseek(fs
, 0, SEEK_SET
);
666 char *p
= (char *) so
;
667 if (fread(p
, 1, sizeof(mcSoHeader_t
), fs
) != sizeof(mcSoHeader_t
))
670 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
671 return MC_DRV_ERR_INVALID_PARAMETER
;
673 p
+= sizeof(mcSoHeader_t
);
674 if (fread(p
, 1, MC_SO_SIZE(so
->soHeader
.plainLen
,
675 so
->soHeader
.encryptedLen
)
676 - sizeof(mcSoHeader_t
), fs
) !=
677 MC_SO_SIZE(so
->soHeader
.plainLen
, so
->soHeader
.encryptedLen
)
678 - sizeof(mcSoHeader_t
))
681 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
682 return MC_DRV_ERR_INVALID_PARAMETER
;
690 //------------------------------------------------------------------------------
691 static size_t getFileContent(
697 uint8_t *content
= NULL
;
700 pStream
= fopen(pPath
, "rb");
701 if (pStream
== NULL
) {
702 LOG_E("Error: Cannot open file: %s.", pPath
);
706 if (fseek(pStream
, 0L, SEEK_END
) != 0) {
707 LOG_E("Error: Cannot read file: %s.", pPath
);
711 filesize
= ftell(pStream
);
713 LOG_E("Error: Cannot get the file size: %s.", pPath
);
718 LOG_E("Error: Empty file: %s.", pPath
);
722 /* Set the file pointer at the beginning of the file */
723 if (fseek(pStream
, 0L, SEEK_SET
) != 0) {
724 LOG_E("Error: Cannot read file: %s.", pPath
);
728 /* Allocate a buffer for the content */
729 content
= (uint8_t *)malloc(filesize
);
730 if (content
== NULL
) {
731 LOG_E("Error: Cannot read file: Out of memory.");
735 /* Read data from the file into the buffer */
736 if (fread(content
, (size_t)filesize
, 1, pStream
) != 1) {
737 LOG_E("Error: Cannot read file: %s.", pPath
);
743 *ppContent
= content
;
745 /* Return number of bytes read */
746 return (size_t)filesize
;
749 if (content
!= NULL
) {
756 //------------------------------------------------------------------------------
757 static bool mcCheckUuid(const mcUuid_t
*uuid
, const char *filename
)
759 uint8_t *pTAData
= NULL
;
763 nTASize
= getFileContent(filename
, &pTAData
);
765 LOG_E("err: Trusted Application not found.");
770 if (nTASize
< sizeof(mclfHeaderV24_t
)) {
772 LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size");
776 mclfHeaderV2_t
*header20
= (mclfHeaderV2_t
*)pTAData
;
778 // Check header version
779 if (header20
->intro
.version
< MC_MAKE_VERSION(2, 4)) {
781 LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4");
786 if (memcmp(uuid
, &header20
->uuid
, sizeof(mcUuid_t
)) == 0) {
797 //this function deletes all the files owned by a GP TA and stored in the tbase secure storage dir.
798 //then it deletes GP TA folder.
799 static int CleanupGPTAStorage(const char *basename
)
804 string TAPath
= getTlRegistryPath()+"/TbStorage/"+ basename
;
806 if (NULL
!= (dp
= opendir(TAPath
.c_str()))) {
807 while (NULL
!= (de
= readdir(dp
))) {
808 if (de
->d_name
[0] != '.') {
809 string dname
= TAPath
+ "/" + string (de
->d_name
);
810 LOG_I("delete DT: %s", dname
.c_str());
811 if (0 != (e
= remove(dname
.c_str()))) {
812 LOG_E("remove UUID-files %s failed! error: %d", dname
.c_str(), e
);
819 LOG_I("delete dir: %s", TAPath
.c_str());
820 if (0 != (e
= rmdir(TAPath
.c_str()))) {
821 LOG_E("remove UUID-dir failed! errno: %d", e
);
828 static void deleteSPTA(const mcUuid_t
*uuid
, const mcSpid_t spid
, bool checkUuid
)
834 // Delete TABIN and SPID files - we loop searching required spid file
835 string pathname
= getRegistryPath();
836 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
837 while (NULL
!= (de
= readdir(dp
))) {
841 size_t pch_dot
, pch_slash
;
842 spidFile
= pathname
+ '/' + string(de
->d_name
);
843 pch_dot
= spidFile
.find_last_of('.');
844 if (pch_dot
== string::npos
) continue;
845 pch_slash
= spidFile
.find_last_of('/');
846 if ((pch_slash
!= string::npos
) && (pch_slash
> pch_dot
)) continue;
847 if (spidFile
.substr(pch_dot
).compare(GP_TA_SPID_FILE_EXT
) != 0) continue;
849 mcSpid_t curSpid
= 0;
851 int fd
= open(spidFile
.c_str(), O_RDONLY
);
853 if (read(fd
, &curSpid
, sizeof(mcSpid_t
))!=sizeof(mcSpid_t
)) {
858 if (spid
== curSpid
) {
859 tabinFile
= spidFile
.substr(0, pch_dot
) + GP_TA_BIN_FILE_EXT
;
860 if ((!checkUuid
)||(mcCheckUuid(uuid
, tabinFile
.c_str()))) {
861 tabinUuid
= spidFile
.substr(0, pch_dot
);
862 if (0 != (e
= CleanupGPTAStorage(tabinUuid
.c_str()))){
863 LOG_E("cleanup TA Storage dir failed! errno: %d", e
);
864 //return MC_DRV_ERR_UNKNOWN;
866 if (0 != (e
= remove(tabinFile
.c_str()))) {
867 LOG_E("remove TA file failed! errno: %d", e
);
868 //return MC_DRV_ERR_UNKNOWN;
870 if (0 != (e
= remove(spidFile
.c_str()))) {
871 LOG_E("remove SPID file failed! errno: %d", e
);
872 //return MC_DRV_ERR_UNKNOWN;
874 if (checkUuid
) break;
885 //------------------------------------------------------------------------------
886 mcResult_t
mcRegistryCleanupTrustlet(const mcUuid_t
*uuid
, const mcSpid_t spid
)
893 LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
894 return MC_DRV_ERR_INVALID_PARAMETER
;
897 // Delete all TA related data
898 string pathname
= getTlDataPath(uuid
);
899 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
900 while (NULL
!= (de
= readdir(dp
))) {
901 if (de
->d_name
[0] != '.') {
902 string dname
= pathname
+ "/" + string (de
->d_name
);
903 LOG_I("delete DT: %s", dname
.c_str());
904 if (0 != (e
= remove(dname
.c_str()))) {
905 LOG_E("remove UUID-data %s failed! error: %d", dname
.c_str(), e
);
912 LOG_I("delete dir: %s", pathname
.c_str());
913 if (0 != (e
= rmdir(pathname
.c_str()))) {
914 LOG_E("remove UUID-dir failed! errno: %d", e
);
915 return MC_DRV_ERR_UNKNOWN
;
919 // Delete TA binary with the name uuid.tlbin
920 string tlBinFilePath
= getTlBinFilePath(uuid
);
921 LOG_I("delete Tlb: %s", tlBinFilePath
.c_str());
922 if (0 != (e
= remove(tlBinFilePath
.c_str()))) {
923 LOG_E("remove Tlb failed! errno: %d", e
);
924 // return MC_DRV_ERR_UNKNOWN; // a trustlet-binary must not be present ! (registered but not usable)
927 // Delete TABIN and SPID files - we loop searching required spid file
928 deleteSPTA(uuid
,spid
,true);
930 string tlContFilePath
= getTlContFilePath(uuid
, spid
);
931 LOG_I("delete Tlc: %s", tlContFilePath
.c_str());
932 if (0 != (e
= remove(tlContFilePath
.c_str()))) {
933 LOG_E("remove Tlc failed! errno: %d", e
);
934 return MC_DRV_ERR_UNKNOWN
;
940 //------------------------------------------------------------------------------
941 mcResult_t
mcRegistryCleanupSp(mcSpid_t spid
)
951 LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
952 return MC_DRV_ERR_INVALID_PARAMETER
;
954 len
= sizeof(mcSoSpCont_t
);
955 ret
= mcRegistryReadSp(spid
, &data
, &len
);
956 if (MC_DRV_OK
!= ret
|| len
!= sizeof(mcSoSpCont_t
)) {
957 LOG_E("read SP->UUID aborted! Return code: %d", ret
);
960 for (i
= 0; (i
< MC_CONT_CHILDREN_COUNT
) && (ret
== MC_DRV_OK
); i
++) {
961 if (0 != strncmp((const char *) & (data
.cont
.children
[i
]), (const char *)&MC_UUID_FREE
, sizeof(mcUuid_t
))) {
962 ret
= mcRegistryCleanupTrustlet(&(data
.cont
.children
[i
]), spid
);
965 if (MC_DRV_OK
!= ret
) {
966 LOG_E("delete SP->UUID failed! Return code: %d", ret
);
970 // Delete remaining TABIN and SPID files
971 deleteSPTA(NULL
,spid
,false);
973 string pathname
= getSpDataPath(spid
);
975 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
976 while (NULL
!= (de
= readdir(dp
))) {
977 if (de
->d_name
[0] != '.') {
978 string dname
= pathname
+ "/" + string (de
->d_name
);
979 LOG_I("delete DT: %s", dname
.c_str());
980 if (0 != (e
= remove(dname
.c_str()))) {
981 LOG_E("remove SPID-data %s failed! error: %d", dname
.c_str(), e
);
988 LOG_I("delete dir: %s", pathname
.c_str());
989 if (0 != (e
= rmdir(pathname
.c_str()))) {
990 LOG_E("remove SPID-dir failed! error: %d", e
);
991 return MC_DRV_ERR_UNKNOWN
;
994 string spContFilePath
= getSpContFilePath(spid
);
995 LOG_I("delete Sp: %s", spContFilePath
.c_str());
996 if (0 != (e
= remove(spContFilePath
.c_str()))) {
997 LOG_E("remove SP failed! error: %d", e
);
998 return MC_DRV_ERR_UNKNOWN
;
1004 //------------------------------------------------------------------------------
1005 mcResult_t
mcRegistryCleanupRoot(void)
1008 mcSoRootCont_t data
;
1011 len
= sizeof(mcSoRootCont_t
);
1012 ret
= mcRegistryReadRoot(&data
, &len
);
1013 if (MC_DRV_OK
!= ret
|| len
!= sizeof(mcSoRootCont_t
)) {
1014 LOG_E("read Root aborted! Return code: %d", ret
);
1017 for (i
= 0; (i
< MC_CONT_CHILDREN_COUNT
) && (ret
== MC_DRV_OK
); i
++) {
1018 mcSpid_t spid
= data
.cont
.children
[i
];
1019 if (spid
!= MC_SPID_FREE
) {
1020 ret
= mcRegistryCleanupSp(spid
);
1021 if (MC_DRV_OK
!= ret
) {
1022 LOG_E("Cleanup SP failed! Return code: %d", ret
);
1028 string rootContFilePath
= getRootContFilePath();
1029 LOG_I("Delete root: %s", rootContFilePath
.c_str());
1030 if (0 != (e
= remove(rootContFilePath
.c_str()))) {
1031 LOG_E("Delete root failed! error: %d", e
);
1032 return MC_DRV_ERR_UNKNOWN
;
1037 //------------------------------------------------------------------------------
1038 regObject_t
*mcRegistryMemGetServiceBlob(mcSpid_t spid
, void *trustlet
, uint32_t tlSize
)
1040 regObject_t
*regobj
= NULL
;
1042 // Ensure that a UUID is provided.
1043 if (NULL
== trustlet
) {
1044 LOG_E("No trustlet buffer given");
1048 // Check service blob size.
1049 if (tlSize
> MAX_TL_SIZE
) {
1050 LOG_E("mcRegistryMemGetServiceBlob() failed: service blob too big: %d", tlSize
);
1054 mclfIntro_t
*pIntro
= (mclfIntro_t
*)trustlet
;
1055 // Check TL magic value.
1056 if (pIntro
->magic
!= MC_SERVICE_HEADER_MAGIC_BE
) {
1057 LOG_E("mcRegistryMemGetServiceBlob() failed: wrong header magic value: %d", pIntro
->magic
);
1061 // Get service type.
1062 mclfHeaderV2_t
*pHeader
= (mclfHeaderV2_t
*)trustlet
;
1065 const char *service_types
[] = {
1066 "illegal", "Driver", "Trustlet", "System Trustlet"
1068 int serviceType_safe
= pHeader
->serviceType
> SERVICE_TYPE_SYSTEM_TRUSTLET
? SERVICE_TYPE_ILLEGAL
: pHeader
->serviceType
;
1069 LOG_I(" Service is a %s (service type %d)", service_types
[serviceType_safe
], pHeader
->serviceType
);
1073 LOG_I(" Trustlet text %u data %u ", pHeader
->text
.len
, pHeader
->data
.len
);
1075 // If loadable driver or system trustlet.
1076 if (pHeader
->serviceType
== SERVICE_TYPE_DRIVER
|| pHeader
->serviceType
== SERVICE_TYPE_SYSTEM_TRUSTLET
) {
1077 // Take trustlet blob 'as is'.
1078 if (NULL
== (regobj
= (regObject_t
*) (malloc(sizeof(regObject_t
) + tlSize
)))) {
1079 LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
1082 regobj
->len
= tlSize
;
1083 regobj
->tlStartOffset
= 0;
1084 memcpy((char *)regobj
->value
, trustlet
, tlSize
);
1085 // If user trustlet.
1086 } else if (pHeader
->serviceType
== SERVICE_TYPE_SP_TRUSTLET
) {
1087 // Take trustlet blob and append root, sp, and tl container.
1088 size_t regObjValueSize
= tlSize
+ sizeof(mcBlobLenInfo_t
) + 3 * MAX_SO_CONT_SIZE
;
1090 // Prepare registry object.
1091 if (NULL
== (regobj
= (regObject_t
*) malloc(sizeof(regObject_t
) + regObjValueSize
))) {
1092 LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
1095 regobj
->len
= regObjValueSize
;
1096 regobj
->tlStartOffset
= sizeof(mcBlobLenInfo_t
);
1097 uint8_t *p
= regobj
->value
;
1099 // Reserve space for the blob length structure
1100 mcBlobLenInfo_ptr lenInfo
= (mcBlobLenInfo_ptr
)p
;
1101 lenInfo
->magic
= MC_TLBLOBLEN_MAGIC
;
1102 p
+= sizeof(mcBlobLenInfo_t
);
1103 // Fill in trustlet blob after the len info
1104 memcpy(p
, trustlet
, tlSize
);
1107 // Final registry object value looks like this:
1109 // +---------------+---------------------------+-----------+---------+---------+
1110 // | Blob Len Info | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont |
1111 // +---------------+---------------------------+-----------+-------------------+
1112 // /------ Trustlet BLOB ------/
1114 // /------------------ regobj->header.len -------------------------------------/
1116 // start at the end of the trustlet blob
1119 uint32_t soTltContSize
= MAX_SO_CONT_SIZE
;
1122 // Fill in root container.
1123 len
= sizeof(mcSoRootCont_t
);
1124 if (MC_DRV_OK
!= (ret
= mcRegistryReadRoot(p
, &len
))) {
1127 lenInfo
->rootContBlobSize
= len
;
1130 // Fill in SP container.
1131 len
= sizeof(mcSoSpCont_t
);
1132 if (MC_DRV_OK
!= (ret
= mcRegistryReadSp(spid
, p
, &len
))) {
1135 lenInfo
->spContBlobSize
= len
;
1138 // Fill in TLT Container
1139 // We know exactly how much space is left in the buffer
1140 soTltContSize
= regObjValueSize
- tlSize
+ sizeof(mcBlobLenInfo_t
)
1141 - lenInfo
->spContBlobSize
- lenInfo
->rootContBlobSize
;
1142 if (MC_DRV_OK
!= (ret
= mcRegistryReadTrustletCon(&pHeader
->uuid
, spid
, p
, &soTltContSize
))) {
1145 lenInfo
->tlContBlobSize
= soTltContSize
;
1146 LOG_I(" Trustlet container %u bytes loaded", soTltContSize
);
1147 // Depending on the trustlet container size we decide which structure to use
1148 // Unfortunate design but it should have to do for now
1149 if (soTltContSize
== sizeof(mcSoTltCont_2_0_t
)) {
1150 LOG_I(" Using 2.0 trustlet container");
1151 } else if (soTltContSize
== sizeof(mcSoTltCont_2_1_t
)) {
1152 LOG_I(" Using 2.1 trustlet container");
1154 LOG_E("Trustlet container has unknown size");
1159 if (MC_DRV_OK
!= ret
) {
1160 LOG_E("mcRegistryMemGetServiceBlob() failed: Error code: %d", ret
);
1164 // Now we know the sizes for all containers so set the correct size
1165 regobj
->len
= sizeof(mcBlobLenInfo_t
) + tlSize
+
1166 lenInfo
->rootContBlobSize
+
1167 lenInfo
->spContBlobSize
+
1168 lenInfo
->tlContBlobSize
;
1169 // Any other service type.
1171 LOG_E("mcRegistryMemGetServiceBlob() failed: Unsupported service type %u", pHeader
->serviceType
);
1177 //------------------------------------------------------------------------------
1178 regObject_t
*mcRegistryFileGetServiceBlob(const char *trustlet
, mcSpid_t spid
)
1181 regObject_t
*regobj
= NULL
;
1184 // Ensure that a file name is provided.
1185 if (trustlet
== NULL
) {
1186 LOG_E("No file given");
1190 int fd
= open(trustlet
, O_RDONLY
);
1192 LOG_E("Cannot open %s", trustlet
);
1196 if (fstat(fd
, &sb
) == -1) {
1197 LOG_E("mcRegistryFileGetServiceBlob() failed: Cound't get file size");
1201 buffer
= mmap(NULL
, sb
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1202 if (buffer
== MAP_FAILED
) {
1203 LOG_E("mcRegistryFileGetServiceBlob(): Failed to map file to memory");
1207 regobj
= mcRegistryMemGetServiceBlob(spid
, buffer
, sb
.st_size
);
1209 // We don't actually care if either of them fails but should still print warnings
1210 if (munmap(buffer
, sb
.st_size
)) {
1211 LOG_E("mcRegistryFileGetServiceBlob(): Failed to unmap memory");
1216 LOG_E("mcRegistryFileGetServiceBlob(): Failed to close file %s", trustlet
);
1223 //------------------------------------------------------------------------------
1224 regObject_t
*mcRegistryGetServiceBlob(const mcUuid_t
*uuid
, bool isGpUuid
)
1226 // Ensure that a UUID is provided.
1228 LOG_E("No UUID given");
1232 // Open service blob file.
1233 string tlBinFilePath
;
1235 tlBinFilePath
= getTABinFilePath(uuid
);
1237 tlBinFilePath
= getTlBinFilePath(uuid
);
1239 LOG_I("Loading %s", tlBinFilePath
.c_str());
1243 string taspidFilePath
= getTASpidFilePath(uuid
);
1244 int fd
= open(taspidFilePath
.c_str(), O_RDONLY
);
1246 // This can be ok for System TAs
1247 //LOG_ERRNO("open");
1248 //LOG_E("Cannot open %s", taspidFilePath.c_str());
1251 if (read(fd
, &spid
, sizeof(mcSpid_t
))!=sizeof(mcSpid_t
)) {
1259 return mcRegistryFileGetServiceBlob(tlBinFilePath
.c_str(), spid
);
1262 //------------------------------------------------------------------------------
1263 regObject_t
*mcRegistryGetDriverBlob(const char *filename
)
1265 regObject_t
*regobj
= mcRegistryFileGetServiceBlob(filename
, 0);
1267 if (regobj
== NULL
) {
1268 LOG_E("mcRegistryGetDriverBlob() failed");
1272 // Get service type.
1273 mclfHeaderV2_t
*pHeader
= (mclfHeaderV2_t
*)regobj
->value
;
1275 // If file is not a driver we are not interested
1276 if (pHeader
->serviceType
!= SERVICE_TYPE_DRIVER
) {
1277 LOG_E("mcRegistryGetDriverBlob() failed: Unsupported service type %u", pHeader
->serviceType
);