From 720c5f7218efe8a9310bd6c6e1340beda109befa Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Tue, 28 May 2024 17:57:01 +0200 Subject: [PATCH] libubootenv: rework patchset with Digi-specific functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move Digi code out of the upstream files to minimize conflicts in version migrations. * Remove all the TEE client copied code and use the libteeclient library. * Some fixes in the Optee-based environment encryption * Some simplifications in CAAM-based environment encryption. https://onedigi.atlassian.net/browse/DUB-1079 Signed-off-by: Javier Viguera --- ...U-Boot-environment-access-functions.patch} | 4 +- ...port-to-set-dynamic-location-of-env.patch} | 24 +- ...-for-environment-encryption-by-CAAM.patch} | 440 +-- ...t-for-environment-encryption-using-O.patch | 259 ++ ...d-HWID-from-nvmem-device-if-not-avai.patch | 105 - ...t-for-environment-encryption-for-CCM.patch | 2802 ----------------- .../libubootenv/libubootenv_%.bbappend | 15 +- 7 files changed, 543 insertions(+), 3106 deletions(-) rename meta-digi-arm/recipes-bsp/libubootenv/libubootenv/{0002-Implement-U-Boot-environment-access-functions.patch => 0001-Implement-U-Boot-environment-access-functions.patch} (97%) rename meta-digi-arm/recipes-bsp/libubootenv/libubootenv/{0003-tools-env-add-support-to-set-dynamic-location-of-env.patch => 0002-tools-env-add-support-to-set-dynamic-location-of-env.patch} (88%) rename meta-digi-arm/recipes-bsp/libubootenv/libubootenv/{0001-Implement-support-for-environment-encryption-by-CAAM.patch => 0003-Implement-support-for-environment-encryption-by-CAAM.patch} (76%) create mode 100644 meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-Implement-support-for-environment-encryption-using-O.patch delete mode 100644 meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch delete mode 100644 meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0005-Implement-support-for-environment-encryption-for-CCM.patch diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-Implement-U-Boot-environment-access-functions.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-U-Boot-environment-access-functions.patch similarity index 97% rename from meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-Implement-U-Boot-environment-access-functions.patch rename to meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-U-Boot-environment-access-functions.patch index d585a18ad..93730a30b 100644 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-Implement-U-Boot-environment-access-functions.patch +++ b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-U-Boot-environment-access-functions.patch @@ -52,10 +52,10 @@ index 3ed3244..e83b3a5 100644 } #endif diff --git a/src/uboot_env.c b/src/uboot_env.c -index 750b736..b7ad4c4 100644 +index ae85c7e..358dfbb 100644 --- a/src/uboot_env.c +++ b/src/uboot_env.c -@@ -2234,3 +2234,99 @@ void libuboot_exit(struct uboot_ctx *ctx) +@@ -2103,3 +2103,99 @@ void libuboot_exit(struct uboot_ctx *ctx) free(ctx); } diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-tools-env-add-support-to-set-dynamic-location-of-env.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-tools-env-add-support-to-set-dynamic-location-of-env.patch similarity index 88% rename from meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-tools-env-add-support-to-set-dynamic-location-of-env.patch rename to meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-tools-env-add-support-to-set-dynamic-location-of-env.patch index 5bf01172a..a91e17420 100644 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-tools-env-add-support-to-set-dynamic-location-of-env.patch +++ b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0002-tools-env-add-support-to-set-dynamic-location-of-env.patch @@ -27,10 +27,10 @@ Signed-off-by: Gabriel Valcazar 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/uboot_env.c b/src/uboot_env.c -index b7ad4c4..924a6cf 100644 +index 358dfbb..c1f334e 100644 --- a/src/uboot_env.c +++ b/src/uboot_env.c -@@ -591,6 +591,73 @@ static int check_env_device(struct uboot_flash_env *dev) +@@ -581,6 +581,73 @@ static int check_env_device(struct uboot_flash_env *dev) return 0; } @@ -104,7 +104,7 @@ index b7ad4c4..924a6cf 100644 static bool check_compatible_devices(struct uboot_ctx *ctx) { if (!ctx->redundant) -@@ -602,6 +669,12 @@ static bool check_compatible_devices(struct uboot_ctx *ctx) +@@ -592,6 +659,12 @@ static bool check_compatible_devices(struct uboot_ctx *ctx) return false; if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize) return false; @@ -117,7 +117,7 @@ index b7ad4c4..924a6cf 100644 return true; } -@@ -648,7 +721,7 @@ static int fileread(struct uboot_flash_env *dev, void *data) +@@ -638,7 +711,7 @@ static int fileread(struct uboot_flash_env *dev, void *data) return ret; } @@ -126,7 +126,7 @@ index b7ad4c4..924a6cf 100644 { size_t count; size_t blocksize; -@@ -667,6 +740,17 @@ static int mtdread(struct uboot_flash_env *dev, void *data) +@@ -657,6 +730,17 @@ static int mtdread(struct uboot_flash_env *dev, void *data) ret = read(dev->fd, data, dev->envsize); break; case MTD_NANDFLASH: @@ -144,7 +144,7 @@ index b7ad4c4..924a6cf 100644 if (dev->offset) if (lseek(dev->fd, dev->offset, SEEK_SET) < 0) { ret = -EIO; -@@ -742,7 +826,7 @@ static int devread(struct uboot_ctx *ctx, unsigned int copy, void *data) +@@ -732,7 +816,7 @@ static int devread(struct uboot_ctx *ctx, unsigned int copy, void *data) ret = fileread(dev, data); break; case DEVICE_MTD: @@ -154,13 +154,13 @@ index b7ad4c4..924a6cf 100644 case DEVICE_UBI: ret = ubiread(dev, data); diff --git a/src/uboot_private.h b/src/uboot_private.h -index ee2d305..84bd1bc 100644 +index 40e5446..c8fecc4 100644 --- a/src/uboot_private.h +++ b/src/uboot_private.h -@@ -116,10 +116,14 @@ struct uboot_ctx { +@@ -114,10 +114,14 @@ LIST_HEAD(vars, var_entry); + struct uboot_ctx { + /** true if the environment is redundant */ bool redundant; - /** true if the environment is encrypted */ - bool encrypted; + /** true if the environment is dynamic */ + bool dynamic_env; /** set to valid after a successful load */ @@ -169,6 +169,6 @@ index ee2d305..84bd1bc 100644 size_t size; + /** top limit of the dynamic environment */ + loff_t top_limit; - /** usable environment size */ - unsigned int usable_size; /** devices where environment is stored */ + struct uboot_flash_env envdevs[2]; + /** Set which device contains the current(last valid) environment */ diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-support-for-environment-encryption-by-CAAM.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-Implement-support-for-environment-encryption-by-CAAM.patch similarity index 76% rename from meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-support-for-environment-encryption-by-CAAM.patch rename to meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-Implement-support-for-environment-encryption-by-CAAM.patch index d08d3f4e4..0bc88feb2 100644 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0001-Implement-support-for-environment-encryption-by-CAAM.patch +++ b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0003-Implement-support-for-environment-encryption-by-CAAM.patch @@ -15,26 +15,63 @@ Signed-off-by: Diaz de Grenu, Jose Signed-off-by: Gonzalo Ruiz Signed-off-by: Hector Palacios Signed-off-by: Gabriel Valcazar + + # This is the commit message #2: + +fall back to read HWID from nvmem device if not available on DT + +Old U-Boot versions don't populate the HWID on the device tree. This may +be used as a key modifier for TrustFence encryption and, if not available +on the DT, newer firmware may be unable to unencrypt the U-Boot +environment. + +This patch implements a fall-back function to query the HWID directly from +the nvmem device node if it cannot locate it at the DT. +This is only implemented for ccimx6 family, which may be in the case of +having an old U-Boot. + +https://onedigi.atlassian.net/browse/DEL-8444 + +Signed-off-by: Hector Palacios + + # This is the commit message #3: + +ubootenv: generalize env encryption code + +Generalize the code to make room for Optee-based encryption. +* Move the code to the crypt.c/h files to minimize changes on the upstream + uboot_env.c file. +* Rename env_caam_get_keymod to env_get_keymod as this function is not + CAAM-specific. +* Create a public env_crypt function that will select the proper (CAAM, + Optee) implementation. + +Signed-off-by: Javier Viguera --- - src/CMakeLists.txt | 2 + - src/caam_keyblob.h | 42 +++++++ - src/md5.c | 275 ++++++++++++++++++++++++++++++++++++++++++++ - src/md5.h | 24 ++++ - src/uboot_env.c | 131 +++++++++++++++++++++ - src/uboot_private.h | 4 + - 6 files changed, 478 insertions(+) + src/CMakeLists.txt | 4 + + src/caam_keyblob.h | 42 +++++++ + src/crypt.c | 179 +++++++++++++++++++++++++++++ + src/crypt.h | 10 ++ + src/md5.c | 275 +++++++++++++++++++++++++++++++++++++++++++++ + src/md5.h | 24 ++++ + src/uboot_env.c | 18 +++ + 7 files changed, 552 insertions(+) create mode 100644 src/caam_keyblob.h + create mode 100644 src/crypt.c + create mode 100644 src/crypt.h create mode 100644 src/md5.c create mode 100644 src/md5.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index ababe0f..fb1efa2 100644 +index ababe0f..638f1c1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt -@@ -4,6 +4,8 @@ +@@ -4,6 +4,10 @@ cmake_minimum_required (VERSION 2.6) # Sources and private headers SET(libubootenv_SOURCES ++ crypt.c ++ crypt.h + md5.c + md5.h uboot_env.c @@ -88,6 +125,207 @@ index 0000000..e313e87 +#endif + +#endif /* CAAM_KEYBLOB_H */ +diff --git a/src/crypt.c b/src/crypt.c +new file mode 100644 +index 0000000..213cffd +--- /dev/null ++++ b/src/crypt.c +@@ -0,0 +1,179 @@ ++/* ++ * Copyright 2024 Digi International Inc ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "caam_keyblob.h" ++#include "md5.h" ++ ++/* ++ * The BLOB includes a random AES-256 key (32 bytes) and a ++ * Message Authentication Code (MAC) (16 bytes) ++ */ ++#define BLOB_OVERHEAD 48 ++#define CAAM_KEY_DEV "/dev/caam_kb" ++#define MAX_HWID_WORDS 4 ++ ++/* Function that checks if machine is compatible (on the DT) */ ++static bool machine_is_compatible(char *machine) ++{ ++ int fd, nchars, len = 0; ++ int ret = false; ++ char str[256]; ++ char *p = str; ++ ++ fd = open("/proc/device-tree/compatible", O_RDONLY); ++ if (fd < 0) ++ return false; ++ ++ nchars = read(fd, str, 255); ++ while (len < nchars) { ++ if (!strcmp(p, machine)) { ++ ret = true; ++ break; ++ } ++ len += strlen(p) + 1; ++ p += strlen(p) + 1; ++ } ++ close(fd); ++ ++ return ret; ++} ++ ++static int env_get_keymod(unsigned char output[16]) ++{ ++ int i; ++ int len; ++ int fd; ++ uint32_t ocotp_hwid[MAX_HWID_WORDS]; ++ char dt_prop[32]; ++ char buf[sizeof(uint32_t)]; ++ ++ for (i = 0; i < MAX_HWID_WORDS; i++) { ++ sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i); ++ if (access(dt_prop, F_OK) != -1) { ++ fd = open(dt_prop, O_RDONLY); ++ if (fd < 0) ++ return fd; ++ len = read(fd, buf, sizeof(uint32_t)); ++ if (len < 0) { ++ close(fd); ++ return -1; ++ } ++ ocotp_hwid[i] = ntohl(*(uint32_t *) buf); ++ close(fd); ++ } else if (machine_is_compatible("digi,ccimx6ul") || ++ machine_is_compatible("digi,ccimx6")) { ++ /* ++ * If HWID not available on the DT (old U-Boot version), ++ * fall back to read it directly from the nvmem device. ++ */ ++ int hwid_offset = 136; /* (Bank * 8 + Word) * 4 */ ++ ++ /* HWID for CC6 family only has two words */ ++ if (i == 2) ++ break; ++ ++ fd = open("/sys/bus/nvmem/devices/imx-ocotp0/nvmem", ++ O_RDONLY); ++ if (fd < 0) ++ return fd; ++ len = lseek(fd, hwid_offset + i * 4, SEEK_SET); ++ ++ len = read(fd, buf, sizeof(unsigned int)); ++ if (len < 0) { ++ close(fd); ++ return -1; ++ } ++ ocotp_hwid[i] = *(unsigned int *)buf; ++ close(fd); ++ } else { ++ break; ++ } ++ } ++ ++ /* Calculate md5sum on the raw HWID array */ ++ md5((unsigned char *)(&ocotp_hwid), sizeof(uint32_t) * i, output); ++ ++ return 0; ++} ++ ++static int env_caam_crypt(char *data, unsigned int size, const int enc) ++{ ++ struct caam_kb_data enc_data; ++ int fd; ++ int ret = 0; ++ const int len = size; ++ int ioctl_mode; ++ char *buffer; ++ unsigned char key_modifier[16]; ++ ++ ret = env_get_keymod(key_modifier); ++ if (ret) ++ return ret; ++ ++ enc_data.keymod = (char *)key_modifier; ++ enc_data.keymod_len = sizeof(key_modifier); ++ ++ enc_data.keyblob_len = len; ++ enc_data.rawkey_len = len - BLOB_OVERHEAD; ++ ++ buffer = malloc(len); ++ if (!buffer) { ++ printf("Could not allocate memory\n"); ++ return -1; ++ } ++ ++ if (enc) { ++ enc_data.rawkey = data; ++ ioctl_mode = CAAM_KB_ENCRYPT; ++ enc_data.keyblob = buffer; ++ } else { ++ enc_data.keyblob = data; ++ ioctl_mode = CAAM_KB_DECRYPT; ++ enc_data.rawkey = buffer; ++ } ++ ++ if ((fd = open(CAAM_KEY_DEV, O_RDWR)) < 0) { ++ ret = fd; ++ goto free; ++ } ++ ++ ret = ioctl(fd, ioctl_mode, &enc_data); ++ if (ret) { ++ printf("CAAM_KEY_DEV ioctl failed: %d\n", ret); ++ goto out; ++ } ++ ++ memcpy(data, buffer, enc ? len : len - BLOB_OVERHEAD); ++ ++out: ++ close(fd); ++free: ++ free(buffer); ++ ++ return ret; ++} ++ ++int env_crypt(char *data, unsigned int size, const int enc) ++{ ++ return env_caam_crypt(data, size, enc); ++} ++ ++int is_env_encrypted(void) ++{ ++ const char *dt_prop = "/proc/device-tree/digi,uboot-env,encrypted"; ++ ++ return access(dt_prop, F_OK) != -1; ++} +diff --git a/src/crypt.h b/src/crypt.h +new file mode 100644 +index 0000000..8d85c7f +--- /dev/null ++++ b/src/crypt.h +@@ -0,0 +1,10 @@ ++/* ++ * Copyright 2024 Digi International Inc ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#pragma once ++ ++int env_crypt(char *data, unsigned int size, const int enc); ++int is_env_encrypted(void); diff --git a/src/md5.c b/src/md5.c new file mode 100644 index 0000000..47ae8bf @@ -400,146 +638,26 @@ index 0000000..02a9a9d + +#endif /* _MD5_H */ diff --git a/src/uboot_env.c b/src/uboot_env.c -index ae85c7e..750b736 100644 +index c1f334e..30ef835 100644 --- a/src/uboot_env.c +++ b/src/uboot_env.c -@@ -34,11 +34,21 @@ - #include - #include - #include -+#include +@@ -37,6 +37,7 @@ #include #include -+#include "caam_keyblob.h" -+#include "md5.h" ++#include "crypt.h" #include "uboot_private.h" -+/* -+ * The BLOB includes a random AES-256 key (32 bytes) and a -+ * Message Authentication Code (MAC) (16 bytes) -+ */ -+#define BLOB_OVERHEAD 48 -+#define CAAM_KEY_DEV "/dev/caam_kb" -+ #define UBI_MAX_VOLUME 128 - - #define DEVICE_MTD_NAME "/dev/mtd" -@@ -1028,6 +1038,105 @@ const struct uboot_version_info *libuboot_version_info(void) - return &libinfo; - } - -+static int is_env_encrypted(void) -+{ -+ const char *dt_prop = "/proc/device-tree/digi,uboot-env,encrypted"; -+ -+ return access(dt_prop, F_OK) != -1; -+} -+ -+#define MAX_HWID_WORDS 4 -+static int env_caam_get_keymod(unsigned char output[16]) -+{ -+ int i; -+ int len; -+ int fd; -+ uint32_t ocotp_hwid[MAX_HWID_WORDS]; -+ char dt_prop[32]; -+ -+ for (i = 0; i < MAX_HWID_WORDS; i++) { -+ sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i); -+ if (access(dt_prop, F_OK) != -1) { -+ char buf[sizeof(uint32_t)]; -+ -+ fd = open(dt_prop, O_RDONLY); -+ if (fd < 0) -+ return fd; -+ len = read(fd, buf, sizeof(uint32_t)); -+ if (len < 0) { -+ close(fd); -+ return -1; -+ } -+ ocotp_hwid[i] = ntohl(*(uint32_t *)buf); -+ close(fd); -+ } else { -+ break; -+ } -+ } -+ -+ /* Calculate md5sum on the raw HWID array */ -+ md5((unsigned char *)(&ocotp_hwid), sizeof(uint32_t) * i, output); -+ -+ return 0; -+} -+ -+static int env_caam_crypt(char *data, unsigned int size, const int enc) -+{ -+ struct caam_kb_data enc_data; -+ int fd; -+ int ret = 0; -+ const int len = size; -+ int ioctl_mode; -+ char *buffer; -+ unsigned char key_modifier[16]; -+ -+ ret = env_caam_get_keymod(key_modifier); -+ if (ret) -+ return ret; -+ -+ enc_data.keymod = (char *)key_modifier; -+ enc_data.keymod_len = sizeof(key_modifier); -+ -+ enc_data.keyblob_len = len; -+ enc_data.rawkey_len = len - BLOB_OVERHEAD; -+ -+ buffer = malloc(len); -+ if (!buffer) { -+ printf("Could not allocate memory\n"); -+ return -1; -+ } -+ -+ if (enc) { -+ enc_data.rawkey = data; -+ ioctl_mode = CAAM_KB_ENCRYPT; -+ enc_data.keyblob = buffer; -+ } else { -+ enc_data.keyblob = data; -+ ioctl_mode = CAAM_KB_DECRYPT; -+ enc_data.rawkey = buffer; -+ } -+ -+ if ((fd = open(CAAM_KEY_DEV, O_RDWR)) < 0) { -+ ret = fd; -+ goto free; -+ } -+ -+ ret = ioctl(fd, ioctl_mode, &enc_data); -+ if (ret) { -+ printf("CAAM_KEY_DEV ioctl failed: %d\n", ret); -+ goto out; -+ } -+ -+ memcpy(data, buffer, enc ? len : len - BLOB_OVERHEAD); -+ -+out: -+ close(fd); -+free: -+ free(buffer); -+ -+ return ret; -+} -+ - int libuboot_env_store(struct uboot_ctx *ctx) - { - struct var_entry *entry; -@@ -1103,6 +1212,15 @@ int libuboot_env_store(struct uboot_ctx *ctx) +@@ -1187,6 +1188,15 @@ int libuboot_env_store(struct uboot_ctx *ctx) ((struct uboot_env_redund *)image)->flags = flags; } -+ if (ctx->encrypted) { -+ ret = env_caam_crypt(data, ctx->usable_size, 1); ++ if (is_env_encrypted()) { ++ size_t usable_envsize = ctx->size - offsetdata; ++ ret = env_crypt(data, usable_envsize, 1); + if (ret) { -+ fprintf(stderr, -+ "Error: can't encrypt env for flash\n"); ++ fprintf(stderr, "Error: can't encrypt env for flash\n"); + return ret; + } + } @@ -547,56 +665,18 @@ index ae85c7e..750b736 100644 *(uint32_t *)image = crc32(0, (uint8_t *)data, ctx->size - offsetdata); copy = ctx->redundant ? (ctx->current ? 0 : 1) : 0; -@@ -1167,6 +1285,13 @@ static int libuboot_load(struct uboot_ctx *ctx) +@@ -1251,6 +1261,14 @@ static int libuboot_load(struct uboot_ctx *ctx) } crc = *(uint32_t *)(buf[i] + offsetcrc); dev->crc = crc32(0, (uint8_t *)data, usable_envsize); -+ if (ctx->encrypted) { -+ ret = env_caam_crypt((char *)data, ctx->usable_size, 0); ++ if (is_env_encrypted()) { ++ ret = env_crypt(data, usable_envsize, 0); + if (ret) { -+ fprintf(stderr, "Error: can't decrypt environment\n"); ++ fprintf(stderr, ++ "Error: can't decrypt environment\n"); + return ret; + } + } crcenv[i] = dev->crc == crc; if (ctx->redundant) dev->flags = *(uint8_t *)(buf[i] + offsetflags); -@@ -1773,6 +1898,11 @@ int libuboot_read_config_ext(struct uboot_ctx **ctxlist, const char *config) - break; - } - } -+ -+ ctx->usable_size = ctx->size - sizeof(uint32_t); -+ if (ctx->redundant) -+ ctx->usable_size -= sizeof(char); -+ - if (ndev == 0) - retval = -EINVAL; - -@@ -2042,6 +2172,7 @@ int libuboot_initialize(struct uboot_ctx **out, - return -ENOMEM; - - ctx->valid = false; -+ ctx->encrypted = is_env_encrypted(); - ret = libuboot_configure(ctx, envdevs); - - if (ret < 0) { -diff --git a/src/uboot_private.h b/src/uboot_private.h -index 40e5446..ee2d305 100644 ---- a/src/uboot_private.h -+++ b/src/uboot_private.h -@@ -114,10 +114,14 @@ LIST_HEAD(vars, var_entry); - struct uboot_ctx { - /** true if the environment is redundant */ - bool redundant; -+ /** true if the environment is encrypted */ -+ bool encrypted; - /** set to valid after a successful load */ - bool valid; - /** size of the environment */ - size_t size; -+ /** usable environment size */ -+ unsigned int usable_size; - /** devices where environment is stored */ - struct uboot_flash_env envdevs[2]; - /** Set which device contains the current(last valid) environment */ diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-Implement-support-for-environment-encryption-using-O.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-Implement-support-for-environment-encryption-using-O.patch new file mode 100644 index 000000000..848c927a2 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-Implement-support-for-environment-encryption-using-O.patch @@ -0,0 +1,259 @@ +From: Mike Engel +Date: Fri, 26 May 2023 11:21:43 +0200 +Subject: [PATCH] Implement support for environment encryption using Optee + +Co-authored-by: Javier Viguera +Signed-off-by: Mike Engel +Signed-off-by: Javier Viguera +--- + src/CMakeLists.txt | 3 + + src/crypt.c | 10 ++- + src/crypt_optee.c | 172 +++++++++++++++++++++++++++++++++++++++++++++ + src/crypt_optee.h | 10 +++ + 4 files changed, 194 insertions(+), 1 deletion(-) + create mode 100644 src/crypt_optee.c + create mode 100644 src/crypt_optee.h + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 638f1c1..f218b35 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -6,6 +6,8 @@ cmake_minimum_required (VERSION 2.6) + SET(libubootenv_SOURCES + crypt.c + crypt.h ++ crypt_optee.c ++ crypt_optee.h + md5.c + md5.h + uboot_env.c +@@ -26,6 +28,7 @@ ADD_LIBRARY(ubootenv_static STATIC ${libubootenv_SOURCES} ${include_HEADERS}) + SET_TARGET_PROPERTIES(ubootenv_static PROPERTIES OUTPUT_NAME ubootenv) + add_executable(fw_printenv fw_printenv.c) + target_link_libraries(ubootenv z yaml) ++target_link_libraries(ubootenv teec) + target_link_libraries(fw_printenv ubootenv) + add_custom_target(fw_setenv ALL ${CMAKE_COMMAND} -E create_symlink fw_printenv fw_setenv) + +diff --git a/src/crypt.c b/src/crypt.c +index 213cffd..e3f9a5d 100644 +--- a/src/crypt.c ++++ b/src/crypt.c +@@ -15,6 +15,7 @@ + #include + + #include "caam_keyblob.h" ++#include "crypt_optee.h" + #include "md5.h" + + /* +@@ -168,7 +169,14 @@ free: + + int env_crypt(char *data, unsigned int size, const int enc) + { +- return env_caam_crypt(data, size, enc); ++ if (is_env_optee_encrypted()) { ++ unsigned char key_modifier[16]; ++ if (env_get_keymod(key_modifier)) ++ return -1; ++ return env_optee_crypt((char *)key_modifier, data, size, enc); ++ } else { ++ return env_caam_crypt(data, size, enc); ++ } + } + + int is_env_encrypted(void) +diff --git a/src/crypt_optee.c b/src/crypt_optee.c +new file mode 100644 +index 0000000..fc74141 +--- /dev/null ++++ b/src/crypt_optee.c +@@ -0,0 +1,172 @@ ++/* ++ * Copyright 2024 Digi International Inc ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AES_BLOCK_LENGTH 16 ++ ++/* From TA's public header (aes_ta.h) */ ++#define TA_AES_UUID \ ++ { 0xc2fad363, 0x5d9f, 0x4fc4, \ ++ { 0xa4, 0x17, 0x55, 0x58, 0x41, 0xe0, 0x57, 0x45 } } ++#define TA_AES_ALGO_ECB 0 ++#define TA_AES_ALGO_CBC 1 ++#define TA_AES_ALGO_CTR 2 ++#define TA_AES_SIZE_128BIT (128 / 8) ++#define TA_AES_SIZE_256BIT (256 / 8) ++#define TA_AES_MODE_DECODE 0 ++#define TA_AES_MODE_ENCODE 1 ++#define TA_AES_CMD_PREPARE 0 ++#define TA_AES_CMD_SET_KEY 1 ++#define TA_AES_CMD_SET_IV 2 ++#define TA_AES_CMD_CIPHER 3 ++ ++struct tee_ctx { ++ TEEC_Context ctx; ++ TEEC_Session sess; ++}; ++ ++static void prepare_tee_session(struct tee_ctx *ctx) ++{ ++ TEEC_Result ret; ++ uint32_t origin; ++ TEEC_UUID uuid = TA_AES_UUID; ++ ++ ret = TEEC_InitializeContext(NULL, &ctx->ctx); ++ if (ret != TEEC_SUCCESS) ++ printf("TEEC_InitializeContext failed with code 0x%x", ret); ++ ++ /* Open a session with the TA */ ++ ret = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid, ++ TEEC_LOGIN_PUBLIC, NULL, NULL, &origin); ++ if (ret != TEEC_SUCCESS) ++ printf("TEEC_Opensession failed with code 0x%x origin 0x%x", ++ ret, origin); ++ ++} ++ ++static void terminate_tee_session(struct tee_ctx *ctx) ++{ ++ TEEC_CloseSession(&ctx->sess); ++ TEEC_FinalizeContext(&ctx->ctx); ++} ++ ++static void prepare_aes(struct tee_ctx *ctx, int encode) ++{ ++ TEEC_Operation op; ++ uint32_t origin; ++ TEEC_Result res; ++ ++ memset(&op, 0, sizeof(op)); ++ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, ++ TEEC_VALUE_INPUT, ++ TEEC_VALUE_INPUT, TEEC_NONE); ++ ++ op.params[0].value.a = TA_AES_ALGO_CTR; ++ op.params[1].value.a = TA_AES_SIZE_256BIT; ++ op.params[2].value.a = encode ? TA_AES_MODE_ENCODE : TA_AES_MODE_DECODE; ++ ++ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_PREPARE, &op, &origin); ++ if (res != TEEC_SUCCESS) ++ printf("TEEC_InvokeCommand(PREPARE) failed 0x%x origin 0x%x", ++ res, origin); ++} ++ ++static void set_key(struct tee_ctx *ctx, size_t key_sz) ++{ ++ TEEC_Operation op; ++ uint32_t origin; ++ TEEC_Result res; ++ ++ memset(&op, 0, sizeof(op)); ++ ++ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, ++ TEEC_NONE, TEEC_NONE, TEEC_NONE); ++ ++ op.params[0].value.a = key_sz; ++ ++ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_KEY, &op, &origin); ++ if (res != TEEC_SUCCESS) ++ printf("TEEC_InvokeCommand(SET_KEY) failed 0x%x origin 0x%x", ++ res, origin); ++} ++ ++static void set_iv(struct tee_ctx *ctx, char *iv, size_t iv_sz) ++{ ++ TEEC_Operation op; ++ uint32_t origin; ++ TEEC_Result res; ++ ++ memset(&op, 0, sizeof(op)); ++ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, ++ TEEC_NONE, TEEC_NONE, TEEC_NONE); ++ op.params[0].tmpref.buffer = iv; ++ op.params[0].tmpref.size = iv_sz; ++ ++ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_IV, &op, &origin); ++ if (res != TEEC_SUCCESS) ++ printf("TEEC_InvokeCommand(SET_IV) failed 0x%x origin 0x%x", ++ res, origin); ++} ++ ++static void cipher_buffer(struct tee_ctx *ctx, char *in, char *out, size_t sz) ++{ ++ TEEC_Operation op; ++ uint32_t origin; ++ TEEC_Result res; ++ ++ memset(&op, 0, sizeof(op)); ++ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, ++ TEEC_MEMREF_TEMP_OUTPUT, ++ TEEC_NONE, TEEC_NONE); ++ op.params[0].tmpref.buffer = in; ++ op.params[0].tmpref.size = sz; ++ op.params[1].tmpref.buffer = out; ++ op.params[1].tmpref.size = sz; ++ ++ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_CIPHER, &op, &origin); ++ if (res != TEEC_SUCCESS) ++ printf("TEEC_InvokeCommand(CIPHER) failed 0x%x origin 0x%x", ++ res, origin); ++} ++ ++int env_optee_crypt(char *keymod, char *data, unsigned int size, const int enc) ++{ ++ struct tee_ctx tee; ++ char *cryptdata; ++ int ret = 0; ++ ++ prepare_tee_session(&tee); ++ prepare_aes(&tee, enc); ++ set_key(&tee, TA_AES_SIZE_256BIT); ++ set_iv(&tee, keymod, AES_BLOCK_LENGTH); ++ cryptdata = calloc(1, size); ++ if (cryptdata) { ++ cipher_buffer(&tee, data, cryptdata, size); ++ memcpy(data, cryptdata, size); ++ free(cryptdata); ++ } else { ++ printf("%s: can't allocate memory\n", __func__); ++ ret = -ENOMEM; ++ } ++ terminate_tee_session(&tee); ++ ++ return ret; ++} ++ ++int is_env_optee_encrypted(void) ++{ ++ const char *dt_prop = ++ "/proc/device-tree/digi,uboot-env,encrypted-optee"; ++ ++ return access(dt_prop, F_OK) != -1; ++} +diff --git a/src/crypt_optee.h b/src/crypt_optee.h +new file mode 100644 +index 0000000..e0c77a7 +--- /dev/null ++++ b/src/crypt_optee.h +@@ -0,0 +1,10 @@ ++/* ++ * Copyright 2024 Digi International Inc ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#pragma once ++ ++int env_optee_crypt(char *keymod, char *data, unsigned int size, const int enc); ++int is_env_optee_encrypted(void); diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch deleted file mode 100644 index 0f369f5b7..000000000 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch +++ /dev/null @@ -1,105 +0,0 @@ -From: Hector Palacios -Date: Mon, 3 Apr 2023 18:21:07 +0200 -Subject: [PATCH] fall back to read HWID from nvmem device if not available on - DT - -Old U-Boot versions don't populate the HWID on the device tree. This may -be used as a key modifier for TrustFence encryption and, if not available -on the DT, newer firmware may be unable to unencrypt the U-Boot -environment. - -This patch implements a fall-back function to query the HWID directly from -the nvmem device node if it cannot locate it at the DT. -This is only implemented for ccimx6 family, which may be in the case of -having an old U-Boot. - -Signed-off-by: Hector Palacios - -https://onedigi.atlassian.net/browse/DEL-8444 ---- - src/uboot_env.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 52 insertions(+), 2 deletions(-) - -diff --git a/src/uboot_env.c b/src/uboot_env.c -index 924a6cf..d507cac 100644 ---- a/src/uboot_env.c -+++ b/src/uboot_env.c -@@ -1129,6 +1129,32 @@ static int is_env_encrypted(void) - return access(dt_prop, F_OK) != -1; - } - -+/* Function that checks if machine is compatible (on the DT) */ -+static bool machine_is_compatible(char *machine) -+{ -+ int fd, nchars, len = 0; -+ int ret = false; -+ char str[256]; -+ char *p = str; -+ -+ fd = open("/proc/device-tree/compatible", O_RDONLY); -+ if (fd < 0) -+ return false; -+ -+ nchars = read(fd, str, 255); -+ while (len < nchars) { -+ if (!strcmp(p, machine)) { -+ ret = true; -+ break; -+ } -+ len += strlen(p) + 1; -+ p += strlen(p) + 1; -+ } -+ -+ close(fd); -+ return ret; -+} -+ - #define MAX_HWID_WORDS 4 - static int env_caam_get_keymod(unsigned char output[16]) - { -@@ -1137,12 +1163,11 @@ static int env_caam_get_keymod(unsigned char output[16]) - int fd; - uint32_t ocotp_hwid[MAX_HWID_WORDS]; - char dt_prop[32]; -+ char buf[sizeof(uint32_t)]; - - for (i = 0; i < MAX_HWID_WORDS; i++) { - sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i); - if (access(dt_prop, F_OK) != -1) { -- char buf[sizeof(uint32_t)]; -- - fd = open(dt_prop, O_RDONLY); - if (fd < 0) - return fd; -@@ -1153,6 +1178,31 @@ static int env_caam_get_keymod(unsigned char output[16]) - } - ocotp_hwid[i] = ntohl(*(uint32_t *)buf); - close(fd); -+ } else if (machine_is_compatible("digi,ccimx6ul") || -+ machine_is_compatible("digi,ccimx6")) { -+ /* -+ * If HWID not available on the DT (old U-Boot version), -+ * fall back to read it directly from the nvmem device. -+ */ -+ int hwid_offset = 136; /* (Bank * 8 + Word) * 4 */ -+ -+ /* HWID for CC6 family only has two words */ -+ if (i == 2) -+ break; -+ -+ fd = open("/sys/bus/nvmem/devices/imx-ocotp0/nvmem", -+ O_RDONLY); -+ if (fd < 0) -+ return fd; -+ len = lseek(fd, hwid_offset + i * 4, SEEK_SET); -+ -+ len = read(fd, buf, sizeof(unsigned int)); -+ if (len < 0) { -+ close(fd); -+ return -1; -+ } -+ ocotp_hwid[i] = *(unsigned int *)buf; -+ close(fd); - } else { - break; - } diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0005-Implement-support-for-environment-encryption-for-CCM.patch b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0005-Implement-support-for-environment-encryption-for-CCM.patch deleted file mode 100644 index 83c262155..000000000 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv/0005-Implement-support-for-environment-encryption-for-CCM.patch +++ /dev/null @@ -1,2802 +0,0 @@ -From: Mike Engel -Date: Fri, 26 May 2023 11:21:43 +0200 -Subject: [PATCH] Implement support for environment encryption for CCMP1 - -This commit implements environment encryption/decryption of the -u-boot environment in Linux using cryp controller on the CCMP1 -platform. - -Signed-off-by: Mike Engel ---- - src/CMakeLists.txt | 4 + - src/ta_ccmp1_aes.h | 84 +++ - src/tee.h | 417 ++++++++++++++ - src/tee_bench.h | 77 +++ - src/tee_client_api.c | 958 ++++++++++++++++++++++++++++++++ - src/tee_client_api.h | 555 ++++++++++++++++++ - src/tee_client_api_extensions.h | 57 ++ - src/teec_benchmark.h | 37 ++ - src/teec_trace.c | 141 +++++ - src/teec_trace.h | 148 +++++ - src/uboot_env.c | 180 +++++- - 11 files changed, 2654 insertions(+), 4 deletions(-) - create mode 100644 src/ta_ccmp1_aes.h - create mode 100644 src/tee.h - create mode 100644 src/tee_bench.h - create mode 100644 src/tee_client_api.c - create mode 100644 src/tee_client_api.h - create mode 100644 src/tee_client_api_extensions.h - create mode 100644 src/teec_benchmark.h - create mode 100644 src/teec_trace.c - create mode 100644 src/teec_trace.h - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index fb1efa2..04353e9 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -4,6 +4,10 @@ - cmake_minimum_required (VERSION 2.6) - # Sources and private headers - SET(libubootenv_SOURCES -+ teec_trace.c -+ teec_trace.h -+ tee_client_api.c -+ tee_client_api.h - md5.c - md5.h - uboot_env.c -diff --git a/src/ta_ccmp1_aes.h b/src/ta_ccmp1_aes.h -new file mode 100644 -index 0000000..ceab07d ---- /dev/null -+++ b/src/ta_ccmp1_aes.h -@@ -0,0 +1,84 @@ -+/* -+ * Copyright 2023 Digi International Inc -+ * -+ * SPDX-License-Identifier: GPL-2.0+ -+ */ -+ -+#ifndef __TA_CCMP1_AES_H__ -+#define __TA_CCMP1_AES_H__ -+ -+/* -+ * AES is a stream cipher which works a block at a time, with each block -+ * in this case being AES_BLOCK_LENGTH bytes. -+ */ -+ -+enum { -+ AES_STATECOLS = 4, /* columns in the state & expanded key */ -+ AES128_KEYCOLS = 4, /* columns in a key for aes128 */ -+ AES192_KEYCOLS = 6, /* columns in a key for aes128 */ -+ AES256_KEYCOLS = 8, /* columns in a key for aes128 */ -+ AES128_ROUNDS = 10, /* rounds in encryption for aes128 */ -+ AES192_ROUNDS = 12, /* rounds in encryption for aes192 */ -+ AES256_ROUNDS = 14, /* rounds in encryption for aes256 */ -+ AES128_KEY_LENGTH = 128 / 8, -+ AES192_KEY_LENGTH = 192 / 8, -+ AES256_KEY_LENGTH = 256 / 8, -+ AES128_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES128_ROUNDS + 1), -+ AES192_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES192_ROUNDS + 1), -+ AES256_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES256_ROUNDS + 1), -+ AES_BLOCK_LENGTH = 128 / 8, -+}; -+ -+struct aes_ctx { -+ TEEC_Context ctx; -+ TEEC_Session sess; -+}; -+ -+/* The function IDs implemented in the associated TA */ -+ -+/* -+ * TA_AES_CMD_SET_KEY - Allocate resources for the AES ciphering -+ * param[0] (value) Algorithmus -+ * param[1] (value) Key size -+ * param[2] (value) encryption mode (encrypt/decrypt) -+ * param[3] unused -+ */ -+#define TA_AES_CMD_PREPARE 0 -+ -+/* -+ * TA_AES_CMD_SET_KEY - Allocate resources for the AES ciphering -+ * param[0] (memref) key data, size shall equal key length -+ * param[1] unused -+ * param[2] unused -+ * param[3] unused -+ */ -+#define TA_AES_CMD_SET_KEY 1 -+ -+/* -+ * TA_AES_CMD_SET_IV - reset IV -+ * param[0] (memref) initial vector, size shall equal block length -+ * param[1] unused -+ * param[2] unused -+ * param[3] unused -+ */ -+#define TA_AES_CMD_SET_IV 2 -+ -+/* -+ * TA_AES_CMD_CIPHER - Cipher input buffer into output buffer -+ * param[0] (memref) input buffer -+ * param[1] (memref) output buffer (shall be bigger than input buffer) -+ * param[2] unused -+ * param[3] unused -+ */ -+#define TA_AES_CMD_CIPHER 3 -+ -+#define TA_AES_MODE_ENCODE 1 -+#define TA_AES_MODE_DECODE 0 -+ -+#define TA_AES_ALGO_CTR 2 -+ -+/* UUID of the TA */ -+#define TA_STM32MP_CRYP_UUID { 0xc2fad363, 0x5d9f, 0x4fc4, \ -+ { 0xa4, 0x17, 0x55, 0x58, 0x41, 0xe0, 0x57, 0x45 } } -+ -+#endif /* __TA_CCMP1_AES_H__ */ -\ No newline at end of file -diff --git a/src/tee.h b/src/tee.h -new file mode 100644 -index 0000000..f883ebc ---- /dev/null -+++ b/src/tee.h -@@ -0,0 +1,417 @@ -+/* -+ * Copyright (c) 2015-2016, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef __TEE_H -+#define __TEE_H -+ -+#include -+#include -+ -+/* -+ * This file describes the API provided by a TEE driver to user space. -+ * -+ * Each TEE driver defines a TEE specific protocol which is used for the -+ * data passed back and forth using TEE_IOC_CMD. -+ */ -+ -+/* Helpers to make the ioctl defines */ -+#define TEE_IOC_MAGIC 0xa4 -+#define TEE_IOC_BASE 0 -+ -+/* Flags relating to shared memory */ -+#define TEE_IOCTL_SHM_MAPPED 0x1 /* memory mapped in normal world */ -+#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */ -+ -+#define TEE_MAX_ARG_SIZE 1024 -+ -+#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ -+#define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ -+#define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ -+#define TEE_GEN_CAP_MEMREF_NULL (1 << 3) /* Support NULL MemRef */ -+ -+#define TEE_MEMREF_NULL ((__u64)-1) /* NULL MemRef Buffer */ -+ -+/* -+ * TEE Implementation ID -+ */ -+#define TEE_IMPL_ID_OPTEE 1 -+#define TEE_IMPL_ID_AMDTEE 2 -+ -+/* -+ * OP-TEE specific capabilities -+ */ -+#define TEE_OPTEE_CAP_TZ (1 << 0) -+ -+/** -+ * struct tee_ioctl_version_data - TEE version -+ * @impl_id: [out] TEE implementation id -+ * @impl_caps: [out] Implementation specific capabilities -+ * @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above -+ * -+ * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above. -+ * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_* -+ * is valid when @impl_id == TEE_IMPL_ID_OPTEE. -+ */ -+struct tee_ioctl_version_data { -+ __u32 impl_id; -+ __u32 impl_caps; -+ __u32 gen_caps; -+}; -+ -+/** -+ * TEE_IOC_VERSION - query version of TEE -+ * -+ * Takes a tee_ioctl_version_data struct and returns with the TEE version -+ * data filled in. -+ */ -+#define TEE_IOC_VERSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \ -+ struct tee_ioctl_version_data) -+ -+/** -+ * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument -+ * @size: [in/out] Size of shared memory to allocate -+ * @flags: [in/out] Flags to/from allocation. -+ * @id: [out] Identifier of the shared memory -+ * -+ * The flags field should currently be zero as input. Updated by the call -+ * with actual flags as defined by TEE_IOCTL_SHM_* above. -+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below. -+ */ -+struct tee_ioctl_shm_alloc_data { -+ __u64 size; -+ __u32 flags; -+ __s32 id; -+}; -+ -+/** -+ * TEE_IOC_SHM_ALLOC - allocate shared memory -+ * -+ * Allocates shared memory between the user space process and secure OS. -+ * -+ * Returns a file descriptor on success or < 0 on failure -+ * -+ * The returned file descriptor is used to map the shared memory into user -+ * space. The shared memory is freed when the descriptor is closed and the -+ * memory is unmapped. -+ */ -+#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \ -+ struct tee_ioctl_shm_alloc_data) -+ -+/** -+ * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument -+ * @fd: [in] file descriptor identifying the shared memory -+ * @size: [out] Size of shared memory to allocate -+ * @flags: [in] Flags to/from allocation. -+ * @id: [out] Identifier of the shared memory -+ * -+ * The flags field should currently be zero as input. Updated by the call -+ * with actual flags as defined by TEE_IOCTL_SHM_* above. -+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below. -+ */ -+struct tee_ioctl_shm_register_fd_data { -+ __s64 fd; -+ __u64 size; -+ __u32 flags; -+ __s32 id; -+} __aligned(8); -+ -+/* -+ * Attributes for struct tee_ioctl_param, selects field in the union -+ */ -+#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */ -+ -+/* -+ * These defines value parameters (struct tee_ioctl_param_value) -+ */ -+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1 -+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2 -+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */ -+ -+/* -+ * These defines shared memory reference parameters (struct -+ * tee_ioctl_param_memref) -+ */ -+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5 -+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6 -+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */ -+ -+/* -+ * Mask for the type part of the attribute, leaves room for more types -+ */ -+#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff -+ -+/* Meta parameter carrying extra information about the message. */ -+#define TEE_IOCTL_PARAM_ATTR_META 0x100 -+ -+/* Mask of all known attr bits */ -+#define TEE_IOCTL_PARAM_ATTR_MASK \ -+ (TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META) -+ -+/* -+ * Matches TEEC_LOGIN_* in GP TEE Client API -+ * Are only defined for GP compliant TEEs -+ */ -+#define TEE_IOCTL_LOGIN_PUBLIC 0 -+#define TEE_IOCTL_LOGIN_USER 1 -+#define TEE_IOCTL_LOGIN_GROUP 2 -+#define TEE_IOCTL_LOGIN_APPLICATION 4 -+#define TEE_IOCTL_LOGIN_USER_APPLICATION 5 -+#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6 -+ -+/** -+ * struct tee_ioctl_param - parameter -+ * @attr: attributes -+ * @a: if a memref, offset into the shared memory object, else a value parameter -+ * @b: if a memref, size of the buffer, else a value parameter -+ * @c: if a memref, shared memory identifier, else a value parameter -+ * -+ * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in -+ * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and -+ * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE -+ * indicates that none of the members are used. -+ * -+ * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an -+ * identifier representing the shared memory object. A memref can reference -+ * a part of a shared memory by specifying an offset (@a) and size (@b) of -+ * the object. To supply the entire shared memory object set the offset -+ * (@a) to 0 and size (@b) to the previously returned size of the object. -+ */ -+struct tee_ioctl_param { -+ __u64 attr; -+ __u64 a; -+ __u64 b; -+ __u64 c; -+}; -+ -+#define TEE_IOCTL_UUID_LEN 16 -+ -+/** -+ * struct tee_ioctl_open_session_arg - Open session argument -+ * @uuid: [in] UUID of the Trusted Application -+ * @clnt_uuid: [in] UUID of client -+ * @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above -+ * @cancel_id: [in] Cancellation id, a unique value to identify this request -+ * @session: [out] Session id -+ * @ret: [out] return value -+ * @ret_origin [out] origin of the return value -+ * @num_params [in] number of parameters following this struct -+ */ -+struct tee_ioctl_open_session_arg { -+ __u8 uuid[TEE_IOCTL_UUID_LEN]; -+ __u8 clnt_uuid[TEE_IOCTL_UUID_LEN]; -+ __u32 clnt_login; -+ __u32 cancel_id; -+ __u32 session; -+ __u32 ret; -+ __u32 ret_origin; -+ __u32 num_params; -+ /* num_params tells the actual number of element in params */ -+ struct tee_ioctl_param params[]; -+}; -+ -+/** -+ * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application -+ * -+ * Takes a struct tee_ioctl_buf_data which contains a struct -+ * tee_ioctl_open_session_arg followed by any array of struct -+ * tee_ioctl_param -+ */ -+#define TEE_IOC_OPEN_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \ -+ struct tee_ioctl_buf_data) -+ -+/** -+ * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted -+ * Application -+ * @func: [in] Trusted Application function, specific to the TA -+ * @session: [in] Session id -+ * @cancel_id: [in] Cancellation id, a unique value to identify this request -+ * @ret: [out] return value -+ * @ret_origin [out] origin of the return value -+ * @num_params [in] number of parameters following this struct -+ */ -+struct tee_ioctl_invoke_arg { -+ __u32 func; -+ __u32 session; -+ __u32 cancel_id; -+ __u32 ret; -+ __u32 ret_origin; -+ __u32 num_params; -+ /* num_params tells the actual number of element in params */ -+ struct tee_ioctl_param params[]; -+}; -+ -+/** -+ * TEE_IOC_INVOKE - Invokes a function in a Trusted Application -+ * -+ * Takes a struct tee_ioctl_buf_data which contains a struct -+ * tee_invoke_func_arg followed by any array of struct tee_param -+ */ -+#define TEE_IOC_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \ -+ struct tee_ioctl_buf_data) -+ -+/** -+ * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl -+ * @cancel_id: [in] Cancellation id, a unique value to identify this request -+ * @session: [in] Session id, if the session is opened, else set to 0 -+ */ -+struct tee_ioctl_cancel_arg { -+ __u32 cancel_id; -+ __u32 session; -+}; -+ -+/** -+ * TEE_IOC_CANCEL - Cancels an open session or invoke -+ */ -+#define TEE_IOC_CANCEL _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \ -+ struct tee_ioctl_cancel_arg) -+ -+/** -+ * struct tee_ioctl_close_session_arg - Closes an open session -+ * @session: [in] Session id -+ */ -+struct tee_ioctl_close_session_arg { -+ __u32 session; -+}; -+ -+/** -+ * TEE_IOC_CLOSE_SESSION - Closes a session -+ */ -+#define TEE_IOC_CLOSE_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \ -+ struct tee_ioctl_close_session_arg) -+ -+/** -+ * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function -+ * @func: [in] supplicant function -+ * @num_params [in/out] number of parameters following this struct -+ * -+ * @num_params is the number of params that tee-supplicant has room to -+ * receive when input, @num_params is the number of actual params -+ * tee-supplicant receives when output. -+ */ -+struct tee_iocl_supp_recv_arg { -+ __u32 func; -+ __u32 num_params; -+ /* num_params tells the actual number of element in params */ -+ struct tee_ioctl_param params[]; -+}; -+ -+/** -+ * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function -+ * -+ * Takes a struct tee_ioctl_buf_data which contains a struct -+ * tee_iocl_supp_recv_arg followed by any array of struct tee_param -+ */ -+#define TEE_IOC_SUPPL_RECV _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \ -+ struct tee_ioctl_buf_data) -+ -+/** -+ * struct tee_iocl_supp_send_arg - Send a response to a received request -+ * @ret: [out] return value -+ * @num_params [in] number of parameters following this struct -+ */ -+struct tee_iocl_supp_send_arg { -+ __u32 ret; -+ __u32 num_params; -+ /* num_params tells the actual number of element in params */ -+ struct tee_ioctl_param params[]; -+}; -+ -+/** -+ * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function -+ * -+ * Takes a struct tee_ioctl_buf_data which contains a struct -+ * tee_iocl_supp_send_arg followed by any array of struct tee_param -+ */ -+#define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ -+ struct tee_ioctl_buf_data) -+ -+/** -+ * struct tee_ioctl_shm_register_data - Shared memory register argument -+ * @addr: [in] Start address of shared memory to register -+ * @length: [in/out] Length of shared memory to register -+ * @flags: [in/out] Flags to/from registration. -+ * @id: [out] Identifier of the shared memory -+ * -+ * The flags field should currently be zero as input. Updated by the call -+ * with actual flags as defined by TEE_IOCTL_SHM_* above. -+ * This structure is used as argument for TEE_IOC_SHM_REGISTER below. -+ */ -+struct tee_ioctl_shm_register_data { -+ __u64 addr; -+ __u64 length; -+ __u32 flags; -+ __s32 id; -+}; -+ -+/** -+ * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor -+ * -+ * Returns a file descriptor on success or < 0 on failure -+ * -+ * The returned file descriptor refers to the shared memory object in kernel -+ * land. The shared memory is freed when the descriptor is closed. -+ */ -+#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ -+ struct tee_ioctl_shm_register_fd_data) -+ -+/** -+ * struct tee_ioctl_buf_data - Variable sized buffer -+ * @buf_ptr: [in] A __user pointer to a buffer -+ * @buf_len: [in] Length of the buffer above -+ * -+ * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE, -+ * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below. -+ */ -+struct tee_ioctl_buf_data { -+ __u64 buf_ptr; -+ __u64 buf_len; -+}; -+ -+/** -+ * TEE_IOC_SHM_REGISTER - Register shared memory argument -+ * -+ * Registers shared memory between the user space process and secure OS. -+ * -+ * Returns a file descriptor on success or < 0 on failure -+ * -+ * The shared memory is unregisterred when the descriptor is closed. -+ */ -+#define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \ -+ struct tee_ioctl_shm_register_data) -+/* -+ * Five syscalls are used when communicating with the TEE driver. -+ * open(): opens the device associated with the driver -+ * ioctl(): as described above operating on the file descriptor from open() -+ * close(): two cases -+ * - closes the device file descriptor -+ * - closes a file descriptor connected to allocated shared memory -+ * mmap(): maps shared memory into user space using information from struct -+ * tee_ioctl_shm_alloc_data -+ * munmap(): unmaps previously shared memory -+ */ -+ -+#endif /*__TEE_H*/ -diff --git a/src/tee_bench.h b/src/tee_bench.h -new file mode 100644 -index 0000000..600407f ---- /dev/null -+++ b/src/tee_bench.h -@@ -0,0 +1,77 @@ -+/* -+ * Copyright (c) 2017, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef TEE_BENCH_H -+#define TEE_BENCH_H -+ -+#include -+ -+#define PTA_BENCHMARK_UUID \ -+ { 0x0b9a63b0, 0xb4c6, 0x4c85, \ -+ { 0xa2, 0x84, 0xa2, 0x28, 0xef, 0x54, 0x7b, 0x4e } } -+ -+#define BENCHMARK_CMD(id) (0xFA190000 | ((id) & 0xFFFF)) -+#define BENCHMARK_CMD_REGISTER_MEMREF BENCHMARK_CMD(1) -+#define BENCHMARK_CMD_GET_MEMREF BENCHMARK_CMD(2) -+#define BENCHMARK_CMD_UNREGISTER BENCHMARK_CMD(3) -+ -+/* -+ * Cycle count divider is enabled (in PMCR), -+ * CCNT value is incremented every 64th clock cycle -+ */ -+#define TEE_BENCH_DIVIDER 64 -+/* max amount of timestamps per buffer */ -+#define TEE_BENCH_MAX_STAMPS 32 -+#define TEE_BENCH_MAX_MASK (TEE_BENCH_MAX_STAMPS - 1) -+ -+/* OP-TEE susbsystems ids */ -+#define TEE_BENCH_CLIENT 0x10000000 -+#define TEE_BENCH_KMOD 0x20000000 -+#define TEE_BENCH_CORE 0x30000000 -+#define TEE_BENCH_UTEE 0x40000000 -+#define TEE_BENCH_DUMB_TA 0xF0000001 -+ -+/* storing timestamp */ -+struct tee_time_st { -+ uint64_t cnt; /* stores value from CNTPCT register */ -+ uint64_t addr; /* stores value from program counter register */ -+ uint64_t src; /* OP-TEE subsystem id */ -+}; -+ -+/* per-cpu circular buffer for timestamps */ -+struct tee_ts_cpu_buf { -+ uint64_t head; -+ uint64_t tail; -+ struct tee_time_st stamps[TEE_BENCH_MAX_STAMPS]; -+}; -+ -+/* memory layout for shared memory, where timestamps will be stored */ -+struct tee_ts_global { -+ uint64_t cores; -+ struct tee_ts_cpu_buf cpu_buf[]; -+}; -+#endif /* TEE_BENCH_H */ -diff --git a/src/tee_client_api.c b/src/tee_client_api.c -new file mode 100644 -index 0000000..2b07d30 ---- /dev/null -+++ b/src/tee_client_api.c -@@ -0,0 +1,958 @@ -+/* -+ * Copyright (c) 2015-2016, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef __aligned -+#define __aligned(x) __attribute__((__aligned__(x))) -+#endif -+#include -+ -+#include "teec_benchmark.h" -+ -+#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -+ -+/* How many device sequence numbers will be tried before giving up */ -+#define TEEC_MAX_DEV_SEQ 10 -+ -+/* Helpers to access memref parts of a struct tee_ioctl_param */ -+#define MEMREF_SHM_ID(p) ((p)->c) -+#define MEMREF_SHM_OFFS(p) ((p)->a) -+#define MEMREF_SIZE(p) ((p)->b) -+ -+/* -+ * Internal flags of TEEC_SharedMemory::internal.flags -+ */ -+#define SHM_FLAG_BUFFER_ALLOCED (1u << 0) -+#define SHM_FLAG_SHADOW_BUFFER_ALLOCED (1u << 1) -+ -+static pthread_mutex_t teec_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+static void teec_mutex_lock(pthread_mutex_t *mu) -+{ -+ pthread_mutex_lock(mu); -+} -+ -+static void teec_mutex_unlock(pthread_mutex_t *mu) -+{ -+ pthread_mutex_unlock(mu); -+} -+ -+static void *teec_paged_aligned_alloc(size_t sz) -+{ -+ void *p = NULL; -+ -+ if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz)) -+ return p; -+ -+ return NULL; -+} -+ -+static int teec_open_dev(const char *devname, const char *capabilities, -+ uint32_t *gen_caps) -+{ -+ int fd = 0; -+ struct tee_ioctl_version_data vers; -+ -+ memset(&vers, 0, sizeof(vers)); -+ -+ fd = open(devname, O_RDWR); -+ if (fd < 0) -+ return -1; -+ -+ if (ioctl(fd, TEE_IOC_VERSION, &vers)) { -+ EMSG("TEE_IOC_VERSION failed"); -+ goto err; -+ } -+ -+ /* We can only handle GP TEEs */ -+ if (!(vers.gen_caps & TEE_GEN_CAP_GP)) -+ goto err; -+ -+ if (capabilities) { -+ if (strcmp(capabilities, "optee-tz") == 0) { -+ if (vers.impl_id != TEE_IMPL_ID_OPTEE) -+ goto err; -+ if (!(vers.impl_caps & TEE_OPTEE_CAP_TZ)) -+ goto err; -+ } else { -+ /* Unrecognized capability requested */ -+ goto err; -+ } -+ } -+ -+ *gen_caps = vers.gen_caps; -+ return fd; -+err: -+ close(fd); -+ return -1; -+} -+ -+static int teec_shm_alloc(int fd, size_t size, int *id) -+{ -+ int shm_fd = 0; -+ struct tee_ioctl_shm_alloc_data data; -+ -+ memset(&data, 0, sizeof(data)); -+ -+ data.size = size; -+ shm_fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data); -+ if (shm_fd < 0) -+ return -1; -+ *id = data.id; -+ return shm_fd; -+} -+ -+static int teec_shm_register(int fd, void *buf, size_t size, int *id) -+{ -+ int shm_fd = 0; -+ struct tee_ioctl_shm_register_data data; -+ -+ memset(&data, 0, sizeof(data)); -+ -+ data.addr = (uintptr_t)buf; -+ data.length = size; -+ shm_fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data); -+ if (shm_fd < 0) -+ return -1; -+ *id = data.id; -+ return shm_fd; -+} -+ -+TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *ctx) -+{ -+ char devname[PATH_MAX] = { 0 }; -+ int fd = 0; -+ size_t n = 0; -+ -+ if (!ctx) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ for (n = 0; n < TEEC_MAX_DEV_SEQ; n++) { -+ uint32_t gen_caps = 0; -+ -+ snprintf(devname, sizeof(devname), "/dev/tee%zu", n); -+ fd = teec_open_dev(devname, name, &gen_caps); -+ if (fd >= 0) { -+ ctx->fd = fd; -+ ctx->reg_mem = gen_caps & TEE_GEN_CAP_REG_MEM; -+ ctx->memref_null = gen_caps & TEE_GEN_CAP_MEMREF_NULL; -+ return TEEC_SUCCESS; -+ } -+ } -+ -+ return TEEC_ERROR_ITEM_NOT_FOUND; -+} -+ -+void TEEC_FinalizeContext(TEEC_Context *ctx) -+{ -+ if (ctx) -+ close(ctx->fd); -+} -+ -+ -+static TEEC_Result teec_pre_process_tmpref(TEEC_Context *ctx, -+ uint32_t param_type, TEEC_TempMemoryReference *tmpref, -+ struct tee_ioctl_param *param, -+ TEEC_SharedMemory *shm) -+{ -+ TEEC_Result res = TEEC_ERROR_GENERIC; -+ -+ switch (param_type) { -+ case TEEC_MEMREF_TEMP_INPUT: -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; -+ shm->flags = TEEC_MEM_INPUT; -+ break; -+ case TEEC_MEMREF_TEMP_OUTPUT: -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; -+ shm->flags = TEEC_MEM_OUTPUT; -+ break; -+ case TEEC_MEMREF_TEMP_INOUT: -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; -+ shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; -+ break; -+ default: -+ return TEEC_ERROR_BAD_PARAMETERS; -+ } -+ shm->size = tmpref->size; -+ -+ if (!tmpref->buffer) { -+ if (tmpref->size) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if (ctx->memref_null) { -+ /* Null pointer, indicate no shared memory attached */ -+ MEMREF_SHM_ID(param) = TEE_MEMREF_NULL; -+ shm->id = -1; -+ } else { -+ res = TEEC_AllocateSharedMemory(ctx, shm); -+ if (res != TEEC_SUCCESS) -+ return res; -+ MEMREF_SHM_ID(param) = shm->id; -+ } -+ } else { -+ shm->buffer = tmpref->buffer; -+ res = TEEC_RegisterSharedMemory(ctx, shm); -+ if (res != TEEC_SUCCESS) -+ return res; -+ -+ if (shm->shadow_buffer) -+ memcpy(shm->shadow_buffer, tmpref->buffer, -+ tmpref->size); -+ -+ MEMREF_SHM_ID(param) = shm->id; -+ } -+ -+ MEMREF_SIZE(param) = tmpref->size; -+ -+ return TEEC_SUCCESS; -+} -+ -+static TEEC_Result teec_pre_process_whole( -+ TEEC_RegisteredMemoryReference *memref, -+ struct tee_ioctl_param *param) -+{ -+ const uint32_t inout = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; -+ uint32_t flags = memref->parent->flags & inout; -+ TEEC_SharedMemory *shm = NULL; -+ -+ if (flags == inout) -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; -+ else if (flags & TEEC_MEM_INPUT) -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; -+ else if (flags & TEEC_MEM_OUTPUT) -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; -+ else -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ shm = memref->parent; -+ /* -+ * We're using a shadow buffer in this reference, copy the real buffer -+ * into the shadow buffer if needed. We'll copy it back once we've -+ * returned from the call to secure world. -+ */ -+ if (shm->shadow_buffer && (flags & TEEC_MEM_INPUT)) -+ memcpy(shm->shadow_buffer, shm->buffer, shm->size); -+ -+ MEMREF_SHM_ID(param) = shm->id; -+ MEMREF_SIZE(param) = shm->size; -+ -+ return TEEC_SUCCESS; -+} -+ -+static TEEC_Result teec_pre_process_partial(uint32_t param_type, -+ TEEC_RegisteredMemoryReference *memref, -+ struct tee_ioctl_param *param) -+{ -+ uint32_t req_shm_flags = 0; -+ TEEC_SharedMemory *shm = NULL; -+ -+ switch (param_type) { -+ case TEEC_MEMREF_PARTIAL_INPUT: -+ req_shm_flags = TEEC_MEM_INPUT; -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; -+ break; -+ case TEEC_MEMREF_PARTIAL_OUTPUT: -+ req_shm_flags = TEEC_MEM_OUTPUT; -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; -+ break; -+ case TEEC_MEMREF_PARTIAL_INOUT: -+ req_shm_flags = TEEC_MEM_OUTPUT | TEEC_MEM_INPUT; -+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; -+ break; -+ default: -+ return TEEC_ERROR_BAD_PARAMETERS; -+ } -+ -+ shm = memref->parent; -+ -+ if ((shm->flags & req_shm_flags) != req_shm_flags) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if ((memref->offset + memref->size < memref->offset) || -+ (memref->offset + memref->size > shm->size)) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ /* -+ * We're using a shadow buffer in this reference, copy the real buffer -+ * into the shadow buffer if needed. We'll copy it back once we've -+ * returned from the call to secure world. -+ */ -+ if (shm->shadow_buffer && param_type != TEEC_MEMREF_PARTIAL_OUTPUT) -+ memcpy((char *)shm->shadow_buffer + memref->offset, -+ (char *)shm->buffer + memref->offset, memref->size); -+ -+ MEMREF_SHM_ID(param) = shm->id; -+ MEMREF_SHM_OFFS(param) = memref->offset; -+ MEMREF_SIZE(param) = memref->size; -+ -+ return TEEC_SUCCESS; -+} -+ -+static TEEC_Result teec_pre_process_operation(TEEC_Context *ctx, -+ TEEC_Operation *operation, -+ struct tee_ioctl_param *params, -+ TEEC_SharedMemory *shms) -+{ -+ TEEC_Result res = TEEC_ERROR_GENERIC; -+ size_t n = 0; -+ -+ memset(shms, 0, sizeof(TEEC_SharedMemory) * -+ TEEC_CONFIG_PAYLOAD_REF_COUNT); -+ -+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) -+ shms[n].id = -1; -+ -+ if (!operation) { -+ memset(params, 0, sizeof(struct tee_ioctl_param) * -+ TEEC_CONFIG_PAYLOAD_REF_COUNT); -+ return TEEC_SUCCESS; -+ } -+ -+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { -+ uint32_t param_type = 0; -+ -+ param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); -+ switch (param_type) { -+ case TEEC_NONE: -+ params[n].attr = param_type; -+ break; -+ case TEEC_VALUE_INPUT: -+ case TEEC_VALUE_OUTPUT: -+ case TEEC_VALUE_INOUT: -+ params[n].attr = param_type; -+ params[n].a = operation->params[n].value.a; -+ params[n].b = operation->params[n].value.b; -+ break; -+ case TEEC_MEMREF_TEMP_INPUT: -+ case TEEC_MEMREF_TEMP_OUTPUT: -+ case TEEC_MEMREF_TEMP_INOUT: -+ res = teec_pre_process_tmpref(ctx, param_type, -+ &operation->params[n].tmpref, params + n, -+ shms + n); -+ if (res != TEEC_SUCCESS) -+ return res; -+ break; -+ case TEEC_MEMREF_WHOLE: -+ res = teec_pre_process_whole( -+ &operation->params[n].memref, -+ params + n); -+ if (res != TEEC_SUCCESS) -+ return res; -+ break; -+ case TEEC_MEMREF_PARTIAL_INPUT: -+ case TEEC_MEMREF_PARTIAL_OUTPUT: -+ case TEEC_MEMREF_PARTIAL_INOUT: -+ res = teec_pre_process_partial(param_type, -+ &operation->params[n].memref, params + n); -+ if (res != TEEC_SUCCESS) -+ return res; -+ break; -+ default: -+ return TEEC_ERROR_BAD_PARAMETERS; -+ } -+ } -+ -+ return TEEC_SUCCESS; -+} -+ -+static void teec_post_process_tmpref(uint32_t param_type, -+ TEEC_TempMemoryReference *tmpref, -+ struct tee_ioctl_param *param, -+ TEEC_SharedMemory *shm) -+{ -+ if (param_type != TEEC_MEMREF_TEMP_INPUT) { -+ if (tmpref->buffer && shm->shadow_buffer) -+ memcpy(tmpref->buffer, shm->shadow_buffer, -+ MIN(MEMREF_SIZE(param), tmpref->size)); -+ -+ tmpref->size = MEMREF_SIZE(param); -+ } -+} -+ -+static void teec_post_process_whole(TEEC_RegisteredMemoryReference *memref, -+ struct tee_ioctl_param *param) -+{ -+ TEEC_SharedMemory *shm = memref->parent; -+ -+ if (shm->flags & TEEC_MEM_OUTPUT) { -+ -+ /* -+ * We're using a shadow buffer in this reference, copy back -+ * the shadow buffer into the real buffer now that we've -+ * returned from secure world. -+ */ -+ if (shm->shadow_buffer && MEMREF_SIZE(param) <= shm->size) -+ memcpy(shm->buffer, shm->shadow_buffer, -+ MEMREF_SIZE(param)); -+ -+ memref->size = MEMREF_SIZE(param); -+ } -+} -+ -+static void teec_post_process_partial(uint32_t param_type, -+ TEEC_RegisteredMemoryReference *memref, -+ struct tee_ioctl_param *param) -+{ -+ if (param_type != TEEC_MEMREF_PARTIAL_INPUT) { -+ TEEC_SharedMemory *shm = memref->parent; -+ -+ /* -+ * We're using a shadow buffer in this reference, copy back -+ * the shadow buffer into the real buffer now that we've -+ * returned from secure world. -+ */ -+ if (shm->shadow_buffer && MEMREF_SIZE(param) <= memref->size) -+ memcpy((char *)shm->buffer + memref->offset, -+ (char *)shm->shadow_buffer + memref->offset, -+ MEMREF_SIZE(param)); -+ -+ memref->size = MEMREF_SIZE(param); -+ } -+} -+ -+static void teec_post_process_operation(TEEC_Operation *operation, -+ struct tee_ioctl_param *params, -+ TEEC_SharedMemory *shms) -+{ -+ size_t n = 0; -+ -+ if (!operation) -+ return; -+ -+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { -+ uint32_t param_type = 0; -+ -+ param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); -+ switch (param_type) { -+ case TEEC_VALUE_INPUT: -+ break; -+ case TEEC_VALUE_OUTPUT: -+ case TEEC_VALUE_INOUT: -+ operation->params[n].value.a = params[n].a; -+ operation->params[n].value.b = params[n].b; -+ break; -+ case TEEC_MEMREF_TEMP_INPUT: -+ case TEEC_MEMREF_TEMP_OUTPUT: -+ case TEEC_MEMREF_TEMP_INOUT: -+ teec_post_process_tmpref(param_type, -+ &operation->params[n].tmpref, params + n, -+ shms + n); -+ break; -+ case TEEC_MEMREF_WHOLE: -+ teec_post_process_whole(&operation->params[n].memref, -+ params + n); -+ break; -+ case TEEC_MEMREF_PARTIAL_INPUT: -+ case TEEC_MEMREF_PARTIAL_OUTPUT: -+ case TEEC_MEMREF_PARTIAL_INOUT: -+ teec_post_process_partial(param_type, -+ &operation->params[n].memref, params + n); -+ default: -+ break; -+ } -+ } -+} -+ -+static void teec_free_temp_refs(TEEC_Operation *operation, -+ TEEC_SharedMemory *shms) -+{ -+ size_t n = 0; -+ -+ if (!operation) -+ return; -+ -+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { -+ switch (TEEC_PARAM_TYPE_GET(operation->paramTypes, n)) { -+ case TEEC_MEMREF_TEMP_INPUT: -+ case TEEC_MEMREF_TEMP_OUTPUT: -+ case TEEC_MEMREF_TEMP_INOUT: -+ TEEC_ReleaseSharedMemory(shms + n); -+ break; -+ default: -+ break; -+ } -+ } -+} -+ -+static TEEC_Result ioctl_errno_to_res(int err) -+{ -+ switch (err) { -+ case ENOMEM: -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ case EINVAL: -+ return TEEC_ERROR_BAD_PARAMETERS; -+ default: -+ return TEEC_ERROR_GENERIC; -+ } -+} -+ -+static void uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], const TEEC_UUID *s) -+{ -+ d[0] = s->timeLow >> 24; -+ d[1] = s->timeLow >> 16; -+ d[2] = s->timeLow >> 8; -+ d[3] = s->timeLow; -+ d[4] = s->timeMid >> 8; -+ d[5] = s->timeMid; -+ d[6] = s->timeHiAndVersion >> 8; -+ d[7] = s->timeHiAndVersion; -+ memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode)); -+} -+ -+static void setup_client_data(struct tee_ioctl_open_session_arg *arg, -+ uint32_t connection_method, -+ const void *connection_data) -+{ -+ arg->clnt_login = connection_method; -+ -+ switch (connection_method) { -+ case TEE_IOCTL_LOGIN_PUBLIC: -+ /* No connection data to pass */ -+ break; -+ case TEE_IOCTL_LOGIN_USER: -+ /* Kernel auto-fills UID and forms client UUID */ -+ break; -+ case TEE_IOCTL_LOGIN_GROUP: -+ /* -+ * Connection data for group login is uint32_t and rest of -+ * clnt_uuid is set as zero. -+ * -+ * Kernel verifies group membership and then forms client UUID. -+ */ -+ memcpy(arg->clnt_uuid, connection_data, sizeof(gid_t)); -+ break; -+ case TEE_IOCTL_LOGIN_APPLICATION: -+ /* -+ * Kernel auto-fills application identifier and forms client -+ * UUID. -+ */ -+ break; -+ case TEE_IOCTL_LOGIN_USER_APPLICATION: -+ /* -+ * Kernel auto-fills application identifier, UID and forms -+ * client UUID. -+ */ -+ break; -+ case TEE_IOCTL_LOGIN_GROUP_APPLICATION: -+ /* -+ * Connection data for group login is uint32_t rest of -+ * clnt_uuid is set as zero. -+ * -+ * Kernel verifies group membership, auto-fills application -+ * identifier and then forms client UUID. -+ */ -+ memcpy(arg->clnt_uuid, connection_data, sizeof(gid_t)); -+ break; -+ default: -+ /* -+ * Unknown login method, don't pass any connection data as we -+ * don't know size. -+ */ -+ break; -+ } -+} -+ -+TEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session, -+ const TEEC_UUID *destination, -+ uint32_t connection_method, const void *connection_data, -+ TEEC_Operation *operation, uint32_t *ret_origin) -+{ -+ struct tee_ioctl_open_session_arg *arg = NULL; -+ struct tee_ioctl_param *params = NULL; -+ TEEC_Result res = TEEC_ERROR_GENERIC; -+ uint32_t eorig = 0; -+ int rc = 0; -+ const size_t arg_size = sizeof(struct tee_ioctl_open_session_arg) + -+ TEEC_CONFIG_PAYLOAD_REF_COUNT * -+ sizeof(struct tee_ioctl_param); -+ union { -+ struct tee_ioctl_open_session_arg arg; -+ uint8_t data[arg_size]; -+ } buf; -+ struct tee_ioctl_buf_data buf_data; -+ TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; -+ -+ memset(&buf, 0, sizeof(buf)); -+ memset(&shm, 0, sizeof(shm)); -+ memset(&buf_data, 0, sizeof(buf_data)); -+ -+ if (!ctx || !session) { -+ eorig = TEEC_ORIGIN_API; -+ res = TEEC_ERROR_BAD_PARAMETERS; -+ goto out; -+ } -+ -+ buf_data.buf_ptr = (uintptr_t)&buf; -+ buf_data.buf_len = sizeof(buf); -+ -+ arg = &buf.arg; -+ arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; -+ params = (struct tee_ioctl_param *)(arg + 1); -+ -+ uuid_to_octets(arg->uuid, destination); -+ -+ setup_client_data(arg, connection_method, connection_data); -+ -+ res = teec_pre_process_operation(ctx, operation, params, shm); -+ if (res != TEEC_SUCCESS) { -+ eorig = TEEC_ORIGIN_API; -+ goto out_free_temp_refs; -+ } -+ -+ rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data); -+ if (rc) { -+ EMSG("TEE_IOC_OPEN_SESSION failed"); -+ eorig = TEEC_ORIGIN_COMMS; -+ res = ioctl_errno_to_res(errno); -+ goto out_free_temp_refs; -+ } -+ res = arg->ret; -+ eorig = arg->ret_origin; -+ if (res == TEEC_SUCCESS) { -+ session->ctx = ctx; -+ session->session_id = arg->session; -+ } -+ teec_post_process_operation(operation, params, shm); -+ -+out_free_temp_refs: -+ teec_free_temp_refs(operation, shm); -+out: -+ if (ret_origin) -+ *ret_origin = eorig; -+ return res; -+} -+ -+void TEEC_CloseSession(TEEC_Session *session) -+{ -+ struct tee_ioctl_close_session_arg arg; -+ -+ memset(&arg, 0, sizeof(arg)); -+ -+ if (!session) -+ return; -+ -+ arg.session = session->session_id; -+ if (ioctl(session->ctx->fd, TEE_IOC_CLOSE_SESSION, &arg)) -+ EMSG("Failed to close session 0x%x", session->session_id); -+} -+ -+TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id, -+ TEEC_Operation *operation, uint32_t *error_origin) -+{ -+ struct tee_ioctl_invoke_arg *arg = NULL; -+ struct tee_ioctl_param *params = NULL; -+ TEEC_Result res = TEEC_ERROR_GENERIC; -+ uint32_t eorig = 0; -+ int rc = 0; -+ const size_t arg_size = sizeof(struct tee_ioctl_invoke_arg) + -+ TEEC_CONFIG_PAYLOAD_REF_COUNT * -+ sizeof(struct tee_ioctl_param); -+ union { -+ struct tee_ioctl_invoke_arg arg; -+ uint8_t data[arg_size]; -+ } buf; -+ struct tee_ioctl_buf_data buf_data; -+ TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; -+ -+ memset(&buf, 0, sizeof(buf)); -+ memset(&buf_data, 0, sizeof(buf_data)); -+ memset(&shm, 0, sizeof(shm)); -+ -+ if (!session) { -+ eorig = TEEC_ORIGIN_API; -+ res = TEEC_ERROR_BAD_PARAMETERS; -+ goto out; -+ } -+ -+ bm_timestamp(); -+ -+ buf_data.buf_ptr = (uintptr_t)&buf; -+ buf_data.buf_len = sizeof(buf); -+ -+ arg = &buf.arg; -+ arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; -+ params = (struct tee_ioctl_param *)(arg + 1); -+ -+ arg->session = session->session_id; -+ arg->func = cmd_id; -+ -+ if (operation) { -+ teec_mutex_lock(&teec_mutex); -+ operation->session = session; -+ teec_mutex_unlock(&teec_mutex); -+ } -+ -+ res = teec_pre_process_operation(session->ctx, operation, params, shm); -+ if (res != TEEC_SUCCESS) { -+ eorig = TEEC_ORIGIN_API; -+ goto out_free_temp_refs; -+ } -+ -+ rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data); -+ if (rc) { -+ EMSG("TEE_IOC_INVOKE failed"); -+ eorig = TEEC_ORIGIN_COMMS; -+ res = ioctl_errno_to_res(errno); -+ goto out_free_temp_refs; -+ } -+ -+ res = arg->ret; -+ eorig = arg->ret_origin; -+ teec_post_process_operation(operation, params, shm); -+ -+ bm_timestamp(); -+ -+out_free_temp_refs: -+ teec_free_temp_refs(operation, shm); -+out: -+ if (error_origin) -+ *error_origin = eorig; -+ return res; -+} -+ -+void TEEC_RequestCancellation(TEEC_Operation *operation) -+{ -+ TEEC_Session *session = NULL; -+ struct tee_ioctl_cancel_arg arg; -+ -+ memset(&arg, 0, sizeof(arg)); -+ -+ if (!operation) -+ return; -+ -+ teec_mutex_lock(&teec_mutex); -+ session = operation->session; -+ teec_mutex_unlock(&teec_mutex); -+ -+ if (!session) -+ return; -+ -+ arg.session = session->session_id; -+ arg.cancel_id = 0; -+ -+ if (ioctl(session->ctx->fd, TEE_IOC_CANCEL, &arg)) -+ EMSG("TEE_IOC_CANCEL: %s", strerror(errno)); -+} -+ -+TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) -+{ -+ TEEC_Result res = TEEC_SUCCESS; -+ int fd = 0; -+ size_t s = 0; -+ -+ if (!ctx || !shm) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if (!shm->buffer) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ s = shm->size; -+ if (!s) -+ s = 8; -+ if (ctx->reg_mem) { -+ fd = teec_shm_register(ctx->fd, shm->buffer, s, &shm->id); -+ if (fd >= 0) { -+ shm->registered_fd = fd; -+ shm->shadow_buffer = NULL; -+ shm->internal.flags = 0; -+ goto out; -+ } -+ -+ /* -+ * If we're here TEE_IOC_SHM_REGISTER failed, probably -+ * because some read-only memory was supplied and the Linux -+ * kernel doesn't like that at the moment. -+ * -+ * The error could also have some other origin. In any case -+ * we're not making matters worse by trying to allocate and -+ * register a shadow buffer before giving up. -+ */ -+ shm->shadow_buffer = teec_paged_aligned_alloc(s); -+ if (!shm->shadow_buffer) -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ fd = teec_shm_register(ctx->fd, shm->shadow_buffer, s, -+ &shm->id); -+ if (fd >= 0) { -+ shm->registered_fd = fd; -+ shm->internal.flags = SHM_FLAG_SHADOW_BUFFER_ALLOCED; -+ goto out; -+ } -+ -+ if (errno == ENOMEM) -+ res = TEEC_ERROR_OUT_OF_MEMORY; -+ else -+ res = TEEC_ERROR_GENERIC; -+ free(shm->shadow_buffer); -+ shm->shadow_buffer = NULL; -+ return res; -+ } else { -+ fd = teec_shm_alloc(ctx->fd, s, &shm->id); -+ if (fd < 0) -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ -+ shm->shadow_buffer = mmap(NULL, s, PROT_READ | PROT_WRITE, -+ MAP_SHARED, fd, 0); -+ close(fd); -+ if (shm->shadow_buffer == (void *)MAP_FAILED) { -+ shm->id = -1; -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ } -+ shm->registered_fd = -1; -+ shm->internal.flags = 0; -+ } -+ -+out: -+ shm->alloced_size = s; -+ return TEEC_SUCCESS; -+} -+ -+TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *ctx, -+ TEEC_SharedMemory *shm, -+ int fd) -+{ -+ int rfd = 0; -+ struct tee_ioctl_shm_register_fd_data data; -+ -+ memset(&data, 0, sizeof(data)); -+ -+ if (!ctx || !shm || fd < 0) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ data.fd = fd; -+ rfd = ioctl(ctx->fd, TEE_IOC_SHM_REGISTER_FD, &data); -+ if (rfd < 0) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ shm->buffer = NULL; -+ shm->shadow_buffer = NULL; -+ shm->registered_fd = rfd; -+ shm->id = data.id; -+ shm->size = data.size; -+ return TEEC_SUCCESS; -+} -+ -+TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) -+{ -+ int fd = 0; -+ size_t s = 0; -+ -+ if (!ctx || !shm) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) -+ return TEEC_ERROR_BAD_PARAMETERS; -+ -+ s = shm->size; -+ if (!s) -+ s = 8; -+ -+ if (ctx->reg_mem) { -+ shm->buffer = teec_paged_aligned_alloc(s); -+ if (!shm->buffer) -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ -+ fd = teec_shm_register(ctx->fd, shm->buffer, s, &shm->id); -+ if (fd < 0) { -+ free(shm->buffer); -+ shm->buffer = NULL; -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ } -+ shm->registered_fd = fd; -+ } else { -+ fd = teec_shm_alloc(ctx->fd, s, &shm->id); -+ if (fd < 0) -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ -+ shm->buffer = mmap(NULL, s, PROT_READ | PROT_WRITE, -+ MAP_SHARED, fd, 0); -+ close(fd); -+ if (shm->buffer == (void *)MAP_FAILED) { -+ shm->id = -1; -+ return TEEC_ERROR_OUT_OF_MEMORY; -+ } -+ shm->registered_fd = -1; -+ } -+ -+ shm->shadow_buffer = NULL; -+ shm->alloced_size = s; -+ shm->internal.flags = SHM_FLAG_BUFFER_ALLOCED; -+ return TEEC_SUCCESS; -+} -+ -+void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shm) -+{ -+ if (!shm || shm->id == -1) -+ return; -+ -+ if (shm->shadow_buffer) { -+ if (shm->registered_fd >= 0) { -+ if (shm->internal.flags & -+ SHM_FLAG_SHADOW_BUFFER_ALLOCED) -+ free(shm->shadow_buffer); -+ close(shm->registered_fd); -+ } else { -+ munmap(shm->shadow_buffer, shm->alloced_size); -+ } -+ } else if (shm->buffer) { -+ if (shm->registered_fd >= 0) { -+ if (shm->internal.flags & SHM_FLAG_BUFFER_ALLOCED) -+ free(shm->buffer); -+ close(shm->registered_fd); -+ } else { -+ munmap(shm->buffer, shm->alloced_size); -+ } -+ } else if (shm->registered_fd >= 0) { -+ close(shm->registered_fd); -+ } -+ -+ shm->id = -1; -+ shm->shadow_buffer = NULL; -+ shm->buffer = NULL; -+ shm->registered_fd = -1; -+ shm->internal.flags = 0; -+} -diff --git a/src/tee_client_api.h b/src/tee_client_api.h -new file mode 100644 -index 0000000..1693998 ---- /dev/null -+++ b/src/tee_client_api.h -@@ -0,0 +1,555 @@ -+/* -+ * Copyright (c) 2014, STMicroelectronics International N.V. -+ * All rights reserved. -+ * Copyright (c) 2015, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef TEE_CLIENT_API_H -+#define TEE_CLIENT_API_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+/* -+ * Defines the number of available memory references in an open session or -+ * invoke command operation payload. -+ */ -+#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4 -+ -+/** -+ * Defines the maximum size of a single shared memory block, in bytes, of both -+ * API allocated and API registered memory. There is no good value to put here -+ * (limits depend on specific config used), so this define does not provide any -+ * restriction in this implementation. -+ */ -+#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE ULONG_MAX -+ -+/** -+ * Flag constants indicating the type of parameters encoded inside the -+ * operation payload (TEEC_Operation), Type is uint32_t. -+ * -+ * TEEC_NONE The Parameter is not used -+ * -+ * TEEC_VALUE_INPUT The Parameter is a TEEC_Value tagged as input. -+ * -+ * TEEC_VALUE_OUTPUT The Parameter is a TEEC_Value tagged as output. -+ * -+ * TEEC_VALUE_INOUT The Parameter is a TEEC_Value tagged as both as -+ * input and output, i.e., for which both the -+ * behaviors of TEEC_VALUE_INPUT and -+ * TEEC_VALUE_OUTPUT apply. -+ * -+ * TEEC_MEMREF_TEMP_INPUT The Parameter is a TEEC_TempMemoryReference -+ * describing a region of memory which needs to be -+ * temporarily registered for the duration of the -+ * Operation and is tagged as input. -+ * -+ * TEEC_MEMREF_TEMP_OUTPUT Same as TEEC_MEMREF_TEMP_INPUT, but the Memory -+ * Reference is tagged as output. The -+ * Implementation may update the size field to -+ * reflect the required output size in some use -+ * cases. -+ * -+ * TEEC_MEMREF_TEMP_INOUT A Temporary Memory Reference tagged as both -+ * input and output, i.e., for which both the -+ * behaviors of TEEC_MEMREF_TEMP_INPUT and -+ * TEEC_MEMREF_TEMP_OUTPUT apply. -+ * -+ * TEEC_MEMREF_WHOLE The Parameter is a Registered Memory Reference -+ * that refers to the entirety of its parent Shared -+ * Memory block. The parameter structure is a -+ * TEEC_MemoryReference. In this structure, the -+ * Implementation MUST read only the parent field -+ * and MAY update the size field when the operation -+ * completes. -+ * -+ * TEEC_MEMREF_PARTIAL_INPUT A Registered Memory Reference structure that -+ * refers to a partial region of its parent Shared -+ * Memory block and is tagged as input. -+ * -+ * TEEC_MEMREF_PARTIAL_OUTPUT Registered Memory Reference structure that -+ * refers to a partial region of its parent Shared -+ * Memory block and is tagged as output. -+ * -+ * TEEC_MEMREF_PARTIAL_INOUT The Registered Memory Reference structure that -+ * refers to a partial region of its parent Shared -+ * Memory block and is tagged as both input and -+ * output, i.e., for which both the behaviors of -+ * TEEC_MEMREF_PARTIAL_INPUT and -+ * TEEC_MEMREF_PARTIAL_OUTPUT apply. -+ */ -+#define TEEC_NONE 0x00000000 -+#define TEEC_VALUE_INPUT 0x00000001 -+#define TEEC_VALUE_OUTPUT 0x00000002 -+#define TEEC_VALUE_INOUT 0x00000003 -+#define TEEC_MEMREF_TEMP_INPUT 0x00000005 -+#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006 -+#define TEEC_MEMREF_TEMP_INOUT 0x00000007 -+#define TEEC_MEMREF_WHOLE 0x0000000C -+#define TEEC_MEMREF_PARTIAL_INPUT 0x0000000D -+#define TEEC_MEMREF_PARTIAL_OUTPUT 0x0000000E -+#define TEEC_MEMREF_PARTIAL_INOUT 0x0000000F -+ -+/** -+ * Flag constants indicating the data transfer direction of memory in -+ * TEEC_Parameter. TEEC_MEM_INPUT signifies data transfer direction from the -+ * client application to the TEE. TEEC_MEM_OUTPUT signifies data transfer -+ * direction from the TEE to the client application. Type is uint32_t. -+ * -+ * TEEC_MEM_INPUT The Shared Memory can carry data from the client -+ * application to the Trusted Application. -+ * TEEC_MEM_OUTPUT The Shared Memory can carry data from the Trusted -+ * Application to the client application. -+ */ -+#define TEEC_MEM_INPUT 0x00000001 -+#define TEEC_MEM_OUTPUT 0x00000002 -+ -+/** -+ * Return values. Type is TEEC_Result -+ * -+ * TEEC_SUCCESS The operation was successful. -+ * TEEC_ERROR_GENERIC Non-specific cause. -+ * TEEC_ERROR_ACCESS_DENIED Access privileges are not sufficient. -+ * TEEC_ERROR_CANCEL The operation was canceled. -+ * TEEC_ERROR_ACCESS_CONFLICT Concurrent accesses caused conflict. -+ * TEEC_ERROR_EXCESS_DATA Too much data for the requested operation was -+ * passed. -+ * TEEC_ERROR_BAD_FORMAT Input data was of invalid format. -+ * TEEC_ERROR_BAD_PARAMETERS Input parameters were invalid. -+ * TEEC_ERROR_BAD_STATE Operation is not valid in the current state. -+ * TEEC_ERROR_ITEM_NOT_FOUND The requested data item is not found. -+ * TEEC_ERROR_NOT_IMPLEMENTED The requested operation should exist but is not -+ * yet implemented. -+ * TEEC_ERROR_NOT_SUPPORTED The requested operation is valid but is not -+ * supported in this implementation. -+ * TEEC_ERROR_NO_DATA Expected data was missing. -+ * TEEC_ERROR_OUT_OF_MEMORY System ran out of resources. -+ * TEEC_ERROR_BUSY The system is busy working on something else. -+ * TEEC_ERROR_COMMUNICATION Communication with a remote party failed. -+ * TEEC_ERROR_SECURITY A security fault was detected. -+ * TEEC_ERROR_SHORT_BUFFER The supplied buffer is too short for the -+ * generated output. -+ * TEEC_ERROR_TARGET_DEAD Trusted Application has panicked -+ * during the operation. -+ */ -+ -+/** -+ * Standard defined error codes. -+ */ -+#define TEEC_SUCCESS 0x00000000 -+#define TEEC_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 -+#define TEEC_ERROR_GENERIC 0xFFFF0000 -+#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001 -+#define TEEC_ERROR_CANCEL 0xFFFF0002 -+#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003 -+#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004 -+#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005 -+#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 -+#define TEEC_ERROR_BAD_STATE 0xFFFF0007 -+#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008 -+#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009 -+#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A -+#define TEEC_ERROR_NO_DATA 0xFFFF000B -+#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C -+#define TEEC_ERROR_BUSY 0xFFFF000D -+#define TEEC_ERROR_COMMUNICATION 0xFFFF000E -+#define TEEC_ERROR_SECURITY 0xFFFF000F -+#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 -+#define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011 -+#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 -+#define TEEC_ERROR_STORAGE_NO_SPACE 0xFFFF3041 -+ -+/** -+ * Function error origins, of type TEEC_ErrorOrigin. These indicate where in -+ * the software stack a particular return value originates from. -+ * -+ * TEEC_ORIGIN_API The error originated within the TEE Client API -+ * implementation. -+ * TEEC_ORIGIN_COMMS The error originated within the underlying -+ * communications stack linking the rich OS with -+ * the TEE. -+ * TEEC_ORIGIN_TEE The error originated within the common TEE code. -+ * TEEC_ORIGIN_TRUSTED_APP The error originated within the Trusted Application -+ * code. -+ */ -+#define TEEC_ORIGIN_API 0x00000001 -+#define TEEC_ORIGIN_COMMS 0x00000002 -+#define TEEC_ORIGIN_TEE 0x00000003 -+#define TEEC_ORIGIN_TRUSTED_APP 0x00000004 -+ -+/** -+ * Session login methods, for use in TEEC_OpenSession() as parameter -+ * connectionMethod. Type is uint32_t. -+ * -+ * TEEC_LOGIN_PUBLIC No login data is provided. -+ * TEEC_LOGIN_USER Login data about the user running the Client -+ * Application process is provided. -+ * TEEC_LOGIN_GROUP Login data about the group running the Client -+ * Application process is provided. -+ * TEEC_LOGIN_APPLICATION Login data about the running Client Application -+ * itself is provided. -+ * TEEC_LOGIN_USER_APPLICATION Login data about the user and the running -+ * Client Application itself is provided. -+ * TEEC_LOGIN_GROUP_APPLICATION Login data about the group and the running -+ * Client Application itself is provided. -+ */ -+#define TEEC_LOGIN_PUBLIC 0x00000000 -+#define TEEC_LOGIN_USER 0x00000001 -+#define TEEC_LOGIN_GROUP 0x00000002 -+#define TEEC_LOGIN_APPLICATION 0x00000004 -+#define TEEC_LOGIN_USER_APPLICATION 0x00000005 -+#define TEEC_LOGIN_GROUP_APPLICATION 0x00000006 -+ -+/** -+ * Encode the paramTypes according to the supplied types. -+ * -+ * @param p0 The first param type. -+ * @param p1 The second param type. -+ * @param p2 The third param type. -+ * @param p3 The fourth param type. -+ */ -+#define TEEC_PARAM_TYPES(p0, p1, p2, p3) \ -+ ((p0) | ((p1) << 4) | ((p2) << 8) | ((p3) << 12)) -+ -+/** -+ * Get the i_th param type from the paramType. -+ * -+ * @param p The paramType. -+ * @param i The i-th parameter to get the type for. -+ */ -+#define TEEC_PARAM_TYPE_GET(p, i) (((p) >> (i * 4)) & 0xF) -+ -+typedef uint32_t TEEC_Result; -+ -+/** -+ * struct TEEC_Context - Represents a connection between a client application -+ * and a TEE. -+ */ -+typedef struct { -+ /* Implementation defined */ -+ int fd; -+ bool reg_mem; -+ bool memref_null; -+} TEEC_Context; -+ -+/** -+ * This type contains a Universally Unique Resource Identifier (UUID) type as -+ * defined in RFC4122. These UUID values are used to identify Trusted -+ * Applications. -+ */ -+typedef struct { -+ uint32_t timeLow; -+ uint16_t timeMid; -+ uint16_t timeHiAndVersion; -+ uint8_t clockSeqAndNode[8]; -+} TEEC_UUID; -+ -+/** -+ * struct TEEC_SharedMemory - Memory to transfer data between a client -+ * application and trusted code. -+ * -+ * @param buffer The memory buffer which is to be, or has been, shared -+ * with the TEE. -+ * @param size The size, in bytes, of the memory buffer. -+ * @param flags Bit-vector which holds properties of buffer. -+ * The bit-vector can contain either or both of the -+ * TEEC_MEM_INPUT and TEEC_MEM_OUTPUT flags. -+ * -+ * A shared memory block is a region of memory allocated in the context of the -+ * client application memory space that can be used to transfer data between -+ * that client application and a trusted application. The user of this struct -+ * is responsible to populate the buffer pointer. -+ */ -+typedef struct { -+ void *buffer; -+ size_t size; -+ uint32_t flags; -+ /* -+ * Implementation-Defined -+ */ -+ int id; -+ size_t alloced_size; -+ void *shadow_buffer; -+ int registered_fd; -+ union { -+ bool dummy; -+ uint8_t flags; -+ } internal; -+} TEEC_SharedMemory; -+ -+/** -+ * struct TEEC_TempMemoryReference - Temporary memory to transfer data between -+ * a client application and trusted code, only used for the duration of the -+ * operation. -+ * -+ * @param buffer The memory buffer which is to be, or has been shared with -+ * the TEE. -+ * @param size The size, in bytes, of the memory buffer. -+ * -+ * A memory buffer that is registered temporarily for the duration of the -+ * operation to be called. -+ */ -+typedef struct { -+ void *buffer; -+ size_t size; -+} TEEC_TempMemoryReference; -+ -+/** -+ * struct TEEC_RegisteredMemoryReference - use a pre-registered or -+ * pre-allocated shared memory block of memory to transfer data between -+ * a client application and trusted code. -+ * -+ * @param parent Points to a shared memory structure. The memory reference -+ * may utilize the whole shared memory or only a part of it. -+ * Must not be NULL -+ * -+ * @param size The size, in bytes, of the memory buffer. -+ * -+ * @param offset The offset, in bytes, of the referenced memory region from -+ * the start of the shared memory block. -+ * -+ */ -+typedef struct { -+ TEEC_SharedMemory *parent; -+ size_t size; -+ size_t offset; -+} TEEC_RegisteredMemoryReference; -+ -+/** -+ * struct TEEC_Value - Small raw data container -+ * -+ * Instead of allocating a shared memory buffer this structure can be used -+ * to pass small raw data between a client application and trusted code. -+ * -+ * @param a The first integer value. -+ * -+ * @param b The second value. -+ */ -+typedef struct { -+ uint32_t a; -+ uint32_t b; -+} TEEC_Value; -+ -+/** -+ * union TEEC_Parameter - Memory container to be used when passing data between -+ * client application and trusted code. -+ * -+ * Either the client uses a shared memory reference, parts of it or a small raw -+ * data container. -+ * -+ * @param tmpref A temporary memory reference only valid for the duration -+ * of the operation. -+ * -+ * @param memref The entire shared memory or parts of it. -+ * -+ * @param value The small raw data container to use -+ */ -+typedef union { -+ TEEC_TempMemoryReference tmpref; -+ TEEC_RegisteredMemoryReference memref; -+ TEEC_Value value; -+} TEEC_Parameter; -+ -+/** -+ * struct TEEC_Session - Represents a connection between a client application -+ * and a trusted application. -+ */ -+typedef struct { -+ /* Implementation defined */ -+ TEEC_Context *ctx; -+ uint32_t session_id; -+} TEEC_Session; -+ -+/** -+ * struct TEEC_Operation - Holds information and memory references used in -+ * TEEC_InvokeCommand(). -+ * -+ * @param started Client must initialize to zero if it needs to cancel -+ * an operation about to be performed. -+ * @param paramTypes Type of data passed. Use TEEC_PARAM_TYPES macro to -+ * create the correct flags. -+ * 0 means TEEC_NONE is passed for all params. -+ * @param params Array of parameters of type TEEC_Parameter. -+ * @param session Internal pointer to the last session used by -+ * TEEC_InvokeCommand with this operation. -+ * -+ */ -+typedef struct { -+ uint32_t started; -+ uint32_t paramTypes; -+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; -+ /* Implementation-Defined */ -+ TEEC_Session *session; -+} TEEC_Operation; -+ -+/** -+ * TEEC_InitializeContext() - Initializes a context holding connection -+ * information on the specific TEE, designated by the name string. -+ -+ * @param name A zero-terminated string identifying the TEE to connect to. -+ * If name is set to NULL, the default TEE is connected to. NULL -+ * is the only supported value in this version of the API -+ * implementation. -+ * -+ * @param context The context structure which is to be initialized. -+ * -+ * @return TEEC_SUCCESS The initialization was successful. -+ * @return TEEC_Result Something failed. -+ */ -+TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context); -+ -+/** -+ * TEEC_FinalizeContext() - Destroys a context holding connection information -+ * on the specific TEE. -+ * -+ * This function destroys an initialized TEE context, closing the connection -+ * between the client application and the TEE. This function must only be -+ * called when all sessions related to this TEE context have been closed and -+ * all shared memory blocks have been released. -+ * -+ * @param context The context to be destroyed. -+ */ -+void TEEC_FinalizeContext(TEEC_Context *context); -+ -+/** -+ * TEEC_OpenSession() - Opens a new session with the specified trusted -+ * application. -+ * -+ * @param context The initialized TEE context structure in which -+ * scope to open the session. -+ * @param session The session to initialize. -+ * @param destination A structure identifying the trusted application -+ * with which to open a session. -+ * -+ * @param connectionMethod The connection method to use. -+ * @param connectionData Any data necessary to connect with the chosen -+ * connection method. Not supported, should be set to -+ * NULL. -+ * @param operation An operation structure to use in the session. May -+ * be set to NULL to signify no operation structure -+ * needed. -+ * -+ * @param returnOrigin A parameter which will hold the error origin if -+ * this function returns any value other than -+ * TEEC_SUCCESS. -+ * -+ * @return TEEC_SUCCESS OpenSession successfully opened a new session. -+ * @return TEEC_Result Something failed. -+ * -+ */ -+TEEC_Result TEEC_OpenSession(TEEC_Context *context, -+ TEEC_Session *session, -+ const TEEC_UUID *destination, -+ uint32_t connectionMethod, -+ const void *connectionData, -+ TEEC_Operation *operation, -+ uint32_t *returnOrigin); -+ -+/** -+ * TEEC_CloseSession() - Closes the session which has been opened with the -+ * specific trusted application. -+ * -+ * @param session The opened session to close. -+ */ -+void TEEC_CloseSession(TEEC_Session *session); -+ -+/** -+ * TEEC_InvokeCommand() - Executes a command in the specified trusted -+ * application. -+ * -+ * @param session A handle to an open connection to the trusted -+ * application. -+ * @param commandID Identifier of the command in the trusted application -+ * to invoke. -+ * @param operation An operation structure to use in the invoke command. -+ * May be set to NULL to signify no operation structure -+ * needed. -+ * @param returnOrigin A parameter which will hold the error origin if this -+ * function returns any value other than TEEC_SUCCESS. -+ * -+ * @return TEEC_SUCCESS OpenSession successfully opened a new session. -+ * @return TEEC_Result Something failed. -+ */ -+TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, -+ uint32_t commandID, -+ TEEC_Operation *operation, -+ uint32_t *returnOrigin); -+ -+/** -+ * TEEC_RegisterSharedMemory() - Register a block of existing memory as a -+ * shared block within the scope of the specified context. -+ * -+ * @param context The initialized TEE context structure in which scope to -+ * open the session. -+ * @param sharedMem pointer to the shared memory structure to register. -+ * -+ * @return TEEC_SUCCESS The registration was successful. -+ * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. -+ * @return TEEC_Result Something failed. -+ */ -+TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, -+ TEEC_SharedMemory *sharedMem); -+ -+/** -+ * TEEC_AllocateSharedMemory() - Allocate shared memory for TEE. -+ * -+ * @param context The initialized TEE context structure in which scope to -+ * open the session. -+ * @param sharedMem Pointer to the allocated shared memory. -+ * -+ * @return TEEC_SUCCESS The registration was successful. -+ * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. -+ * @return TEEC_Result Something failed. -+ */ -+TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, -+ TEEC_SharedMemory *sharedMem); -+ -+/** -+ * TEEC_ReleaseSharedMemory() - Free or deregister the shared memory. -+ * -+ * @param sharedMem Pointer to the shared memory to be freed. -+ */ -+void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMemory); -+ -+/** -+ * TEEC_RequestCancellation() - Request the cancellation of a pending open -+ * session or command invocation. -+ * -+ * @param operation Pointer to an operation previously passed to open session -+ * or invoke. -+ */ -+void TEEC_RequestCancellation(TEEC_Operation *operation); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/src/tee_client_api_extensions.h b/src/tee_client_api_extensions.h -new file mode 100644 -index 0000000..85298aa ---- /dev/null -+++ b/src/tee_client_api_extensions.h -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (c) 2016, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef TEE_CLIENT_API_EXTENSIONS_H -+#define TEE_CLIENT_API_EXTENSIONS_H -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * TEEC_RegisterMemoryFileDescriptor() - Register a block of existing memory as -+ * a shared block within the scope of the specified context. -+ * -+ * @param context The initialized TEE context structure in which scope to -+ * open the session. -+ * @param sharedMem pointer to the shared memory structure to register. -+ * @param fd file descriptor of the target memory. -+ * -+ * @return TEEC_SUCCESS The registration was successful. -+ * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. -+ * @return TEEC_Result Something failed. -+ */ -+TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *context, -+ TEEC_SharedMemory *sharedMem, -+ int fd); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* TEE_CLIENT_API_EXTENSIONS_H */ -diff --git a/src/teec_benchmark.h b/src/teec_benchmark.h -new file mode 100644 -index 0000000..17d99ac ---- /dev/null -+++ b/src/teec_benchmark.h -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (c) 2017, Linaro Limited -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef __TEEC_BENCHMARK_H -+#define __TEEC_BENCHMARK_H -+ -+#ifdef CFG_TEE_BENCHMARK -+void bm_timestamp(void); -+#else -+static inline void bm_timestamp(void) {} -+#endif -+ -+#endif /* __TEEC_BENCHMARK_H */ -diff --git a/src/teec_trace.c b/src/teec_trace.c -new file mode 100644 -index 0000000..7194c8c ---- /dev/null -+++ b/src/teec_trace.c -@@ -0,0 +1,141 @@ -+/* -+ * Copyright (c) 2014, STMicroelectronics International N.V. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "teec_trace.h" -+ -+#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -+ -+/* -+ * The length of the prefix is 37, for example it looks like this: -+ * P = Prefix -+ * M = Message -+ * F = Function name -+ * L = Line number -+ * PPPP: MMMMM [FFFFFFFFFFFFFFF : LLLLL] -+ */ -+#define MAX_PRINT_SIZE 256 -+ -+#ifdef TEEC_LOG_FILE -+static void log_to_file(const char *buffer) -+{ -+ FILE *log_file = fopen(TEEC_LOG_FILE, "a"); -+ -+ if (log_file != NULL) { -+ fprintf(log_file, "%s", buffer); -+ fclose(log_file); -+ log_file = NULL; -+ } -+} -+#else -+#define log_to_file(buffer) -+#endif -+ -+static const char * const trace_level_strings[] = { -+ "", "ERR", "INF", "DBG", "FLW" -+}; -+ -+void _dprintf(const char *function, int line, int level, const char *prefix, -+ const char *fmt, ...) -+{ -+ char msg[MAX_PRINT_SIZE]; -+ int n = 0; -+ va_list ap; -+ -+ if (function) { -+ int thread_id = syscall(SYS_gettid); -+ -+ n = snprintf(msg, sizeof(msg), "%s [%d] %s:%s:%d: ", -+ trace_level_strings[level], thread_id, prefix, -+ function, line); -+ if (n < 0) -+ return; -+ } -+ -+ if ((size_t)n < sizeof(msg)) { -+ va_start(ap, fmt); -+ n = vsnprintf(msg + n, sizeof(msg) - n, fmt, ap); -+ va_end(ap); -+ if (n < 0) -+ return; -+ } -+ -+ fprintf(stdout, "%s", msg); -+ log_to_file(msg); -+} -+ -+#if (defined(DEBUGLEVEL_3) || defined(DEBUGLEVEL_true) || defined(DEBUGLEVEL_4)) -+void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen) -+{ -+ fprintf(stderr, "#### %s\n", bname); -+ -+ while (blen > 0) { -+ size_t n = 0; -+ -+ for (n = 0; n < 16; n++) { -+ if (n < blen) -+ fprintf(stderr, "%02x ", (int)buffer[n]); -+ else -+ fprintf(stderr, " "); -+ -+ if (n == 7) -+ fprintf(stderr, " "); -+ } -+ -+ fprintf(stderr, " |"); -+ -+ for (n = 0; n < 16; n++) { -+ if (n < blen) { -+ if (isprint(buffer[n])) -+ fprintf(stderr, "%c", (int)buffer[n]); -+ else -+ fprintf(stderr, "."); -+ } -+ } -+ -+ fprintf(stderr, "|\n"); -+ -+ blen -= MIN(blen, 16); -+ buffer += 16; -+ } -+} -+#else -+void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen) -+{ -+ (void)bname; -+ (void)buffer; -+ (void)blen; -+} -+#endif -diff --git a/src/teec_trace.h b/src/teec_trace.h -new file mode 100644 -index 0000000..b1e37ec ---- /dev/null -+++ b/src/teec_trace.h -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (c) 2014, STMicroelectronics International N.V. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef TEEC_TRACE_H -+#define TEEC_TRACE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#define BINARY_PREFIX "LT" -+ -+#ifndef BINARY_PREFIX -+#error "BINARY_PREFIX not defined" -+#endif -+ -+/* -+ * Trace levels. -+ * -+ * ERROR is used when some kind of error has happened, this is most likely the -+ * print you will use most of the time when you report some kind of error. -+ * -+ * INFO is used when you want to print some 'normal' text to the user. -+ * This is the default level. -+ * -+ * DEBUG is used to print extra information to enter deeply in the module. -+ * -+ * FLOW is used to print the execution flox, typically the in/out of functions. -+ * -+ * */ -+ -+#define TRACE_ERROR 1 -+#define TRACE_INFO 2 -+#define TRACE_DEBUG 3 -+#define TRACE_FLOW 4 -+ -+#if defined(DEBUGLEVEL_0) && !defined(DEBUGLEVEL) -+#define DEBUGLEVEL TRACE_ERROR -+#endif -+ -+#if defined(DEBUGLEVEL_1) && !defined(DEBUGLEVEL) -+#define DEBUGLEVEL TRACE_ERROR -+#endif -+ -+#if defined(DEBUGLEVEL_2) && !defined(DEBUGLEVEL) -+#define DEBUGLEVEL TRACE_INFO -+#endif -+ -+#if defined(DEBUGLEVEL_3) && !defined(DEBUGLEVEL) -+#define DEBUGLEVEL TRACE_DEBUG -+#endif -+ -+#if defined(DEBUGLEVEL_4) && !defined(DEBUGLEVEL) -+#define DEBUGLEVEL TRACE_FLOW -+#endif -+ -+#ifndef DEBUGLEVEL -+/* Default debug level. */ -+#define DEBUGLEVEL TRACE_INFO -+#endif -+ -+/* -+ * This define make sure that parameters are checked in the same manner as it -+ * is done in the normal printf function. -+ */ -+#define __PRINTFLIKE(__fmt, __varargs) __attribute__\ -+ ((__format__(__printf__, __fmt, __varargs))) -+ -+void _dprintf(const char *function, int line, int level, const char *prefix, -+ const char *fmt, ...) __PRINTFLIKE(5, 6); -+ -+#define dprintf(level, x...) do { \ -+ if ((level) <= DEBUGLEVEL) { \ -+ _dprintf(__func__, __LINE__, level, \ -+ BINARY_PREFIX, x); \ -+ } \ -+ } while (0) -+ -+#define EMSG(fmt, ...) dprintf(TRACE_ERROR, fmt "\n", ##__VA_ARGS__) -+#define IMSG(fmt, ...) dprintf(TRACE_INFO, fmt "\n", ##__VA_ARGS__) -+#define DMSG(fmt, ...) dprintf(TRACE_DEBUG, fmt "\n", ##__VA_ARGS__) -+#define FMSG(fmt, ...) dprintf(TRACE_FLOW, fmt "\n", ##__VA_ARGS__) -+ -+#define INMSG(fmt, ...) FMSG("> " fmt, ##__VA_ARGS__) -+#define OUTMSG(fmt, ...) FMSG("< " fmt, ##__VA_ARGS__) -+#define OUTRMSG(r) \ -+ do { \ -+ if (r) \ -+ EMSG("Function returns with [%d]", r); \ -+ OUTMSG("r=[%d]", r); \ -+ return r; \ -+ } while (0) -+ -+#define dprintf_raw(level, x...) do { \ -+ if ((level) <= DEBUGLEVEL) \ -+ _dprintf(0, 0, (level), BINARY_PREFIX, x); \ -+ } while (0) -+ -+#define EMSG_RAW(fmt, ...) dprintf_raw(TRACE_ERROR, fmt, ##__VA_ARGS__) -+#define IMSG_RAW(fmt, ...) dprintf_raw(TRACE_INFO, fmt, ##__VA_ARGS__) -+#define DMSG_RAW(fmt, ...) dprintf_raw(TRACE_DEBUG, fmt, ##__VA_ARGS__) -+#define FMSG_RAW(fmt, ...) dprintf_raw(TRACE_FLOW, fmt, ##__VA_ARGS__) -+ -+/* -+ * This function will hex and ascii dump a buffer. -+ * -+ * Note that this function will only print if debug flag -+ * DEBUGLEVEL is INFO or FLOOD. -+ * -+ * @param bname Information string describing the buffer. -+ * @param buffer Pointer to the buffer. -+ * @param blen Length of the buffer. -+ * -+ * @return void -+ */ -+void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/src/uboot_env.c b/src/uboot_env.c -index d507cac..aa33930 100644 ---- a/src/uboot_env.c -+++ b/src/uboot_env.c -@@ -42,6 +42,9 @@ - #include "md5.h" - #include "uboot_private.h" - -+#include -+#include -+ - /* - * The BLOB includes a random AES-256 key (32 bytes) and a - * Message Authentication Code (MAC) (16 bytes) -@@ -1156,7 +1159,7 @@ static bool machine_is_compatible(char *machine) - } - - #define MAX_HWID_WORDS 4 --static int env_caam_get_keymod(unsigned char output[16]) -+static int env_encryption_get_keymod(unsigned char output[16]) - { - int i; - int len; -@@ -1224,7 +1227,7 @@ static int env_caam_crypt(char *data, unsigned int size, const int enc) - char *buffer; - unsigned char key_modifier[16]; - -- ret = env_caam_get_keymod(key_modifier); -+ ret = env_encryption_get_keymod(key_modifier); - if (ret) - return ret; - -@@ -1271,6 +1274,165 @@ free: - return ret; - } - -+void prepare_tee_session(struct aes_ctx *ctx) -+{ -+ TEEC_Result ret; -+ uint32_t origin; -+ TEEC_UUID uuid = TA_STM32MP_CRYP_UUID; -+ -+ ret = TEEC_InitializeContext(NULL, &ctx->ctx); -+ if (ret != TEEC_SUCCESS) -+ printf("TEEC_InitializeContext failed with code 0x%x", ret); -+ -+ /* Open a session with the TA */ -+ ret = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid, -+ TEEC_LOGIN_PUBLIC, NULL, NULL, &origin); -+ if (ret != TEEC_SUCCESS) -+ printf("TEEC_Opensession failed with code 0x%x origin 0x%x", -+ ret, origin); -+ -+} -+ -+void terminate_tee_session(struct aes_ctx *ctx) -+{ -+ TEEC_CloseSession(&ctx->sess); -+ TEEC_FinalizeContext(&ctx->ctx); -+} -+ -+void prepare_aes(struct aes_ctx *ctx, int encode) -+{ -+ TEEC_Operation op; -+ uint32_t origin; -+ TEEC_Result res; -+ -+ memset(&op, 0, sizeof(op)); -+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, -+ TEEC_VALUE_INPUT, -+ TEEC_VALUE_INPUT, -+ TEEC_NONE); -+ -+ op.params[0].value.a = TA_AES_ALGO_CTR; -+ op.params[1].value.a = AES128_KEY_LENGTH; -+ op.params[2].value.a = encode ? TA_AES_MODE_ENCODE : -+ TA_AES_MODE_DECODE; -+ -+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_PREPARE, -+ &op, &origin); -+ if (res != TEEC_SUCCESS) -+ printf("TEEC_InvokeCommand(PREPARE) failed 0x%x origin 0x%x", -+ res, origin); -+} -+ -+void set_key(struct aes_ctx *ctx, size_t key_sz) -+{ -+ TEEC_Operation op; -+ uint32_t origin; -+ TEEC_Result res; -+ -+ memset(&op, 0, sizeof(op)); -+ -+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, -+ TEEC_NONE, TEEC_NONE, TEEC_NONE); -+ -+ op.params[0].value.a = key_sz; -+ -+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_KEY, -+ &op, &origin); -+ if (res != TEEC_SUCCESS) -+ printf("TEEC_InvokeCommand(SET_KEY) failed 0x%x origin 0x%x", -+ res, origin); -+} -+ -+void set_iv(struct aes_ctx *ctx, char *iv, size_t iv_sz) -+{ -+ TEEC_Operation op; -+ uint32_t origin; -+ TEEC_Result res; -+ -+ memset(&op, 0, sizeof(op)); -+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, -+ TEEC_NONE, TEEC_NONE, TEEC_NONE); -+ op.params[0].tmpref.buffer = iv; -+ op.params[0].tmpref.size = iv_sz; -+ -+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_IV, -+ &op, &origin); -+ if (res != TEEC_SUCCESS) -+ printf("TEEC_InvokeCommand(SET_IV) failed 0x%x origin 0x%x", -+ res, origin); -+} -+ -+void cipher_buffer(struct aes_ctx *ctx, char *in, char *out, size_t sz) -+{ -+ TEEC_Operation op; -+ uint32_t origin; -+ TEEC_Result res; -+ -+ memset(&op, 0, sizeof(op)); -+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, -+ TEEC_MEMREF_TEMP_OUTPUT, -+ TEEC_NONE, TEEC_NONE); -+ op.params[0].tmpref.buffer = in; -+ op.params[0].tmpref.size = sz; -+ op.params[1].tmpref.buffer = out; -+ op.params[1].tmpref.size = sz; -+ -+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_CIPHER, -+ &op, &origin); -+ if (res != TEEC_SUCCESS) -+ printf("TEEC_InvokeCommand(CIPHER) failed 0x%x origin 0x%x", -+ res, origin); -+} -+ -+static int env_ccmp1_crypt(char *data, unsigned int size, const int enc) -+{ -+ int ret, i; -+ uint32_t origin; -+ struct aes_ctx *aes; -+ char *iv, *ciph; -+ TEEC_UUID uuid = TA_STM32MP_CRYP_UUID; -+ unsigned char key_modifier[16]; -+ -+ /* Allocate all the buffer */ -+ iv = calloc(AES_BLOCK_LENGTH, sizeof(char)); -+ ciph = calloc(size+1, sizeof(unsigned int)); -+ -+ if (!iv || !ciph) { -+ printf("%s: can't allocate memory\n", __func__); -+ ret = -ENOMEM; -+ goto err_free_buffs; -+ } -+ -+ /* Get key_modifer for IV */ -+ ret = env_encryption_get_keymod(key_modifier); -+ if (ret) -+ return ret; -+ -+ memcpy(iv, key_modifier, AES_BLOCK_LENGTH); -+ aes = (struct aes_ctx*)malloc(sizeof(struct aes_ctx)); -+ if (aes == NULL) { -+ printf("%s: can't allocate context memory\n", __func__); -+ ret = -ENOMEM; -+ } else { -+ prepare_tee_session(aes); -+ -+ prepare_aes(aes, enc); -+ set_key(aes, AES128_KEY_LENGTH); -+ set_iv(aes, iv, AES_BLOCK_LENGTH); -+ memset(ciph, 0, size); -+ cipher_buffer(aes, data, ciph, size); -+ /* copy ciphered data */ -+ memcpy(data, ciph, size); -+ free(aes); -+ } -+ -+err_free_buffs: -+ free(iv); -+ free(ciph); -+ -+ return ret; -+} -+ - int libuboot_env_store(struct uboot_ctx *ctx) - { - struct var_entry *entry; -@@ -1347,7 +1509,12 @@ int libuboot_env_store(struct uboot_ctx *ctx) - } - - if (ctx->encrypted) { -- ret = env_caam_crypt(data, ctx->usable_size, 1); -+ /* Detect the platform */ -+ if (machine_is_compatible("digi,ccmp15") || -+ machine_is_compatible("digi,ccmp13")) -+ ret = env_ccmp1_crypt(data, ctx->usable_size, 1); -+ else -+ ret = env_caam_crypt(data, ctx->usable_size, 1); - if (ret) { - fprintf(stderr, - "Error: can't encrypt env for flash\n"); -@@ -1420,7 +1587,12 @@ static int libuboot_load(struct uboot_ctx *ctx) - crc = *(uint32_t *)(buf[i] + offsetcrc); - dev->crc = crc32(0, (uint8_t *)data, usable_envsize); - if (ctx->encrypted) { -- ret = env_caam_crypt((char *)data, ctx->usable_size, 0); -+ /* Detect the platform */ -+ if (machine_is_compatible("digi,ccmp15") || -+ machine_is_compatible("digi,ccmp13")) -+ ret = env_ccmp1_crypt((char *)data, ctx->usable_size, 0); -+ else -+ ret = env_caam_crypt((char *)data, ctx->usable_size, 0); - if (ret) { - fprintf(stderr, "Error: can't decrypt environment\n"); - return ret; diff --git a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv_%.bbappend b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv_%.bbappend index 5ff1b39e6..3a0ee0f8d 100644 --- a/meta-digi-arm/recipes-bsp/libubootenv/libubootenv_%.bbappend +++ b/meta-digi-arm/recipes-bsp/libubootenv/libubootenv_%.bbappend @@ -15,13 +15,18 @@ FW_CONFIG_FILE:ccmp1 = "${@bb.utils.contains('IMAGE_FEATURES', 'read-only-rootfs 'ubi/fw_env.config_default', \ 'ubi/fw_env.config', d)}" +DEPENDS += "${@oe.utils.conditional('OPTEE_PATCHES', '', '', 'optee-client', d)}" + +OPTEE_PATCHES = "" +OPTEE_PATCHES:ccimx93 = "file://0004-Implement-support-for-environment-encryption-using-O.patch" +OPTEE_PATCHES:ccmp1 = "file://0004-Implement-support-for-environment-encryption-using-O.patch" + SRC_URI += " \ file://${FW_CONFIG_FILE} \ - file://0001-Implement-support-for-environment-encryption-by-CAAM.patch \ - file://0002-Implement-U-Boot-environment-access-functions.patch \ - file://0003-tools-env-add-support-to-set-dynamic-location-of-env.patch \ - file://0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch \ - file://0005-Implement-support-for-environment-encryption-for-CCM.patch \ + file://0001-Implement-U-Boot-environment-access-functions.patch \ + file://0002-tools-env-add-support-to-set-dynamic-location-of-env.patch \ + file://0003-Implement-support-for-environment-encryption-by-CAAM.patch \ + ${@bb.utils.contains('MACHINE_FEATURES', 'optee', '${OPTEE_PATCHES}', '', d)} \ " do_install:append() {