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_VENDOR_PATH "/vendor/app/mcRegistry"
76 #define MC_REGISTRY_FALLBACK_PATH "/data/app/mcRegistry"
77 #define AUTH_TOKEN_FILE_NAME "00000000.authtokcont"
78 #define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH"
79 #define ROOT_FILE_NAME "00000000.rootcont"
80 #define SP_CONT_FILE_EXT ".spcont"
81 #define TL_CONT_FILE_EXT ".tlcont"
82 #define DATA_CONT_FILE_EXT ".datacont"
83 #define TL_BIN_FILE_EXT ".tlbin"
84 #define GP_TA_BIN_FILE_EXT ".tabin"
85 #define GP_TA_SPID_FILE_EXT ".spid"
89 //------------------------------------------------------------------------------
90 static string
byteArrayToString(const void *bytes
, size_t elems
)
92 char hx
[elems
* 2 + 1];
94 for (size_t i
= 0; i
< elems
; i
++) {
95 sprintf(&hx
[i
* 2], "%02x", ((uint8_t *)bytes
)[i
]);
100 //------------------------------------------------------------------------------
101 static string
uint32ToString(uint32_t value
)
104 snprintf(hx
, sizeof(hx
), "%08X", value
);
106 return string(str
.rbegin(), str
.rend());
109 //------------------------------------------------------------------------------
110 static bool doesDirExist(const char *path
)
113 if (path
!= NULL
&& stat(path
, &ss
) == 0 && S_ISDIR(ss
.st_mode
)) {
119 //------------------------------------------------------------------------------
120 static string
getRegistryPath()
124 // use the default registry path.
125 registryPath
= MC_REGISTRY_CONTAINER_PATH
;
126 LOG_I(" Using default registry path %s", registryPath
.c_str());
128 assert(registryPath
.length() != 0);
133 //------------------------------------------------------------------------------
134 string
getTlRegistryPath()
138 // First, attempt to use regular registry environment variable.
139 if (doesDirExist(MC_REGISTRY_DEFAULT_PATH
)) {
140 registryPath
= MC_REGISTRY_DEFAULT_PATH
;
141 LOG_I(" Using MC_REGISTRY_PATH %s", registryPath
.c_str());
142 } else if (doesDirExist(MC_REGISTRY_VENDOR_PATH
)) {
143 // Second, attempt to use regular registry environment variable.
144 registryPath
= MC_REGISTRY_VENDOR_PATH
;
145 LOG_I(" Using MC_REGISTRY_VENDOR_PATH %s", registryPath
.c_str());
146 } else if (doesDirExist(MC_REGISTRY_FALLBACK_PATH
)) {
147 // Third, attempt to use fallback registry environment variable.
148 registryPath
= MC_REGISTRY_FALLBACK_PATH
;
149 LOG_I(" Using MC_REGISTRY_FALLBACK_PATH %s", registryPath
.c_str());
152 // As a last resort, use the default registry path.
153 if (registryPath
.length() == 0) {
154 registryPath
= MC_REGISTRY_CONTAINER_PATH
;
155 LOG_I(" Using default registry path %s", registryPath
.c_str());
158 assert(registryPath
.length() != 0);
163 //------------------------------------------------------------------------------
164 static string
getAuthTokenFilePath()
167 string authTokenPath
;
169 // First, attempt to use regular auth token path environment variable.
170 path
= getenv(ENV_MC_AUTH_TOKEN_PATH
);
171 if (doesDirExist(path
)) {
172 LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path
);
173 authTokenPath
= path
;
175 authTokenPath
= getRegistryPath();
176 LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath
.c_str());
179 return authTokenPath
+ "/" + AUTH_TOKEN_FILE_NAME
;
182 //------------------------------------------------------------------------------
183 static string
getRootContFilePath()
185 return getRegistryPath() + "/" + ROOT_FILE_NAME
;
188 //------------------------------------------------------------------------------
189 static string
getSpDataPath(mcSpid_t spid
)
191 return getRegistryPath() + "/" + uint32ToString(spid
);
194 //------------------------------------------------------------------------------
195 static string
getSpContFilePath(mcSpid_t spid
)
197 return getRegistryPath() + "/" + uint32ToString(spid
) + SP_CONT_FILE_EXT
;
200 //------------------------------------------------------------------------------
201 static string
getTlContFilePath(const mcUuid_t
*uuid
, const mcSpid_t spid
)
203 return getRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
))
204 + "." + uint32ToString(spid
) + TL_CONT_FILE_EXT
;
207 //------------------------------------------------------------------------------
208 static string
getTlDataPath(const mcUuid_t
*uuid
)
210 return getRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
));
213 //------------------------------------------------------------------------------
214 static string
getTlDataFilePath(const mcUuid_t
*uuid
, mcPid_t pid
)
216 return getTlDataPath(uuid
) + "/" + uint32ToString(pid
.data
) + DATA_CONT_FILE_EXT
;
219 //------------------------------------------------------------------------------
220 static string
getTlBinFilePath(const mcUuid_t
*uuid
)
222 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + TL_BIN_FILE_EXT
;
225 //------------------------------------------------------------------------------
226 static string
getTABinFilePath(const mcUuid_t
*uuid
)
228 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + GP_TA_BIN_FILE_EXT
;
231 //------------------------------------------------------------------------------
232 static string
getTASpidFilePath(const mcUuid_t
*uuid
)
234 return getTlRegistryPath() + "/" + byteArrayToString(uuid
, sizeof(*uuid
)) + GP_TA_SPID_FILE_EXT
;
237 //------------------------------------------------------------------------------
238 mcResult_t
mcRegistryStoreAuthToken(void *so
, uint32_t size
)
240 if (so
== NULL
|| size
> 3 * MAX_SO_CONT_SIZE
) {
241 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
242 return MC_DRV_ERR_INVALID_PARAMETER
;
244 const string
&authTokenFilePath
= getAuthTokenFilePath();
245 LOG_I("store AuthToken: %s", authTokenFilePath
.c_str());
247 FILE *fs
= fopen(authTokenFilePath
.c_str(), "wb");
249 LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
250 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
252 fseek(fs
, 0, SEEK_SET
);
253 fwrite((char *)so
, 1, size
, fs
);
261 //------------------------------------------------------------------------------
262 mcResult_t
mcRegistryReadAuthToken(mcSoAuthTokenCont_t
*so
)
265 LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
266 return MC_DRV_ERR_INVALID_PARAMETER
;
268 const string
&authTokenFilePath
= getAuthTokenFilePath();
269 LOG_I("read AuthToken: %s", authTokenFilePath
.c_str());
271 FILE *fs
= fopen(authTokenFilePath
.c_str(), "rb");
273 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
274 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
276 fseek(fs
, 0, SEEK_END
);
277 int32_t filesize
= ftell(fs
);
278 if (sizeof(mcSoAuthTokenCont_t
) != filesize
) {
280 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES
);
281 return MC_DRV_ERR_OUT_OF_RESOURCES
;
283 fseek(fs
, 0, SEEK_SET
);
284 if (fread((char *)so
, 1, sizeof(mcSoAuthTokenCont_t
), fs
) !=
285 sizeof(mcSoAuthTokenCont_t
))
288 LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
289 return MC_DRV_ERR_INVALID_PARAMETER
;
296 //------------------------------------------------------------------------------
297 mcResult_t
mcRegistryDeleteAuthToken(void)
299 if (remove(getAuthTokenFilePath().c_str())) {
300 LOG_ERRNO("Delete Auth token file!");
301 return MC_DRV_ERR_UNKNOWN
;
307 //------------------------------------------------------------------------------
308 mcResult_t
mcRegistryStoreRoot(void *so
, uint32_t size
)
310 if (so
== NULL
|| size
> 3 * MAX_SO_CONT_SIZE
) {
311 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
312 return MC_DRV_ERR_INVALID_PARAMETER
;
315 const string
&rootContFilePath
= getRootContFilePath();
316 LOG_I("store Root: %s", rootContFilePath
.c_str());
318 FILE *fs
= fopen(rootContFilePath
.c_str(), "wb");
320 LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
321 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
323 fseek(fs
, 0, SEEK_SET
);
324 fwrite((char *)so
, 1, size
, fs
);
332 //------------------------------------------------------------------------------
333 mcResult_t
mcRegistryReadRoot(void *so
, uint32_t *size
)
335 const string
&rootContFilePath
= getRootContFilePath();
339 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
340 return MC_DRV_ERR_INVALID_PARAMETER
;
342 LOG_I(" Opening %s", rootContFilePath
.c_str());
344 FILE *fs
= fopen(rootContFilePath
.c_str(), "rb");
346 LOG_W("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
347 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
349 readBytes
= fread((char *)so
, 1, *size
, fs
);
356 LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
357 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
362 //------------------------------------------------------------------------------
363 mcResult_t
mcRegistryStoreSp(mcSpid_t spid
, void *so
, uint32_t size
)
365 if ((spid
== 0) || (so
== NULL
) || size
> 3 * MAX_SO_CONT_SIZE
) {
366 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
367 return MC_DRV_ERR_INVALID_PARAMETER
;
370 const string
&spContFilePath
= getSpContFilePath(spid
);
371 LOG_I("store SP: %s", spContFilePath
.c_str());
373 FILE *fs
= fopen(spContFilePath
.c_str(), "wb");
375 LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
376 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
378 fseek(fs
, 0, SEEK_SET
);
379 fwrite((char *)so
, 1, size
, fs
);
387 //------------------------------------------------------------------------------
388 mcResult_t
mcRegistryReadSp(mcSpid_t spid
, void *so
, uint32_t *size
)
390 const string
&spContFilePath
= getSpContFilePath(spid
);
392 if ((spid
== 0) || (so
== NULL
)) {
393 LOG_E("mcRegistry read So.Sp(SpId=0x%x) failed", spid
);
394 return MC_DRV_ERR_INVALID_PARAMETER
;
396 LOG_I(" Reading %s", spContFilePath
.c_str());
398 FILE *fs
= fopen(spContFilePath
.c_str(), "rb");
400 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
401 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
403 readBytes
= fread((char *)so
, 1, *size
, fs
);
410 LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
411 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
416 //------------------------------------------------------------------------------
417 mcResult_t
mcRegistryStoreTrustletCon(const mcUuid_t
*uuid
, const mcSpid_t spid
, void *so
, uint32_t size
)
419 if ((uuid
== NULL
) || (so
== NULL
) || size
> 3 * MAX_SO_CONT_SIZE
) {
420 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
421 return MC_DRV_ERR_INVALID_PARAMETER
;
424 const string
&tlContFilePath
= getTlContFilePath(uuid
, spid
);
425 LOG_I("store TLc: %s", tlContFilePath
.c_str());
427 FILE *fs
= fopen(tlContFilePath
.c_str(), "wb");
429 LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
430 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
432 fseek(fs
, 0, SEEK_SET
);
433 fwrite((char *)so
, 1, size
, fs
);
440 static uint32_t getAsUint32BE(
441 void *pValueUnaligned
444 uint8_t *p
= (uint8_t *)pValueUnaligned
;
445 uint32_t val
= p
[3] | (p
[2] << 8) | (p
[1] << 16) | (p
[0] << 24);
449 mcResult_t
mcRegistryStoreTABlob(mcSpid_t spid
, void *blob
, uint32_t size
)
452 LOG_I("mcRegistryStoreTABlob started");
455 if (size
< sizeof(mclfHeaderV24_t
)) {
456 LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size");
457 return MC_DRV_ERR_INVALID_PARAMETER
;
460 mclfHeaderV24_t
*header24
= (mclfHeaderV24_t
*)blob
;
461 mclfHeaderV2_t
*header20
= (mclfHeaderV2_t
*)blob
;
463 // Check header version
464 if (header20
->intro
.version
< MC_MAKE_VERSION(2, 4)) {
465 LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4");
466 return MC_DRV_ERR_TA_HEADER_ERROR
;
470 if (header24
->gp_level
!= 1) {
471 LOG_E("RegistryStoreTABlob failed - TA blob header gp_level is not equal to 1");
472 return MC_DRV_ERR_TA_HEADER_ERROR
;
476 switch (header20
->serviceType
) {
477 case SERVICE_TYPE_SYSTEM_TRUSTLET
: {
479 if (spid
!= MC_SPID_SYSTEM
) {
480 LOG_E("RegistryStoreTABlob failed - SPID is not equal to %d for System TA", spid
);
481 return MC_DRV_ERR_INVALID_PARAMETER
;
483 memcpy(&uuid
, &header20
->uuid
, sizeof(mcUuid_t
));
486 case SERVICE_TYPE_SP_TRUSTLET
: {
488 if (spid
>= MC_SPID_SYSTEM
) {
489 LOG_E("RegistryStoreTABlob failed - SPID is equal to %u ", spid
);
490 return MC_DRV_ERR_INVALID_PARAMETER
;
493 uuid_attestation
*pUa
= (uuid_attestation
*) & ((uint8_t *)blob
)[header24
->attestationOffset
];
494 // Check attestation size
495 if ((header24
->attestationOffset
> size
) && (header24
->attestationOffset
+ getAsUint32BE(&pUa
->size
) > size
)) {
496 LOG_E("RegistryStoreTABlob failed - Attestation size is not correct");
497 return MC_DRV_ERR_TA_HEADER_ERROR
;
500 // Check attestation size
501 if (getAsUint32BE(&pUa
->size
) < sizeof(uuid_attestation
)) {
502 LOG_E("RegistryStoreTABlob failed - Attestation size is equal to %d and is less then %d", getAsUint32BE(&pUa
->size
), sizeof(uuid_attestation
));
503 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
507 if (memcmp(pUa
->magic
, MAGIC
, AT_MAGIC_SIZE
)) {
508 LOG_E("RegistryStoreTABlob failed - Attestation magic word is not correct");
509 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
513 if (getAsUint32BE(&pUa
->version
) != AT_VERSION
) {
514 LOG_E("RegistryStoreTABlob failed - Attestation version is equal to %08X. It has to be equal to %08X", getAsUint32BE(&pUa
->version
), AT_VERSION
);
515 return MC_DRV_ERR_TA_ATTESTATION_ERROR
;
518 memcpy(&uuid
, &pUa
->uuid
, sizeof(mcUuid_t
));
522 return MC_DRV_ERR_INVALID_PARAMETER
;
525 const string tlBinFilePath
= getTABinFilePath((mcUuid_t
*)&uuid
);
527 LOG_I("Store TA blob at: %s", tlBinFilePath
.c_str());
529 FILE *fs
= fopen(tlBinFilePath
.c_str(), "wb");
531 LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
532 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
534 fseek(fs
, 0, SEEK_SET
);
535 fwrite(blob
, 1, size
, fs
);
539 if (header20
->serviceType
== SERVICE_TYPE_SP_TRUSTLET
) {
540 const string taspidFilePath
= getTASpidFilePath((mcUuid_t
*)&uuid
);
542 LOG_I("Store spid file at: %s", taspidFilePath
.c_str());
544 FILE *fs
= fopen(taspidFilePath
.c_str(), "wb");
546 //TODO: shouldn't we delete TA blob file ?
547 LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
548 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
550 fseek(fs
, 0, SEEK_SET
);
551 fwrite(&spid
, 1, sizeof(mcSpid_t
), fs
);
558 //------------------------------------------------------------------------------
559 mcResult_t
mcRegistryReadTrustletCon(const mcUuid_t
*uuid
, const mcSpid_t spid
, void *so
, uint32_t *size
)
561 if ((uuid
== NULL
) || (so
== NULL
)) {
562 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
563 return MC_DRV_ERR_INVALID_PARAMETER
;
566 const string
&tlContFilePath
= getTlContFilePath(uuid
, spid
);
567 LOG_I("read TLc: %s", tlContFilePath
.c_str());
569 FILE *fs
= fopen(tlContFilePath
.c_str(), "rb");
571 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
572 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
574 fseek(fs
, 0, SEEK_SET
);
575 readBytes
= fread((char *)so
, 1, *size
, fs
);
582 LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
583 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
588 //------------------------------------------------------------------------------
589 mcResult_t
mcRegistryStoreData(void *so
, uint32_t size
)
591 mcSoDataCont_t
*dataCont
= (mcSoDataCont_t
*)so
;
593 if (dataCont
== NULL
|| size
!= sizeof(mcSoDataCont_t
)) {
594 LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
595 return MC_DRV_ERR_INVALID_PARAMETER
;
597 string pathname
, filename
;
599 switch (dataCont
->cont
.type
) {
600 case CONT_TYPE_SPDATA
:
601 LOG_E("SPDATA not supported");
602 return MC_DRV_ERR_INVALID_PARAMETER
;
604 case CONT_TYPE_TLDATA
:
605 pathname
= getTlDataPath(&dataCont
->cont
.uuid
);
606 filename
= getTlDataFilePath(&dataCont
->cont
.uuid
, dataCont
->cont
.pid
);
609 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
610 return MC_DRV_ERR_INVALID_PARAMETER
;
612 if (mkdir(pathname
.c_str(), 0777) < 0)
614 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
615 return MC_DRV_ERR_INVALID_PARAMETER
;
618 LOG_I("store DT: %s", filename
.c_str());
620 FILE *fs
= fopen(filename
.c_str(), "wb");
622 LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
623 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
625 fseek(fs
, 0, SEEK_SET
);
626 fwrite((char *)dataCont
, 1, MC_SO_SIZE(dataCont
->soHeader
.plainLen
, dataCont
->soHeader
.encryptedLen
), fs
);
634 //------------------------------------------------------------------------------
635 mcResult_t
mcRegistryReadData(uint32_t context
, const mcCid_t
*cid
, mcPid_t pid __unused
,
636 mcSoDataCont_t
*so
, uint32_t maxLen
)
639 if ((NULL
== cid
) || (NULL
== so
)) {
640 LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
641 return MC_DRV_ERR_INVALID_PARAMETER
;
646 LOG_E("SPDATA not supported");
647 return MC_DRV_ERR_INVALID_PARAMETER
;
650 filename
= getTlDataFilePath(&so
->cont
.uuid
, so
->cont
.pid
);
653 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
654 return MC_DRV_ERR_INVALID_PARAMETER
;
656 LOG_I("read DT: %s", filename
.c_str());
658 FILE *fs
= fopen(filename
.c_str(), "rb");
660 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE
);
661 return MC_DRV_ERR_INVALID_DEVICE_FILE
;
663 fseek(fs
, 0, SEEK_END
);
664 uint32_t filesize
= ftell(fs
);
665 if (maxLen
< filesize
) {
667 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES
);
668 return MC_DRV_ERR_OUT_OF_RESOURCES
;
670 fseek(fs
, 0, SEEK_SET
);
671 char *p
= (char *) so
;
672 if (fread(p
, 1, sizeof(mcSoHeader_t
), fs
) != sizeof(mcSoHeader_t
))
675 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
676 return MC_DRV_ERR_INVALID_PARAMETER
;
678 p
+= sizeof(mcSoHeader_t
);
679 if (fread(p
, 1, MC_SO_SIZE(so
->soHeader
.plainLen
,
680 so
->soHeader
.encryptedLen
)
681 - sizeof(mcSoHeader_t
), fs
) !=
682 MC_SO_SIZE(so
->soHeader
.plainLen
, so
->soHeader
.encryptedLen
)
683 - sizeof(mcSoHeader_t
))
686 LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
687 return MC_DRV_ERR_INVALID_PARAMETER
;
695 //------------------------------------------------------------------------------
696 static size_t getFileContent(
702 uint8_t *content
= NULL
;
705 pStream
= fopen(pPath
, "rb");
706 if (pStream
== NULL
) {
707 LOG_E("Error: Cannot open file: %s.", pPath
);
711 if (fseek(pStream
, 0L, SEEK_END
) != 0) {
712 LOG_E("Error: Cannot read file: %s.", pPath
);
716 filesize
= ftell(pStream
);
718 LOG_E("Error: Cannot get the file size: %s.", pPath
);
723 LOG_E("Error: Empty file: %s.", pPath
);
727 /* Set the file pointer at the beginning of the file */
728 if (fseek(pStream
, 0L, SEEK_SET
) != 0) {
729 LOG_E("Error: Cannot read file: %s.", pPath
);
733 /* Allocate a buffer for the content */
734 content
= (uint8_t *)malloc(filesize
);
735 if (content
== NULL
) {
736 LOG_E("Error: Cannot read file: Out of memory.");
740 /* Read data from the file into the buffer */
741 if (fread(content
, (size_t)filesize
, 1, pStream
) != 1) {
742 LOG_E("Error: Cannot read file: %s.", pPath
);
748 *ppContent
= content
;
750 /* Return number of bytes read */
751 return (size_t)filesize
;
754 if (content
!= NULL
) {
761 //------------------------------------------------------------------------------
762 static bool mcCheckUuid(const mcUuid_t
*uuid
, const char *filename
)
764 uint8_t *pTAData
= NULL
;
768 nTASize
= getFileContent(filename
, &pTAData
);
770 LOG_E("err: Trusted Application not found.");
775 if (nTASize
< sizeof(mclfHeaderV24_t
)) {
777 LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size");
781 mclfHeaderV2_t
*header20
= (mclfHeaderV2_t
*)pTAData
;
783 // Check header version
784 if (header20
->intro
.version
< MC_MAKE_VERSION(2, 4)) {
786 LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4");
791 if (memcmp(uuid
, &header20
->uuid
, sizeof(mcUuid_t
)) == 0) {
802 //this function deletes all the files owned by a GP TA and stored in the tbase secure storage dir.
803 //then it deletes GP TA folder.
804 static int CleanupGPTAStorage(const char *basename
)
809 string TAPath
= getTlRegistryPath()+"/TbStorage/"+ basename
;
811 if (NULL
!= (dp
= opendir(TAPath
.c_str()))) {
812 while (NULL
!= (de
= readdir(dp
))) {
813 if (de
->d_name
[0] != '.') {
814 string dname
= TAPath
+ "/" + string (de
->d_name
);
815 LOG_I("delete DT: %s", dname
.c_str());
816 if (0 != (e
= remove(dname
.c_str()))) {
817 LOG_E("remove UUID-files %s failed! error: %d", dname
.c_str(), e
);
824 LOG_I("delete dir: %s", TAPath
.c_str());
825 if (0 != (e
= rmdir(TAPath
.c_str()))) {
826 LOG_E("remove UUID-dir failed! errno: %d", e
);
833 static void deleteSPTA(const mcUuid_t
*uuid
, const mcSpid_t spid
, bool checkUuid
)
839 // Delete TABIN and SPID files - we loop searching required spid file
840 string pathname
= getRegistryPath();
841 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
842 while (NULL
!= (de
= readdir(dp
))) {
846 size_t pch_dot
, pch_slash
;
847 spidFile
= pathname
+ '/' + string(de
->d_name
);
848 pch_dot
= spidFile
.find_last_of('.');
849 if (pch_dot
== string::npos
) continue;
850 pch_slash
= spidFile
.find_last_of('/');
851 if ((pch_slash
!= string::npos
) && (pch_slash
> pch_dot
)) continue;
852 if (spidFile
.substr(pch_dot
).compare(GP_TA_SPID_FILE_EXT
) != 0) continue;
854 mcSpid_t curSpid
= 0;
856 int fd
= open(spidFile
.c_str(), O_RDONLY
);
858 if (read(fd
, &curSpid
, sizeof(mcSpid_t
))!=sizeof(mcSpid_t
)) {
863 if (spid
== curSpid
) {
864 tabinFile
= spidFile
.substr(0, pch_dot
) + GP_TA_BIN_FILE_EXT
;
865 if ((!checkUuid
)||(mcCheckUuid(uuid
, tabinFile
.c_str()))) {
866 tabinUuid
= spidFile
.substr(0, pch_dot
);
867 if (0 != (e
= CleanupGPTAStorage(tabinUuid
.c_str()))){
868 LOG_E("cleanup TA Storage dir failed! errno: %d", e
);
869 //return MC_DRV_ERR_UNKNOWN;
871 if (0 != (e
= remove(tabinFile
.c_str()))) {
872 LOG_E("remove TA file failed! errno: %d", e
);
873 //return MC_DRV_ERR_UNKNOWN;
875 if (0 != (e
= remove(spidFile
.c_str()))) {
876 LOG_E("remove SPID file failed! errno: %d", e
);
877 //return MC_DRV_ERR_UNKNOWN;
879 if (checkUuid
) break;
890 //------------------------------------------------------------------------------
891 mcResult_t
mcRegistryCleanupTrustlet(const mcUuid_t
*uuid
, const mcSpid_t spid
)
898 LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
899 return MC_DRV_ERR_INVALID_PARAMETER
;
902 // Delete all TA related data
903 string pathname
= getTlDataPath(uuid
);
904 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
905 while (NULL
!= (de
= readdir(dp
))) {
906 if (de
->d_name
[0] != '.') {
907 string dname
= pathname
+ "/" + string (de
->d_name
);
908 LOG_I("delete DT: %s", dname
.c_str());
909 if (0 != (e
= remove(dname
.c_str()))) {
910 LOG_E("remove UUID-data %s failed! error: %d", dname
.c_str(), e
);
917 LOG_I("delete dir: %s", pathname
.c_str());
918 if (0 != (e
= rmdir(pathname
.c_str()))) {
919 LOG_E("remove UUID-dir failed! errno: %d", e
);
920 return MC_DRV_ERR_UNKNOWN
;
924 // Delete TA binary with the name uuid.tlbin
925 string tlBinFilePath
= getTlBinFilePath(uuid
);
926 LOG_I("delete Tlb: %s", tlBinFilePath
.c_str());
927 if (0 != (e
= remove(tlBinFilePath
.c_str()))) {
928 LOG_E("remove Tlb failed! errno: %d", e
);
929 // return MC_DRV_ERR_UNKNOWN; // a trustlet-binary must not be present ! (registered but not usable)
932 // Delete TABIN and SPID files - we loop searching required spid file
933 deleteSPTA(uuid
,spid
,true);
935 string tlContFilePath
= getTlContFilePath(uuid
, spid
);
936 LOG_I("delete Tlc: %s", tlContFilePath
.c_str());
937 if (0 != (e
= remove(tlContFilePath
.c_str()))) {
938 LOG_E("remove Tlc failed! errno: %d", e
);
939 return MC_DRV_ERR_UNKNOWN
;
945 //------------------------------------------------------------------------------
946 mcResult_t
mcRegistryCleanupSp(mcSpid_t spid
)
956 LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER
);
957 return MC_DRV_ERR_INVALID_PARAMETER
;
959 len
= sizeof(mcSoSpCont_t
);
960 ret
= mcRegistryReadSp(spid
, &data
, &len
);
961 if (MC_DRV_OK
!= ret
|| len
!= sizeof(mcSoSpCont_t
)) {
962 LOG_E("read SP->UUID aborted! Return code: %d", ret
);
965 for (i
= 0; (i
< MC_CONT_CHILDREN_COUNT
) && (ret
== MC_DRV_OK
); i
++) {
966 if (0 != strncmp((const char *) & (data
.cont
.children
[i
]), (const char *)&MC_UUID_FREE
, sizeof(mcUuid_t
))) {
967 ret
= mcRegistryCleanupTrustlet(&(data
.cont
.children
[i
]), spid
);
970 if (MC_DRV_OK
!= ret
) {
971 LOG_E("delete SP->UUID failed! Return code: %d", ret
);
975 // Delete remaining TABIN and SPID files
976 deleteSPTA(NULL
,spid
,false);
978 string pathname
= getSpDataPath(spid
);
980 if (NULL
!= (dp
= opendir(pathname
.c_str()))) {
981 while (NULL
!= (de
= readdir(dp
))) {
982 if (de
->d_name
[0] != '.') {
983 string dname
= pathname
+ "/" + string (de
->d_name
);
984 LOG_I("delete DT: %s", dname
.c_str());
985 if (0 != (e
= remove(dname
.c_str()))) {
986 LOG_E("remove SPID-data %s failed! error: %d", dname
.c_str(), e
);
993 LOG_I("delete dir: %s", pathname
.c_str());
994 if (0 != (e
= rmdir(pathname
.c_str()))) {
995 LOG_E("remove SPID-dir failed! error: %d", e
);
996 return MC_DRV_ERR_UNKNOWN
;
999 string spContFilePath
= getSpContFilePath(spid
);
1000 LOG_I("delete Sp: %s", spContFilePath
.c_str());
1001 if (0 != (e
= remove(spContFilePath
.c_str()))) {
1002 LOG_E("remove SP failed! error: %d", e
);
1003 return MC_DRV_ERR_UNKNOWN
;
1009 //------------------------------------------------------------------------------
1010 mcResult_t
mcRegistryCleanupRoot(void)
1013 mcSoRootCont_t data
;
1016 len
= sizeof(mcSoRootCont_t
);
1017 ret
= mcRegistryReadRoot(&data
, &len
);
1018 if (MC_DRV_OK
!= ret
|| len
!= sizeof(mcSoRootCont_t
)) {
1019 LOG_E("read Root aborted! Return code: %d", ret
);
1022 for (i
= 0; (i
< MC_CONT_CHILDREN_COUNT
) && (ret
== MC_DRV_OK
); i
++) {
1023 mcSpid_t spid
= data
.cont
.children
[i
];
1024 if (spid
!= MC_SPID_FREE
) {
1025 ret
= mcRegistryCleanupSp(spid
);
1026 if (MC_DRV_OK
!= ret
) {
1027 LOG_E("Cleanup SP failed! Return code: %d", ret
);
1033 string rootContFilePath
= getRootContFilePath();
1034 LOG_I("Delete root: %s", rootContFilePath
.c_str());
1035 if (0 != (e
= remove(rootContFilePath
.c_str()))) {
1036 LOG_E("Delete root failed! error: %d", e
);
1037 return MC_DRV_ERR_UNKNOWN
;
1042 //------------------------------------------------------------------------------
1043 regObject_t
*mcRegistryMemGetServiceBlob(mcSpid_t spid
, void *trustlet
, uint32_t tlSize
)
1045 regObject_t
*regobj
= NULL
;
1047 // Ensure that a UUID is provided.
1048 if (NULL
== trustlet
) {
1049 LOG_E("No trustlet buffer given");
1053 // Check service blob size.
1054 if (tlSize
> MAX_TL_SIZE
) {
1055 LOG_E("mcRegistryMemGetServiceBlob() failed: service blob too big: %d", tlSize
);
1059 mclfIntro_t
*pIntro
= (mclfIntro_t
*)trustlet
;
1060 // Check TL magic value.
1061 if (pIntro
->magic
!= MC_SERVICE_HEADER_MAGIC_BE
) {
1062 LOG_E("mcRegistryMemGetServiceBlob() failed: wrong header magic value: %d", pIntro
->magic
);
1066 // Get service type.
1067 mclfHeaderV2_t
*pHeader
= (mclfHeaderV2_t
*)trustlet
;
1070 const char *service_types
[] = {
1071 "illegal", "Driver", "Trustlet", "System Trustlet"
1073 int serviceType_safe
= pHeader
->serviceType
> SERVICE_TYPE_SYSTEM_TRUSTLET
? SERVICE_TYPE_ILLEGAL
: pHeader
->serviceType
;
1074 LOG_I(" Service is a %s (service type %d)", service_types
[serviceType_safe
], pHeader
->serviceType
);
1078 LOG_I(" Trustlet text %u data %u ", pHeader
->text
.len
, pHeader
->data
.len
);
1080 // If loadable driver or system trustlet.
1081 if (pHeader
->serviceType
== SERVICE_TYPE_DRIVER
|| pHeader
->serviceType
== SERVICE_TYPE_SYSTEM_TRUSTLET
) {
1082 // Take trustlet blob 'as is'.
1083 if (NULL
== (regobj
= (regObject_t
*) (malloc(sizeof(regObject_t
) + tlSize
)))) {
1084 LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
1087 regobj
->len
= tlSize
;
1088 regobj
->tlStartOffset
= 0;
1089 memcpy((char *)regobj
->value
, trustlet
, tlSize
);
1090 // If user trustlet.
1091 } else if (pHeader
->serviceType
== SERVICE_TYPE_SP_TRUSTLET
) {
1092 // Take trustlet blob and append root, sp, and tl container.
1093 size_t regObjValueSize
= tlSize
+ sizeof(mcBlobLenInfo_t
) + 3 * MAX_SO_CONT_SIZE
;
1095 // Prepare registry object.
1096 if (NULL
== (regobj
= (regObject_t
*) malloc(sizeof(regObject_t
) + regObjValueSize
))) {
1097 LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
1100 regobj
->len
= regObjValueSize
;
1101 regobj
->tlStartOffset
= sizeof(mcBlobLenInfo_t
);
1102 uint8_t *p
= regobj
->value
;
1104 // Reserve space for the blob length structure
1105 mcBlobLenInfo_ptr lenInfo
= (mcBlobLenInfo_ptr
)p
;
1106 lenInfo
->magic
= MC_TLBLOBLEN_MAGIC
;
1107 p
+= sizeof(mcBlobLenInfo_t
);
1108 // Fill in trustlet blob after the len info
1109 memcpy(p
, trustlet
, tlSize
);
1112 // Final registry object value looks like this:
1114 // +---------------+---------------------------+-----------+---------+---------+
1115 // | Blob Len Info | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont |
1116 // +---------------+---------------------------+-----------+-------------------+
1117 // /------ Trustlet BLOB ------/
1119 // /------------------ regobj->header.len -------------------------------------/
1121 // start at the end of the trustlet blob
1124 uint32_t soTltContSize
= MAX_SO_CONT_SIZE
;
1127 // Fill in root container.
1128 len
= sizeof(mcSoRootCont_t
);
1129 if (MC_DRV_OK
!= (ret
= mcRegistryReadRoot(p
, &len
))) {
1132 lenInfo
->rootContBlobSize
= len
;
1135 // Fill in SP container.
1136 len
= sizeof(mcSoSpCont_t
);
1137 if (MC_DRV_OK
!= (ret
= mcRegistryReadSp(spid
, p
, &len
))) {
1140 lenInfo
->spContBlobSize
= len
;
1143 // Fill in TLT Container
1144 // We know exactly how much space is left in the buffer
1145 soTltContSize
= regObjValueSize
- tlSize
+ sizeof(mcBlobLenInfo_t
)
1146 - lenInfo
->spContBlobSize
- lenInfo
->rootContBlobSize
;
1147 if (MC_DRV_OK
!= (ret
= mcRegistryReadTrustletCon(&pHeader
->uuid
, spid
, p
, &soTltContSize
))) {
1150 lenInfo
->tlContBlobSize
= soTltContSize
;
1151 LOG_I(" Trustlet container %u bytes loaded", soTltContSize
);
1152 // Depending on the trustlet container size we decide which structure to use
1153 // Unfortunate design but it should have to do for now
1154 if (soTltContSize
== sizeof(mcSoTltCont_2_0_t
)) {
1155 LOG_I(" Using 2.0 trustlet container");
1156 } else if (soTltContSize
== sizeof(mcSoTltCont_2_1_t
)) {
1157 LOG_I(" Using 2.1 trustlet container");
1159 LOG_E("Trustlet container has unknown size");
1164 if (MC_DRV_OK
!= ret
) {
1165 LOG_E("mcRegistryMemGetServiceBlob() failed: Error code: %d", ret
);
1169 // Now we know the sizes for all containers so set the correct size
1170 regobj
->len
= sizeof(mcBlobLenInfo_t
) + tlSize
+
1171 lenInfo
->rootContBlobSize
+
1172 lenInfo
->spContBlobSize
+
1173 lenInfo
->tlContBlobSize
;
1174 // Any other service type.
1176 LOG_E("mcRegistryMemGetServiceBlob() failed: Unsupported service type %u", pHeader
->serviceType
);
1182 //------------------------------------------------------------------------------
1183 regObject_t
*mcRegistryFileGetServiceBlob(const char *trustlet
, mcSpid_t spid
)
1186 regObject_t
*regobj
= NULL
;
1189 // Ensure that a file name is provided.
1190 if (trustlet
== NULL
) {
1191 LOG_E("No file given");
1195 int fd
= open(trustlet
, O_RDONLY
);
1197 LOG_E("Cannot open %s", trustlet
);
1201 if (fstat(fd
, &sb
) == -1) {
1202 LOG_E("mcRegistryFileGetServiceBlob() failed: Cound't get file size");
1206 buffer
= mmap(NULL
, sb
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1207 if (buffer
== MAP_FAILED
) {
1208 LOG_E("mcRegistryFileGetServiceBlob(): Failed to map file to memory");
1212 regobj
= mcRegistryMemGetServiceBlob(spid
, buffer
, sb
.st_size
);
1214 // We don't actually care if either of them fails but should still print warnings
1215 if (munmap(buffer
, sb
.st_size
)) {
1216 LOG_E("mcRegistryFileGetServiceBlob(): Failed to unmap memory");
1221 LOG_E("mcRegistryFileGetServiceBlob(): Failed to close file %s", trustlet
);
1228 //------------------------------------------------------------------------------
1229 regObject_t
*mcRegistryGetServiceBlob(const mcUuid_t
*uuid
, bool isGpUuid
)
1231 // Ensure that a UUID is provided.
1233 LOG_E("No UUID given");
1237 // Open service blob file.
1238 string tlBinFilePath
;
1240 tlBinFilePath
= getTABinFilePath(uuid
);
1242 tlBinFilePath
= getTlBinFilePath(uuid
);
1244 LOG_I("Loading %s", tlBinFilePath
.c_str());
1248 string taspidFilePath
= getTASpidFilePath(uuid
);
1249 int fd
= open(taspidFilePath
.c_str(), O_RDONLY
);
1251 // This can be ok for System TAs
1252 //LOG_ERRNO("open");
1253 //LOG_E("Cannot open %s", taspidFilePath.c_str());
1256 if (read(fd
, &spid
, sizeof(mcSpid_t
))!=sizeof(mcSpid_t
)) {
1264 return mcRegistryFileGetServiceBlob(tlBinFilePath
.c_str(), spid
);
1267 //------------------------------------------------------------------------------
1268 regObject_t
*mcRegistryGetDriverBlob(const char *filename
)
1270 regObject_t
*regobj
= mcRegistryFileGetServiceBlob(filename
, 0);
1272 if (regobj
== NULL
) {
1273 LOG_E("mcRegistryGetDriverBlob() failed");
1277 // Get service type.
1278 mclfHeaderV2_t
*pHeader
= (mclfHeaderV2_t
*)regobj
->value
;
1280 // If file is not a driver we are not interested
1281 if (pHeader
->serviceType
!= SERVICE_TYPE_DRIVER
) {
1282 LOG_E("mcRegistryGetDriverBlob() failed: Unsupported service type %u", pHeader
->serviceType
);