pax_global_header00006660000000000000000000000064145515007120014512gustar00rootroot0000000000000052 comment=f7e4ced15d1fefd073bbfc484fe0e1f74afe96c2 optee_client-4.1.0/000077500000000000000000000000001455150071200141665ustar00rootroot00000000000000optee_client-4.1.0/.github/000077500000000000000000000000001455150071200155265ustar00rootroot00000000000000optee_client-4.1.0/.github/workflows/000077500000000000000000000000001455150071200175635ustar00rootroot00000000000000optee_client-4.1.0/.github/workflows/ci.yml000066400000000000000000000034631455150071200207070ustar00rootroot00000000000000name: CI on: [push, pull_request] permissions: contents: read # to fetch code (actions/checkout) jobs: debian: name: build (Debian) runs-on: ubuntu-latest container: jforissier/optee_client_ci_debian steps: - name: Checkout uses: actions/checkout@v3 - name: arm64 with make run: make -j O=out-make-aarch64 CROSS_COMPILE=aarch64-linux-gnu- - name: armhf with make run: make -j O=out-make-armhf CROSS_COMPILE=arm-linux-gnueabihf- - name: arm64 with cmake run: | set -e -v mkdir out-cmake-aarch64 && cd out-cmake-aarch64 PKG_CONFIG=aarch64-linux-gnu-pkg-config cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc make -j - name: armhf with cmake run: | set -e -v mkdir out-cmake-armhf && cd out-cmake-armhf PKG_CONFIG=arm-linux-gnueabihf-pkg-config cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc make -j ubuntu: name: build (Ubuntu) runs-on: ubuntu-latest container: jforissier/optee_client_ci_ubuntu steps: - name: Checkout uses: actions/checkout@v3 - name: arm64 with make run: make -j O=out-make-aarch64 CROSS_COMPILE=aarch64-linux-gnu- - name: armhf with make run: make -j O=out-make-armhf CROSS_COMPILE=arm-linux-gnueabihf- - name: arm64 with cmake run: | set -e -v mkdir out-cmake-aarch64 && cd out-cmake-aarch64 PKG_CONFIG=aarch64-linux-gnu-pkg-config cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc make -j - name: armhf with cmake run: | set -e -v mkdir out-cmake-armhf && cd out-cmake-armhf PKG_CONFIG=arm-linux-gnueabihf-pkg-config cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc make -j optee_client-4.1.0/.github/workflows/stales.yml000066400000000000000000000023651455150071200216070ustar00rootroot00000000000000name: 'Close stale issues and pull requests with no recent activity' on: schedule: - cron: "15 00 * * *" permissions: issues: write pull-requests: write jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v4.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' stale-pr-message: 'This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' stale-issue-label: Stale stale-pr-label: Stale exempt-issue-labels: bug,enhancement exempt-pr-labels: bug,enhancement days-before-stale: 30 days-before-close: 5 remove-stale-when-updated: true remove-issue-stale-when-updated: true remove-pr-stale-when-updated: true optee_client-4.1.0/Android.mk000066400000000000000000000071211455150071200161000ustar00rootroot00000000000000################################################################################ # Android optee-client, libckteec and optee-supplicant makefile # ################################################################################ LOCAL_PATH := $(call my-dir) # 3 (debug) is too noisy CFG_TEE_CLIENT_LOG_LEVEL ?= 2 CFG_TEE_SUPP_LOG_LEVEL ?= 2 # Define Android-specific configuration before including config.mk CFG_TEE_CLIENT_LOAD_PATH ?= /vendor/lib CFG_TEE_FS_PARENT_PATH ?= /data/vendor/tee CFG_TEE_SUPP_PLUGINS ?= y ifneq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),) CFG_TEE_PLUGIN_LOAD_PATH ?= /vendor/lib64/tee-supplicant/plugins/ else CFG_TEE_PLUGIN_LOAD_PATH ?= /vendor/lib/tee-supplicant/plugins/ endif $(info CFG_TEE_PLUGIN_LOAD_PATH = ${CFG_TEE_PLUGIN_LOAD_PATH}) ################################################################################ # Include optee-client common config and flags # ################################################################################ include $(LOCAL_PATH)/config.mk include $(LOCAL_PATH)/android_flags.mk optee_CFLAGS = $(CFLAGS) ################################################################################ # Build libteec.so - TEE (Trusted Execution Environment) shared library # ################################################################################ include $(CLEAR_VARS) LOCAL_CFLAGS += $(optee_CFLAGS) ifneq ($(CFG_TEE_CLIENT_LOG_FILE),) LOCAL_CFLAGS += -DTEEC_LOG_FILE=\"$(CFG_TEE_CLIENT_LOG_FILE)\" endif LOCAL_CFLAGS += -DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) LOCAL_CFLAGS += -DBINARY_PREFIX=\"TEEC\" LOCAL_SRC_FILES := libteec/src/tee_client_api.c \ libteec/src/teec_trace.c ifeq ($(CFG_TEE_BENCHMARK),y) LOCAL_CFLAGS += -DCFG_TEE_BENCHMARK LOCAL_SRC_FILES += teec_benchmark.c endif LOCAL_C_INCLUDES := $(LOCAL_PATH)/libteec/include LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libteec LOCAL_MODULE_TAGS := optional LOCAL_VENDOR_MODULE := true # Build the 32-bit and 64-bit versions. LOCAL_MULTILIB := both LOCAL_MODULE_TARGET_ARCH := arm arm64 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libteec/include include $(BUILD_SHARED_LIBRARY) ################################################################################ # Build libckteec.so # ################################################################################ include $(CLEAR_VARS) LOCAL_CFLAGS += $(optee_CFLAGS) LOCAL_SRC_FILES := libckteec/src/pkcs11_api.c \ libckteec/src/ck_debug.c \ libckteec/src/ck_helpers.c \ libckteec/src/invoke_ta.c \ libckteec/src/pkcs11_processing.c \ libckteec/src/pkcs11_token.c \ libckteec/src/serializer.c \ libckteec/src/serialize_ck.c LOCAL_C_INCLUDES := $(LOCAL_PATH)/libteec/include \ $(LOCAL_PATH)/libckteec/include LOCAL_SHARED_LIBRARIES := libteec LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libckteec LOCAL_MODULE_TAGS := optional LOCAL_VENDOR_MODULE := true # Build the 32-bit and 64-bit versions. LOCAL_MULTILIB := both LOCAL_MODULE_TARGET_ARCH := arm arm64 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libckteec/include include $(BUILD_SHARED_LIBRARY) ################################################################################ # Build TEE Supplicant # ################################################################################ include $(LOCAL_PATH)/tee-supplicant/tee_supplicant_android.mk optee_client-4.1.0/CMakeLists.txt000066400000000000000000000030451455150071200167300ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.4) project(optee_client C) # https://cmake.org/Wiki/CMake_Useful_Variables set(CMAKE_TOOLCHAIN_FILE CMakeToolchain.txt) option(CFG_WERROR "Build with -Werror" TRUE) option(WITH_TEEACL "Build libteeacl" TRUE) include(GNUInstallDirs) ################################################################################ # Compiler flags: # We want to use the same flags in the entire optee_client git ################################################################################ add_compile_options( -Wall -Wbad-function-cast -Wcast-align -Werror-implicit-function-declaration -Wextra -Wfloat-equal -Wformat-nonliteral -Wformat-security -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wshadow -Wstrict-prototypes -Wswitch-default -Wwrite-strings -fPIC ) if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") add_compile_options( -Wunsafe-loop-optimizations ) endif() if(CFG_WERROR) add_compile_options(-Werror) endif(CFG_WERROR) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) endif(CCACHE_FOUND) add_subdirectory(libteec) add_subdirectory(tee-supplicant) add_subdirectory(libckteec) if(WITH_TEEACL) find_package(PkgConfig REQUIRED) pkg_check_modules(uuid REQUIRED IMPORTED_TARGET uuid) add_subdirectory(libteeacl) endif(WITH_TEEACL) add_subdirectory(libseteec) optee_client-4.1.0/CMakeToolchain.txt000066400000000000000000000001001455150071200175370ustar00rootroot00000000000000set (CMAKE_SYSTEM_NAME Linux) set (CMAKE_SYSTEM_PROCESSOR arm) optee_client-4.1.0/LICENSE000066400000000000000000000026101455150071200151720ustar00rootroot00000000000000Unless it has its own copyright/license embedded in its body, each source file is subject to the following license terms: 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. optee_client-4.1.0/Makefile000066400000000000000000000147231455150071200156350ustar00rootroot00000000000000# Public variables are stored in config.mk include ./config.mk ######################################################################### # Set Internal Variables # # May be modified to match your setup # ######################################################################### ifneq ($(V),1) VPREFIX := @ endif export VPREFIX EXPORT_DIR ?= $(O)/export DESTDIR ?= $(EXPORT_DIR) SBINDIR ?= /usr/sbin LIBDIR ?= /usr/lib INCLUDEDIR ?= /usr/include sbindir ?= $(SBINDIR) libdir ?= $(LIBDIR) includedir ?= $(INCLUDEDIR) WITH_TEEACL ?= 1 .PHONY: all build build-libteec build-libckteec build-libseteec \ build-libteeacl install copy_export clean cscope \ clean-cscope \ checkpatch-pre-req checkpatch-modified-patch checkpatch-modified-file \ checkpatch-last-commit-patch checkpatch-last-commit-file \ checkpatch-base-commit-patch checkpatch-base-commit-file \ checkpatch-all-files distclean all: build install build-libteec: @echo "Building libteec.so" @$(MAKE) --directory=libteec --no-print-directory --no-builtin-variables \ CFG_TEE_BENCHMARK=$(CFG_TEE_BENCHMARK) CFG_TEE_CLIENT_LOG_LEVEL=$(CFG_TEE_CLIENT_LOG_LEVEL) build-tee-supplicant: build-libteec @echo "Building tee-supplicant" $(MAKE) --directory=tee-supplicant --no-print-directory --no-builtin-variables CFG_TEE_SUPP_LOG_LEVEL=$(CFG_TEE_SUPP_LOG_LEVEL) build: build-libteec build-tee-supplicant build-libckteec build-libseteec ifeq ($(WITH_TEEACL),1) build: build-libteeacl endif build-libckteec: build-libteec @echo "Building libckteec.so" @$(MAKE) --directory=libckteec --no-print-directory --no-builtin-variables build-libseteec: build-libteec @echo "Building libseteec.so" @$(MAKE) --directory=libseteec --no-print-directory --no-builtin-variables build-libteeacl: @echo "Building libteeacl.so" @$(MAKE) --directory=libteeacl --no-print-directory --no-builtin-variables install: copy_export clean: clean-libteec clean-tee-supplicant clean-cscope clean-libckteec \ clean-libseteec ifeq ($(WITH_TEEACL),1) clean: clean-libteeacl endif clean-libteec: @$(MAKE) --directory=libteec --no-print-directory clean clean-tee-supplicant: @$(MAKE) --directory=tee-supplicant --no-print-directory clean clean-libckteec: @$(MAKE) --directory=libckteec --no-print-directory clean clean-libseteec: @$(MAKE) --directory=libseteec --no-print-directory clean clean-libteeacl: @$(MAKE) --directory=libteeacl --no-print-directory clean cscope: @echo " CSCOPE" ${VPREFIX}find ${CURDIR} -name "*.[chsS]" > cscope.files ${VPREFIX}cscope -b -q -k clean-cscope: ${VPREFIX}rm -f cscope.* # Various checkpatch targets. The ones ending with "patch" only considers the # patch, whilst the ones ending with "file" checks the complete file. # +-------------------------------+------------+----------------------------+ # | Target commit | File/Patch | Comment | # +-------------------------------+------------+----------------------------+ # | checkpatch-modified-patch | Patch | Check local modifications | # +-------------------------------+------------+----------------------------+ # | checkpatch-modified-file | File | Check Local modifications | # +-------------------------------+------------+----------------------------+ # | checkpatch-last-commit-patch | Patch | Check against HEAD^ | # +-------------------------------+------------+----------------------------+ # | checkpatch-last-commit-file | File | Check against HEAD^ | # +-------------------------------+------------+----------------------------+ # | checkpatch-base-commit-patch | Patch | Against specic commit | # +-------------------------------+------------+----------------------------+ # | checkpatch-base-commit-file | File | Against specic commit | # +-------------------------------+------------+----------------------------+ # | checkpatch-all-files | File | Check all tracked files | # +-------------------------------+------------+----------------------------+ CHECKPATCH_IGNORE ?= --ignore NEW_TYPEDEFS --no-signoff CHECKPATCH_STRICT ?= --strict CHECKPATCH_ARGS ?= $(CHECKPATCH_IGNORE) $(CHECKPATCH_STRICT) --no-tree --terse CHECKPATCH_PATCH_ARGS := $(CHECKPATCH_ARGS) --patch CHECKPATCH_FILE_ARGS := $(CHECKPATCH_ARGS) --file --no-patch checkpatch-pre-req: @echo " CHECKPATCH" ifndef CHECKPATCH $(error "Environment variable CHECKPATCH must point to Linux kernels checkpatch script") else ifeq (,$(wildcard ${CHECKPATCH})) $(error "CHECKPATCH points to the incorrect file") endif endif checkpatch-modified-patch: checkpatch-pre-req ${VPREFIX}git diff | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true checkpatch-modified-file: checkpatch-pre-req ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only) checkpatch-last-commit-patch: checkpatch-pre-req ${VPREFIX}git diff HEAD^ | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true checkpatch-last-commit-file: checkpatch-pre-req ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only HEAD^) checkpatch-base-commit-patch: checkpatch-pre-req ifndef BASE_COMMIT $(error "Environment variable BASE_COMMIT must contain a valid commit") endif ${VPREFIX}git diff $(BASE_COMMIT) | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true checkpatch-base-commit-file: checkpatch-pre-req ifndef BASE_COMMIT $(error "Environment variable BASE_COMMIT must contain a valid commit") endif ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only ${BASE_COMMIT}) checkpatch-all-files: checkpatch-pre-req ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git ls-files) distclean: clean copy_export: build mkdir -p $(DESTDIR)$(sbindir) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) cp config.mk $(DESTDIR)/$(includedir)/optee_client_config.mk cp -d ${O}/libteec/libteec.so* $(DESTDIR)$(libdir) cp -d ${O}/libteec/libteec.a $(DESTDIR)$(libdir) cp ${O}/tee-supplicant/tee-supplicant $(DESTDIR)$(sbindir) cp libteec/include/*.h $(DESTDIR)$(includedir) cp libckteec/include/*.h $(DESTDIR)$(includedir) cp -d ${O}/libckteec/libckteec.so* $(DESTDIR)$(libdir) cp -d ${O}/libckteec/libckteec.a $(DESTDIR)$(libdir) ifeq ($(WITH_TEEACL),1) cp libteeacl/include/*.h $(DESTDIR)$(includedir) cp -d ${O}/libteeacl/libteeacl.so* $(DESTDIR)$(libdir) cp -d ${O}/libteeacl/libteeacl.a $(DESTDIR)$(libdir) endif cp libseteec/include/*.h $(DESTDIR)$(includedir) cp -d ${O}/libseteec/libseteec.so* $(DESTDIR)$(libdir) cp -d ${O}/libseteec/libseteec.a $(DESTDIR)$(libdir) optee_client-4.1.0/README.md000066400000000000000000000006651455150071200154540ustar00rootroot00000000000000# OP-TEE Client API This git contains source code for the non-secure side implementation of the OP-TEE project making up the client library and tee-supplicant. All official OP-TEE documentation has moved to http://optee.readthedocs.io. The information that used to be here in this git can be found under [optee_client]. // OP-TEE core maintainers [optee_client]: https://optee.readthedocs.io/en/latest/building/gits/optee_client.html optee_client-4.1.0/android_flags.mk000066400000000000000000000016441455150071200173200ustar00rootroot00000000000000######################################################################### # COMMON COMPILATION FLAGS # ######################################################################### CFLAGS := -Wall -Wbad-function-cast -Wcast-align \ -Werror-implicit-function-declaration -Wextra \ -Wfloat-equal -Wformat-nonliteral -Wformat-security \ -Wformat=2 -Winit-self -Wmissing-declarations \ -Wmissing-format-attribute -Wmissing-include-dirs \ -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs \ -Wpointer-arith -Wshadow -Wstrict-prototypes \ -Wswitch-default \ -Wwrite-strings ifeq ($(CFG_WERROR),y) CFLAGS += -Werror endif CFLAGS += -c -fPIC DEBUG ?= 0 ifeq ($(DEBUG), 1) CFLAGS += -DDEBUG -O0 -g endif RM := rm -rf define rmdir if [ -d "$(1)" ] ; then rmdir --ignore-fail-on-non-empty $(1) ; fi endef optee_client-4.1.0/ci/000077500000000000000000000000001455150071200145615ustar00rootroot00000000000000optee_client-4.1.0/ci/Dockerfile.debian000066400000000000000000000006531455150071200200000ustar00rootroot00000000000000# Dockerfile for CI image used in ../.github/workflows/ci.yml FROM debian:bullseye-slim MAINTAINER Jerome Forissier ENV LANG=C.UTF-8 RUN dpkg --add-architecture armhf RUN dpkg --add-architecture arm64 RUN apt update RUN apt upgrade -y RUN apt install -y \ cmake \ dpkg-dev \ gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabihf \ make \ pkg-config \ uuid-dev:armhf \ uuid-dev:arm64 optee_client-4.1.0/ci/Dockerfile.ubuntu000066400000000000000000000030121455150071200200700ustar00rootroot00000000000000# Dockerfile for CI image used in ../.github/workflows/ci.yml FROM ubuntu:22.04 MAINTAINER Jerome Forissier ENV LANG=C.UTF-8 RUN dpkg --add-architecture armhf RUN dpkg --add-architecture arm64 RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse' > /etc/apt/sources.list RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted universe multiverse' >> /etc/apt/sources.list RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse' >> /etc/apt/sources.list RUN apt update RUN apt upgrade -y RUN apt install -y \ cmake \ dpkg-dev \ gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabihf \ make \ pkg-config \ uuid-dev:armhf \ uuid-dev:arm64 optee_client-4.1.0/config.mk000066400000000000000000000053031455150071200157650ustar00rootroot00000000000000######################################################################### # Public variables # # Developers may override these values when calling the makefile, # # as for example # # CFG_TEE_CLIENT_LOG_LEVEL=1 make # # Note: # # Please do not use export to declare the variables, so that to avoid # # compiling problem for android platform # ######################################################################### # CFG_TEE_CLIENT_LOG_LEVEL # Client (User Non Secure) log level # Supported values: 0 (no traces) to 4 (all traces) CFG_TEE_CLIENT_LOG_LEVEL?=1 # CFG_TEE_SUPP_LOG_LEVEL # Supplicant log level # Supported values: 0 (no traces) to 4 (all traces) CFG_TEE_SUPP_LOG_LEVEL?=1 # CFG_TEE_FS_PARENT_PATH # Path to folder that will contain TEE filesystem. # This folder can be created with the required permission in an init # script during boot, else it will be created by the tee-supplicant on # first REE FS access. CFG_TEE_FS_PARENT_PATH ?= /data/tee # CFG_TEE_CLIENT_LOG_FILE # The location of the client log file when logging to file is enabled. CFG_TEE_CLIENT_LOG_FILE ?= $(CFG_TEE_FS_PARENT_PATH)/teec.log # CFG_TEE_CLIENT_LOAD_PATH # Colon-separated list of paths where tee-supplicant loads TAs from. # For example: CFG_TEE_CLIENT_LOAD_PATH ?= /lib:/vendor/lib # Note that the TA files are typically in a sub-directory (see the # --ta-dir option). CFG_TEE_CLIENT_LOAD_PATH ?= /lib # CFG_TEE_SUPP_PLUGINS # Enable (y) or disable (n) TEE supplicant plugin support CFG_TEE_SUPP_PLUGINS ?= y # CFG_TEE_PLUGIN_LOAD_PATH # The location of the user plugins CFG_TEE_PLUGIN_LOAD_PATH ?= /usr/lib/tee-supplicant/plugins/ # CFG_GP_SOCKETS # Enable Global Platform Sockets support CFG_GP_SOCKETS ?= y # CFG_TA_GPROF_SUPPORT # Enable dumping gprof data, not used unless secure world decides # to dump something CFG_TA_GPROF_SUPPORT ?= y # CFG_FTRACE_SUPPORT # Enable dumping ftrace data, not used unless secure world decides # to dump something CFG_FTRACE_SUPPORT ?= y # Default output directory. # May be absolute, or relative to the optee_client source directory. O ?= out # To be used instead of $(O) in sub-directories OO := $(if $(filter /%,$(O)),$(O),$(CURDIR)/../$(O)) ######################################################################### # Private Values # ######################################################################### # Check that settings are coherent. optee_client-4.1.0/flags.mk000066400000000000000000000023361455150071200156170ustar00rootroot00000000000000######################################################################### # COMMON COMPILATION FLAGS # ######################################################################### CROSS_COMPILE ?= arm-linux-gnueabihf- CC ?= $(CROSS_COMPILE)gcc AR ?= $(CROSS_COMPILE)ar PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config C_COMPILER=$(shell readlink -f $$(which $(CC))) override CFLAGS += -Wall -Wbad-function-cast -Wcast-align \ -Werror-implicit-function-declaration -Wextra \ -Wfloat-equal -Wformat-nonliteral -Wformat-security \ -Wformat=2 -Winit-self -Wmissing-declarations \ -Wmissing-format-attribute -Wmissing-include-dirs \ -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs \ -Wpointer-arith -Wshadow -Wstrict-prototypes \ -Wswitch-default -Wwrite-strings -D_FILE_OFFSET_BITS=64 ifneq (,$(findstring gcc,$(C_COMPILER))) override CFLAGS += -Wunsafe-loop-optimizations endif ifeq ($(CFG_WERROR),y) override CFLAGS += -Werror endif override CFLAGS += -c -fPIC DEBUG ?= 0 ifeq ($(DEBUG), 1) override CFLAGS += -DDEBUG -O0 -g endif RM := rm -f define rmdir if [ -d "$(1)" ] ; then rmdir --ignore-fail-on-non-empty $(1) ; fi endef optee_client-4.1.0/libckteec/000077500000000000000000000000001455150071200161135ustar00rootroot00000000000000optee_client-4.1.0/libckteec/CMakeLists.txt000066400000000000000000000042331455150071200206550ustar00rootroot00000000000000project(ckteec VERSION 0.1.0 LANGUAGES C) ################################################################################ # Packages ################################################################################ find_package(Threads REQUIRED) if(NOT THREADS_FOUND) message(FATAL_ERROR "Threads not found") endif() include(GNUInstallDirs) ################################################################################ # Source files ################################################################################ set(SRC src/pkcs11_api.c src/ck_debug.c src/ck_helpers.c src/invoke_ta.c src/pkcs11_processing.c src/pkcs11_token.c src/serializer.c src/serialize_ck.c ) ################################################################################ # Built library ################################################################################ add_library(ckteec ${SRC}) set_target_properties(ckteec PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) ################################################################################ # Flags always set ################################################################################ target_compile_definitions(ckteec PRIVATE -D_GNU_SOURCE PRIVATE -DBINARY_PREFIX="LT" ) ################################################################################ # Optional flags ################################################################################ ################################################################################ # Public and private header and library dependencies ################################################################################ target_include_directories(ckteec PUBLIC $ $ PRIVATE src ) target_include_directories(teec PUBLIC include ) target_link_libraries(ckteec PRIVATE pthread PRIVATE teec PRIVATE m ) ################################################################################ # Install targets ################################################################################ install(TARGETS ckteec DESTINATION ${CMAKE_INSTALL_LIBDIR} ) add_subdirectory(include) optee_client-4.1.0/libckteec/Makefile000066400000000000000000000043701455150071200175570ustar00rootroot00000000000000include ../flags.mk include ../config.mk OUT_DIR := $(OO)/libckteec .PHONY: all libckteec clean all: libckteec install: libckteec LIB_NAME := libckteec MAJOR_VERSION := 0 MINOR_VERSION := 1 PATCH_VERSION := 0 LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) LIBCKTEEC_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) LIBCKTEEC_AR_LIBRARY := $(LIB_NAME).a LIBCKTEEC_SRC_DIR := src LIBCKTEEC_SRCS = pkcs11_api.c LIBCKTEEC_SRCS += ck_debug.c LIBCKTEEC_SRCS += ck_helpers.c LIBCKTEEC_SRCS += invoke_ta.c LIBCKTEEC_SRCS += pkcs11_processing.c LIBCKTEEC_SRCS += pkcs11_token.c LIBCKTEEC_SRCS += serializer.c LIBCKTEEC_SRCS += serialize_ck.c LIBCKTEEC_INCLUDES = ${CURDIR}/include LIBCKTEEC_INCLUDES += ${CURDIR}/../libteec/include LIBCKTEEC_CFLAGS := $(addprefix -I, $(LIBCKTEEC_INCLUDES)) \ $(CFLAGS) -D_GNU_SOURCE -fPIC LIBCKTEEC_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec LIBCKTEEC_OBJ_DIR := $(OUT_DIR) LIBCKTEEC_OBJS := $(patsubst %.c,$(LIBCKTEEC_OBJ_DIR)/%.o, $(LIBCKTEEC_SRCS)) $(LIBCKTEEC_OBJ_DIR)/%.o: ${LIBCKTEEC_SRC_DIR}/%.c $(VPREFIX)mkdir -p $(LIBCKTEEC_OBJ_DIR) @echo " CC $<" $(VPREFIX)$(CC) $(LIBCKTEEC_CFLAGS) -c $< -o $@ libckteec: $(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY) $(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY): $(LIBCKTEEC_OBJS) @echo " LINK $@" $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(LIBCKTEEC_LFLAGS) @echo "" libckteec: $(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY) $(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY): $(LIBCKTEEC_OBJS) @echo " AR $@" $(VPREFIX)$(AR) rcs $@ $+ libckteec: $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so ################################################################################ # Cleaning up configuration ################################################################################ clean: $(RM) $(LIBCKTEEC_OBJS) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) $(RM) $(OUT_DIR)/$(LIB_MAJOR) $(RM) $(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY) $(RM) $(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY) $(call rmdir,$(OUT_DIR)) optee_client-4.1.0/libckteec/include/000077500000000000000000000000001455150071200175365ustar00rootroot00000000000000optee_client-4.1.0/libckteec/include/CMakeLists.txt000066400000000000000000000005331455150071200222770ustar00rootroot00000000000000project(libckteec-headers C) FILE(GLOB INSTALL_HEADERS "*.h") add_library(${PROJECT_NAME} INTERFACE) target_include_directories( ${PROJECT_NAME} INTERFACE $ $ ) install(FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) optee_client-4.1.0/libckteec/include/ck_debug.h000066400000000000000000000025131455150071200214530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2020, Linaro Limited */ #ifndef LIBCKTEEC_CK_DEBUG_H #define LIBCKTEEC_CK_DEBUG_H #include /* Return a pointer to a string buffer of "CKR_xxx\0" return value ID */ const char *ckr2str(CK_RV id); /* ckm2str - Return string buffer of "CKM_xxx\0" for a mechanism ID */ const char *ckm2str(CK_MECHANISM_TYPE id); /* slot_ckf2str - Return string buffer of "CKF_xxx\0" for a slot flag */ const char *slot_ckf2str(CK_ULONG flag); /* token_ckf2str - Return string buffer "CKF_xxx\0" for a token flag */ const char *token_ckf2str(CK_ULONG flag); /* mecha_ckf2str - Return string buffer "CKF_xxx\0" for a mechanism flag */ const char *mecha_ckf2str(CK_ULONG flag); /* session_ckf2str - Return string buffer "CKF_xxx\0" for a session flag */ const char *session_ckf2str(CK_ULONG flag); /* session_cks2str - Return string buffer "CKS_xxx\0" for a session state */ const char *session_cks2str(CK_ULONG flag); /* Return a pointer to a string buffer of "CKA_xxx\0" attribute ID */ const char *cka2str(CK_ATTRIBUTE_TYPE id); /* Return a pointer to a string buffer of "CKO_xxx\0" object class ID */ const char *cko2str(CK_OBJECT_CLASS id); /* Return a pointer to a string buffer of "CKK_xxx\0" key type ID */ const char *ckk2str(CK_KEY_TYPE id); #endif /*LIBCKTEEC_CK_DEBUG_H*/ optee_client-4.1.0/libckteec/include/pkcs11.h000066400000000000000000001203641455150071200210170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2020, Linaro Limited */ #ifndef PKCS11_H #define PKCS11_H #ifdef __cplusplus extern "C" { #endif /* * PKCS#11 Cryptoki API v2.40-errata01, See specification from: * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/os/pkcs11-base-v2.40-errata01-os-complete.html */ #define CK_PKCS11_VERSION_MAJOR 2 #define CK_PKCS11_VERSION_MINOR 40 #define CK_PKCS11_VERSION_PATCH 1 typedef unsigned char CK_BYTE; typedef unsigned long CK_ULONG; typedef long CK_LONG; typedef CK_BYTE CK_CHAR; typedef CK_BYTE CK_UTF8CHAR; typedef CK_BYTE *CK_BYTE_PTR; typedef CK_ULONG *CK_ULONG_PTR; typedef CK_CHAR *CK_CHAR_PTR; typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; typedef void *CK_VOID_PTR; typedef CK_VOID_PTR *CK_VOID_PTR_PTR; typedef CK_BYTE CK_BBOOL; #define CK_TRUE 1 #define CK_FALSE 0 typedef CK_ULONG CK_FLAGS; #define CK_UNAVAILABLE_INFORMATION (~0UL) #define CK_EFFECTIVELY_INFINITE 0UL typedef CK_ULONG CK_SESSION_HANDLE; typedef CK_SESSION_HANDLE *CK_SESSION_HANDLE_PTR; typedef CK_ULONG CK_OBJECT_HANDLE; typedef CK_OBJECT_HANDLE *CK_OBJECT_HANDLE_PTR; #define CK_INVALID_HANDLE 0 typedef CK_ULONG CK_SLOT_ID; typedef CK_SLOT_ID *CK_SLOT_ID_PTR; typedef struct CK_VERSION CK_VERSION; typedef struct CK_VERSION *CK_VERSION_PTR; struct CK_VERSION { CK_BYTE major; CK_BYTE minor; }; typedef struct CK_DATE CK_DATE; typedef struct CK_DATE *CK_DATE_PTR; struct CK_DATE { CK_CHAR year[4]; CK_CHAR month[2]; CK_CHAR day[2]; }; /* * PKCS#11 Objects attributes */ typedef CK_ULONG CK_ATTRIBUTE_TYPE; typedef struct CK_ATTRIBUTE CK_ATTRIBUTE; typedef struct CK_ATTRIBUTE *CK_ATTRIBUTE_PTR; struct CK_ATTRIBUTE { CK_ATTRIBUTE_TYPE type; CK_VOID_PTR pValue; CK_ULONG ulValueLen; }; /* * Values for CK_ATTRIBUTE_TYPE * * This does not cover the full PKCS#11 IDs. */ #define CKF_ARRAY_ATTRIBUTE (1U << 30) #define CKA_VENDOR_DEFINED (1U << 31) #define CKA_CLASS 0x0000 #define CKA_TOKEN 0x0001 #define CKA_PRIVATE 0x0002 #define CKA_LABEL 0x0003 #define CKA_APPLICATION 0x0010 #define CKA_VALUE 0x0011 #define CKA_OBJECT_ID 0x0012 #define CKA_CERTIFICATE_TYPE 0x0080 #define CKA_ISSUER 0x0081 #define CKA_SERIAL_NUMBER 0x0082 #define CKA_AC_ISSUER 0x0083 #define CKA_OWNER 0x0084 #define CKA_ATTR_TYPES 0x0085 #define CKA_TRUSTED 0x0086 #define CKA_CERTIFICATE_CATEGORY 0x0087 #define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x0088 #define CKA_URL 0x0089 #define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x008a #define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x008b #define CKA_NAME_HASH_ALGORITHM 0x008c #define CKA_CHECK_VALUE 0x0090 #define CKA_KEY_TYPE 0x0100 #define CKA_SUBJECT 0x0101 #define CKA_ID 0x0102 #define CKA_SENSITIVE 0x0103 #define CKA_ENCRYPT 0x0104 #define CKA_DECRYPT 0x0105 #define CKA_WRAP 0x0106 #define CKA_UNWRAP 0x0107 #define CKA_SIGN 0x0108 #define CKA_SIGN_RECOVER 0x0109 #define CKA_VERIFY 0x010a #define CKA_VERIFY_RECOVER 0x010b #define CKA_DERIVE 0x010c #define CKA_START_DATE 0x0110 #define CKA_END_DATE 0x0111 #define CKA_MODULUS 0x0120 #define CKA_MODULUS_BITS 0x0121 #define CKA_PUBLIC_EXPONENT 0x0122 #define CKA_PRIVATE_EXPONENT 0x0123 #define CKA_PRIME_1 0x0124 #define CKA_PRIME_2 0x0125 #define CKA_EXPONENT_1 0x0126 #define CKA_EXPONENT_2 0x0127 #define CKA_COEFFICIENT 0x0128 #define CKA_PUBLIC_KEY_INFO 0x0129 #define CKA_PRIME 0x0130 #define CKA_SUBPRIME 0x0131 #define CKA_BASE 0x0132 #define CKA_PRIME_BITS 0x0133 #define CKA_SUBPRIME_BITS 0x0134 #define CKA_VALUE_BITS 0x0160 #define CKA_VALUE_LEN 0x0161 #define CKA_EXTRACTABLE 0x0162 #define CKA_LOCAL 0x0163 #define CKA_NEVER_EXTRACTABLE 0x0164 #define CKA_ALWAYS_SENSITIVE 0x0165 #define CKA_KEY_GEN_MECHANISM 0x0166 #define CKA_MODIFIABLE 0x0170 #define CKA_COPYABLE 0x0171 #define CKA_DESTROYABLE 0x0172 #define CKA_EC_PARAMS 0x0180 #define CKA_EC_POINT 0x0181 #define CKA_ALWAYS_AUTHENTICATE 0x0202 #define CKA_WRAP_WITH_TRUSTED 0x0210 #define CKA_WRAP_TEMPLATE (0x0211 | CKF_ARRAY_ATTRIBUTE) #define CKA_UNWRAP_TEMPLATE (0x0212 | CKF_ARRAY_ATTRIBUTE) #define CKA_DERIVE_TEMPLATE (0x0213 | CKF_ARRAY_ATTRIBUTE) #define CKA_OTP_FORMAT 0x0220 #define CKA_OTP_LENGTH 0x0221 #define CKA_OTP_TIME_INTERVAL 0x0222 #define CKA_OTP_USER_FRIENDLY_MODE 0x0223 #define CKA_OTP_CHALLENGE_REQUIREMENT 0x0224 #define CKA_OTP_TIME_REQUIREMENT 0x0225 #define CKA_OTP_COUNTER_REQUIREMENT 0x0226 #define CKA_OTP_PIN_REQUIREMENT 0x0227 #define CKA_OTP_COUNTER 0x022e #define CKA_OTP_TIME 0x022f #define CKA_OTP_USER_IDENTIFIER 0x022a #define CKA_OTP_SERVICE_IDENTIFIER 0x022b #define CKA_OTP_SERVICE_LOGO 0x022c #define CKA_OTP_SERVICE_LOGO_TYPE 0x022d #define CKA_GOSTR3410_PARAMS 0x0250 #define CKA_GOSTR3411_PARAMS 0x0251 #define CKA_GOST28147_PARAMS 0x0252 #define CKA_HW_FEATURE_TYPE 0x0300 #define CKA_RESET_ON_INIT 0x0301 #define CKA_HAS_RESET 0x0302 #define CKA_PIXEL_X 0x0400 #define CKA_PIXEL_Y 0x0401 #define CKA_RESOLUTION 0x0402 #define CKA_CHAR_ROWS 0x0403 #define CKA_CHAR_COLUMNS 0x0404 #define CKA_COLOR 0x0405 #define CKA_BITS_PER_PIXEL 0x0406 #define CKA_CHAR_SETS 0x0480 #define CKA_ENCODING_METHODS 0x0481 #define CKA_MIME_TYPES 0x0482 #define CKA_MECHANISM_TYPE 0x0500 #define CKA_REQUIRED_CMS_ATTRIBUTES 0x0501 #define CKA_DEFAULT_CMS_ATTRIBUTES 0x0502 #define CKA_SUPPORTED_CMS_ATTRIBUTES 0x0503 #define CKA_ALLOWED_MECHANISMS (0x0600 | CKF_ARRAY_ATTRIBUTE) /* Attribute CKA_CLASS refers to a CK_OBJECT_CLASS typed value */ typedef CK_ULONG CK_OBJECT_CLASS; typedef CK_OBJECT_CLASS *CK_OBJECT_CLASS_PTR; /* Values for type CK_OBJECT_CLASS */ #define CKO_VENDOR_DEFINED (1U << 31) #define CKO_DATA 0x0 #define CKO_CERTIFICATE 0x1 #define CKO_PUBLIC_KEY 0x2 #define CKO_PRIVATE_KEY 0x3 #define CKO_SECRET_KEY 0x4 #define CKO_HW_FEATURE 0x5 #define CKO_DOMAIN_PARAMETERS 0x6 #define CKO_MECHANISM 0x7 #define CKO_OTP_KEY 0x8 /* Attribute CKA_KEY_TYPE refers to a CK_KEY_TYPE typed value */ typedef CK_ULONG CK_KEY_TYPE; typedef CK_KEY_TYPE *CK_KEY_TYPE_PTR; /* * Values for type CK_KEY_TYPE * * This does not cover the full PKCS#11 IDs. */ #define CKK_VENDOR_DEFINED (1U << 31) #define CKK_RSA 0x000 #define CKK_DSA 0x001 #define CKK_DH 0x002 #define CKK_ECDSA 0x003 #define CKK_EC 0x003 #define CKK_GENERIC_SECRET 0x010 #define CKK_DES3 0x015 #define CKK_AES 0x01f #define CKK_HOTP 0x023 #define CKK_MD5_HMAC 0x027 #define CKK_SHA_1_HMAC 0x028 #define CKK_SHA256_HMAC 0x02b #define CKK_SHA384_HMAC 0x02c #define CKK_SHA512_HMAC 0x02d #define CKK_SHA224_HMAC 0x02e #define CKK_EC_EDWARDS 0x040 /* PKCS#11 v3.1-cs01 */ /* * Certificates */ typedef CK_ULONG CK_CERTIFICATE_TYPE; typedef CK_ULONG CK_CERTIFICATE_CATEGORY; /* * Valid values for attribute CKA_CERTIFICATE_TYPE */ #define CKC_X_509 0x00000000UL #define CKC_X_509_ATTR_CERT 0x00000001UL #define CKC_WTLS 0x00000002UL /* * Valid values for attribute CKA_CERTIFICATE_CATEGORY */ #define CK_CERTIFICATE_CATEGORY_UNSPECIFIED 0UL #define CK_CERTIFICATE_CATEGORY_TOKEN_USER 1UL #define CK_CERTIFICATE_CATEGORY_AUTHORITY 2UL #define CK_CERTIFICATE_CATEGORY_OTHER_ENTITY 3UL /* * Mechanisms * * Note: a mechanism can be referenced as object reference in some PKCS#11 API * functions. In such case, the object hold attribute CKA_MECHANISM_TYPE which * refers to a CK_MECHANISM_TYPE typed value that defines the target mechanism. */ typedef CK_ULONG CK_MECHANISM_TYPE; typedef CK_MECHANISM_TYPE *CK_MECHANISM_TYPE_PTR; /* * Values for type CK_MECHANISM_TYPE * * This does not cover the full PKCS#11 IDs. */ #define CKM_VENDOR_DEFINED (1U << 31) #define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000 #define CKM_RSA_PKCS 0x00001 #define CKM_RSA_9796 0x00002 #define CKM_RSA_X_509 0x00003 #define CKM_MD5_RSA_PKCS 0x00005 #define CKM_SHA1_RSA_PKCS 0x00006 #define CKM_RSA_PKCS_OAEP 0x00009 #define CKM_RSA_PKCS_PSS 0x0000d #define CKM_SHA1_RSA_PKCS_PSS 0x0000e #define CKM_SHA256_RSA_PKCS 0x00040 #define CKM_SHA384_RSA_PKCS 0x00041 #define CKM_SHA512_RSA_PKCS 0x00042 #define CKM_SHA256_RSA_PKCS_PSS 0x00043 #define CKM_SHA384_RSA_PKCS_PSS 0x00044 #define CKM_SHA512_RSA_PKCS_PSS 0x00045 #define CKM_SHA224_RSA_PKCS 0x00046 #define CKM_SHA224_RSA_PKCS_PSS 0x00047 #define CKM_SHA512_224 0x00048 #define CKM_SHA512_224_HMAC 0x00049 #define CKM_SHA512_224_HMAC_GENERAL 0x0004a #define CKM_SHA512_224_KEY_DERIVATION 0x0004b #define CKM_SHA512_256 0x0004c #define CKM_SHA512_256_HMAC 0x0004d #define CKM_SHA512_256_HMAC_GENERAL 0x0004e #define CKM_SHA512_256_KEY_DERIVATION 0x0004f #define CKM_DES3_ECB 0x00132 #define CKM_DES3_CBC 0x00133 #define CKM_DES3_MAC 0x00134 #define CKM_DES3_MAC_GENERAL 0x00135 #define CKM_DES3_CBC_PAD 0x00136 #define CKM_DES3_CMAC_GENERAL 0x00137 #define CKM_DES3_CMAC 0x00138 #define CKM_MD5 0x00210 #define CKM_MD5_HMAC 0x00211 #define CKM_MD5_HMAC_GENERAL 0x00212 #define CKM_SHA_1 0x00220 #define CKM_SHA_1_HMAC 0x00221 #define CKM_SHA_1_HMAC_GENERAL 0x00222 #define CKM_SHA256 0x00250 #define CKM_SHA256_HMAC 0x00251 #define CKM_SHA256_HMAC_GENERAL 0x00252 #define CKM_SHA224 0x00255 #define CKM_SHA224_HMAC 0x00256 #define CKM_SHA224_HMAC_GENERAL 0x00257 #define CKM_SHA384 0x00260 #define CKM_SHA384_HMAC 0x00261 #define CKM_SHA384_HMAC_GENERAL 0x00262 #define CKM_SHA512 0x00270 #define CKM_SHA512_HMAC 0x00271 #define CKM_SHA512_HMAC_GENERAL 0x00272 #define CKM_HOTP_KEY_GEN 0x00290 #define CKM_HOTP 0x00291 #define CKM_GENERIC_SECRET_KEY_GEN 0x00350 #define CKM_MD5_KEY_DERIVATION 0x00390 #define CKM_MD2_KEY_DERIVATION 0x00391 #define CKM_SHA1_KEY_DERIVATION 0x00392 #define CKM_SHA256_KEY_DERIVATION 0x00393 #define CKM_SHA384_KEY_DERIVATION 0x00394 #define CKM_SHA512_KEY_DERIVATION 0x00395 #define CKM_SHA224_KEY_DERIVATION 0x00396 #define CKM_EC_KEY_PAIR_GEN 0x01040 #define CKM_ECDSA 0x01041 #define CKM_ECDSA_SHA1 0x01042 #define CKM_ECDSA_SHA224 0x01043 #define CKM_ECDSA_SHA256 0x01044 #define CKM_ECDSA_SHA384 0x01045 #define CKM_ECDSA_SHA512 0x01046 #define CKM_ECDH1_DERIVE 0x01050 #define CKM_ECDH1_COFACTOR_DERIVE 0x01051 #define CKM_ECMQV_DERIVE 0x01052 #define CKM_ECDH_AES_KEY_WRAP 0x01053 #define CKM_RSA_AES_KEY_WRAP 0x01054 #define CKM_EC_EDWARDS_KEY_PAIR_GEN 0x01055 #define CKM_EDDSA 0x01057 #define CKM_AES_KEY_GEN 0x01080 #define CKM_AES_ECB 0x01081 #define CKM_AES_CBC 0x01082 #define CKM_AES_MAC 0x01083 #define CKM_AES_MAC_GENERAL 0x01084 #define CKM_AES_CBC_PAD 0x01085 #define CKM_AES_CTR 0x01086 #define CKM_AES_GCM 0x01087 #define CKM_AES_CCM 0x01088 #define CKM_AES_CTS 0x01089 #define CKM_AES_CMAC 0x0108a #define CKM_AES_CMAC_GENERAL 0x0108b #define CKM_AES_XCBC_MAC 0x0108c #define CKM_AES_XCBC_MAC_96 0x0108d #define CKM_AES_GMAC 0x0108e #define CKM_DES3_ECB_ENCRYPT_DATA 0x01102 #define CKM_DES3_CBC_ENCRYPT_DATA 0x01103 #define CKM_AES_ECB_ENCRYPT_DATA 0x01104 #define CKM_AES_CBC_ENCRYPT_DATA 0x01105 #define CKM_AES_KEY_WRAP 0x02109 #define CKM_AES_KEY_WRAP_PAD 0x0210a typedef struct CK_MECHANISM_INFO CK_MECHANISM_INFO; typedef struct CK_MECHANISM_INFO *CK_MECHANISM_INFO_PTR; struct CK_MECHANISM_INFO { CK_ULONG ulMinKeySize; CK_ULONG ulMaxKeySize; CK_FLAGS flags; }; /* Flags for field flags of struct ck_mechanism_info */ #define CKF_HW (1U << 0) #define CKF_ENCRYPT (1U << 8) #define CKF_DECRYPT (1U << 9) #define CKF_DIGEST (1U << 10) #define CKF_SIGN (1U << 11) #define CKF_SIGN_RECOVER (1U << 12) #define CKF_VERIFY (1U << 13) #define CKF_VERIFY_RECOVER (1U << 14) #define CKF_GENERATE (1U << 15) #define CKF_GENERATE_KEY_PAIR (1U << 16) #define CKF_WRAP (1U << 17) #define CKF_UNWRAP (1U << 18) #define CKF_DERIVE (1U << 19) #define CKF_EC_F_P (1U << 20) #define CKF_EC_F_2M (1U << 21) #define CKF_EC_ECPARAMETERS (1U << 22) #define CKF_EC_NAMEDCURVE (1U << 23) #define CKF_EC_UNCOMPRESS (1U << 24) #define CKF_EC_COMPRESS (1U << 25) #define CKF_EXTENSION (1U << 31) /* * Mechanism parameter structures * * This does not cover the whole mechanism parameter structures defined by * the PKCS#11. To be updated when needed. */ typedef struct CK_MECHANISM CK_MECHANISM; typedef struct CK_MECHANISM *CK_MECHANISM_PTR; struct CK_MECHANISM { CK_MECHANISM_TYPE mechanism; CK_VOID_PTR pParameter; CK_ULONG ulParameterLen; }; typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; /* Values for type CK_RSA_PKCS_MGF_TYPE */ #define CKG_MGF1_SHA1 0x0001UL #define CKG_MGF1_SHA224 0x0005UL #define CKG_MGF1_SHA256 0x0002UL #define CKG_MGF1_SHA384 0x0003UL #define CKG_MGF1_SHA512 0x0004UL typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; /* Values for type CK_RSA_PKCS_OAEP_SOURCE_TYPE */ #define CKZ_DATA_SPECIFIED 0x0001UL /* MAC General parameters */ typedef CK_ULONG CK_MAC_GENERAL_PARAMS; typedef CK_MAC_GENERAL_PARAMS *CK_MAC_GENERAL_PARAMS_PTR; /* * CK_EC_KDF_TYPE is used to indicate the Key Derivation Function (KDF) applied * to derive keying data from a shared secret. */ typedef CK_ULONG CK_EC_KDF_TYPE; /* * Elliptic curve Diffie-Hellman key derivation * Elliptic curve Diffie-Hellman cofactor key derivation parameters */ typedef struct CK_ECDH1_DERIVE_PARAMS CK_ECDH1_DERIVE_PARAMS; typedef struct CK_ECDH1_DERIVE_PARAMS *CK_ECDH1_DERIVE_PARAMS_PTR; struct CK_ECDH1_DERIVE_PARAMS { CK_EC_KDF_TYPE kdf; CK_ULONG ulSharedDataLen; CK_BYTE_PTR pSharedData; CK_ULONG ulPublicDataLen; CK_BYTE_PTR pPublicData; }; /* AES CBC encryption parameters */ typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_AES_CBC_ENCRYPT_DATA_PARAMS; typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS *CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { CK_BYTE iv[16]; CK_BYTE_PTR pData; CK_ULONG length; }; /* AES CTR parameters */ typedef struct CK_AES_CTR_PARAMS CK_AES_CTR_PARAMS; typedef struct CK_AES_CTR_PARAMS *CK_AES_CTR_PARAMS_PTR; struct CK_AES_CTR_PARAMS { CK_ULONG ulCounterBits; CK_BYTE cb[16]; }; /* AES GCM parameters */ typedef struct CK_GCM_PARAMS CK_GCM_PARAMS; typedef struct CK_GCM_PARAMS *CK_GCM_PARAMS_PTR; struct CK_GCM_PARAMS { CK_BYTE_PTR pIv; CK_ULONG ulIvLen; CK_ULONG ulIvBits; CK_BYTE_PTR pAAD; CK_ULONG ulAADLen; CK_ULONG ulTagBits; }; /* EdDSA (RFC 8032) */ typedef struct CK_EDDSA_PARAMS { CK_BYTE phFlag; CK_ULONG ulContextDataLen; CK_BYTE_PTR pContextData; } CK_EDDSA_PARAMS; typedef CK_EDDSA_PARAMS *CK_EDDSA_PARAMS_PTR; /* AES CCM parameters */ typedef struct CK_CCM_PARAMS CK_CCM_PARAMS; typedef struct CK_CCM_PARAMS *CK_CCM_PARAMS_PTR; struct CK_CCM_PARAMS { CK_ULONG ulDataLen; CK_BYTE_PTR pNonce; CK_ULONG ulNonceLen; CK_BYTE_PTR pAAD; CK_ULONG ulAADLen; CK_ULONG ulMACLen; }; typedef struct CK_KEY_DERIVATION_STRING_DATA CK_KEY_DERIVATION_STRING_DATA; typedef struct CK_KEY_DERIVATION_STRING_DATA *CK_KEY_DERIVATION_STRING_DATA_PTR; struct CK_KEY_DERIVATION_STRING_DATA { CK_BYTE_PTR pData; CK_ULONG ulLen; }; /* Parameters for CKM_RSA_PKCS_PSS */ typedef struct CK_RSA_PKCS_PSS_PARAMS CK_RSA_PKCS_PSS_PARAMS; typedef struct CK_RSA_PKCS_PSS_PARAMS *CK_RSA_PKCS_PSS_PARAMS_PTR; struct CK_RSA_PKCS_PSS_PARAMS { CK_MECHANISM_TYPE hashAlg; CK_RSA_PKCS_MGF_TYPE mgf; CK_ULONG sLen; }; /* Parameters for CKM_RSA_PKCS_OAEP */ typedef struct CK_RSA_PKCS_OAEP_PARAMS CK_RSA_PKCS_OAEP_PARAMS; typedef struct CK_RSA_PKCS_OAEP_PARAMS *CK_RSA_PKCS_OAEP_PARAMS_PTR; struct CK_RSA_PKCS_OAEP_PARAMS { CK_MECHANISM_TYPE hashAlg; CK_RSA_PKCS_MGF_TYPE mgf; CK_RSA_PKCS_OAEP_SOURCE_TYPE source; CK_VOID_PTR pSourceData; CK_ULONG ulSourceDataLen; }; typedef struct CK_RSA_AES_KEY_WRAP_PARAMS { CK_ULONG ulAESKeyBits; CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams; } CK_RSA_AES_KEY_WRAP_PARAMS; typedef CK_RSA_AES_KEY_WRAP_PARAMS *CK_RSA_AES_KEY_WRAP_PARAMS_PTR; /* * PKCS#11 return values */ typedef CK_ULONG CK_RV; /* Values for type CK_RV */ #define CKR_VENDOR_DEFINED (1U << 31) #define CKR_OK 0x0000 #define CKR_CANCEL 0x0001 #define CKR_HOST_MEMORY 0x0002 #define CKR_SLOT_ID_INVALID 0x0003 #define CKR_GENERAL_ERROR 0x0005 #define CKR_FUNCTION_FAILED 0x0006 #define CKR_ARGUMENTS_BAD 0x0007 #define CKR_NO_EVENT 0x0008 #define CKR_NEED_TO_CREATE_THREADS 0x0009 #define CKR_CANT_LOCK 0x000a #define CKR_ATTRIBUTE_READ_ONLY 0x0010 #define CKR_ATTRIBUTE_SENSITIVE 0x0011 #define CKR_ATTRIBUTE_TYPE_INVALID 0x0012 #define CKR_ATTRIBUTE_VALUE_INVALID 0x0013 #define CKR_ACTION_PROHIBITED 0x001b #define CKR_DATA_INVALID 0x0020 #define CKR_DATA_LEN_RANGE 0x0021 #define CKR_DEVICE_ERROR 0x0030 #define CKR_DEVICE_MEMORY 0x0031 #define CKR_DEVICE_REMOVED 0x0032 #define CKR_ENCRYPTED_DATA_INVALID 0x0040 #define CKR_ENCRYPTED_DATA_LEN_RANGE 0x0041 #define CKR_FUNCTION_CANCELED 0x0050 #define CKR_FUNCTION_NOT_PARALLEL 0x0051 #define CKR_FUNCTION_NOT_SUPPORTED 0x0054 #define CKR_KEY_HANDLE_INVALID 0x0060 #define CKR_KEY_SIZE_RANGE 0x0062 #define CKR_KEY_TYPE_INCONSISTENT 0x0063 #define CKR_KEY_NOT_NEEDED 0x0064 #define CKR_KEY_CHANGED 0x0065 #define CKR_KEY_NEEDED 0x0066 #define CKR_KEY_INDIGESTIBLE 0x0067 #define CKR_KEY_FUNCTION_NOT_PERMITTED 0x0068 #define CKR_KEY_NOT_WRAPPABLE 0x0069 #define CKR_KEY_UNEXTRACTABLE 0x006a #define CKR_MECHANISM_INVALID 0x0070 #define CKR_MECHANISM_PARAM_INVALID 0x0071 #define CKR_OBJECT_HANDLE_INVALID 0x0082 #define CKR_OPERATION_ACTIVE 0x0090 #define CKR_OPERATION_NOT_INITIALIZED 0x0091 #define CKR_PIN_INCORRECT 0x00a0 #define CKR_PIN_INVALID 0x00a1 #define CKR_PIN_LEN_RANGE 0x00a2 #define CKR_PIN_EXPIRED 0x00a3 #define CKR_PIN_LOCKED 0x00a4 #define CKR_SESSION_CLOSED 0x00b0 #define CKR_SESSION_COUNT 0x00b1 #define CKR_SESSION_HANDLE_INVALID 0x00b3 #define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x00b4 #define CKR_SESSION_READ_ONLY 0x00b5 #define CKR_SESSION_EXISTS 0x00b6 #define CKR_SESSION_READ_ONLY_EXISTS 0x00b7 #define CKR_SESSION_READ_WRITE_SO_EXISTS 0x00b8 #define CKR_SIGNATURE_INVALID 0x00c0 #define CKR_SIGNATURE_LEN_RANGE 0x00c1 #define CKR_TEMPLATE_INCOMPLETE 0x00d0 #define CKR_TEMPLATE_INCONSISTENT 0x00d1 #define CKR_TOKEN_NOT_PRESENT 0x00e0 #define CKR_TOKEN_NOT_RECOGNIZED 0x00e1 #define CKR_TOKEN_WRITE_PROTECTED 0x00e2 #define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x00f0 #define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x00f1 #define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x00f2 #define CKR_USER_ALREADY_LOGGED_IN 0x0100 #define CKR_USER_NOT_LOGGED_IN 0x0101 #define CKR_USER_PIN_NOT_INITIALIZED 0x0102 #define CKR_USER_TYPE_INVALID 0x0103 #define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x0104 #define CKR_USER_TOO_MANY_TYPES 0x0105 #define CKR_WRAPPED_KEY_INVALID 0x0110 #define CKR_WRAPPED_KEY_LEN_RANGE 0x0112 #define CKR_WRAPPING_KEY_HANDLE_INVALID 0x0113 #define CKR_WRAPPING_KEY_SIZE_RANGE 0x0114 #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x0115 #define CKR_RANDOM_SEED_NOT_SUPPORTED 0x0120 #define CKR_RANDOM_NO_RNG 0x0121 #define CKR_DOMAIN_PARAMS_INVALID 0x0130 #define CKR_CURVE_NOT_SUPPORTED 0x0140 #define CKR_BUFFER_TOO_SMALL 0x0150 #define CKR_SAVED_STATE_INVALID 0x0160 #define CKR_INFORMATION_SENSITIVE 0x0170 #define CKR_STATE_UNSAVEABLE 0x0180 #define CKR_CRYPTOKI_NOT_INITIALIZED 0x0190 #define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x0191 #define CKR_MUTEX_BAD 0x01a0 #define CKR_MUTEX_NOT_LOCKED 0x01a1 #define CKR_NEW_PIN_MODE 0x01b0 #define CKR_NEXT_OTP 0x01b1 #define CKR_EXCEEDED_MAX_ITERATIONS 0x01b5 #define CKR_FIPS_SELF_TEST_FAILED 0x01b6 #define CKR_LIBRARY_LOAD_FAILED 0x01b7 #define CKR_PIN_TOO_WEAK 0x01b8 #define CKR_PUBLIC_KEY_INVALID 0x01b9 #define CKR_FUNCTION_REJECTED 0x0200 /* * PKCS#11 API functions */ /* Argument for C_GetInfo */ typedef struct CK_INFO CK_INFO; typedef struct CK_INFO *CK_INFO_PTR; struct CK_INFO { CK_VERSION cryptokiVersion; CK_UTF8CHAR manufacturerID[32]; CK_FLAGS flags; CK_UTF8CHAR libraryDescription[32]; CK_VERSION libraryVersion; }; /* Argument for C_GetSlotInfo */ typedef struct CK_SLOT_INFO CK_SLOT_INFO; typedef struct CK_SLOT_INFO *CK_SLOT_INFO_PTR; struct CK_SLOT_INFO { CK_UTF8CHAR slotDescription[64]; CK_UTF8CHAR manufacturerID[32]; CK_FLAGS flags; CK_VERSION hardwareVersion; CK_VERSION firmwareVersion; }; /* Values for field flags of struct ck_slot_info */ #define CKF_TOKEN_PRESENT (1U << 0) #define CKF_REMOVABLE_DEVICE (1U << 1) #define CKF_HW_SLOT (1U << 2) /* Argument for C_GetTokenInfo */ typedef struct CK_TOKEN_INFO CK_TOKEN_INFO; typedef struct CK_TOKEN_INFO *CK_TOKEN_INFO_PTR; struct CK_TOKEN_INFO { CK_UTF8CHAR label[32]; CK_UTF8CHAR manufacturerID[32]; CK_UTF8CHAR model[16]; CK_CHAR serialNumber[16]; CK_FLAGS flags; CK_ULONG ulMaxSessionCount; CK_ULONG ulSessionCount; CK_ULONG ulMaxRwSessionCount; CK_ULONG ulRwSessionCount; CK_ULONG ulMaxPinLen; CK_ULONG ulMinPinLen; CK_ULONG ulTotalPublicMemory; CK_ULONG ulFreePublicMemory; CK_ULONG ulTotalPrivateMemory; CK_ULONG ulFreePrivateMemory; CK_VERSION hardwareVersion; CK_VERSION firmwareVersion; CK_CHAR utcTime[16]; }; /* Values for field flags of struct ck_token_info */ #define CKF_RNG (1U << 0) #define CKF_WRITE_PROTECTED (1U << 1) #define CKF_LOGIN_REQUIRED (1U << 2) #define CKF_USER_PIN_INITIALIZED (1U << 3) #define CKF_RESTORE_KEY_NOT_NEEDED (1U << 5) #define CKF_CLOCK_ON_TOKEN (1U << 6) #define CKF_PROTECTED_AUTHENTICATION_PATH (1U << 8) #define CKF_DUAL_CRYPTO_OPERATIONS (1U << 9) #define CKF_TOKEN_INITIALIZED (1U << 10) #define CKF_SECONDARY_AUTHENTICATION (1U << 11) #define CKF_USER_PIN_COUNT_LOW (1U << 16) #define CKF_USER_PIN_FINAL_TRY (1U << 17) #define CKF_USER_PIN_LOCKED (1U << 18) #define CKF_USER_PIN_TO_BE_CHANGED (1U << 19) #define CKF_SO_PIN_COUNT_LOW (1U << 20) #define CKF_SO_PIN_FINAL_TRY (1U << 21) #define CKF_SO_PIN_LOCKED (1U << 22) #define CKF_SO_PIN_TO_BE_CHANGED (1U << 23) #define CKF_ERROR_STATE (1U << 24) /* Argument for C_GetSessionInfo */ typedef struct CK_SESSION_INFO CK_SESSION_INFO; typedef struct CK_SESSION_INFO *CK_SESSION_INFO_PTR; typedef CK_ULONG CK_STATE; /* Values for CK_STATE */ #define CKS_RO_PUBLIC_SESSION 0 #define CKS_RO_USER_FUNCTIONS 1 #define CKS_RW_PUBLIC_SESSION 2 #define CKS_RW_USER_FUNCTIONS 3 #define CKS_RW_SO_FUNCTIONS 4 struct CK_SESSION_INFO { CK_SLOT_ID slotID; CK_STATE state; CK_FLAGS flags; CK_ULONG ulDeviceError; }; /* Values for field flags of struct ck_session_info */ #define CKF_RW_SESSION (1U << 1) #define CKF_SERIAL_SESSION (1U << 2) /* Argument for C_Login */ typedef CK_ULONG CK_USER_TYPE; /* Values for CK_USER_TYPE */ #define CKU_SO 0 #define CKU_USER 1 #define CKU_CONTEXT_SPECIFIC 2 /* Values for argument flags of C_WaitForSlotEvent */ #define CKF_DONT_BLOCK 1 /* Argument for CK_NOTIFY typed callback function */ typedef CK_ULONG CK_NOTIFICATION; /* Values for CK_NOTIFICATION */ #define CKN_SURRENDER 0 #define CKN_OTP_CHANGED 1 /* Callback handler types */ typedef CK_RV (*CK_NOTIFY) (CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, CK_VOID_PTR pApplication); typedef CK_RV (*CK_CREATEMUTEX) (CK_VOID_PTR_PTR ppMutex); typedef CK_RV (*CK_DESTROYMUTEX) (CK_VOID_PTR pMutex); typedef CK_RV (*CK_LOCKMUTEX) (CK_VOID_PTR pMutex); typedef CK_RV (*CK_UNLOCKMUTEX) (CK_VOID_PTR pMutex); /* Argument for C_GetFunctionList */ typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; typedef struct CK_FUNCTION_LIST *CK_FUNCTION_LIST_PTR; typedef struct CK_FUNCTION_LIST **CK_FUNCTION_LIST_PTR_PTR; struct CK_FUNCTION_LIST { CK_VERSION version; CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs); CK_RV (*C_Finalize)(CK_VOID_PTR pReserved); CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo); CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount); CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen); CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession); CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession); CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID); CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo); CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen); CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey); CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession); CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject); CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject); CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject); CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize); CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount); CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession); CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen); CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen); CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen); CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen); CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism); CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey); CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen); CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen); CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen); CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession); CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession); CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR slotID, CK_VOID_PTR pReserved); }; /* Optional init_args structure for C_Initialize */ typedef struct CK_C_INITIALIZE_ARGS CK_C_INITIALIZE_ARGS; typedef struct CK_C_INITIALIZE_ARGS *CK_C_INITIALIZE_ARGS_PTR; struct CK_C_INITIALIZE_ARGS { CK_CREATEMUTEX CreateMutex; CK_DESTROYMUTEX DestroyMutex; CK_LOCKMUTEX LockMutex; CK_UNLOCKMUTEX UnlockMutex; CK_FLAGS flags; CK_VOID_PTR reserved; }; /* Flags for field flags of struct ck_c_initialize_args */ #define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1U << 0) #define CKF_OS_LOCKING_OK (1U << 1) CK_RV C_Initialize(CK_VOID_PTR pInitArgs); CK_RV C_Finalize(CK_VOID_PTR pReserved); CK_RV C_GetInfo(CK_INFO_PTR pInfo); CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount); CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo); CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen); CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession); CK_RV C_CloseSession(CK_SESSION_HANDLE hSession); CK_RV C_CloseAllSessions(CK_SLOT_ID slotID); CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo); CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen); CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey); CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); CK_RV C_Logout(CK_SESSION_HANDLE hSession); CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject); CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject); CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject); CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize); CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount); CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession); CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen); CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen); CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen); CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen); CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism); CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen); CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen); CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey); CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen); CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey); CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen); CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen); CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession); CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession); CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR slotID, CK_VOID_PTR pReserved); #ifdef __cplusplus } #endif #endif /*PKCS11_H*/ optee_client-4.1.0/libckteec/include/pkcs11_ta.h000066400000000000000000001261141455150071200215020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2020, Linaro Limited */ #ifndef PKCS11_TA_H #define PKCS11_TA_H #include #include #define PKCS11_TA_UUID { 0xfd02c9da, 0x306c, 0x48c7, \ { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } } /* PKCS11 trusted application version information */ #define PKCS11_TA_VERSION_MAJOR 0 #define PKCS11_TA_VERSION_MINOR 1 #define PKCS11_TA_VERSION_PATCH 0 /* Attribute specific values */ #define PKCS11_CK_UNAVAILABLE_INFORMATION UINT32_C(0xFFFFFFFF) #define PKCS11_UNDEFINED_ID UINT32_C(0xFFFFFFFF) #define PKCS11_FALSE false #define PKCS11_TRUE true /* * Note on PKCS#11 TA commands ABI * * For evolution of the TA API and to not mess with the GPD TEE 4 parameters * constraint, all the PKCS11 TA invocation commands use a subset of available * the GPD TEE invocation parameter types. * * Param#0 is used for the so-called control arguments of the invoked command * and for providing a PKCS#11 compliant status code for the request command. * Param#0 is an in/out memory reference (aka memref[0]). The input buffer * stores serialized arguments for the command. The output buffer store the * 32bit TA return code for the command. As a consequence, param#0 shall * always be an input/output memory reference of at least 32bit, more if * the command expects more input arguments. * * When the TA returns with TEE_SUCCESS result, client shall always get the * 32bit value stored in param#0 output buffer and use the value as TA * return code for the invoked command. * * Param#1 can be used for input data arguments of the invoked command. * It is unused or is an input memory reference, aka memref[1]. * Evolution of the API may use memref[1] for output data as well. * * Param#2 is mostly used for output data arguments of the invoked command * and for output handles generated from invoked commands. * Few commands uses it for a secondary input data buffer argument. * It is unused or is an input/output/in-out memory reference, aka memref[2]. * * Param#3 is currently unused and reserved for evolution of the API. */ enum pkcs11_ta_cmd { /* * PKCS11_CMD_PING Ack TA presence and return version info * * [in] memref[0] = 32bit, unused, must be 0 * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = [ * 32bit version major value, * 32bit version minor value * 32bit version patch value * ] */ PKCS11_CMD_PING = 0, /* * PKCS11_CMD_SLOT_LIST - Get the table of the valid slot IDs * * [in] memref[0] = 32bit, unused, must be 0 * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array slot_ids[slot counts] * * The TA instance may represent several PKCS#11 slots and * associated tokens. This commadn reports the IDs of embedded tokens. * This command relates the PKCS#11 API function C_GetSlotList(). */ PKCS11_CMD_SLOT_LIST = 1, /* * PKCS11_CMD_SLOT_INFO - Get cryptoki structured slot information * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_slot_info)info * * The TA instance may represent several PKCS#11 slots/tokens. * This command relates the PKCS#11 API function C_GetSlotInfo(). */ PKCS11_CMD_SLOT_INFO = 2, /* * PKCS11_CMD_TOKEN_INFO - Get cryptoki structured token information * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_token_info)info * * The TA instance may represent several PKCS#11 slots/tokens. * This command relates the PKCS#11 API function C_GetTokenInfo(). */ PKCS11_CMD_TOKEN_INFO = 3, /* * PKCS11_CMD_MECHANISM_IDS - Get list of the supported mechanisms * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array mechanism IDs * * This command relates to the PKCS#11 API function * C_GetMechanismList(). */ PKCS11_CMD_MECHANISM_IDS = 4, /* * PKCS11_CMD_MECHANISM_INFO - Get information on a specific mechanism * * [in] memref[0] = [ * 32bit slot ID, * 32bit mechanism ID (PKCS11_CKM_*) * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_mechanism_info)info * * This command relates to the PKCS#11 API function * C_GetMechanismInfo(). */ PKCS11_CMD_MECHANISM_INFO = 5, /* * PKCS11_CMD_OPEN_SESSION - Open a session * * [in] memref[0] = [ * 32bit slot ID, * 32bit session flags, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit session handle * * This command relates to the PKCS#11 API function C_OpenSession(). */ PKCS11_CMD_OPEN_SESSION = 6, /* * PKCS11_CMD_CLOSE_SESSION - Close an opened session * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_CloseSession(). */ PKCS11_CMD_CLOSE_SESSION = 7, /* * PKCS11_CMD_CLOSE_ALL_SESSIONS - Close all client sessions on token * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function * C_CloseAllSessions(). */ PKCS11_CMD_CLOSE_ALL_SESSIONS = 8, /* * PKCS11_CMD_SESSION_INFO - Get Cryptoki information on a session * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_session_info)info * * This command relates to the PKCS#11 API function C_GetSessionInfo(). */ PKCS11_CMD_SESSION_INFO = 9, /* * PKCS11_CMD_INIT_TOKEN - Initialize PKCS#11 token * * [in] memref[0] = [ * 32bit slot ID, * 32bit PIN length, * byte array label[32] * byte array PIN[PIN length], * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_InitToken(). */ PKCS11_CMD_INIT_TOKEN = 10, /* * PKCS11_CMD_INIT_PIN - Initialize user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit PIN byte size, * byte array: PIN data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_InitPIN(). */ PKCS11_CMD_INIT_PIN = 11, /* * PKCS11_CMD_SET_PIN - Change user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit old PIN byte size, * 32bit new PIN byte size, * byte array: PIN data, * byte array: new PIN data, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_SetPIN(). */ PKCS11_CMD_SET_PIN = 12, /* * PKCS11_CMD_LOGIN - Initialize user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit user identifier, enum pkcs11_user_type * 32bit PIN byte size, * byte array: PIN data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_Login(). */ PKCS11_CMD_LOGIN = 13, /* * PKCS11_CMD_LOGOUT - Log out from token * * [in] memref[0] = [ * 32bit session handle, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_Logout(). */ PKCS11_CMD_LOGOUT = 14, /* * PKCS11_CMD_CREATE_OBJECT - Create a raw client assembled object in * the session or token * * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_CreateObject(). */ PKCS11_CMD_CREATE_OBJECT = 15, /* * PKCS11_CMD_DESTROY_OBJECT - Destroy an object * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DestroyObject(). */ PKCS11_CMD_DESTROY_OBJECT = 16, /* * PKCS11_CMD_ENCRYPT_INIT - Initialize encryption processing * PKCS11_CMD_DECRYPT_INIT - Initialize decryption processing * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle of the key, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * These commands relate to the PKCS#11 API functions * C_EncryptInit() and C_DecryptInit(). */ PKCS11_CMD_ENCRYPT_INIT = 17, PKCS11_CMD_DECRYPT_INIT = 18, /* * PKCS11_CMD_ENCRYPT_UPDATE - Update encryption processing * PKCS11_CMD_DECRYPT_UPDATE - Update decryption processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions * C_EncryptUpdate() and C_DecryptUpdate(). */ PKCS11_CMD_ENCRYPT_UPDATE = 19, PKCS11_CMD_DECRYPT_UPDATE = 20, /* * PKCS11_CMD_ENCRYPT_FINAL - Finalize encryption processing * PKCS11_CMD_DECRYPT_FINAL - Finalize decryption processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions * C_EncryptFinal() and C_DecryptFinal(). */ PKCS11_CMD_ENCRYPT_FINAL = 21, PKCS11_CMD_DECRYPT_FINAL = 22, /* * PKCS11_CMD_ENCRYPT_ONESHOT - Update and finalize encryption * processing * PKCS11_CMD_DECRYPT_ONESHOT - Update and finalize decryption * processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions C_Encrypt and * C_Decrypt. */ PKCS11_CMD_ENCRYPT_ONESHOT = 23, PKCS11_CMD_DECRYPT_ONESHOT = 24, /* * PKCS11_CMD_SIGN_INIT - Initialize a signature computation * processing * PKCS11_CMD_VERIFY_INIT - Initialize a signature verification * processing * * [in] memref[0] = [ * 32bit session handle, * 32bit key handle, * (struct pkcs11_attribute_head)mechanism + * mechanism params, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * These commands relate to the PKCS#11 API functions C_SignInit() and * C_VerifyInit(). */ PKCS11_CMD_SIGN_INIT = 25, PKCS11_CMD_VERIFY_INIT = 26, /* * PKCS11_CMD_SIGN_UPDATE - Update a signature computation processing * PKCS11_CMD_VERIFY_UPDATE - Update a signature verification processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * * These commands relate to the PKCS#11 API functions C_SignUpdate() and * C_VerifyUpdate(). */ PKCS11_CMD_SIGN_UPDATE = 27, PKCS11_CMD_VERIFY_UPDATE = 28, /* * PKCS11_CMD_SIGN_FINAL - Finalize a signature computation processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output signature * * This command relates to the PKCS#11 API functions C_SignFinal(). */ PKCS11_CMD_SIGN_FINAL = 29, /* * PKCS11_CMD_VERIFY_FINAL - Finalize a signature verification * processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[2] = input signature to be processed * * This command relates to the PKCS#11 API functions C_VerifyFinal(). */ PKCS11_CMD_VERIFY_FINAL = 30, /* * PKCS11_CMD_SIGN_ONESHOT - Compute a signature * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = byte array: generated signature * * This command relates to the PKCS#11 API function C_Sign(). */ PKCS11_CMD_SIGN_ONESHOT = 31, /* * PKCS11_CMD_VERIFY_ONESHOT - Compute and compare a signature * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [in] memref[2] = input signature to be processed * * This command relates to the PKCS#11 API function C_Verify(). */ PKCS11_CMD_VERIFY_ONESHOT = 32, /* * PKCS11_CMD_GENERATE_KEY - Generate a symmetric key or domain * parameters * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_GenerateKey(). */ PKCS11_CMD_GENERATE_KEY = 33, /* * PKCS11_CMD_FIND_OBJECTS_INIT - Initialize an object search * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_FindOjectsInit(). */ PKCS11_CMD_FIND_OBJECTS_INIT = 34, /* * PKCS11_CMD_FIND_OBJECTS - Get handles of matching objects * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array object_handle_array[N] * * This command relates to the PKCS#11 API function C_FindOjects(). * The size of object_handle_array depends on the size of the output * buffer provided by the client. */ PKCS11_CMD_FIND_OBJECTS = 35, /* * PKCS11_CMD_FIND_OBJECTS_FINAL - Finalize current objects search * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_FindOjectsFinal(). */ PKCS11_CMD_FIND_OBJECTS_FINAL = 36, /* * PKCS11_CMD_GET_OBJECT_SIZE - Get byte size used by object in the TEE * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object_byte_size * * This command relates to the PKCS#11 API function C_GetObjectSize(). */ PKCS11_CMD_GET_OBJECT_SIZE = 37, /* * PKCS11_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s) * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_object_head)attribs + attributes * data * * This command relates to the PKCS#11 API function C_GetAttributeValue. * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). Upon successful * completion, the TA returns the provided template filled with expected * data through output argument memref[2] (referred here again as * attribs + attributes data). */ PKCS11_CMD_GET_ATTRIBUTE_VALUE = 38, /* * PKCS11_CMD_SET_ATTRIBUTE_VALUE - Set the value of object attribute(s) * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_SetAttributeValue. * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). */ PKCS11_CMD_SET_ATTRIBUTE_VALUE = 39, /* * PKCS11_CMD_COPY_OBJECT - Copies an object, creating a new object for * the copy. * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_CopyObject(). * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). */ PKCS11_CMD_COPY_OBJECT = 40, /* * PKCS11_CMD_SEED_RANDOM - Seed random data generator * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = byte array: seed material to feed into the RNG * * This command relates to the PKCS#11 API function C_SeedRandom(). */ PKCS11_CMD_SEED_RANDOM = 41, /* * PKCS11_CMD_GENERATE_RANDOM - Generate random data * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = byte array: generated random * * This command relates to the PKCS#11 API function C_GenerateRandom(). */ PKCS11_CMD_GENERATE_RANDOM = 42, /* * PKCS11_CMD_DERIVE_KEY - Derive a key from a parent key. * * [in] memref[0] = [ * 32bit session handle, * 32bit parent key handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_DeriveKey(). */ PKCS11_CMD_DERIVE_KEY = 43, /* * PKCS11_CMD_RELEASE_ACTIVE_PROCESSING - Release active processing * * [in] memref[0] = [ * 32bit session handle, * 32bit enum pkcs11_ta_cmd * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command is used to release active processing in case of * Cryptoki API invocation error is detected in user space processing. * Function derived from pkcs11_ta_cmd is used to verify that active * processing matches. */ PKCS11_CMD_RELEASE_ACTIVE_PROCESSING = 44, /* * PKCS11_CMD_DIGEST_INIT - Initialize a digest computation processing * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DigestInit(). */ PKCS11_CMD_DIGEST_INIT = 45, /* * PKCS11_CMD_DIGEST_KEY - Update digest with a key * * [in] memref[0] = [ * 32bit session handle, * 32bit key handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DigestKey(). */ PKCS11_CMD_DIGEST_KEY = 46, /* * PKCS11_CMD_DIGEST_UPDATE - Update digest with data * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * * This command relates to the PKCS#11 API function C_DigestUpdate(). */ PKCS11_CMD_DIGEST_UPDATE = 47, /* * PKCS11_CMD_DIGEST_FINAL - Finalize a digest computation processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output digest * * This command relates to the PKCS#11 API function C_DigestFinal(). */ PKCS11_CMD_DIGEST_FINAL = 48, /* * PKCS11_CMD_DIGEST_ONESHOT - Compute a digest * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = byte array: generated digest * * This command relates to the PKCS#11 API function C_Digest(). */ PKCS11_CMD_DIGEST_ONESHOT = 49, /* * PKCS11_CMD_GENERATE_KEY_PAIR - Generate an asymmetric key pair * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)public key attribs + * attributes data, * (struct pkcs11_object_head)private key attribs + * attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = [ * 32bit public key object handle, * 32bit private key object handle * ] * * This command relates to the PKCS#11 API function * C_GenerateKeyPair(). */ PKCS11_CMD_GENERATE_KEY_PAIR = 50, /* * PKCS11_CMD_WRAP_KEY - Wraps a private or secret key. * * [in] memref[0] = [ * 32bit session handle, * 32bit wrapping key handle, * 32bit key handle, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = wrapped key * * This command relates to the PKCS#11 API function C_WrapKey(). */ PKCS11_CMD_WRAP_KEY = 51, /* * PKCS11_CMD_UNWRAP_KEY - Unwraps a wrapped key, creating a new * private or secret key object. * * [in] memref[0] = [ * 32bit session handle, * 32bit unwrapping key handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = wrapped key * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_UnwrapKey(). */ PKCS11_CMD_UNWRAP_KEY = 52, }; /* * Command return codes * PKCS11_ relates CryptoKi client API CKR_ */ enum pkcs11_rc { PKCS11_CKR_OK = 0, PKCS11_CKR_CANCEL = 0x0001, PKCS11_CKR_SLOT_ID_INVALID = 0x0003, PKCS11_CKR_GENERAL_ERROR = 0x0005, PKCS11_CKR_FUNCTION_FAILED = 0x0006, PKCS11_CKR_ARGUMENTS_BAD = 0x0007, PKCS11_CKR_ATTRIBUTE_READ_ONLY = 0x0010, PKCS11_CKR_ATTRIBUTE_SENSITIVE = 0x0011, PKCS11_CKR_ATTRIBUTE_TYPE_INVALID = 0x0012, PKCS11_CKR_ATTRIBUTE_VALUE_INVALID = 0x0013, PKCS11_CKR_ACTION_PROHIBITED = 0x001b, PKCS11_CKR_DATA_INVALID = 0x0020, PKCS11_CKR_DATA_LEN_RANGE = 0x0021, PKCS11_CKR_DEVICE_ERROR = 0x0030, PKCS11_CKR_DEVICE_MEMORY = 0x0031, PKCS11_CKR_DEVICE_REMOVED = 0x0032, PKCS11_CKR_ENCRYPTED_DATA_INVALID = 0x0040, PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE = 0x0041, PKCS11_CKR_KEY_HANDLE_INVALID = 0x0060, PKCS11_CKR_KEY_SIZE_RANGE = 0x0062, PKCS11_CKR_KEY_TYPE_INCONSISTENT = 0x0063, PKCS11_CKR_KEY_INDIGESTIBLE = 0x0067, PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED = 0x0068, PKCS11_CKR_KEY_NOT_WRAPPABLE = 0x0069, PKCS11_CKR_KEY_UNEXTRACTABLE = 0x006a, PKCS11_CKR_MECHANISM_INVALID = 0x0070, PKCS11_CKR_MECHANISM_PARAM_INVALID = 0x0071, PKCS11_CKR_OBJECT_HANDLE_INVALID = 0x0082, PKCS11_CKR_OPERATION_ACTIVE = 0x0090, PKCS11_CKR_OPERATION_NOT_INITIALIZED = 0x0091, PKCS11_CKR_PIN_INCORRECT = 0x00a0, PKCS11_CKR_PIN_INVALID = 0x00a1, PKCS11_CKR_PIN_LEN_RANGE = 0x00a2, PKCS11_CKR_PIN_EXPIRED = 0x00a3, PKCS11_CKR_PIN_LOCKED = 0x00a4, PKCS11_CKR_SESSION_CLOSED = 0x00b0, PKCS11_CKR_SESSION_COUNT = 0x00b1, PKCS11_CKR_SESSION_HANDLE_INVALID = 0x00b3, PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x00b4, PKCS11_CKR_SESSION_READ_ONLY = 0x00b5, PKCS11_CKR_SESSION_EXISTS = 0x00b6, PKCS11_CKR_SESSION_READ_ONLY_EXISTS = 0x00b7, PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS = 0x00b8, PKCS11_CKR_SIGNATURE_INVALID = 0x00c0, PKCS11_CKR_SIGNATURE_LEN_RANGE = 0x00c1, PKCS11_CKR_TEMPLATE_INCOMPLETE = 0x00d0, PKCS11_CKR_TEMPLATE_INCONSISTENT = 0x00d1, PKCS11_CKR_TOKEN_NOT_PRESENT = 0x00e0, PKCS11_CKR_TOKEN_NOT_RECOGNIZED = 0x00e1, PKCS11_CKR_TOKEN_WRITE_PROTECTED = 0x00e2, PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x00f0, PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x00f1, PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x00f2, PKCS11_CKR_USER_ALREADY_LOGGED_IN = 0x0100, PKCS11_CKR_USER_NOT_LOGGED_IN = 0x0101, PKCS11_CKR_USER_PIN_NOT_INITIALIZED = 0x0102, PKCS11_CKR_USER_TYPE_INVALID = 0x0103, PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x0104, PKCS11_CKR_USER_TOO_MANY_TYPES = 0x0105, PKCS11_CKR_WRAPPED_KEY_INVALID = 0x0110, PKCS11_CKR_WRAPPED_KEY_LEN_RANGE = 0x0112, PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID = 0x0113, PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE = 0x0114, PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x0115, PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED = 0x0120, PKCS11_CKR_RANDOM_NO_RNG = 0x0121, PKCS11_CKR_DOMAIN_PARAMS_INVALID = 0x0130, PKCS11_CKR_CURVE_NOT_SUPPORTED = 0x0140, PKCS11_CKR_BUFFER_TOO_SMALL = 0x0150, PKCS11_CKR_SAVED_STATE_INVALID = 0x0160, PKCS11_CKR_INFORMATION_SENSITIVE = 0x0170, PKCS11_CKR_STATE_UNSAVEABLE = 0x0180, PKCS11_CKR_PIN_TOO_WEAK = 0x01b8, PKCS11_CKR_PUBLIC_KEY_INVALID = 0x01b9, PKCS11_CKR_FUNCTION_REJECTED = 0x0200, /* Vendor specific IDs not returned to client */ PKCS11_RV_NOT_FOUND = 0x80000000, PKCS11_RV_NOT_IMPLEMENTED = 0x80000001, }; /* * Arguments for PKCS11_CMD_SLOT_INFO */ #define PKCS11_SLOT_DESC_SIZE 64 #define PKCS11_SLOT_MANUFACTURER_SIZE 32 #define PKCS11_SLOT_VERSION_SIZE 2 struct pkcs11_slot_info { uint8_t slot_description[PKCS11_SLOT_DESC_SIZE]; uint8_t manufacturer_id[PKCS11_SLOT_MANUFACTURER_SIZE]; uint32_t flags; uint8_t hardware_version[PKCS11_SLOT_VERSION_SIZE]; uint8_t firmware_version[PKCS11_SLOT_VERSION_SIZE]; }; /* * Values for pkcs11_slot_info::flags. * PKCS11_CKFS_ reflects CryptoKi client API slot flags CKF_. */ #define PKCS11_CKFS_TOKEN_PRESENT (1U << 0) #define PKCS11_CKFS_REMOVABLE_DEVICE (1U << 1) #define PKCS11_CKFS_HW_SLOT (1U << 2) /* * Arguments for PKCS11_CMD_TOKEN_INFO */ #define PKCS11_TOKEN_LABEL_SIZE 32 #define PKCS11_TOKEN_MANUFACTURER_SIZE 32 #define PKCS11_TOKEN_MODEL_SIZE 16 #define PKCS11_TOKEN_SERIALNUM_SIZE 16 struct pkcs11_token_info { uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; uint8_t manufacturer_id[PKCS11_TOKEN_MANUFACTURER_SIZE]; uint8_t model[PKCS11_TOKEN_MODEL_SIZE]; uint8_t serial_number[PKCS11_TOKEN_SERIALNUM_SIZE]; uint32_t flags; uint32_t max_session_count; uint32_t session_count; uint32_t max_rw_session_count; uint32_t rw_session_count; uint32_t max_pin_len; uint32_t min_pin_len; uint32_t total_public_memory; uint32_t free_public_memory; uint32_t total_private_memory; uint32_t free_private_memory; uint8_t hardware_version[2]; uint8_t firmware_version[2]; uint8_t utc_time[16]; }; /* * Values for pkcs11_token_info::flags. * PKCS11_CKFT_ reflects CryptoKi client API token flags CKF_. */ #define PKCS11_CKFT_RNG (1U << 0) #define PKCS11_CKFT_WRITE_PROTECTED (1U << 1) #define PKCS11_CKFT_LOGIN_REQUIRED (1U << 2) #define PKCS11_CKFT_USER_PIN_INITIALIZED (1U << 3) #define PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED (1U << 5) #define PKCS11_CKFT_CLOCK_ON_TOKEN (1U << 6) #define PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH (1U << 8) #define PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS (1U << 9) #define PKCS11_CKFT_TOKEN_INITIALIZED (1U << 10) #define PKCS11_CKFT_SECONDARY_AUTHENTICATION (1U << 11) #define PKCS11_CKFT_USER_PIN_COUNT_LOW (1U << 16) #define PKCS11_CKFT_USER_PIN_FINAL_TRY (1U << 17) #define PKCS11_CKFT_USER_PIN_LOCKED (1U << 18) #define PKCS11_CKFT_USER_PIN_TO_BE_CHANGED (1U << 19) #define PKCS11_CKFT_SO_PIN_COUNT_LOW (1U << 20) #define PKCS11_CKFT_SO_PIN_FINAL_TRY (1U << 21) #define PKCS11_CKFT_SO_PIN_LOCKED (1U << 22) #define PKCS11_CKFT_SO_PIN_TO_BE_CHANGED (1U << 23) #define PKCS11_CKFT_ERROR_STATE (1U << 24) /* Values for user identity */ enum pkcs11_user_type { PKCS11_CKU_SO = 0x000, PKCS11_CKU_USER = 0x001, PKCS11_CKU_CONTEXT_SPECIFIC = 0x002, }; /* * TEE Identity based authentication for tokens * * When configuration CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled TEE Identity * based authentication scheme is enabled. * * Feature enablement per token basis is controlled by token flag: * pkcs11_token_info->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH * * When calling C_InitToken() mode is determined based on SO PIN value. * - If the PIN is empty (or NULL_PTR) then active client TEE Identity will be * used as SO TEE Identity * - If the PIN is given then normal PIN behavior is used * * Once TEE Identity based authentication is activated following operational * changes happen: * - PIN failure counters are disabled to prevent token authentication lockups * - Switching to different authentication mode needs C_InitToken() * - When C_Login() or so is performed actual PIN value is ignored and active * client TEE Identity will be used * * Different types of TEE Identity authentication methods can be configured: * - Configured with C_InitToken(), C_InitPIN() or by C_SetPIN() * - PIN value follows below PIN syntax * * TEE Identity based authenticate PIN syntax: * - PIN value: NULL_PTR or empty * - Use active client TEE Identity * - PIN value: public * - TEE public login * - PIN value: user: * - TEE user login with client UUID matching user credentials * - PIN value: group: * - TEE group login with client UUID matching group credentials */ /* Keywords for protected authenticated path PIN parser */ #define PKCS11_AUTH_TEE_IDENTITY_PUBLIC "public" #define PKCS11_AUTH_TEE_IDENTITY_USER "user:" #define PKCS11_AUTH_TEE_IDENTITY_GROUP "group:" /* * Values for 32bit session flags argument to PKCS11_CMD_OPEN_SESSION * and pkcs11_session_info::flags. * PKCS11_CKFSS_ reflects CryptoKi client API session flags CKF_. */ #define PKCS11_CKFSS_RW_SESSION (1U << 1) #define PKCS11_CKFSS_SERIAL_SESSION (1U << 2) /* * Arguments for PKCS11_CMD_SESSION_INFO */ struct pkcs11_session_info { uint32_t slot_id; uint32_t state; uint32_t flags; uint32_t device_error; }; /* Valid values for pkcs11_session_info::state */ enum pkcs11_session_state { PKCS11_CKS_RO_PUBLIC_SESSION = 0, PKCS11_CKS_RO_USER_FUNCTIONS = 1, PKCS11_CKS_RW_PUBLIC_SESSION = 2, PKCS11_CKS_RW_USER_FUNCTIONS = 3, PKCS11_CKS_RW_SO_FUNCTIONS = 4, }; /* * Arguments for PKCS11_CMD_MECHANISM_INFO */ struct pkcs11_mechanism_info { uint32_t min_key_size; uint32_t max_key_size; uint32_t flags; }; /* * Values for pkcs11_mechanism_info::flags. * PKCS11_CKFM_ reflects CryptoKi client API mechanism flags CKF_. */ #define PKCS11_CKFM_HW (1U << 0) #define PKCS11_CKFM_ENCRYPT (1U << 8) #define PKCS11_CKFM_DECRYPT (1U << 9) #define PKCS11_CKFM_DIGEST (1U << 10) #define PKCS11_CKFM_SIGN (1U << 11) #define PKCS11_CKFM_SIGN_RECOVER (1U << 12) #define PKCS11_CKFM_VERIFY (1U << 13) #define PKCS11_CKFM_VERIFY_RECOVER (1U << 14) #define PKCS11_CKFM_GENERATE (1U << 15) #define PKCS11_CKFM_GENERATE_KEY_PAIR (1U << 16) #define PKCS11_CKFM_WRAP (1U << 17) #define PKCS11_CKFM_UNWRAP (1U << 18) #define PKCS11_CKFM_DERIVE (1U << 19) #define PKCS11_CKFM_EC_F_P (1U << 20) #define PKCS11_CKFM_EC_F_2M (1U << 21) #define PKCS11_CKFM_EC_ECPARAMETERS (1U << 22) #define PKCS11_CKFM_EC_NAMEDCURVE (1U << 23) #define PKCS11_CKFM_EC_UNCOMPRESS (1U << 24) #define PKCS11_CKFM_EC_COMPRESS (1U << 25) /* * pkcs11_object_head - Header of object whose data are serialized in memory * * An object is made of several attributes. Attributes are stored one next to * the other with byte alignment as a serialized byte array. The byte array * of serialized attributes is prepended with the size of the attrs[] array * in bytes and the number of attributes in the array, yielding the struct * pkcs11_object_head. * * @attrs_size - byte size of whole byte array attrs[] * @attrs_count - number of attribute items stored in attrs[] * @attrs - then starts the attributes data */ struct pkcs11_object_head { uint32_t attrs_size; uint32_t attrs_count; uint8_t attrs[]; }; /* * Attribute reference in the TA ABI. Each attribute starts with a header * structure followed by the attribute value. The attribute byte size is * defined in the attribute header. * * @id - the 32bit identifier of the attribute, see PKCS11_CKA_ * @size - the 32bit value attribute byte size * @data - then starts the attribute value */ struct pkcs11_attribute_head { uint32_t id; uint32_t size; uint8_t data[]; }; /* * Attribute identification IDs as of v2.40 excluding deprecated IDs. * Valid values for struct pkcs11_attribute_head::id * PKCS11_CKA_ reflects CryptoKi client API attribute IDs CKA_. */ enum pkcs11_attr_id { PKCS11_CKA_CLASS = 0x0000, PKCS11_CKA_TOKEN = 0x0001, PKCS11_CKA_PRIVATE = 0x0002, PKCS11_CKA_LABEL = 0x0003, PKCS11_CKA_APPLICATION = 0x0010, PKCS11_CKA_VALUE = 0x0011, PKCS11_CKA_OBJECT_ID = 0x0012, PKCS11_CKA_CERTIFICATE_TYPE = 0x0080, PKCS11_CKA_ISSUER = 0x0081, PKCS11_CKA_SERIAL_NUMBER = 0x0082, PKCS11_CKA_AC_ISSUER = 0x0083, PKCS11_CKA_OWNER = 0x0084, PKCS11_CKA_ATTR_TYPES = 0x0085, PKCS11_CKA_TRUSTED = 0x0086, PKCS11_CKA_CERTIFICATE_CATEGORY = 0x0087, PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x0088, PKCS11_CKA_URL = 0x0089, PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x008a, PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x008b, PKCS11_CKA_NAME_HASH_ALGORITHM = 0x008c, PKCS11_CKA_CHECK_VALUE = 0x0090, PKCS11_CKA_KEY_TYPE = 0x0100, PKCS11_CKA_SUBJECT = 0x0101, PKCS11_CKA_ID = 0x0102, PKCS11_CKA_SENSITIVE = 0x0103, PKCS11_CKA_ENCRYPT = 0x0104, PKCS11_CKA_DECRYPT = 0x0105, PKCS11_CKA_WRAP = 0x0106, PKCS11_CKA_UNWRAP = 0x0107, PKCS11_CKA_SIGN = 0x0108, PKCS11_CKA_SIGN_RECOVER = 0x0109, PKCS11_CKA_VERIFY = 0x010a, PKCS11_CKA_VERIFY_RECOVER = 0x010b, PKCS11_CKA_DERIVE = 0x010c, PKCS11_CKA_START_DATE = 0x0110, PKCS11_CKA_END_DATE = 0x0111, PKCS11_CKA_MODULUS = 0x0120, PKCS11_CKA_MODULUS_BITS = 0x0121, PKCS11_CKA_PUBLIC_EXPONENT = 0x0122, PKCS11_CKA_PRIVATE_EXPONENT = 0x0123, PKCS11_CKA_PRIME_1 = 0x0124, PKCS11_CKA_PRIME_2 = 0x0125, PKCS11_CKA_EXPONENT_1 = 0x0126, PKCS11_CKA_EXPONENT_2 = 0x0127, PKCS11_CKA_COEFFICIENT = 0x0128, PKCS11_CKA_PUBLIC_KEY_INFO = 0x0129, PKCS11_CKA_PRIME = 0x0130, PKCS11_CKA_SUBPRIME = 0x0131, PKCS11_CKA_BASE = 0x0132, PKCS11_CKA_PRIME_BITS = 0x0133, PKCS11_CKA_SUBPRIME_BITS = 0x0134, PKCS11_CKA_VALUE_BITS = 0x0160, PKCS11_CKA_VALUE_LEN = 0x0161, PKCS11_CKA_EXTRACTABLE = 0x0162, PKCS11_CKA_LOCAL = 0x0163, PKCS11_CKA_NEVER_EXTRACTABLE = 0x0164, PKCS11_CKA_ALWAYS_SENSITIVE = 0x0165, PKCS11_CKA_KEY_GEN_MECHANISM = 0x0166, PKCS11_CKA_MODIFIABLE = 0x0170, PKCS11_CKA_COPYABLE = 0x0171, PKCS11_CKA_DESTROYABLE = 0x0172, PKCS11_CKA_EC_PARAMS = 0x0180, PKCS11_CKA_EC_POINT = 0x0181, PKCS11_CKA_ALWAYS_AUTHENTICATE = 0x0202, PKCS11_CKA_WRAP_WITH_TRUSTED = 0x0210, /* * The leading 4 comes from the PKCS#11 spec or:ing with * CKF_ARRAY_ATTRIBUTE = 0x40000000. */ PKCS11_CKA_WRAP_TEMPLATE = 0x40000211, PKCS11_CKA_UNWRAP_TEMPLATE = 0x40000212, PKCS11_CKA_DERIVE_TEMPLATE = 0x40000213, PKCS11_CKA_OTP_FORMAT = 0x0220, PKCS11_CKA_OTP_LENGTH = 0x0221, PKCS11_CKA_OTP_TIME_INTERVAL = 0x0222, PKCS11_CKA_OTP_USER_FRIENDLY_MODE = 0x0223, PKCS11_CKA_OTP_CHALLENGE_REQUIREMENT = 0x0224, PKCS11_CKA_OTP_TIME_REQUIREMENT = 0x0225, PKCS11_CKA_OTP_COUNTER_REQUIREMENT = 0x0226, PKCS11_CKA_OTP_PIN_REQUIREMENT = 0x0227, PKCS11_CKA_OTP_COUNTER = 0x022e, PKCS11_CKA_OTP_TIME = 0x022f, PKCS11_CKA_OTP_USER_IDENTIFIER = 0x022a, PKCS11_CKA_OTP_SERVICE_IDENTIFIER = 0x022b, PKCS11_CKA_OTP_SERVICE_LOGO = 0x022c, PKCS11_CKA_OTP_SERVICE_LOGO_TYPE = 0x022d, PKCS11_CKA_GOSTR3410_PARAMS = 0x0250, PKCS11_CKA_GOSTR3411_PARAMS = 0x0251, PKCS11_CKA_GOST28147_PARAMS = 0x0252, PKCS11_CKA_HW_FEATURE_TYPE = 0x0300, PKCS11_CKA_RESET_ON_INIT = 0x0301, PKCS11_CKA_HAS_RESET = 0x0302, PKCS11_CKA_PIXEL_X = 0x0400, PKCS11_CKA_PIXEL_Y = 0x0401, PKCS11_CKA_RESOLUTION = 0x0402, PKCS11_CKA_CHAR_ROWS = 0x0403, PKCS11_CKA_CHAR_COLUMNS = 0x0404, PKCS11_CKA_COLOR = 0x0405, PKCS11_CKA_BITS_PER_PIXEL = 0x0406, PKCS11_CKA_CHAR_SETS = 0x0480, PKCS11_CKA_ENCODING_METHODS = 0x0481, PKCS11_CKA_MIME_TYPES = 0x0482, PKCS11_CKA_MECHANISM_TYPE = 0x0500, PKCS11_CKA_REQUIRED_CMS_ATTRIBUTES = 0x0501, PKCS11_CKA_DEFAULT_CMS_ATTRIBUTES = 0x0502, PKCS11_CKA_SUPPORTED_CMS_ATTRIBUTES = 0x0503, /* * The leading 4 comes from the PKCS#11 spec or:ing with * CKF_ARRAY_ATTRIBUTE = 0x40000000. */ PKCS11_CKA_ALLOWED_MECHANISMS = 0x40000600, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKA_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CLASS * PKCS11_CKO_ reflects CryptoKi client API object class IDs CKO_. */ enum pkcs11_class_id { PKCS11_CKO_DATA = 0x000, PKCS11_CKO_CERTIFICATE = 0x001, PKCS11_CKO_PUBLIC_KEY = 0x002, PKCS11_CKO_PRIVATE_KEY = 0x003, PKCS11_CKO_SECRET_KEY = 0x004, PKCS11_CKO_HW_FEATURE = 0x005, PKCS11_CKO_DOMAIN_PARAMETERS = 0x006, PKCS11_CKO_MECHANISM = 0x007, PKCS11_CKO_OTP_KEY = 0x008, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKO_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_KEY_TYPE * PKCS11_CKK_ reflects CryptoKi client API key type IDs CKK_. * Note that this is only a subset of the PKCS#11 specification. */ enum pkcs11_key_type { PKCS11_CKK_RSA = 0x000, PKCS11_CKK_DSA = 0x001, PKCS11_CKK_DH = 0x002, PKCS11_CKK_EC = 0x003, PKCS11_CKK_GENERIC_SECRET = 0x010, PKCS11_CKK_AES = 0x01f, PKCS11_CKK_MD5_HMAC = 0x027, PKCS11_CKK_SHA_1_HMAC = 0x028, PKCS11_CKK_SHA256_HMAC = 0x02b, PKCS11_CKK_SHA384_HMAC = 0x02c, PKCS11_CKK_SHA512_HMAC = 0x02d, PKCS11_CKK_SHA224_HMAC = 0x02e, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKK_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CERTIFICATE_TYPE */ enum pkcs11_certificate_type { PKCS11_CKC_X_509 = 0x00000000UL, PKCS11_CKC_X_509_ATTR_CERT = 0x00000001UL, PKCS11_CKC_WTLS = 0x00000002UL, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKC_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CERTIFICATE_CATEGORY */ enum pkcs11_certificate_category { PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0UL, PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1UL, PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY = 2UL, PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3UL, }; /* * Valid values for mechanism IDs * PKCS11_CKM_ reflects CryptoKi client API mechanism IDs CKM_. */ enum pkcs11_mechanism_id { PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000, PKCS11_CKM_RSA_PKCS = 0x00001, PKCS11_CKM_RSA_9796 = 0x00002, PKCS11_CKM_RSA_X_509 = 0x00003, PKCS11_CKM_MD5_RSA_PKCS = 0x00005, PKCS11_CKM_SHA1_RSA_PKCS = 0x00006, PKCS11_CKM_RSA_PKCS_OAEP = 0x00009, PKCS11_CKM_RSA_PKCS_PSS = 0x0000d, PKCS11_CKM_SHA1_RSA_PKCS_PSS = 0x0000e, PKCS11_CKM_SHA256_RSA_PKCS = 0x00040, PKCS11_CKM_SHA384_RSA_PKCS = 0x00041, PKCS11_CKM_SHA512_RSA_PKCS = 0x00042, PKCS11_CKM_SHA256_RSA_PKCS_PSS = 0x00043, PKCS11_CKM_SHA384_RSA_PKCS_PSS = 0x00044, PKCS11_CKM_SHA512_RSA_PKCS_PSS = 0x00045, PKCS11_CKM_SHA224_RSA_PKCS = 0x00046, PKCS11_CKM_SHA224_RSA_PKCS_PSS = 0x00047, PKCS11_CKM_SHA512_224 = 0x00048, PKCS11_CKM_SHA512_224_HMAC = 0x00049, PKCS11_CKM_SHA512_224_HMAC_GENERAL = 0x0004a, PKCS11_CKM_SHA512_224_KEY_DERIVATION = 0x0004b, PKCS11_CKM_SHA512_256 = 0x0004c, PKCS11_CKM_SHA512_256_HMAC = 0x0004d, PKCS11_CKM_SHA512_256_HMAC_GENERAL = 0x0004e, PKCS11_CKM_SHA512_256_KEY_DERIVATION = 0x0004f, PKCS11_CKM_DES3_ECB = 0x00132, PKCS11_CKM_DES3_CBC = 0x00133, PKCS11_CKM_DES3_MAC = 0x00134, PKCS11_CKM_DES3_MAC_GENERAL = 0x00135, PKCS11_CKM_DES3_CBC_PAD = 0x00136, PKCS11_CKM_DES3_CMAC_GENERAL = 0x00137, PKCS11_CKM_DES3_CMAC = 0x00138, PKCS11_CKM_MD5 = 0x00210, PKCS11_CKM_MD5_HMAC = 0x00211, PKCS11_CKM_MD5_HMAC_GENERAL = 0x00212, PKCS11_CKM_SHA_1 = 0x00220, PKCS11_CKM_SHA_1_HMAC = 0x00221, PKCS11_CKM_SHA_1_HMAC_GENERAL = 0x00222, PKCS11_CKM_SHA256 = 0x00250, PKCS11_CKM_SHA256_HMAC = 0x00251, PKCS11_CKM_SHA256_HMAC_GENERAL = 0x00252, PKCS11_CKM_SHA224 = 0x00255, PKCS11_CKM_SHA224_HMAC = 0x00256, PKCS11_CKM_SHA224_HMAC_GENERAL = 0x00257, PKCS11_CKM_SHA384 = 0x00260, PKCS11_CKM_SHA384_HMAC = 0x00261, PKCS11_CKM_SHA384_HMAC_GENERAL = 0x00262, PKCS11_CKM_SHA512 = 0x00270, PKCS11_CKM_SHA512_HMAC = 0x00271, PKCS11_CKM_SHA512_HMAC_GENERAL = 0x00272, PKCS11_CKM_HOTP_KEY_GEN = 0x00290, PKCS11_CKM_HOTP = 0x00291, PKCS11_CKM_GENERIC_SECRET_KEY_GEN = 0x00350, PKCS11_CKM_MD5_KEY_DERIVATION = 0x00390, PKCS11_CKM_MD2_KEY_DERIVATION = 0x00391, PKCS11_CKM_SHA1_KEY_DERIVATION = 0x00392, PKCS11_CKM_SHA256_KEY_DERIVATION = 0x00393, PKCS11_CKM_SHA384_KEY_DERIVATION = 0x00394, PKCS11_CKM_SHA512_KEY_DERIVATION = 0x00395, PKCS11_CKM_SHA224_KEY_DERIVATION = 0x00396, PKCS11_CKM_EC_KEY_PAIR_GEN = 0x01040, PKCS11_CKM_ECDSA = 0x01041, PKCS11_CKM_ECDSA_SHA1 = 0x01042, PKCS11_CKM_ECDSA_SHA224 = 0x01043, PKCS11_CKM_ECDSA_SHA256 = 0x01044, PKCS11_CKM_ECDSA_SHA384 = 0x01045, PKCS11_CKM_ECDSA_SHA512 = 0x01046, PKCS11_CKM_ECDH1_DERIVE = 0x01050, PKCS11_CKM_ECDH1_COFACTOR_DERIVE = 0x01051, PKCS11_CKM_ECMQV_DERIVE = 0x01052, PKCS11_CKM_ECDH_AES_KEY_WRAP = 0x01053, PKCS11_CKM_RSA_AES_KEY_WRAP = 0x01054, PKCS11_CKM_EDDSA = 0x01057, PKCS11_CKM_AES_KEY_GEN = 0x01080, PKCS11_CKM_AES_ECB = 0x01081, PKCS11_CKM_AES_CBC = 0x01082, PKCS11_CKM_AES_MAC = 0x01083, PKCS11_CKM_AES_MAC_GENERAL = 0x01084, PKCS11_CKM_AES_CBC_PAD = 0x01085, PKCS11_CKM_AES_CTR = 0x01086, PKCS11_CKM_AES_GCM = 0x01087, PKCS11_CKM_AES_CCM = 0x01088, PKCS11_CKM_AES_CTS = 0x01089, PKCS11_CKM_AES_CMAC = 0x0108a, PKCS11_CKM_AES_CMAC_GENERAL = 0x0108b, PKCS11_CKM_AES_XCBC_MAC = 0x0108c, PKCS11_CKM_AES_XCBC_MAC_96 = 0x0108d, PKCS11_CKM_AES_GMAC = 0x0108e, PKCS11_CKM_DES3_ECB_ENCRYPT_DATA = 0x01102, PKCS11_CKM_DES3_CBC_ENCRYPT_DATA = 0x01103, PKCS11_CKM_AES_ECB_ENCRYPT_DATA = 0x01104, PKCS11_CKM_AES_CBC_ENCRYPT_DATA = 0x01105, PKCS11_CKM_AES_KEY_WRAP = 0x02109, PKCS11_CKM_AES_KEY_WRAP_PAD = 0x0210a, /* * Vendor extensions below. * PKCS11 added IDs for operation not related to a CK mechanism ID */ PKCS11_PROCESSING_IMPORT = 0x80000000, PKCS11_CKM_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values MG function identifiers * PKCS11_CKG_ reflects CryptoKi client API MG function IDs CKG_. */ enum pkcs11_mgf_id { PKCS11_CKG_MGF1_SHA1 = 0x0001, PKCS11_CKG_MGF1_SHA224 = 0x0005, PKCS11_CKG_MGF1_SHA256 = 0x0002, PKCS11_CKG_MGF1_SHA384 = 0x0003, PKCS11_CKG_MGF1_SHA512 = 0x0004, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKG_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for RSA PKCS/OAEP source type identifier * PKCS11_CKZ_ reflects CryptoKi client API source type IDs CKZ_. */ #define PKCS11_CKZ_DATA_SPECIFIED 0x0001 #endif /*PKCS11_TA_H*/ optee_client-4.1.0/libckteec/src/000077500000000000000000000000001455150071200167025ustar00rootroot00000000000000optee_client-4.1.0/libckteec/src/ck_debug.c000066400000000000000000000331251455150071200206150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include "local_utils.h" #define CK2STR_ENTRY(id) case id: return #id const char *ckr2str(CK_RV id) { switch (id) { CK2STR_ENTRY(CKR_OK); CK2STR_ENTRY(CKR_CANCEL); CK2STR_ENTRY(CKR_HOST_MEMORY); CK2STR_ENTRY(CKR_SLOT_ID_INVALID); CK2STR_ENTRY(CKR_GENERAL_ERROR); CK2STR_ENTRY(CKR_FUNCTION_FAILED); CK2STR_ENTRY(CKR_ARGUMENTS_BAD); CK2STR_ENTRY(CKR_NO_EVENT); CK2STR_ENTRY(CKR_NEED_TO_CREATE_THREADS); CK2STR_ENTRY(CKR_CANT_LOCK); CK2STR_ENTRY(CKR_ATTRIBUTE_READ_ONLY); CK2STR_ENTRY(CKR_ATTRIBUTE_SENSITIVE); CK2STR_ENTRY(CKR_ATTRIBUTE_TYPE_INVALID); CK2STR_ENTRY(CKR_ATTRIBUTE_VALUE_INVALID); CK2STR_ENTRY(CKR_ACTION_PROHIBITED); CK2STR_ENTRY(CKR_DATA_INVALID); CK2STR_ENTRY(CKR_DATA_LEN_RANGE); CK2STR_ENTRY(CKR_DEVICE_ERROR); CK2STR_ENTRY(CKR_DEVICE_MEMORY); CK2STR_ENTRY(CKR_DEVICE_REMOVED); CK2STR_ENTRY(CKR_ENCRYPTED_DATA_INVALID); CK2STR_ENTRY(CKR_ENCRYPTED_DATA_LEN_RANGE); CK2STR_ENTRY(CKR_FUNCTION_CANCELED); CK2STR_ENTRY(CKR_FUNCTION_NOT_PARALLEL); CK2STR_ENTRY(CKR_FUNCTION_NOT_SUPPORTED); CK2STR_ENTRY(CKR_KEY_HANDLE_INVALID); CK2STR_ENTRY(CKR_KEY_SIZE_RANGE); CK2STR_ENTRY(CKR_KEY_TYPE_INCONSISTENT); CK2STR_ENTRY(CKR_KEY_NOT_NEEDED); CK2STR_ENTRY(CKR_KEY_CHANGED); CK2STR_ENTRY(CKR_KEY_NEEDED); CK2STR_ENTRY(CKR_KEY_INDIGESTIBLE); CK2STR_ENTRY(CKR_KEY_FUNCTION_NOT_PERMITTED); CK2STR_ENTRY(CKR_KEY_NOT_WRAPPABLE); CK2STR_ENTRY(CKR_KEY_UNEXTRACTABLE); CK2STR_ENTRY(CKR_MECHANISM_INVALID); CK2STR_ENTRY(CKR_MECHANISM_PARAM_INVALID); CK2STR_ENTRY(CKR_OBJECT_HANDLE_INVALID); CK2STR_ENTRY(CKR_OPERATION_ACTIVE); CK2STR_ENTRY(CKR_OPERATION_NOT_INITIALIZED); CK2STR_ENTRY(CKR_PIN_INCORRECT); CK2STR_ENTRY(CKR_PIN_INVALID); CK2STR_ENTRY(CKR_PIN_LEN_RANGE); CK2STR_ENTRY(CKR_PIN_EXPIRED); CK2STR_ENTRY(CKR_PIN_LOCKED); CK2STR_ENTRY(CKR_SESSION_CLOSED); CK2STR_ENTRY(CKR_SESSION_COUNT); CK2STR_ENTRY(CKR_SESSION_HANDLE_INVALID); CK2STR_ENTRY(CKR_SESSION_PARALLEL_NOT_SUPPORTED); CK2STR_ENTRY(CKR_SESSION_READ_ONLY); CK2STR_ENTRY(CKR_SESSION_EXISTS); CK2STR_ENTRY(CKR_SESSION_READ_ONLY_EXISTS); CK2STR_ENTRY(CKR_SESSION_READ_WRITE_SO_EXISTS); CK2STR_ENTRY(CKR_SIGNATURE_INVALID); CK2STR_ENTRY(CKR_SIGNATURE_LEN_RANGE); CK2STR_ENTRY(CKR_TEMPLATE_INCOMPLETE); CK2STR_ENTRY(CKR_TEMPLATE_INCONSISTENT); CK2STR_ENTRY(CKR_TOKEN_NOT_PRESENT); CK2STR_ENTRY(CKR_TOKEN_NOT_RECOGNIZED); CK2STR_ENTRY(CKR_TOKEN_WRITE_PROTECTED); CK2STR_ENTRY(CKR_UNWRAPPING_KEY_HANDLE_INVALID); CK2STR_ENTRY(CKR_UNWRAPPING_KEY_SIZE_RANGE); CK2STR_ENTRY(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT); CK2STR_ENTRY(CKR_USER_ALREADY_LOGGED_IN); CK2STR_ENTRY(CKR_USER_NOT_LOGGED_IN); CK2STR_ENTRY(CKR_USER_PIN_NOT_INITIALIZED); CK2STR_ENTRY(CKR_USER_TYPE_INVALID); CK2STR_ENTRY(CKR_USER_ANOTHER_ALREADY_LOGGED_IN); CK2STR_ENTRY(CKR_USER_TOO_MANY_TYPES); CK2STR_ENTRY(CKR_WRAPPED_KEY_INVALID); CK2STR_ENTRY(CKR_WRAPPED_KEY_LEN_RANGE); CK2STR_ENTRY(CKR_WRAPPING_KEY_HANDLE_INVALID); CK2STR_ENTRY(CKR_WRAPPING_KEY_SIZE_RANGE); CK2STR_ENTRY(CKR_WRAPPING_KEY_TYPE_INCONSISTENT); CK2STR_ENTRY(CKR_RANDOM_SEED_NOT_SUPPORTED); CK2STR_ENTRY(CKR_RANDOM_NO_RNG); CK2STR_ENTRY(CKR_DOMAIN_PARAMS_INVALID); CK2STR_ENTRY(CKR_CURVE_NOT_SUPPORTED); CK2STR_ENTRY(CKR_BUFFER_TOO_SMALL); CK2STR_ENTRY(CKR_SAVED_STATE_INVALID); CK2STR_ENTRY(CKR_INFORMATION_SENSITIVE); CK2STR_ENTRY(CKR_STATE_UNSAVEABLE); CK2STR_ENTRY(CKR_CRYPTOKI_NOT_INITIALIZED); CK2STR_ENTRY(CKR_CRYPTOKI_ALREADY_INITIALIZED); CK2STR_ENTRY(CKR_MUTEX_BAD); CK2STR_ENTRY(CKR_MUTEX_NOT_LOCKED); CK2STR_ENTRY(CKR_NEW_PIN_MODE); CK2STR_ENTRY(CKR_NEXT_OTP); CK2STR_ENTRY(CKR_EXCEEDED_MAX_ITERATIONS); CK2STR_ENTRY(CKR_FIPS_SELF_TEST_FAILED); CK2STR_ENTRY(CKR_LIBRARY_LOAD_FAILED); CK2STR_ENTRY(CKR_PIN_TOO_WEAK); CK2STR_ENTRY(CKR_PUBLIC_KEY_INVALID); CK2STR_ENTRY(CKR_FUNCTION_REJECTED); default: if (id & CKR_VENDOR_DEFINED) return "Vendor defined"; else return "Unknown ID"; } } const char *ckm2str(CK_MECHANISM_TYPE id) { switch (id) { CK2STR_ENTRY(CKM_RSA_PKCS_KEY_PAIR_GEN); CK2STR_ENTRY(CKM_RSA_PKCS); CK2STR_ENTRY(CKM_RSA_9796); CK2STR_ENTRY(CKM_RSA_X_509); CK2STR_ENTRY(CKM_MD5_RSA_PKCS); CK2STR_ENTRY(CKM_SHA1_RSA_PKCS); CK2STR_ENTRY(CKM_RSA_PKCS_OAEP); CK2STR_ENTRY(CKM_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA1_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA256_RSA_PKCS); CK2STR_ENTRY(CKM_SHA384_RSA_PKCS); CK2STR_ENTRY(CKM_SHA512_RSA_PKCS); CK2STR_ENTRY(CKM_SHA256_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA384_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA512_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA224_RSA_PKCS); CK2STR_ENTRY(CKM_SHA224_RSA_PKCS_PSS); CK2STR_ENTRY(CKM_SHA512_224); CK2STR_ENTRY(CKM_SHA512_224_HMAC); CK2STR_ENTRY(CKM_SHA512_224_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA512_224_KEY_DERIVATION); CK2STR_ENTRY(CKM_SHA512_256); CK2STR_ENTRY(CKM_SHA512_256_HMAC); CK2STR_ENTRY(CKM_SHA512_256_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA512_256_KEY_DERIVATION); CK2STR_ENTRY(CKM_MD5); CK2STR_ENTRY(CKM_MD5_HMAC); CK2STR_ENTRY(CKM_MD5_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA_1); CK2STR_ENTRY(CKM_SHA_1_HMAC); CK2STR_ENTRY(CKM_SHA_1_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA256); CK2STR_ENTRY(CKM_SHA256_HMAC); CK2STR_ENTRY(CKM_SHA256_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA224); CK2STR_ENTRY(CKM_SHA224_HMAC); CK2STR_ENTRY(CKM_SHA224_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA384); CK2STR_ENTRY(CKM_SHA384_HMAC); CK2STR_ENTRY(CKM_SHA384_HMAC_GENERAL); CK2STR_ENTRY(CKM_SHA512); CK2STR_ENTRY(CKM_SHA512_HMAC); CK2STR_ENTRY(CKM_SHA512_HMAC_GENERAL); CK2STR_ENTRY(CKM_HOTP_KEY_GEN); CK2STR_ENTRY(CKM_HOTP); CK2STR_ENTRY(CKM_GENERIC_SECRET_KEY_GEN); CK2STR_ENTRY(CKM_SHA1_KEY_DERIVATION); CK2STR_ENTRY(CKM_SHA256_KEY_DERIVATION); CK2STR_ENTRY(CKM_SHA384_KEY_DERIVATION); CK2STR_ENTRY(CKM_SHA512_KEY_DERIVATION); CK2STR_ENTRY(CKM_SHA224_KEY_DERIVATION); CK2STR_ENTRY(CKM_EC_KEY_PAIR_GEN); CK2STR_ENTRY(CKM_ECDSA); CK2STR_ENTRY(CKM_ECDSA_SHA1); CK2STR_ENTRY(CKM_ECDSA_SHA224); CK2STR_ENTRY(CKM_ECDSA_SHA256); CK2STR_ENTRY(CKM_ECDSA_SHA384); CK2STR_ENTRY(CKM_ECDSA_SHA512); CK2STR_ENTRY(CKM_ECDH1_DERIVE); CK2STR_ENTRY(CKM_ECDH1_COFACTOR_DERIVE); CK2STR_ENTRY(CKM_ECMQV_DERIVE); CK2STR_ENTRY(CKM_ECDH_AES_KEY_WRAP); CK2STR_ENTRY(CKM_RSA_AES_KEY_WRAP); CK2STR_ENTRY(CKM_AES_KEY_GEN); CK2STR_ENTRY(CKM_AES_ECB); CK2STR_ENTRY(CKM_AES_CBC); CK2STR_ENTRY(CKM_AES_MAC); CK2STR_ENTRY(CKM_AES_MAC_GENERAL); CK2STR_ENTRY(CKM_AES_CBC_PAD); CK2STR_ENTRY(CKM_AES_CTR); CK2STR_ENTRY(CKM_AES_GCM); CK2STR_ENTRY(CKM_AES_CCM); CK2STR_ENTRY(CKM_AES_CTS); CK2STR_ENTRY(CKM_AES_CMAC); CK2STR_ENTRY(CKM_AES_CMAC_GENERAL); CK2STR_ENTRY(CKM_AES_XCBC_MAC); CK2STR_ENTRY(CKM_AES_XCBC_MAC_96); CK2STR_ENTRY(CKM_AES_GMAC); CK2STR_ENTRY(CKM_DES3_ECB_ENCRYPT_DATA); CK2STR_ENTRY(CKM_DES3_CBC_ENCRYPT_DATA); CK2STR_ENTRY(CKM_AES_ECB_ENCRYPT_DATA); CK2STR_ENTRY(CKM_AES_CBC_ENCRYPT_DATA); CK2STR_ENTRY(CKM_AES_KEY_WRAP); CK2STR_ENTRY(CKM_AES_KEY_WRAP_PAD); default: if (id & CKM_VENDOR_DEFINED) return "Vendor defined"; else return "Unknown ID"; } } const char *slot_ckf2str(CK_ULONG flag) { switch (flag) { CK2STR_ENTRY(CKF_TOKEN_PRESENT); CK2STR_ENTRY(CKF_REMOVABLE_DEVICE); CK2STR_ENTRY(CKF_HW_SLOT); default: return "Unknown flag"; } } const char *token_ckf2str(CK_ULONG flag) { switch (flag) { CK2STR_ENTRY(CKF_RNG); CK2STR_ENTRY(CKF_WRITE_PROTECTED); CK2STR_ENTRY(CKF_LOGIN_REQUIRED); CK2STR_ENTRY(CKF_USER_PIN_INITIALIZED); CK2STR_ENTRY(CKF_RESTORE_KEY_NOT_NEEDED); CK2STR_ENTRY(CKF_CLOCK_ON_TOKEN); CK2STR_ENTRY(CKF_PROTECTED_AUTHENTICATION_PATH); CK2STR_ENTRY(CKF_DUAL_CRYPTO_OPERATIONS); CK2STR_ENTRY(CKF_TOKEN_INITIALIZED); CK2STR_ENTRY(CKF_SECONDARY_AUTHENTICATION); CK2STR_ENTRY(CKF_USER_PIN_COUNT_LOW); CK2STR_ENTRY(CKF_USER_PIN_FINAL_TRY); CK2STR_ENTRY(CKF_USER_PIN_LOCKED); CK2STR_ENTRY(CKF_USER_PIN_TO_BE_CHANGED); CK2STR_ENTRY(CKF_SO_PIN_COUNT_LOW); CK2STR_ENTRY(CKF_SO_PIN_FINAL_TRY); CK2STR_ENTRY(CKF_SO_PIN_LOCKED); CK2STR_ENTRY(CKF_SO_PIN_TO_BE_CHANGED); CK2STR_ENTRY(CKF_ERROR_STATE); default: return "Unknown flag"; } } const char *mecha_ckf2str(CK_ULONG flag) { switch (flag) { CK2STR_ENTRY(CKF_HW); CK2STR_ENTRY(CKF_ENCRYPT); CK2STR_ENTRY(CKF_DECRYPT); CK2STR_ENTRY(CKF_DIGEST); CK2STR_ENTRY(CKF_SIGN); CK2STR_ENTRY(CKF_SIGN_RECOVER); CK2STR_ENTRY(CKF_VERIFY); CK2STR_ENTRY(CKF_VERIFY_RECOVER); CK2STR_ENTRY(CKF_GENERATE); CK2STR_ENTRY(CKF_GENERATE_KEY_PAIR); CK2STR_ENTRY(CKF_WRAP); CK2STR_ENTRY(CKF_UNWRAP); CK2STR_ENTRY(CKF_DERIVE); CK2STR_ENTRY(CKF_EC_F_P); CK2STR_ENTRY(CKF_EC_F_2M); CK2STR_ENTRY(CKF_EC_ECPARAMETERS); CK2STR_ENTRY(CKF_EC_NAMEDCURVE); CK2STR_ENTRY(CKF_EC_UNCOMPRESS); CK2STR_ENTRY(CKF_EC_COMPRESS); CK2STR_ENTRY(CKF_EXTENSION); default: return "Unknown flag"; } } const char *session_ckf2str(CK_ULONG flag) { switch (flag) { CK2STR_ENTRY(CKF_RW_SESSION); CK2STR_ENTRY(CKF_SERIAL_SESSION); default: return "Unknown flag"; } } const char *session_cks2str(CK_ULONG flag) { switch (flag) { CK2STR_ENTRY(CKS_RO_PUBLIC_SESSION); CK2STR_ENTRY(CKS_RO_USER_FUNCTIONS); CK2STR_ENTRY(CKS_RW_PUBLIC_SESSION); CK2STR_ENTRY(CKS_RW_USER_FUNCTIONS); CK2STR_ENTRY(CKS_RW_SO_FUNCTIONS); default: return "Unknown flag"; } } const char *cka2str(CK_ATTRIBUTE_TYPE id) { switch (id) { /* Standard CK attributes */ CK2STR_ENTRY(CKA_CLASS); CK2STR_ENTRY(CKA_TOKEN); CK2STR_ENTRY(CKA_PRIVATE); CK2STR_ENTRY(CKA_LABEL); CK2STR_ENTRY(CKA_APPLICATION); CK2STR_ENTRY(CKA_VALUE); CK2STR_ENTRY(CKA_OBJECT_ID); CK2STR_ENTRY(CKA_CERTIFICATE_TYPE); CK2STR_ENTRY(CKA_ISSUER); CK2STR_ENTRY(CKA_SERIAL_NUMBER); CK2STR_ENTRY(CKA_AC_ISSUER); CK2STR_ENTRY(CKA_OWNER); CK2STR_ENTRY(CKA_ATTR_TYPES); CK2STR_ENTRY(CKA_TRUSTED); CK2STR_ENTRY(CKA_CERTIFICATE_CATEGORY); CK2STR_ENTRY(CKA_JAVA_MIDP_SECURITY_DOMAIN); CK2STR_ENTRY(CKA_URL); CK2STR_ENTRY(CKA_HASH_OF_SUBJECT_PUBLIC_KEY); CK2STR_ENTRY(CKA_HASH_OF_ISSUER_PUBLIC_KEY); CK2STR_ENTRY(CKA_NAME_HASH_ALGORITHM); CK2STR_ENTRY(CKA_CHECK_VALUE); CK2STR_ENTRY(CKA_KEY_TYPE); CK2STR_ENTRY(CKA_SUBJECT); CK2STR_ENTRY(CKA_ID); CK2STR_ENTRY(CKA_SENSITIVE); CK2STR_ENTRY(CKA_ENCRYPT); CK2STR_ENTRY(CKA_DECRYPT); CK2STR_ENTRY(CKA_WRAP); CK2STR_ENTRY(CKA_UNWRAP); CK2STR_ENTRY(CKA_SIGN); CK2STR_ENTRY(CKA_SIGN_RECOVER); CK2STR_ENTRY(CKA_VERIFY); CK2STR_ENTRY(CKA_VERIFY_RECOVER); CK2STR_ENTRY(CKA_DERIVE); CK2STR_ENTRY(CKA_START_DATE); CK2STR_ENTRY(CKA_END_DATE); CK2STR_ENTRY(CKA_MODULUS); CK2STR_ENTRY(CKA_MODULUS_BITS); CK2STR_ENTRY(CKA_PUBLIC_EXPONENT); CK2STR_ENTRY(CKA_PRIVATE_EXPONENT); CK2STR_ENTRY(CKA_PRIME_1); CK2STR_ENTRY(CKA_PRIME_2); CK2STR_ENTRY(CKA_EXPONENT_1); CK2STR_ENTRY(CKA_EXPONENT_2); CK2STR_ENTRY(CKA_COEFFICIENT); CK2STR_ENTRY(CKA_PUBLIC_KEY_INFO); CK2STR_ENTRY(CKA_PRIME); CK2STR_ENTRY(CKA_SUBPRIME); CK2STR_ENTRY(CKA_BASE); CK2STR_ENTRY(CKA_PRIME_BITS); CK2STR_ENTRY(CKA_SUBPRIME_BITS); CK2STR_ENTRY(CKA_VALUE_BITS); CK2STR_ENTRY(CKA_VALUE_LEN); CK2STR_ENTRY(CKA_EXTRACTABLE); CK2STR_ENTRY(CKA_LOCAL); CK2STR_ENTRY(CKA_NEVER_EXTRACTABLE); CK2STR_ENTRY(CKA_ALWAYS_SENSITIVE); CK2STR_ENTRY(CKA_KEY_GEN_MECHANISM); CK2STR_ENTRY(CKA_MODIFIABLE); CK2STR_ENTRY(CKA_COPYABLE); CK2STR_ENTRY(CKA_DESTROYABLE); CK2STR_ENTRY(CKA_EC_PARAMS); CK2STR_ENTRY(CKA_EC_POINT); CK2STR_ENTRY(CKA_ALWAYS_AUTHENTICATE); CK2STR_ENTRY(CKA_WRAP_WITH_TRUSTED); CK2STR_ENTRY(CKA_WRAP_TEMPLATE); CK2STR_ENTRY(CKA_UNWRAP_TEMPLATE); CK2STR_ENTRY(CKA_DERIVE_TEMPLATE); CK2STR_ENTRY(CKA_OTP_FORMAT); CK2STR_ENTRY(CKA_OTP_LENGTH); CK2STR_ENTRY(CKA_OTP_TIME_INTERVAL); CK2STR_ENTRY(CKA_OTP_USER_FRIENDLY_MODE); CK2STR_ENTRY(CKA_OTP_CHALLENGE_REQUIREMENT); CK2STR_ENTRY(CKA_OTP_TIME_REQUIREMENT); CK2STR_ENTRY(CKA_OTP_COUNTER_REQUIREMENT); CK2STR_ENTRY(CKA_OTP_PIN_REQUIREMENT); CK2STR_ENTRY(CKA_OTP_COUNTER); CK2STR_ENTRY(CKA_OTP_TIME); CK2STR_ENTRY(CKA_OTP_USER_IDENTIFIER); CK2STR_ENTRY(CKA_OTP_SERVICE_IDENTIFIER); CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO); CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO_TYPE); CK2STR_ENTRY(CKA_GOSTR3410_PARAMS); CK2STR_ENTRY(CKA_GOSTR3411_PARAMS); CK2STR_ENTRY(CKA_GOST28147_PARAMS); CK2STR_ENTRY(CKA_HW_FEATURE_TYPE); CK2STR_ENTRY(CKA_RESET_ON_INIT); CK2STR_ENTRY(CKA_HAS_RESET); CK2STR_ENTRY(CKA_PIXEL_X); CK2STR_ENTRY(CKA_PIXEL_Y); CK2STR_ENTRY(CKA_RESOLUTION); CK2STR_ENTRY(CKA_CHAR_ROWS); CK2STR_ENTRY(CKA_CHAR_COLUMNS); CK2STR_ENTRY(CKA_COLOR); CK2STR_ENTRY(CKA_BITS_PER_PIXEL); CK2STR_ENTRY(CKA_CHAR_SETS); CK2STR_ENTRY(CKA_ENCODING_METHODS); CK2STR_ENTRY(CKA_MIME_TYPES); CK2STR_ENTRY(CKA_MECHANISM_TYPE); CK2STR_ENTRY(CKA_REQUIRED_CMS_ATTRIBUTES); CK2STR_ENTRY(CKA_DEFAULT_CMS_ATTRIBUTES); CK2STR_ENTRY(CKA_SUPPORTED_CMS_ATTRIBUTES); CK2STR_ENTRY(CKA_ALLOWED_MECHANISMS); CK2STR_ENTRY(CKA_VENDOR_DEFINED); default: if (id & CKA_VENDOR_DEFINED) return "Vendor defined"; else return "Unknown ID"; } } const char *cko2str(CK_OBJECT_CLASS id) { switch (id) { CK2STR_ENTRY(CKO_DATA); CK2STR_ENTRY(CKO_CERTIFICATE); CK2STR_ENTRY(CKO_PUBLIC_KEY); CK2STR_ENTRY(CKO_PRIVATE_KEY); CK2STR_ENTRY(CKO_SECRET_KEY); CK2STR_ENTRY(CKO_HW_FEATURE); CK2STR_ENTRY(CKO_DOMAIN_PARAMETERS); CK2STR_ENTRY(CKO_MECHANISM); CK2STR_ENTRY(CKO_OTP_KEY); CK2STR_ENTRY(CKO_VENDOR_DEFINED); default: return "Unknown"; } } const char *ckk2str(CK_KEY_TYPE id) { switch (id) { CK2STR_ENTRY(CKK_RSA); CK2STR_ENTRY(CKK_DSA); CK2STR_ENTRY(CKK_DH); CK2STR_ENTRY(CKK_ECDSA); CK2STR_ENTRY(CKK_GENERIC_SECRET); CK2STR_ENTRY(CKK_DES3); CK2STR_ENTRY(CKK_AES); CK2STR_ENTRY(CKK_HOTP); CK2STR_ENTRY(CKK_MD5_HMAC); CK2STR_ENTRY(CKK_SHA_1_HMAC); CK2STR_ENTRY(CKK_SHA256_HMAC); CK2STR_ENTRY(CKK_SHA384_HMAC); CK2STR_ENTRY(CKK_SHA512_HMAC); CK2STR_ENTRY(CKK_SHA224_HMAC); CK2STR_ENTRY(CKK_VENDOR_DEFINED); default: return "Unknown"; } } optee_client-4.1.0/libckteec/src/ck_helpers.c000066400000000000000000000011011455150071200211560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include "ck_helpers.h" #ifdef DEBUG void ckteec_assert_expected_rv(const char *function, CK_RV rv, const CK_RV *expected_rv, size_t expected_count) { size_t n = 0; for (n = 0; n < expected_count; n++) if (rv == expected_rv[n]) return; fprintf(stderr, "libckteec: %s: unexpected return value 0x%lx (%s)\n", function, rv, ckr2str(rv)); assert(0); } #endif optee_client-4.1.0/libckteec/src/ck_helpers.h000066400000000000000000000012521455150071200211720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Linaro Limited */ #ifndef LIBCKTEEC_CK_HELPERS_H #define LIBCKTEEC_CK_HELPERS_H #include #include #include "local_utils.h" #ifdef DEBUG #define ASSERT_CK_RV(_rv, ...) \ do { \ const CK_RV ref[] = { __VA_ARGS__ }; \ size_t count = ARRAY_SIZE(ref); \ \ ckteec_assert_expected_rv(__func__, (_rv), ref, count); \ } while (0) void ckteec_assert_expected_rv(const char *function, CK_RV rv, const CK_RV *expected_rv, size_t expected_count); #else #define ASSERT_CK_RV(_rv, ...) (void)0 #endif /*DEBUG*/ #endif /*LIBCKTEEC_CK_HELPERS_H*/ optee_client-4.1.0/libckteec/src/invoke_ta.c000066400000000000000000000201521455150071200210250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ /* BINARY_PREFIX is expected by teec_trace.h */ #ifndef BINARY_PREFIX #define BINARY_PREFIX "ckteec" #endif #include #include #include #include #include #include #include #include #include #include #include #include "ck_helpers.h" #include "invoke_ta.h" #include "local_utils.h" struct ta_context { pthread_mutex_t init_mutex; bool initiated; TEEC_Context context; TEEC_Session session; }; static struct ta_context ta_ctx = { .init_mutex = PTHREAD_MUTEX_INITIALIZER, }; bool ckteec_invoke_initiated(void) { return ta_ctx.initiated; } TEEC_SharedMemory *ckteec_alloc_shm(size_t size, enum ckteec_shm_dir dir) { TEEC_SharedMemory *shm = NULL; switch (dir) { case CKTEEC_SHM_IN: case CKTEEC_SHM_OUT: case CKTEEC_SHM_INOUT: break; default: return NULL; } shm = calloc(1, sizeof(TEEC_SharedMemory)); if (!shm) return NULL; shm->size = size; if (dir == CKTEEC_SHM_IN || dir == CKTEEC_SHM_INOUT) shm->flags |= TEEC_MEM_INPUT; if (dir == CKTEEC_SHM_OUT || dir == CKTEEC_SHM_INOUT) shm->flags |= TEEC_MEM_OUTPUT; if (TEEC_AllocateSharedMemory(&ta_ctx.context, shm)) { free(shm); return NULL; } return shm; } TEEC_SharedMemory *ckteec_register_shm(void *buffer, size_t size, enum ckteec_shm_dir dir) { TEEC_SharedMemory *shm = NULL; switch (dir) { case CKTEEC_SHM_IN: case CKTEEC_SHM_OUT: case CKTEEC_SHM_INOUT: break; default: return NULL; } shm = calloc(1, sizeof(TEEC_SharedMemory)); if (!shm) return NULL; shm->buffer = buffer; shm->size = size; if (dir == CKTEEC_SHM_IN || dir == CKTEEC_SHM_INOUT) shm->flags |= TEEC_MEM_INPUT; if (dir == CKTEEC_SHM_OUT || dir == CKTEEC_SHM_INOUT) shm->flags |= TEEC_MEM_OUTPUT; if (TEEC_RegisterSharedMemory(&ta_ctx.context, shm)) { free(shm); return NULL; } return shm; } void ckteec_free_shm(TEEC_SharedMemory *shm) { TEEC_ReleaseSharedMemory(shm); free(shm); } static bool is_output_shm(TEEC_SharedMemory *shm) { return shm && (shm->flags & TEEC_MEM_OUTPUT); } CK_RV ckteec_invoke_ta(unsigned long cmd, TEEC_SharedMemory *ctrl, TEEC_SharedMemory *io1, TEEC_SharedMemory *io2, size_t *out2_size, TEEC_SharedMemory *io3, size_t *out3_size) { uint32_t command = (uint32_t)cmd; TEEC_Operation op; uint32_t origin = 0; TEEC_Result res = TEEC_ERROR_GENERIC; uint32_t ta_rc = PKCS11_CKR_GENERAL_ERROR; if ((is_output_shm(io2) && !out2_size) || (is_output_shm(io3) && !out3_size)) return CKR_ARGUMENTS_BAD; memset(&op, 0, sizeof(op)); if (ctrl && !(ctrl->flags & TEEC_MEM_INPUT && ctrl->flags & TEEC_MEM_OUTPUT)) return CKR_ARGUMENTS_BAD; if (ctrl) { op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, 0, 0, 0); op.params[0].memref.parent = ctrl; } else { /* TA mandates param#0 as in/out memref for output status */ op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, 0, 0, 0); op.params[0].tmpref.buffer = &ta_rc; op.params[0].tmpref.size = sizeof(ta_rc); } if (io1) { op.paramTypes |= TEEC_PARAM_TYPES(0, TEEC_MEMREF_WHOLE, 0, 0); op.params[1].memref.parent = io1; } if (io2) { op.paramTypes |= TEEC_PARAM_TYPES(0, 0, TEEC_MEMREF_WHOLE, 0); op.params[2].memref.parent = io2; } if (io3) { op.paramTypes |= TEEC_PARAM_TYPES(0, 0, 0, TEEC_MEMREF_WHOLE); op.params[3].memref.parent = io3; } res = TEEC_InvokeCommand(&ta_ctx.session, command, &op, &origin); switch (res) { case TEEC_SUCCESS: /* Get PKCS11 TA return value from ctrl buffer */ if (ctrl) { if (op.params[0].memref.size == sizeof(ta_rc)) memcpy(&ta_rc, ctrl->buffer, sizeof(ta_rc)); } else { if (op.params[0].tmpref.size != sizeof(ta_rc)) ta_rc = PKCS11_CKR_GENERAL_ERROR; } break; case TEEC_ERROR_SHORT_BUFFER: ta_rc = CKR_BUFFER_TOO_SMALL; break; case TEEC_ERROR_OUT_OF_MEMORY: return CKR_DEVICE_MEMORY; default: return CKR_GENERAL_ERROR; } if (ta_rc == CKR_OK || ta_rc == CKR_BUFFER_TOO_SMALL) { if (is_output_shm(io2)) *out2_size = op.params[2].memref.size; if (is_output_shm(io3)) *out3_size = op.params[3].memref.size; } return ta_rc; } static CK_RV ping_ta(void) { TEEC_Operation op = { 0 }; uint32_t origin = 0; TEEC_Result res = TEEC_SUCCESS; uint32_t ta_version[3] = { 0 }; uint32_t status = 0; memset(&op, 0, sizeof(op)); op.params[0].tmpref.buffer = &status; op.params[0].tmpref.size = sizeof(status); op.params[2].tmpref.buffer = ta_version; op.params[2].tmpref.size = sizeof(ta_version); op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); res = TEEC_InvokeCommand(&ta_ctx.session, PKCS11_CMD_PING, &op, &origin); if (res != TEEC_SUCCESS || origin != TEEC_ORIGIN_TRUSTED_APP || op.params[0].tmpref.size != sizeof(status) || status != PKCS11_CKR_OK) return CKR_DEVICE_ERROR; if (ta_version[0] != PKCS11_TA_VERSION_MAJOR && ta_version[1] > PKCS11_TA_VERSION_MINOR) { EMSG("PKCS11 TA version mismatch: %"PRIu32".%"PRIu32".%"PRIu32, ta_version[0], ta_version[1], ta_version[2]); return CKR_DEVICE_ERROR; } DMSG("PKCS11 TA version %"PRIu32".%"PRIu32".%"PRIu32, ta_version[0], ta_version[1], ta_version[2]); return CKR_OK; } CK_RV ckteec_invoke_init(void) { TEEC_UUID uuid = PKCS11_TA_UUID; uint32_t origin = 0; TEEC_Result res = TEEC_SUCCESS; CK_RV rv = CKR_CRYPTOKI_ALREADY_INITIALIZED; const char *login_type_env = NULL; const char *login_gid_env = NULL; uint32_t login_method = TEEC_LOGIN_PUBLIC; void *login_data = NULL; gid_t login_gid = 0; unsigned long tmpconv = 0; char *endp = NULL; int e = 0; login_type_env = getenv("CKTEEC_LOGIN_TYPE"); if (login_type_env) { if (strcmp(login_type_env, "public") == 0) { login_method = TEEC_LOGIN_PUBLIC; } else if (strcmp(login_type_env, "user") == 0) { login_method = TEEC_LOGIN_USER; } else if (strcmp(login_type_env, "group") == 0) { login_gid_env = getenv("CKTEEC_LOGIN_GID"); if (!login_gid_env || !strlen(login_gid_env)) { EMSG("missing CKTEEC_LOGIN_GID"); rv = CKR_ARGUMENTS_BAD; goto out; } login_method = TEEC_LOGIN_GROUP; tmpconv = strtoul(login_gid_env, &endp, 10); if (errno == ERANGE || tmpconv > (gid_t)-1 || (login_gid_env + strlen(login_gid_env) != endp)) { EMSG("failed to convert CKTEEC_LOGIN_GID"); rv = CKR_ARGUMENTS_BAD; goto out; } login_gid = (gid_t)tmpconv; login_data = &login_gid; } else { EMSG("invalid value for CKTEEC_LOGIN_TYPE"); rv = CKR_ARGUMENTS_BAD; goto out; } } e = pthread_mutex_lock(&ta_ctx.init_mutex); if (e) return CKR_CANT_LOCK; if (ta_ctx.initiated) { rv = CKR_CRYPTOKI_ALREADY_INITIALIZED; goto out; } res = TEEC_InitializeContext(NULL, &ta_ctx.context); if (res != TEEC_SUCCESS) { EMSG("TEEC init context failed\n"); rv = CKR_DEVICE_ERROR; goto out; } res = TEEC_OpenSession(&ta_ctx.context, &ta_ctx.session, &uuid, login_method, login_data, NULL, &origin); if (res != TEEC_SUCCESS) { EMSG("TEEC open session failed %x from %d\n", res, origin); TEEC_FinalizeContext(&ta_ctx.context); rv = CKR_DEVICE_ERROR; goto out; } rv = ping_ta(); if (rv == CKR_OK) { ta_ctx.initiated = true; } else { TEEC_CloseSession(&ta_ctx.session); TEEC_FinalizeContext(&ta_ctx.context); } out: e = pthread_mutex_unlock(&ta_ctx.init_mutex); if (e) { EMSG("pthread_mutex_unlock: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } return rv; } CK_RV ckteec_invoke_terminate(void) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; int e = 0; e = pthread_mutex_lock(&ta_ctx.init_mutex); if (e) { EMSG("pthread_mutex_lock: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } if (!ta_ctx.initiated) goto out; ta_ctx.initiated = false; TEEC_CloseSession(&ta_ctx.session); TEEC_FinalizeContext(&ta_ctx.context); rv = CKR_OK; out: e = pthread_mutex_unlock(&ta_ctx.init_mutex); if (e) { EMSG("pthread_mutex_unlock: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } return rv; } optee_client-4.1.0/libckteec/src/invoke_ta.h000066400000000000000000000056151455150071200210410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 20187-2020, Linaro Limited */ #ifndef LIBCKTEEC_INVOKE_TA_H #define LIBCKTEEC_INVOKE_TA_H #include #include enum ckteec_shm_dir { CKTEEC_SHM_IN, CKTEEC_SHM_OUT, CKTEEC_SHM_INOUT, }; /** * ckteec_alloc_shm - Allocate memory in the TEE SHM (in, out or in/out) * * @size - Allocated size in byte * @dir - Data direction used for the shared memory * * Return a shm reference or NULL on failure. */ TEEC_SharedMemory *ckteec_alloc_shm(size_t size, enum ckteec_shm_dir dir); /** * ckteec_register_shm - Register memory as shared in the TEE SHM * * @buffer - Base address of buffer to register * @size - Allocated size in byte * @dir - Data direction used for the shared memory * * Return a shm reference or NULL on failure. */ TEEC_SharedMemory *ckteec_register_shm(void *buffer, size_t size, enum ckteec_shm_dir dir); /** * ckteec_free_shm - Release allocated or registered emory in the TEE SHM * * @shm - memory reference */ void ckteec_free_shm(TEEC_SharedMemory *shm); /** * ckteec_invoke_ta - Invoke PKCS11 TA for a target request through the TEE * * @cmd - PKCS11 TA command ID * @ctrl - shared memory with serialized request input arguments or NULL * @io1 - In memory buffer argument #1 for the command or NULL * @io2 - In and/or out memory buffer argument #2 for the command or NULL * @out2_size - Reference to @io2 output buffer size or NULL if not applicable * @io3 - In and/or out memory buffer argument #3 for the command or NULL * @out3_size - Reference to @io3 output buffer size or NULL if not applicable * * Return a CR_RV compliant return value */ CK_RV ckteec_invoke_ta(unsigned long cmd, TEEC_SharedMemory *ctrl, TEEC_SharedMemory *io1, TEEC_SharedMemory *io2, size_t *out2_size, TEEC_SharedMemory *io3, size_t *out3_size); static inline CK_RV ckteec_invoke_ctrl(unsigned long cmd, TEEC_SharedMemory *ctrl) { return ckteec_invoke_ta(cmd, ctrl, NULL, NULL, NULL, NULL, NULL); } static inline CK_RV ckteec_invoke_ctrl_in(unsigned long cmd, TEEC_SharedMemory *ctrl, TEEC_SharedMemory *io1) { return ckteec_invoke_ta(cmd, ctrl, io1, NULL, NULL, NULL, NULL); } static inline CK_RV ckteec_invoke_ctrl_out(unsigned long cmd, TEEC_SharedMemory *ctrl, TEEC_SharedMemory *io2, size_t *out_sz) { return ckteec_invoke_ta(cmd, ctrl, NULL, io2, out_sz, NULL, NULL); } /* * ckteec_invoke_init - Initialize TEE session with the PKCS11 TA * * Return a CR_RV compliant return value */ CK_RV ckteec_invoke_init(void); /* * ckteec_invoke_terminate - Release all allocated invocation resources * * Return a CR_RV compliant return value */ CK_RV ckteec_invoke_terminate(void); /* Return true if and only if the PKCS11 TA invocation context is initiated */ bool ckteec_invoke_initiated(void); #endif /*LIBCKTEEC_INVOKE_TA_H*/ optee_client-4.1.0/libckteec/src/local_utils.h000066400000000000000000000005631455150071200213710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Linaro Limited */ #ifndef LIBCKTEEC_LOCAL_UTILS_H #define LIBCKTEEC_LOCAL_UTILS_H #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) #define COMPILE_TIME_ASSERT(x) \ do { \ switch (0) { case 0: case ((x) ? 1: 0) : default : break; } \ } while (0) #endif /*LIBCKTEEC_LOCAL_UTILS_H*/ optee_client-4.1.0/libckteec/src/pkcs11_api.c000066400000000000000000001266431455150071200210150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include "ck_helpers.h" #include "invoke_ta.h" #include "pkcs11_processing.h" #include "pkcs11_token.h" static const CK_FUNCTION_LIST libckteec_function_list = { .version = { .major = CK_PKCS11_VERSION_MAJOR, .minor = CK_PKCS11_VERSION_MINOR, }, .C_Initialize = C_Initialize, .C_Finalize = C_Finalize, .C_GetInfo = C_GetInfo, .C_GetFunctionList = C_GetFunctionList, .C_GetSlotList = C_GetSlotList, .C_GetSlotInfo = C_GetSlotInfo, .C_GetTokenInfo = C_GetTokenInfo, .C_GetMechanismList = C_GetMechanismList, .C_GetMechanismInfo = C_GetMechanismInfo, .C_InitToken = C_InitToken, .C_InitPIN = C_InitPIN, .C_SetPIN = C_SetPIN, .C_OpenSession = C_OpenSession, .C_CloseSession = C_CloseSession, .C_CloseAllSessions = C_CloseAllSessions, .C_GetSessionInfo = C_GetSessionInfo, .C_GetOperationState = C_GetOperationState, .C_SetOperationState = C_SetOperationState, .C_Login = C_Login, .C_Logout = C_Logout, .C_CreateObject = C_CreateObject, .C_CopyObject = C_CopyObject, .C_DestroyObject = C_DestroyObject, .C_GetObjectSize = C_GetObjectSize, .C_GetAttributeValue = C_GetAttributeValue, .C_SetAttributeValue = C_SetAttributeValue, .C_FindObjectsInit = C_FindObjectsInit, .C_FindObjects = C_FindObjects, .C_FindObjectsFinal = C_FindObjectsFinal, .C_EncryptInit = C_EncryptInit, .C_Encrypt = C_Encrypt, .C_EncryptUpdate = C_EncryptUpdate, .C_EncryptFinal = C_EncryptFinal, .C_DecryptInit = C_DecryptInit, .C_Decrypt = C_Decrypt, .C_DecryptUpdate = C_DecryptUpdate, .C_DecryptFinal = C_DecryptFinal, .C_DigestInit = C_DigestInit, .C_Digest = C_Digest, .C_DigestUpdate = C_DigestUpdate, .C_DigestKey = C_DigestKey, .C_DigestFinal = C_DigestFinal, .C_SignInit = C_SignInit, .C_Sign = C_Sign, .C_SignUpdate = C_SignUpdate, .C_SignFinal = C_SignFinal, .C_SignRecoverInit = C_SignRecoverInit, .C_SignRecover = C_SignRecover, .C_VerifyInit = C_VerifyInit, .C_Verify = C_Verify, .C_VerifyUpdate = C_VerifyUpdate, .C_VerifyFinal = C_VerifyFinal, .C_VerifyRecoverInit = C_VerifyRecoverInit, .C_VerifyRecover = C_VerifyRecover, .C_DigestEncryptUpdate = C_DigestEncryptUpdate, .C_DecryptDigestUpdate = C_DecryptDigestUpdate, .C_SignEncryptUpdate = C_SignEncryptUpdate, .C_DecryptVerifyUpdate = C_DecryptVerifyUpdate, .C_GenerateKey = C_GenerateKey, .C_GenerateKeyPair = C_GenerateKeyPair, .C_WrapKey = C_WrapKey, .C_UnwrapKey = C_UnwrapKey, .C_DeriveKey = C_DeriveKey, .C_SeedRandom = C_SeedRandom, .C_GenerateRandom = C_GenerateRandom, .C_GetFunctionStatus = C_GetFunctionStatus, .C_CancelFunction = C_CancelFunction, .C_WaitForSlotEvent = C_WaitForSlotEvent, }; static bool lib_initiated(void) { return ckteec_invoke_initiated(); } CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { CK_C_INITIALIZE_ARGS_PTR args = NULL; CK_RV rv = 0; if (pInitArgs) { args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs; /* Reserved must be set to NULL in this version of PKCS#11 */ if (args->reserved) return CKR_ARGUMENTS_BAD; } rv = ckteec_invoke_init(); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CANT_LOCK, CKR_CRYPTOKI_ALREADY_INITIALIZED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_NEED_TO_CREATE_THREADS, CKR_OK, CKR_MUTEX_BAD); return rv; } CK_RV C_Finalize(CK_VOID_PTR pReserved) { CK_RV rv = 0; /* Reserved must be set to NULL in this version of PKCS#11 */ if (pReserved) return CKR_ARGUMENTS_BAD; rv = ckteec_invoke_terminate(); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK); return rv; } CK_RV C_GetInfo(CK_INFO_PTR pInfo) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_get_info(pInfo); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK); return rv; } CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { if (!ppFunctionList) return CKR_ARGUMENTS_BAD; /* Discard the const attribute when exporting the list address */ *ppFunctionList = (void *)&libckteec_function_list; return CKR_OK; } CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_slot_get_list(tokenPresent, pSlotList, pulCount); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK); return rv; } CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_slot_get_info(slotID, pInfo); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SLOT_ID_INVALID); return rv; } CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_init_token(slotID, pPin, ulPinLen, pLabel); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_PIN_INCORRECT, CKR_PIN_LOCKED, CKR_SESSION_EXISTS, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, CKR_TOKEN_WRITE_PROTECTED); return rv; } CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_token_get_info(slotID, pInfo); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_token_mechanism_ids(slotID, pMechanismList, pulCount); ASSERT_CK_RV(rv, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_token_mechanism_info(slotID, type, pInfo); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_open_session(slotID, flags, pApplication, Notify, phSession); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SESSION_COUNT, CKR_SESSION_PARALLEL_NOT_SUPPORTED, CKR_SESSION_READ_WRITE_SO_EXISTS, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, CKR_TOKEN_WRITE_PROTECTED, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_close_session(hSession); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_close_all_sessions(slotID); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT); return rv; } CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_get_session_info(hSession, pInfo); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_init_pin(hSession, pPin, ulPinLen); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_PIN_INVALID, CKR_PIN_LEN_RANGE, CKR_SESSION_CLOSED, CKR_SESSION_READ_ONLY, CKR_SESSION_HANDLE_INVALID, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_set_pin(hSession, pOldPin, ulOldLen, pNewPin, ulNewLen); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_PIN_INCORRECT, CKR_PIN_INVALID, CKR_PIN_LEN_RANGE, CKR_PIN_LOCKED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TOKEN_WRITE_PROTECTED, CKR_ARGUMENTS_BAD); return rv; } CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_login(hSession, userType, pPin, ulPinLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_PIN_INCORRECT, CKR_PIN_LOCKED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY_EXISTS, CKR_USER_ALREADY_LOGGED_IN, CKR_USER_ANOTHER_ALREADY_LOGGED_IN, CKR_USER_PIN_NOT_INITIALIZED, CKR_USER_TOO_MANY_TYPES, CKR_USER_TYPE_INVALID); return rv; } CK_RV C_Logout(CK_SESSION_HANDLE hSession) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_logout(hSession); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { (void)hSession; (void)pOperationState; (void)pulOperationStateLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { (void)hSession; (void)pOperationState; (void)ulOperationStateLen; (void)hEncryptionKey; (void)hAuthenticationKey; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_create_object(hSession, pTemplate, ulCount, phObject); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_copy_object(hSession, hObject, pTemplate, ulCount, phNewObject); ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_destroy_object(hSession, hObject); ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TOKEN_WRITE_PROTECTED); return rv; } CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_get_object_size(hSession, hObject, pulSize); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_INFORMATION_SENSITIVE, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_get_attribute_value(hSession, hObject, pTemplate, ulCount); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_SENSITIVE, CKR_ATTRIBUTE_TYPE_INVALID, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_set_attribute_value(hSession, hObject, pTemplate, ulCount); ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_find_objects_init(hSession, pTemplate, ulCount); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_find_objects(hSession, phObject, ulMaxObjectCount, pulObjectCount); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_find_objects_final(hSession); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_init(hSession, pMechanism, hKey, CK_FALSE); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_oneshot(hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_update(hSession, pPart, ulPartLen, pEncryptedData, pulEncryptedDataLen, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_final(hSession, pLastEncryptedPart, pulLastEncryptedPartLen, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_init(hSession, pMechanism, hKey, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_oneshot(hSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_update(hSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_encdecrypt_final(hSession, pLastPart, pulLastPartLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_digest_init(hSession, pMechanism); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_digest_oneshot(hSession, pData, ulDataLen, pDigest, pulDigestLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_digest_update(hSession, pPart, ulPartLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_digest_key(hSession, hKey); ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_INDIGESTIBLE, CKR_KEY_SIZE_RANGE, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_digest_final(hSession, pDigest, pulDigestLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_init(hSession, pMechanism, hKey, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_oneshot(hSession, pData, ulDataLen, pSignature, pulSignatureLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, CKR_FUNCTION_REJECTED); return rv; } CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_update(hSession, pPart, ulPartLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_final(hSession, pSignature, pulSignatureLen, CK_TRUE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, CKR_FUNCTION_REJECTED); return rv; } CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { (void)hSession; (void)pMechanism; (void)hKey; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { (void)hSession; (void)pData; (void)ulDataLen; (void)pSignature; (void)pulSignatureLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_init(hSession, pMechanism, hKey, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; CK_ULONG out_size = ulSignatureLen; if (lib_initiated()) rv = ck_signverify_oneshot(hSession, pData, ulDataLen, pSignature, &out_size, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE); return rv; } CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_update(hSession, pPart, ulPartLen, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); return rv; } CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_signverify_final(hSession, pSignature, &ulSignatureLen, CK_FALSE); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE); return rv; } CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { (void)hSession; (void)pMechanism; (void)hKey; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { (void)hSession; (void)pSignature; (void)ulSignatureLen; (void)pData; (void)pulDataLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { (void)hSession; (void)pPart; (void)ulPartLen; (void)pEncryptedPart; (void)pulEncryptedPartLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { (void)hSession; (void)pEncryptedPart; (void)ulEncryptedPartLen; (void)pPart; (void)pulPartLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { (void)hSession; (void)pPart; (void)ulPartLen; (void)pEncryptedPart; (void)pulEncryptedPartLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { (void)hSession; (void)pEncryptedPart; (void)ulEncryptedPartLen; (void)pPart; (void)pulPartLen; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_generate_key(hSession, pMechanism, pTemplate, ulCount, phKey); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_generate_key_pair(hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_wrap_key(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_NOT_WRAPPABLE, CKR_KEY_SIZE_RANGE, CKR_KEY_UNEXTRACTABLE, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, CKR_WRAPPING_KEY_HANDLE_INVALID, CKR_WRAPPING_KEY_SIZE_RANGE, CKR_WRAPPING_KEY_TYPE_INCONSISTENT); return rv; } CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_unwrap_key(hSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulCount, phKey); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_SIZE_RANGE, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, CKR_USER_NOT_LOGGED_IN, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPED_KEY_LEN_RANGE); return rv; } CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_derive_key(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN, CKR_DATA_LEN_RANGE); return rv; } CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_seed_random(hSession, pSeed, ulSeedLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; if (lib_initiated()) rv = ck_generate_random(hSession, pRandomData, ulRandomLen); ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_RANDOM_NO_RNG, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); return rv; } CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession) { (void)hSession; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_PARALLEL; } CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession) { (void)hSession; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_PARALLEL; } CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR slotID, CK_VOID_PTR pReserved) { (void)flags; (void)slotID; (void)pReserved; if (!lib_initiated()) return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_FUNCTION_NOT_SUPPORTED; } optee_client-4.1.0/libckteec/src/pkcs11_processing.c000066400000000000000000001154621455150071200224150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2018, Linaro Limited */ #include #include #include #include #include #include #include "pkcs11_processing.h" #include "invoke_ta.h" #include "serializer.h" #include "serialize_ck.h" CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; struct serializer obj = { 0 }; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !attribs || !count) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&obj, attribs, count); if (rv) goto out; /* Shm io0: (i/o) [session-handle][serialized-attributes] / [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_CREATE_OBJECT, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; out: release_serial_object(&obj); ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; size_t ctrl_size = 0; char *buf = NULL; uint32_t session_handle = session; uint32_t obj_id = obj; /* Shm io0: (i/o) ctrl = [session-handle][object-handle] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_id); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_id, sizeof(obj_id)); rv = ckteec_invoke_ctrl(PKCS11_CMD_DESTROY_OBJECT, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; char *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(decrypt ? PKCS11_CMD_DECRYPT_INIT : PKCS11_CMD_ENCRYPT_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len || (in_len && !in)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data buffer if any */ if (in_len) { in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } } /* Shm io2: output data buffer */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Invoke */ rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_UPDATE : PKCS11_CMD_ENCRYPT_UPDATE, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_UPDATE : PKCS11_CMD_ENCRYPT_UPDATE); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len || (in_len && !in)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data buffer */ in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Shm io2: output data buffer */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_ONESHOT : PKCS11_CMD_ENCRYPT_ONESHOT, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_ONESHOT : PKCS11_CMD_ENCRYPT_ONESHOT); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: output buffer reference */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(decrypt ? PKCS11_CMD_DECRYPT_FINAL : PKCS11_CMD_ENCRYPT_FINAL, ctrl, out_shm, &out_size); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_FINAL : PKCS11_CMD_ENCRYPT_FINAL); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint8_t *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; uint8_t *buf = NULL; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_KEY, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; uint32_t session_handle = session; uint8_t *buf = NULL; if (!in && in_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len && in) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } rv = ckteec_invoke_ctrl_in(PKCS11_CMD_DIGEST_UPDATE, ctrl, io1); goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_UPDATE); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR digest_ref, CK_ULONG_PTR digest_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t out_size = 0; uint8_t *buf = NULL; if ((!in && in_len) || !digest_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len && in) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } /* Shm io2: output digest or null sized shm */ if (digest_ref) { io2 = ckteec_register_shm(digest_ref, *digest_len, CKTEEC_SHM_OUT); } else { /* Query size if output signature */ io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_ONESHOT, ctrl, io1, io2, &out_size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *digest_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !digest_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_ONESHOT); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR digest_ref, CK_ULONG_PTR digest_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t io2_size = 0; uint8_t *buf = NULL; /* * - If digest_ref == NULL AND digest_len == NULL -> need to call TA to * terminate session. * - If digest_len == NULL -> need to call to TA to terminate session. * - If digest_ref == NULL BUT digest_len != NULL just operate normally * to get size of the required buffer */ if (!digest_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io2: output digest or null sized shm */ if (digest_ref) io2 = ckteec_register_shm(digest_ref, *digest_len, CKTEEC_SHM_OUT); else io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_FINAL, ctrl, NULL, io2, &io2_size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *digest_len = io2_size; if (rv == CKR_BUFFER_TOO_SMALL && io2_size && !digest_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_FINAL); bail_invoked: ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; char *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(sign ? PKCS11_CMD_SIGN_INIT : PKCS11_CMD_VERIFY_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_signverify_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; uint32_t session_handle = session; if (!in && in_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data */ in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_in(sign ? PKCS11_CMD_SIGN_UPDATE : PKCS11_CMD_VERIFY_UPDATE, ctrl, in_shm); goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_UPDATE : PKCS11_CMD_VERIFY_UPDATE); bail_invoked: ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR sign_ref, CK_ULONG_PTR sign_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t out_size = 0; if ((in_len && !in) || (!sign && sign_len && *sign_len && !sign_ref) || (sign && !sign_len)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } /* * Shm io2: input signature (if verifying) or null sized shm * or * Shm io2: output signature (if signing) or null sized shm */ if (sign_ref && sign_len && *sign_len) { io2 = ckteec_register_shm(sign_ref, *sign_len, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); } else { /* Query size if output signature */ io2 = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); } if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_ONESHOT : PKCS11_CMD_VERIFY_ONESHOT, ctrl, io1, io2, &out_size, NULL, NULL); if (sign && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *sign_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !sign_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_ONESHOT : PKCS11_CMD_VERIFY_ONESHOT); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_final(CK_SESSION_HANDLE session, CK_BYTE_PTR sign_ref, CK_ULONG_PTR sign_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io = NULL; uint32_t session_handle = session; size_t io_size = 0; if ((!sign && sign_len && *sign_len && !sign_ref) || (sign && !sign_len)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* * Shm io1: input signature (if verifying) or null sized shm * or * Shm io1: output signature (if signing) or null sized shm */ if (sign_ref && sign_len && *sign_len) io = ckteec_register_shm(sign_ref, *sign_len, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); else io = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); if (!io) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_FINAL : PKCS11_CMD_VERIFY_FINAL, ctrl, NULL, io, &io_size, NULL, NULL); if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *sign_len = io_size; if (rv == CKR_BUFFER_TOO_SMALL && io_size && !sign_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_FINAL : PKCS11_CMD_VERIFY_FINAL); bail_invoked: ckteec_free_shm(io); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mecha][serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; } CK_RV ck_find_objects_init(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; struct serializer obj = { 0 }; size_t ctrl_size = 0; char *buf = NULL; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&obj, attribs, count); if (rv) return rv; /* Shm io0: (in/out) ctrl * (in) [session-handle][headed-serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_find_objects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR obj, CK_ULONG max_count, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; uint32_t *handles = NULL; size_t handles_size = max_count * sizeof(uint32_t); CK_ULONG n = 0; CK_ULONG last = 0; size_t out_size = 0; if (!count || (max_count && !obj)) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [object handle list] */ out_shm = ckteec_alloc_shm(handles_size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_FIND_OBJECTS, ctrl, out_shm, &out_size); if (rv || out_size > out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } handles = out_shm->buffer; last = out_size / sizeof(uint32_t); *count = last; for (n = 0; n < last; n++) obj[n] = handles[n]; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_find_objects_final(CK_SESSION_HANDLE session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_FINAL, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_get_object_size(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ULONG_PTR p_size) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; size_t out_size = 0; uint32_t u32_sz = 0; if (!p_size) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) [session][obj-handle] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); /* Shm io2: (out) [object size] */ out_shm = ckteec_alloc_shm(sizeof(uint32_t), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_OBJECT_SIZE, ctrl, out_shm, &out_size); if (rv) goto bail; if (out_shm->size != sizeof(uint32_t)) { rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&u32_sz, out_shm->buffer, out_shm->size); *p_size = u32_sz; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; CK_RV rv2 = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; size_t out_size = 0; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [attributes] */ out_shm = ckteec_alloc_shm(sattr.size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_ATTRIBUTE_VALUE, ctrl, out_shm, &out_size); if (rv == CKR_OK || rv == CKR_ATTRIBUTE_SENSITIVE || rv == CKR_ATTRIBUTE_TYPE_INVALID || rv == CKR_BUFFER_TOO_SMALL) { rv2 = deserialize_ck_attributes(out_shm->buffer, attribs, count); if (rv2) rv = CKR_GENERAL_ERROR; } bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_ATTRIBUTE_VALUE, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_copy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_COPY_OBJECT, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_derive_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE parent_key, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; uint32_t obj_handle = parent_key; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][obj-handle][serialized-mecha][serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_DERIVE_KEY, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; } CK_RV ck_release_active_processing(CK_SESSION_HANDLE session, enum pkcs11_ta_cmd command) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; uint32_t cmd = command; size_t ctrl_size = 0; char *buf = NULL; /* Shm io0: (in/out) ctrl = [session-handle][command] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(cmd); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &cmd, sizeof(cmd)); rv = ckteec_invoke_ctrl(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub_attribs, CK_ULONG pub_count, CK_ATTRIBUTE_PTR priv_attribs, CK_ULONG priv_count, CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer pub_sattr = { 0 }; struct serializer priv_sattr = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint32_t *key_handle = NULL; size_t key_handle_size = 2 * sizeof(*key_handle); char *buf = NULL; size_t out_size = 0; if (!(mechanism && pub_attribs && priv_attribs && pub_key && priv_key)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count); if (rv) goto bail; rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mecha][serialized-pub_attribs] * [serialized-priv_attribs] * (out) [status] */ ctrl_size = sizeof(session_handle) + smecha.size + pub_sattr.size + priv_sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, pub_sattr.buffer, pub_sattr.size); buf += pub_sattr.size; memcpy(buf, priv_sattr.buffer, priv_sattr.size); /* * Shm io2: (out) public key object handle][private key object handle] */ out_shm = ckteec_alloc_shm(key_handle_size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY_PAIR, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } key_handle = out_shm->buffer; *pub_key = key_handle[0]; *priv_key = key_handle[1]; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&priv_sattr); release_serial_object(&pub_sattr); release_serial_object(&smecha); return rv; } CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; uint32_t session_handle = session; uint32_t wrp_key_handle = wrapping_key; uint32_t key_handle = key; size_t ctrl_size = 0; size_t out_size = 0; char *buf = NULL; if (!mechanism || !wrapped_key_len) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][wrapping-key-handle][key-handle] * [serialized-mecha] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(wrp_key_handle) + sizeof(key_handle) + smecha.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &wrp_key_handle, sizeof(wrp_key_handle)); buf += sizeof(wrp_key_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, smecha.buffer, smecha.size); /* Shm io2: output buffer reference - wrapped key */ if (wrapped_key && *wrapped_key_len) out_shm = ckteec_register_shm(wrapped_key, *wrapped_key_len, CKTEEC_SHM_OUT); else /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_WRAP_KEY, ctrl, out_shm, &out_size); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *wrapped_key_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !wrapped_key) rv = CKR_OK; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&smecha); return rv; } CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; uint32_t unwrapping_key_handle = unwrapping_key; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs) || (wrapped_key_len && !wrapped_key)) return CKR_ARGUMENTS_BAD; if (!unwrapping_key) return CKR_UNWRAPPING_KEY_HANDLE_INVALID; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][unwrapping-key-handle][serialized-mecha] * [serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(unwrapping_key_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &unwrapping_key_handle, sizeof(unwrapping_key_handle)); buf += sizeof(unwrapping_key_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io1: input - wrapped key buffer */ in_shm = ckteec_register_shm(wrapped_key, wrapped_key_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_UNWRAP_KEY, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; } optee_client-4.1.0/libckteec/src/pkcs11_processing.h000066400000000000000000000100631455150071200224110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2018, Linaro Limited */ #ifndef LIBCKTEEC_PKCS11_PROCESSING_H #define LIBCKTEEC_PKCS11_PROCESSING_H #include #include CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR phObject); CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj); CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int decrypt); CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt); CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt); CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt); CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism); CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV ck_signverify_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int sign); CK_RV ck_signverify_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, int sign); CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int sign); CK_RV ck_signverify_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int sign); CK_RV ck_generate_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); CK_RV ck_find_objects_init(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count); CK_RV ck_find_objects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR obj, CK_ULONG max_count, CK_ULONG_PTR count); CK_RV ck_find_objects_final(CK_SESSION_HANDLE session); CK_RV ck_get_object_size(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ULONG_PTR p_size); CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count); CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count); CK_RV ck_copy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); CK_RV ck_derive_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); CK_RV ck_release_active_processing(CK_SESSION_HANDLE session, enum pkcs11_ta_cmd command); CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub_attribs, CK_ULONG pub_count, CK_ATTRIBUTE_PTR priv_attribs, CK_ULONG priv_count, CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key); CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len); CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); #endif /*LIBCKTEEC_PKCS11_PROCESSING_H*/ optee_client-4.1.0/libckteec/src/pkcs11_token.c000066400000000000000000000506111455150071200213530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include "ck_helpers.h" #include "invoke_ta.h" #include "local_utils.h" #include "pkcs11_token.h" #define PKCS11_LIB_MANUFACTURER "Linaro" #define PKCS11_LIB_DESCRIPTION "OP-TEE PKCS11 Cryptoki library" /** * Converts uint32_t value to CK_ULONG with unavailable information support * * On 64 bit systems uint32_t cannot handle CK_ULONG defined * CK_UNAVAILABLE_INFORMATION. Check for this specific situation and return * correct value. * * @ta_value: Value form PKCS#11 TA * @return Valid CK_ULONG value */ static CK_ULONG maybe_unavail(uint32_t ta_value) { if (ta_value == PKCS11_CK_UNAVAILABLE_INFORMATION) return CK_UNAVAILABLE_INFORMATION; else return ta_value; } /** * ck_get_info - Get local information for C_GetInfo */ CK_RV ck_get_info(CK_INFO_PTR info) { const CK_INFO lib_info = { .cryptokiVersion = { CK_PKCS11_VERSION_MAJOR, CK_PKCS11_VERSION_MINOR, }, .manufacturerID = PKCS11_LIB_MANUFACTURER, .flags = 0, /* must be zero per the PKCS#11 2.40 */ .libraryDescription = PKCS11_LIB_DESCRIPTION, .libraryVersion = { PKCS11_TA_VERSION_MAJOR, PKCS11_TA_VERSION_MINOR }, }; int n = 0; if (!info) return CKR_ARGUMENTS_BAD; *info = lib_info; /* Pad strings with blank characters */ n = strnlen((char *)info->manufacturerID, sizeof(info->manufacturerID)); memset(&info->manufacturerID[n], ' ', sizeof(info->manufacturerID) - n); n = strnlen((char *)info->libraryDescription, sizeof(info->libraryDescription)); memset(&info->libraryDescription[n], ' ', sizeof(info->libraryDescription) - n); return CKR_OK; } /** * ck_slot_get_list - Wrap C_GetSlotList into PKCS11_CMD_SLOT_LIST */ CK_RV ck_slot_get_list(CK_BBOOL present, CK_SLOT_ID_PTR slots, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *shm = NULL; uint32_t *slot_ids = NULL; size_t client_count = 0; size_t size = 0; size_t n = 0; /* Discard @present: all slots reported by TA are present */ (void)present; if (!count) return CKR_ARGUMENTS_BAD; /* * As per spec, if @slots is NULL, "The contents of *pulCount on * entry to C_GetSlotList has no meaning in this case (...)" */ if (slots) client_count = *count; size = client_count * sizeof(*slot_ids); shm = ckteec_alloc_shm(size, CKTEEC_SHM_OUT); if (!shm) return CKR_HOST_MEMORY; rv = ckteec_invoke_ta(PKCS11_CMD_SLOT_LIST, NULL, NULL, shm, &size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *count = size / sizeof(*slot_ids); if (!slots && rv == CKR_BUFFER_TOO_SMALL) rv = CKR_OK; if (!slots || rv) goto out; slot_ids = shm->buffer; for (n = 0; n < *count; n++) slots[n] = slot_ids[n]; out: ckteec_free_shm(shm); return rv; } /** * ck_slot_get_info - Wrap C_GetSlotInfo into PKCS11_CMD_SLOT_INFO */ CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; struct pkcs11_slot_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SLOT_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = out->buffer; COMPILE_TIME_ASSERT(sizeof(info->slotDescription) == sizeof(ta_info->slot_description)); memcpy(info->slotDescription, ta_info->slot_description, sizeof(info->slotDescription)); COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == sizeof(ta_info->manufacturer_id)); memcpy(info->manufacturerID, ta_info->manufacturer_id, sizeof(info->manufacturerID)); info->flags = ta_info->flags; COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == sizeof(ta_info->hardware_version)); memcpy(&info->hardwareVersion, ta_info->hardware_version, sizeof(info->hardwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == sizeof(ta_info->firmware_version)); memcpy(&info->firmwareVersion, ta_info->firmware_version, sizeof(info->firmwareVersion)); out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_token_get_info - Wrap C_GetTokenInfo into PKCS11_CMD_TOKEN_INFO */ CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t slot_id = slot; struct pkcs11_token_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out_shm = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_TOKEN_INFO, ctrl, out_shm, &out_size); if (rv) goto out; if (out_size != out_shm->size) { rv = CKR_DEVICE_ERROR; goto out; } ta_info = out_shm->buffer; COMPILE_TIME_ASSERT(sizeof(info->label) == sizeof(ta_info->label)); memcpy(info->label, ta_info->label, sizeof(info->label)); COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == sizeof(ta_info->manufacturer_id)); memcpy(info->manufacturerID, ta_info->manufacturer_id, sizeof(info->manufacturerID)); COMPILE_TIME_ASSERT(sizeof(info->model) == sizeof(ta_info->model)); memcpy(info->model, ta_info->model, sizeof(info->model)); COMPILE_TIME_ASSERT(sizeof(info->serialNumber) == sizeof(ta_info->serial_number)); memcpy(info->serialNumber, ta_info->serial_number, sizeof(info->serialNumber)); info->flags = ta_info->flags; info->ulMaxSessionCount = maybe_unavail(ta_info->max_session_count); info->ulSessionCount = maybe_unavail(ta_info->session_count); info->ulMaxRwSessionCount = maybe_unavail(ta_info->max_rw_session_count); info->ulRwSessionCount = maybe_unavail(ta_info->rw_session_count); info->ulMaxPinLen = ta_info->max_pin_len; info->ulMinPinLen = ta_info->min_pin_len; info->ulTotalPublicMemory = maybe_unavail(ta_info->total_public_memory); info->ulFreePublicMemory = maybe_unavail(ta_info->free_public_memory); info->ulTotalPrivateMemory = maybe_unavail(ta_info->total_private_memory); info->ulFreePrivateMemory = maybe_unavail(ta_info->free_private_memory); COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == sizeof(ta_info->hardware_version)); memcpy(&info->hardwareVersion, ta_info->hardware_version, sizeof(info->hardwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == sizeof(ta_info->firmware_version)); memcpy(&info->firmwareVersion, ta_info->firmware_version, sizeof(info->firmwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->utcTime) == sizeof(ta_info->utc_time)); memcpy(&info->utcTime, ta_info->utc_time, sizeof(info->utcTime)); out: ckteec_free_shm(ctrl); ckteec_free_shm(out_shm); return rv; } /** * ck_token_mechanism_ids - Wrap C_GetMechanismList */ CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot, CK_MECHANISM_TYPE_PTR mechanisms, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t *mecha_ids = NULL; size_t out_size = 0; size_t n = 0; if (!count) return CKR_ARGUMENTS_BAD; /* * As per spec, if @mechanism is NULL, "The contents of *pulCount on * entry to C_GetMechanismList has no meaning in this case (...)" */ if (mechanisms) out_size = *count * sizeof(*mecha_ids); ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out = ckteec_alloc_shm(out_size, CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_IDS, ctrl, out, &out_size); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *count = out_size / sizeof(*mecha_ids); if (!mechanisms && rv == CKR_BUFFER_TOO_SMALL) rv = CKR_OK; if (!mechanisms || rv) goto out; mecha_ids = out->buffer; for (n = 0; n < *count; n++) mechanisms[n] = mecha_ids[n]; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_token_mechanism_info - Wrap C_GetMechanismInfo into command MECHANISM_INFO */ CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t mecha_type = type; struct pkcs11_mechanism_info *ta_info = NULL; char *buf = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(mecha_type), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &mecha_type, sizeof(mecha_type)); out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = out->buffer; info->ulMinKeySize = ta_info->min_key_size; info->ulMaxKeySize = ta_info->max_key_size; info->flags = ta_info->flags; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_OPEN_{RW|RO}_SESSION * * Note: cookie and callback are not utilized by libckteec and are silently * sinked in to have better out-of-box compatibility with 3rd party libraries * and applications which provides the callback. */ CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t u32_flags = flags; uint32_t handle = 0; size_t out_size = 0; uint8_t *buf; /* Ignore notify callback */ (void)cookie; (void)callback; if ((flags & ~(CKF_RW_SESSION | CKF_SERIAL_SESSION)) || !session) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [slot-id][flags] / [status] */ ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(u32_flags), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = (uint8_t *)ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &u32_flags, sizeof(u32_flags)); /* Shm io2: (out) [session handle] */ out = ckteec_alloc_shm(sizeof(handle), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_OPEN_SESSION, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } memcpy(&handle, out->buffer, sizeof(handle)); *session = handle; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_CLOSE_SESSION */ CK_RV ck_close_session(CK_SESSION_HANDLE session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_SESSION, ctrl); out: ckteec_free_shm(ctrl); return rv; } /** * ck_close_all_sessions - Wrap C_CloseAllSessions into TA command */ CK_RV ck_close_all_sessions(CK_SLOT_ID slot) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t slot_id = slot; /* Shm io0: (in/out) ctrl = [slot-id] / [status] */ ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_ALL_SESSIONS, ctrl); out: ckteec_free_shm(ctrl); return rv; } /** * ck_get_session_info - Wrap C_GetSessionInfo into PKCS11_CMD_SESSION_INFO */ CK_RV ck_get_session_info(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t session_handle = session; struct pkcs11_session_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [session info] */ out = ckteec_alloc_shm(sizeof(struct pkcs11_session_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SESSION_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = (struct pkcs11_session_info *)out->buffer; info->slotID = ta_info->slot_id; info->state = ta_info->state; info->flags = ta_info->flags; info->ulDeviceError = ta_info->device_error; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_init_token - Wrap C_InitToken into PKCS11_CMD_INIT_TOKEN */ CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t slot_id = slot; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; if (!label) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [slot-id][pin_len][label][pin] / [status] */ ctrl_size = sizeof(slot_id) + sizeof(pkcs11_pin_len) + 32 * sizeof(uint8_t) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, label, 32 * sizeof(uint8_t)); buf += 32 * sizeof(uint8_t); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_TOKEN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_init_pin - Wrap C_InitPIN into PKCS11_CMD_INIT_PIN */ CK_RV ck_init_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [session][pin_len][pin] / [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_pin_len) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_PIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_set_pin - Wrap C_SetPIN into PKCS11_CMD_SET_PIN */ CK_RV ck_set_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old, CK_ULONG old_len, CK_UTF8CHAR_PTR new, CK_ULONG new_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_old_len = old_len; uint32_t pkcs11_new_len = new_len; size_t ctrl_size = 0; char *buf; if ((!old && old_len) || (!new && new_len)) return CKR_ARGUMENTS_BAD; /* * Shm io0: (in/out) ctrl * (in) [session][old_pin_len][new_pin_len][old pin][new pin] * (out) [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_old_len) + sizeof(pkcs11_new_len) + pkcs11_old_len + pkcs11_new_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_old_len, sizeof(pkcs11_old_len)); buf += sizeof(pkcs11_old_len); memcpy(buf, &pkcs11_new_len, sizeof(pkcs11_new_len)); buf += sizeof(pkcs11_new_len); memcpy(buf, old, pkcs11_old_len); buf += pkcs11_old_len; memcpy(buf, new, pkcs11_new_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_PIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_login - Wrap C_Login into PKCS11_CMD_LOGIN */ CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_user = user_type; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; /* Shm io0: (i/o) ctrl = [session][user][pin length][pin] / [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_user) + sizeof(pkcs11_pin_len) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_user, sizeof(pkcs11_user)); buf += sizeof(pkcs11_user); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_logout - Wrap C_Logout into PKCS11_CMD_LOGOUT */ CK_RV ck_logout(CK_SESSION_HANDLE session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; /* io0 = [session-handle] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGOUT, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG length) { CK_RV rv = CKR_GENERAL_ERROR; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; uint32_t session_handle = session; if (!seed && length) return CKR_ARGUMENTS_BAD; if (!seed) return CKR_OK; /* Shm io0: (i/o) [session-handle] / [status] */ ctrl_size = sizeof(session_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: (in) [seed data] */ in_shm = ckteec_register_shm(seed, length, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_in(PKCS11_CMD_SEED_RANDOM, ctrl, in_shm); out: ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG length) { CK_RV rv = CKR_GENERAL_ERROR; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!data && length) return CKR_ARGUMENTS_BAD; if (!data) return CKR_OK; /* Shm io0: (i/o) [session-handle] / [status] */ ctrl_size = sizeof(session_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [generated random] */ out_shm = ckteec_register_shm(data, length, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_RANDOM, ctrl, out_shm, &out_size); out: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } optee_client-4.1.0/libckteec/src/pkcs11_token.h000066400000000000000000000032661455150071200213640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef LIBCKTEEC_PKCS11_TOKEN_H #define LIBCKTEEC_PKCS11_TOKEN_H #include #include "invoke_ta.h" CK_RV ck_get_info(CK_INFO_PTR info); CK_RV ck_slot_get_list(CK_BBOOL present, CK_SLOT_ID_PTR slots, CK_ULONG_PTR count); CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info); CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info); CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot, CK_MECHANISM_TYPE_PTR mechanisms, CK_ULONG_PTR count); CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info); CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session); CK_RV ck_close_session(CK_SESSION_HANDLE session); CK_RV ck_close_all_sessions(CK_SLOT_ID slot); CK_RV ck_get_session_info(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info); CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label); CK_RV ck_init_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len); CK_RV ck_set_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old, CK_ULONG old_len, CK_UTF8CHAR_PTR new, CK_ULONG new_len); CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len); CK_RV ck_logout(CK_SESSION_HANDLE session); CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG length); CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG length); #endif /*LIBCKTEEC_PKCS11_TOKEN_H*/ optee_client-4.1.0/libckteec/src/serialize_ck.c000066400000000000000000000471621455150071200215240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include "ck_helpers.h" #include "local_utils.h" #include "serializer.h" #include "serialize_ck.h" /* * Serialization and de-serialization logic * * Cryptoki API works in a way that user application uses memory references * in object attributes description. TA can be invoked with only a small set * of possible references to caller memory. Thus a Cryptoki object, made of * data and pointers to data, is reassembled into a byte array where each * attribute info (ID, value size, value) is appended with byte alignment. This * so-called serialized object can be passed through the TA API. * * Initial entry to PKCS11 TA uses serialize_ck_attributes(). When TA * returns with updated serialized data to be passed back to caller, we call * deserialize_ck_attributes(). * * Special handling is performed for CK_ULONG passing which may be either 32 * bits or 64 bits depending on target device architecture. In TA interface * this is handled as unsigned 32 bit data type. * * When user application is querying attributes in example with * C_GetAttributeValue() user may allocate larger value buffers. During entry * to TA shared buffer is allocated in serialize_ck_attributes() based on * caller's arguments. For each attribute TA verifies if value fits in * the buffer and if it does, value is returned. Value size in buffer is * updated to indicate real size of the value. When call is returned back to * REE deserialize_ck_attributes() is invoked and then both input arguments and * serialization buffer are used to return values to caller. Provided input * arguments from caller are used to determine serialization buffer structure * and then actual values and value sizes are then decoded from serialization * buffer and returned to caller in caller's allocated memory. */ /* * Generic way of serializing CK keys, certificates, mechanism parameters, ... * In cryptoki 2.40 parameters are almost all packaged as structure below: */ struct ck_ref { CK_ULONG id; CK_BYTE_PTR ptr; CK_ULONG len; }; /* * This is for attributes that contains data memory indirections. * In other words, an attributes that defines a list of attributes. * They are identified from the attribute type CKA_... * * @obj - ref used to track the serial object being created * @attribute - pointer to a structure aligned of the CK_ATTRIBUTE struct */ static CK_RV serialize_indirect_attribute(struct serializer *obj, CK_ATTRIBUTE_PTR attribute) { CK_ATTRIBUTE_PTR attr = NULL; CK_ULONG count = 0; CK_RV rv = CKR_GENERAL_ERROR; struct serializer obj2 = { 0 }; switch (attribute->type) { /* These are serialized each separately */ case CKA_DERIVE_TEMPLATE: case CKA_WRAP_TEMPLATE: case CKA_UNWRAP_TEMPLATE: count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE); attr = (CK_ATTRIBUTE_PTR)attribute->pValue; break; default: return CKR_NO_EVENT; } /* Create a serialized object for the content */ rv = serialize_ck_attributes(&obj2, attr, count); if (rv) return rv; /* * Append the created serialized object into target object: * [attrib-id][byte-size][attributes-data] */ rv = serialize_32b(obj, attribute->type); if (rv) return rv; rv = serialize_32b(obj, obj2.size); if (rv) return rv; rv = serialize_buffer(obj, obj2.buffer, obj2.size); if (rv) return rv; obj->item_count++; return rv; } static CK_RV deserialize_indirect_attribute(struct pkcs11_attribute_head *obj, CK_ATTRIBUTE_PTR attribute) { CK_ULONG count = 0; CK_ATTRIBUTE_PTR attr = NULL; switch (attribute->type) { /* These are serialized each separately */ case CKA_DERIVE_TEMPLATE: case CKA_WRAP_TEMPLATE: case CKA_UNWRAP_TEMPLATE: count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE); attr = (CK_ATTRIBUTE_PTR)attribute->pValue; break; default: return CKR_GENERAL_ERROR; } return deserialize_ck_attributes(obj->data, attr, count); } static int ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id) { switch (attribute_id) { case CKA_CLASS: case CKA_CERTIFICATE_TYPE: case CKA_CERTIFICATE_CATEGORY: case CKA_NAME_HASH_ALGORITHM: case CKA_KEY_TYPE: case CKA_HW_FEATURE_TYPE: case CKA_MECHANISM_TYPE: case CKA_KEY_GEN_MECHANISM: case CKA_VALUE_LEN: case CKA_MODULUS_BITS: return true; default: return false; } } static CK_RV serialize_ck_attribute(struct serializer *obj, CK_ATTRIBUTE *attr) { CK_MECHANISM_TYPE *type = NULL; uint32_t pkcs11_size = 0; uint32_t pkcs11_data32 = 0; void *pkcs11_pdata = NULL; uint32_t *mech_buf = NULL; CK_RV rv = CKR_GENERAL_ERROR; unsigned int n = 0; unsigned int m = 0; if (attr->type == PKCS11_UNDEFINED_ID) return CKR_ATTRIBUTE_TYPE_INVALID; switch (attr->type) { case CKA_DERIVE_TEMPLATE: case CKA_WRAP_TEMPLATE: case CKA_UNWRAP_TEMPLATE: return serialize_indirect_attribute(obj, attr); case CKA_ALLOWED_MECHANISMS: n = attr->ulValueLen / sizeof(CK_ULONG); pkcs11_size = n * sizeof(uint32_t); mech_buf = malloc(pkcs11_size); if (!mech_buf) return CKR_HOST_MEMORY; type = attr->pValue; for (m = 0; m < n; m++) { mech_buf[m] = type[m]; if (mech_buf[m] == PKCS11_UNDEFINED_ID) { rv = CKR_MECHANISM_INVALID; goto out; } } pkcs11_pdata = mech_buf; break; /* Attributes which data value do not need conversion (aside ulong) */ default: pkcs11_pdata = attr->pValue; if (!attr->pValue) { pkcs11_size = 0; } else if (ck_attr_is_ulong(attr->type)) { CK_ULONG ck_ulong = 0; if (attr->ulValueLen < sizeof(CK_ULONG)) return CKR_ATTRIBUTE_VALUE_INVALID; memcpy(&ck_ulong, attr->pValue, sizeof(ck_ulong)); pkcs11_data32 = ck_ulong; pkcs11_pdata = &pkcs11_data32; pkcs11_size = sizeof(uint32_t); } else { pkcs11_size = attr->ulValueLen; } break; } rv = serialize_32b(obj, attr->type); if (rv) goto out; rv = serialize_32b(obj, pkcs11_size); if (rv) goto out; rv = serialize_buffer(obj, pkcs11_pdata, pkcs11_size); if (rv) goto out; obj->item_count++; out: free(mech_buf); return rv; } /* CK attribute reference arguments are list of attribute item */ CK_RV serialize_ck_attributes(struct serializer *obj, CK_ATTRIBUTE_PTR attributes, CK_ULONG count) { CK_ULONG n = 0; CK_RV rv = CKR_OK; rv = init_serial_object(obj); if (rv) return rv; for (n = 0; n < count; n++) { rv = serialize_ck_attribute(obj, attributes + n); if (rv) break; } if (rv) release_serial_object(obj); else finalize_serial_object(obj); return rv; } static CK_RV deserialize_mecha_list(CK_MECHANISM_TYPE *dst, void *src, size_t count) { char *ta_src = src; size_t n = 0; uint32_t mecha_id = 0; for (n = 0; n < count; n++) { memcpy(&mecha_id, ta_src + n * sizeof(mecha_id), sizeof(mecha_id)); dst[n] = mecha_id; } return CKR_OK; } static CK_RV deserialize_ck_attribute(struct pkcs11_attribute_head *in, uint8_t *data, CK_ATTRIBUTE_PTR out) { CK_ULONG ck_ulong = 0; uint32_t pkcs11_data32 = 0; CK_RV rv = CKR_OK; out->type = in->id; if (in->size == PKCS11_CK_UNAVAILABLE_INFORMATION) { out->ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_OK; } if (!out->pValue && ck_attr_is_ulong(out->type)) { out->ulValueLen = sizeof(CK_ULONG); return CKR_OK; } if (out->ulValueLen < in->size) { out->ulValueLen = in->size; return CKR_OK; } if (!out->pValue) return CKR_OK; /* Specific ulong encoded as 32bit in PKCS11 TA API */ if (ck_attr_is_ulong(out->type)) { if (out->ulValueLen < sizeof(CK_ULONG)) return CKR_ATTRIBUTE_VALUE_INVALID; memcpy(&pkcs11_data32, data, sizeof(uint32_t)); if (out->type == CKA_KEY_GEN_MECHANISM && pkcs11_data32 == PKCS11_CK_UNAVAILABLE_INFORMATION) ck_ulong = CK_UNAVAILABLE_INFORMATION; else ck_ulong = pkcs11_data32; memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG)); out->ulValueLen = sizeof(CK_ULONG); return CKR_OK; } switch (out->type) { case CKA_DERIVE_TEMPLATE: case CKA_WRAP_TEMPLATE: case CKA_UNWRAP_TEMPLATE: rv = deserialize_indirect_attribute(in, out->pValue); break; case CKA_ALLOWED_MECHANISMS: rv = deserialize_mecha_list(out->pValue, data, in->size / sizeof(uint32_t)); out->ulValueLen = in->size / sizeof(uint32_t) * sizeof(CK_ULONG); break; /* Attributes which data value do not need conversion (aside ulong) */ default: memcpy(out->pValue, data, in->size); out->ulValueLen = in->size; break; } return rv; } CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes, CK_ULONG count) { CK_ATTRIBUTE_PTR cur_attr = attributes; CK_ULONG n = 0; CK_RV rv = CKR_OK; uint8_t *curr_head = in; size_t len = 0; curr_head += sizeof(struct pkcs11_object_head); for (n = count; n > 0; n--, cur_attr++, curr_head += len) { struct pkcs11_attribute_head *cli_ref = (void *)curr_head; struct pkcs11_attribute_head cli_head = { 0 }; void *data_ptr = NULL; /* Make copy if header so that is aligned properly. */ memcpy(&cli_head, cli_ref, sizeof(cli_head)); /* Get real data pointer from template data */ data_ptr = cli_ref->data; len = sizeof(cli_head); /* Advance by size provisioned in input serialized buffer */ if (cur_attr->pValue) { if (ck_attr_is_ulong(cur_attr->type)) len += sizeof(uint32_t); else len += cur_attr->ulValueLen; } rv = deserialize_ck_attribute(&cli_head, data_ptr, cur_attr); if (rv) return rv; } return rv; } /* * Serialization of CK mechanism parameters * * Most mechanism have no parameters. * Some mechanism have a single 32bit parameter. * Some mechanism have a specific parameter structure which may contain * indirected data (data referred by a buffer pointer). * * Below are each structure specific mechanisms parameters. */ static CK_RV serialize_mecha_aes_ctr(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_AES_CTR_PARAMS_PTR param = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; uint32_t size = 0; rv = serialize_32b(obj, obj->type); if (rv) return rv; size = sizeof(uint32_t) + sizeof(param->cb); rv = serialize_32b(obj, size); if (rv) return rv; rv = serialize_ck_ulong(obj, param->ulCounterBits); if (rv) return rv; rv = serialize_buffer(obj, param->cb, sizeof(param->cb)); if (rv) return rv; return rv; } static CK_RV serialize_mecha_aes_gcm(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_GCM_PARAMS_PTR param = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; CK_ULONG aad_len = 0; /* AAD is not manadatory */ if (param->pAAD) aad_len = param->ulAADLen; if (!param->pIv) return CKR_MECHANISM_PARAM_INVALID; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, 3 * sizeof(uint32_t) + param->ulIvLen + aad_len); if (rv) return rv; rv = serialize_ck_ulong(obj, param->ulIvLen); if (rv) return rv; rv = serialize_buffer(obj, param->pIv, param->ulIvLen); if (rv) return rv; rv = serialize_ck_ulong(obj, aad_len); if (rv) return rv; rv = serialize_buffer(obj, param->pAAD, aad_len); if (rv) return rv; return serialize_ck_ulong(obj, param->ulTagBits); } static CK_RV serialize_mecha_aes_iv(struct serializer *obj, CK_MECHANISM_PTR mecha) { uint32_t iv_size = mecha->ulParameterLen; CK_RV rv = CKR_GENERAL_ERROR; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, iv_size); if (rv) return rv; return serialize_buffer(obj, mecha->pParameter, mecha->ulParameterLen); } static CK_RV serialize_mecha_key_deriv_str(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_KEY_DERIVATION_STRING_DATA_PTR param = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; uint32_t size = 0; rv = serialize_32b(obj, obj->type); if (rv) return rv; size = sizeof(uint32_t) + param->ulLen; rv = serialize_32b(obj, size); if (rv) return rv; rv = serialize_ck_ulong(obj, param->ulLen); if (rv) return rv; return serialize_buffer(obj, param->pData, param->ulLen); } static CK_RV serialize_mecha_ecdh1_derive_param(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_ECDH1_DERIVE_PARAMS *params = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen + params->ulPublicDataLen; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, params_size); if (rv) return rv; rv = serialize_32b(obj, params->kdf); if (rv) return rv; rv = serialize_32b(obj, params->ulSharedDataLen); if (rv) return rv; rv = serialize_buffer(obj, params->pSharedData, params->ulSharedDataLen); if (rv) return rv; rv = serialize_32b(obj, params->ulPublicDataLen); if (rv) return rv; return serialize_buffer(obj, params->pPublicData, params->ulPublicDataLen); } static CK_RV serialize_mecha_aes_cbc_encrypt_data(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR param = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; uint32_t size = 0; rv = serialize_32b(obj, obj->type); if (rv) return rv; size = sizeof(param->iv) + sizeof(uint32_t) + param->length; rv = serialize_32b(obj, size); if (rv) return rv; rv = serialize_buffer(obj, param->iv, sizeof(param->iv)); if (rv) return rv; rv = serialize_ck_ulong(obj, param->length); if (rv) return rv; return serialize_buffer(obj, param->pData, param->length); } static CK_RV serialize_mecha_rsa_pss_param(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_RSA_PKCS_PSS_PARAMS *params = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; uint32_t params_size = 3 * sizeof(uint32_t); if (mecha->ulParameterLen != sizeof(*params)) return CKR_ARGUMENTS_BAD; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, params_size); if (rv) return rv; rv = serialize_ck_ulong(obj, params->hashAlg); if (rv) return rv; rv = serialize_ck_ulong(obj, params->mgf); if (rv) return rv; return serialize_ck_ulong(obj, params->sLen); } static CK_RV serialize_mecha_rsa_oaep_param(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_RSA_PKCS_OAEP_PARAMS *params = mecha->pParameter; CK_RV rv = CKR_GENERAL_ERROR; size_t params_size = 4 * sizeof(uint32_t) + params->ulSourceDataLen; if (mecha->ulParameterLen != sizeof(*params)) return CKR_ARGUMENTS_BAD; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, params_size); if (rv) return rv; rv = serialize_ck_ulong(obj, params->hashAlg); if (rv) return rv; rv = serialize_ck_ulong(obj, params->mgf); if (rv) return rv; rv = serialize_ck_ulong(obj, params->source); if (rv) return rv; rv = serialize_ck_ulong(obj, params->ulSourceDataLen); if (rv) return rv; return serialize_buffer(obj, params->pSourceData, params->ulSourceDataLen); } static CK_RV serialize_mecha_rsa_aes_key_wrap(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_RSA_AES_KEY_WRAP_PARAMS *params = mecha->pParameter; CK_RSA_PKCS_OAEP_PARAMS *aes_params = params->pOAEPParams; CK_RV rv = CKR_GENERAL_ERROR; size_t params_size = 5 * sizeof(uint32_t) + aes_params->ulSourceDataLen; if (mecha->ulParameterLen != sizeof(*params)) return CKR_ARGUMENTS_BAD; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, params_size); if (rv) return rv; rv = serialize_ck_ulong(obj, params->ulAESKeyBits); if (rv) return rv; rv = serialize_ck_ulong(obj, aes_params->hashAlg); if (rv) return rv; rv = serialize_ck_ulong(obj, aes_params->mgf); if (rv) return rv; rv = serialize_ck_ulong(obj, aes_params->source); if (rv) return rv; rv = serialize_ck_ulong(obj, aes_params->ulSourceDataLen); if (rv) return rv; return serialize_buffer(obj, aes_params->pSourceData, aes_params->ulSourceDataLen); } static CK_RV serialize_mecha_eddsa(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_RV rv = CKR_GENERAL_ERROR; CK_EDDSA_PARAMS *params = mecha->pParameter; rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, 2 * sizeof(uint32_t) + params->ulContextDataLen); if (rv) return rv; rv = serialize_32b(obj, params->phFlag); if (rv) return rv; rv = serialize_32b(obj, params->ulContextDataLen); if (rv) return rv; return serialize_buffer(obj, params->pContextData, params->ulContextDataLen); } static CK_RV serialize_mecha_mac_general_param(struct serializer *obj, CK_MECHANISM_PTR mecha) { CK_RV rv = CKR_GENERAL_ERROR; CK_ULONG ck_data = 0; if (mecha->ulParameterLen != sizeof(ck_data)) return CKR_ARGUMENTS_BAD; memcpy(&ck_data, mecha->pParameter, mecha->ulParameterLen); rv = serialize_32b(obj, obj->type); if (rv) return rv; rv = serialize_32b(obj, sizeof(uint32_t)); if (rv) return rv; return serialize_ck_ulong(obj, ck_data); } /** * serialize_ck_mecha_params - serialize a mechanism type & params * * @obj - serializer used to track the serialization * @mechanism - pointer of the in structure aligned CK_MECHANISM. * * Serialized content: * [mechanism-type][mechanism-param-blob] * * [mechanism-param-blob] depends on mechanism type ID, see * serialize_mecha_XXX(). */ CK_RV serialize_ck_mecha_params(struct serializer *obj, CK_MECHANISM_PTR mechanism) { CK_MECHANISM mecha = { 0 }; CK_RV rv = CKR_GENERAL_ERROR; memset(obj, 0, sizeof(*obj)); obj->object = PKCS11_CKO_MECHANISM; mecha = *mechanism; obj->type = mecha.mechanism; if (obj->type == PKCS11_UNDEFINED_ID) return CKR_MECHANISM_INVALID; switch (mecha.mechanism) { case CKM_GENERIC_SECRET_KEY_GEN: case CKM_AES_KEY_GEN: case CKM_AES_ECB: case CKM_AES_CMAC: case CKM_MD5: case CKM_SHA_1: case CKM_SHA224: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: case CKM_MD5_HMAC: case CKM_SHA_1_HMAC: case CKM_SHA224_HMAC: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC: case CKM_EC_KEY_PAIR_GEN: case CKM_EC_EDWARDS_KEY_PAIR_GEN: case CKM_ECDSA: case CKM_ECDSA_SHA1: case CKM_ECDSA_SHA224: case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: case CKM_RSA_PKCS_KEY_PAIR_GEN: case CKM_RSA_PKCS: case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA224_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: /* No parameter expected, size shall be 0 */ if (mechanism->ulParameterLen) return CKR_MECHANISM_PARAM_INVALID; rv = serialize_32b(obj, obj->type); if (rv) return rv; return serialize_32b(obj, 0); case CKM_EDDSA: return serialize_mecha_eddsa(obj, &mecha); case CKM_AES_CBC: case CKM_AES_CBC_PAD: case CKM_AES_CTS: return serialize_mecha_aes_iv(obj, &mecha); case CKM_AES_CTR: return serialize_mecha_aes_ctr(obj, &mecha); case CKM_AES_GCM: return serialize_mecha_aes_gcm(obj, &mecha); case CKM_AES_ECB_ENCRYPT_DATA: return serialize_mecha_key_deriv_str(obj, &mecha); case CKM_AES_CBC_ENCRYPT_DATA: return serialize_mecha_aes_cbc_encrypt_data(obj, &mecha); case CKM_ECDH1_DERIVE: case CKM_ECDH1_COFACTOR_DERIVE: return serialize_mecha_ecdh1_derive_param(obj, &mecha); case CKM_RSA_PKCS_PSS: case CKM_SHA1_RSA_PKCS_PSS: case CKM_SHA256_RSA_PKCS_PSS: case CKM_SHA384_RSA_PKCS_PSS: case CKM_SHA512_RSA_PKCS_PSS: case CKM_SHA224_RSA_PKCS_PSS: return serialize_mecha_rsa_pss_param(obj, &mecha); case CKM_RSA_PKCS_OAEP: return serialize_mecha_rsa_oaep_param(obj, &mecha); case CKM_AES_CMAC_GENERAL: case CKM_MD5_HMAC_GENERAL: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA224_HMAC_GENERAL: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA512_HMAC_GENERAL: return serialize_mecha_mac_general_param(obj, &mecha); case CKM_RSA_AES_KEY_WRAP: return serialize_mecha_rsa_aes_key_wrap(obj, &mecha); default: return CKR_MECHANISM_INVALID; } } optee_client-4.1.0/libckteec/src/serialize_ck.h000066400000000000000000000013371455150071200215230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef LIBCKTEEC_SERIALIZE_CK_H #define LIBCKTEEC_SERIALIZE_CK_H #include #include "serializer.h" /* Create (and allocate) a serial object for CK_ATTRIBUTE array */ CK_RV serialize_ck_attributes(struct serializer *obj, CK_ATTRIBUTE_PTR attributes, CK_ULONG count); /* Convert PKCS11 TA attributes back to CK_ATTRIBUTE array */ CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes, CK_ULONG count); /* Create (and allocate) a serial object for CK_MECHANISM array */ CK_RV serialize_ck_mecha_params(struct serializer *obj, CK_MECHANISM_PTR mechanisms); #endif /*LIBCKTEEC_SERIALIZE_CK_H*/ optee_client-4.1.0/libckteec/src/serializer.c000066400000000000000000000030501455150071200212150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include "ck_helpers.h" #include "local_utils.h" #include "serializer.h" CK_RV init_serial_object(struct serializer *obj) { struct pkcs11_object_head head = { 0 }; memset(obj, 0, sizeof(*obj)); return serialize_buffer(obj, &head, sizeof(head)); } void finalize_serial_object(struct serializer *obj) { struct pkcs11_object_head head = { 0 }; head.attrs_size = obj->size - sizeof(head); head.attrs_count = obj->item_count; memcpy(obj->buffer, &head, sizeof(head)); } void release_serial_object(struct serializer *obj) { free(obj->buffer); obj->buffer = NULL; } /** * serialize - append data in a serialized buffer * * Serialize data in provided buffer. * Ensure 64byte alignment of appended data in the buffer. */ static CK_RV serialize(char **bstart, size_t *blen, void *data, size_t len) { size_t nlen = *blen + len; char *buf = realloc(*bstart, nlen); if (!buf) return CKR_HOST_MEMORY; memcpy(buf + *blen, data, len); *blen = nlen; *bstart = buf; return CKR_OK; } CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size) { return serialize(&obj->buffer, &obj->size, data, size); } CK_RV serialize_32b(struct serializer *obj, uint32_t data) { return serialize_buffer(obj, &data, sizeof(data)); } CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data) { uint32_t data32 = data; return serialize_buffer(obj, &data32, sizeof(data32)); } optee_client-4.1.0/libckteec/src/serializer.h000066400000000000000000000020111455150071200212160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef LIBCKTEEC_SERIALIZER_H #define LIBCKTEEC_SERIALIZER_H #include #include #include #include /* * Struct used to create the buffer storing the serialized data. * Contains some fields to help parsing content (type/boolprops). */ struct serializer { char *buffer; /* serial buffer base address */ size_t size; /* serial buffer current byte size */ size_t item_count; /* number of items in entry table */ uint32_t object; uint32_t type; }; /* Init/finalize/release a serializer object */ CK_RV init_serial_object(struct serializer *obj); void finalize_serial_object(struct serializer *obj); void release_serial_object(struct serializer *obj); CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size); CK_RV serialize_32b(struct serializer *obj, uint32_t data); CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data); #endif /*LIBCKTEEC_SERIALIZER_H*/ optee_client-4.1.0/libseteec/000077500000000000000000000000001455150071200161255ustar00rootroot00000000000000optee_client-4.1.0/libseteec/CMakeLists.txt000066400000000000000000000037171455150071200206750ustar00rootroot00000000000000project(seteec VERSION 0.1.0 LANGUAGES C) ################################################################################ # Packages ################################################################################ find_package(Threads REQUIRED) if(NOT THREADS_FOUND) message(FATAL_ERROR "Threads not found") endif() include(GNUInstallDirs) ################################################################################ # Source files ################################################################################ set(SRC src/se.c ) ################################################################################ # Built library ################################################################################ add_library(seteec ${SRC}) set_target_properties(seteec PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) ################################################################################ # Flags always set ################################################################################ target_compile_definitions(seteec PRIVATE -D_GNU_SOURCE PRIVATE -DBINARY_PREFIX="LT" ) ################################################################################ # Optional flags ################################################################################ ################################################################################ # Public and private header and library dependencies ################################################################################ target_include_directories(seteec PUBLIC $ $ PRIVATE src ) target_link_libraries(seteec PRIVATE pthread PRIVATE teec ) ################################################################################ # Install targets ################################################################################ install(TARGETS seteec DESTINATION ${CMAKE_INSTALL_LIBDIR} ) add_subdirectory(include) optee_client-4.1.0/libseteec/Makefile000066400000000000000000000040211455150071200175620ustar00rootroot00000000000000include ../flags.mk include ../config.mk OUT_DIR := $(OO)/libseteec .PHONY: all libseteec clean all: libseteec install: libseteec LIB_NAME := libseteec MAJOR_VERSION := 0 MINOR_VERSION := 1 PATCH_VERSION := 0 LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) LIBSETEEC_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) LIBSETEEC_AR_LIBRARY := $(LIB_NAME).a LIBSETEEC_SRC_DIR := src LIBSETEEC_SRCS = se.c LIBSETEEC_INCLUDES = ${CURDIR}/include LIBSETEEC_INCLUDES += ${CURDIR}/../libteec/include LIBSETEEC_CFLAGS := $(addprefix -I, $(LIBSETEEC_INCLUDES)) \ $(CFLAGS) -D_GNU_SOURCE -fPIC LIBSETEEC_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec -lpthread LIBSETEEC_OBJ_DIR := $(OUT_DIR) LIBSETEEC_OBJS := $(patsubst %.c,$(LIBSETEEC_OBJ_DIR)/%.o, $(LIBSETEEC_SRCS)) $(LIBSETEEC_OBJ_DIR)/%.o: ${LIBSETEEC_SRC_DIR}/%.c $(VPREFIX)mkdir -p $(LIBSETEEC_OBJ_DIR) @echo " CC $<" $(VPREFIX)$(CC) $(LIBSETEEC_CFLAGS) -c $< -o $@ libseteec: $(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY) $(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY): $(LIBSETEEC_OBJS) @echo " LINK $@" $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(LIBSETEEC_LFLAGS) @echo "" libseteec: $(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY) $(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY): $(LIBSETEEC_OBJS) @echo " AR $@" $(VPREFIX)$(AR) rcs $@ $+ libseteec: $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so ################################################################################ # Cleaning up configuration ################################################################################ clean: $(RM) $(LIBSETEEC_OBJS) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) $(RM) $(OUT_DIR)/$(LIB_MAJOR) $(RM) $(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY) $(RM) $(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY) $(call rmdir,$(OUT_DIR)) optee_client-4.1.0/libseteec/include/000077500000000000000000000000001455150071200175505ustar00rootroot00000000000000optee_client-4.1.0/libseteec/include/CMakeLists.txt000066400000000000000000000002621455150071200223100ustar00rootroot00000000000000project(libseteec-headers C) FILE(GLOB INSTALL_HEADERS "*.h") add_library(${PROJECT_NAME} INTERFACE) install(FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) optee_client-4.1.0/libseteec/include/se_tee.h000066400000000000000000000045471455150071200211770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Foundries.io * Jorge Ramirez-Ortiz */ #ifndef SE_TEE_H #define SE_TEE_H #include #ifdef __cplusplus extern "C" { #endif typedef unsigned long SE_ULONG; typedef SE_ULONG SE_RV; /* Values for type SR_RV */ #define SER_OK 0x0000 #define SER_CANT_OPEN_SESSION 0x0001 #define SER_ERROR_GENERIC 0x0002 /* * Type identifier for the APDU message as described by Smart Card Standard ISO7816-4 * about ADPU message bodies decoding convention: * * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 */ enum se_apdu_type { SE_APDU_NO_HINT, SE_APDU_CASE_1, SE_APDU_CASE_2, SE_APDU_CASE_2E, SE_APDU_CASE_3, SE_APDU_CASE_3E, SE_APDU_CASE_4, SE_APDU_CASE_4E, }; /** * se_apdu_request() - Send an APDU message and get response. * * @param type Type of the APDU command. * @param hdr Pointer to APDU message header. * @param hdr_len Byte length of message header @hdr. * @param src Pointer to APDU message payload. * @param src_len Byte length of message payload @src. * @param dst Pointer to APDU message reponse buffer. * @param dst_len Byte length of reponse buffer @dst. * * @return SER_CANT_OPEN_SESSION Error opening the TEE session. * @return SER_ERROR_GENERIC Error unspecified. * @return SER_OK On success. */ SE_RV se_apdu_request(enum se_apdu_type type, unsigned char *hdr, size_t hdr_len, unsigned char *src, size_t src_len, unsigned char *dst, size_t *dst_len); /** * se_scp03_enable() - Enable the SCP03 protocol using the keys active in the * Secure Element. * * Enables the SCP03 session with the Secure Element. * * @return SER_CANT_OPEN_SESSION Error opening the TEE session. * @return SER_ERROR_GENERIC Error unspecified. * @return SER_OK On success. */ SE_RV se_scp03_enable(void); /** * se_scp03_rotate_keys_and_enable() - Attempt to replace the active SCP03 keys * and enable the SCP03 session. * * Generates secure keys for the board and writes them in the Secure Element non * volatile memory. Then re-enables the session. * * @return SER_CANT_OPEN_SESSION Error opening the TEE session. * @return SER_ERROR_GENERIC Error unspecified. * @return SER_OK On success. */ SE_RV se_scp03_rotate_keys_and_enable(void); #ifdef __cplusplus } #endif #endif /*SE_TEE_H*/ optee_client-4.1.0/libseteec/src/000077500000000000000000000000001455150071200167145ustar00rootroot00000000000000optee_client-4.1.0/libseteec/src/pta_apdu.h000066400000000000000000000027501455150071200206660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (C) 2021, Foundries Limited * Author: Jorge Ramirez */ #ifndef __PTA_APDU_H #define __PTA_APDU_H #define PTA_APDU_UUID { 0x3f3eb880, 0x3639, 0x11ec, \ { 0x9b, 0x9d, 0x0f, 0x3f, 0xc9, 0x46, 0x8f, 0x50 } } /* * ADPU based communication with the Secure Element * * [in] value[0].a Use APDU TXRX hints: PTA_APDU_TXRX_CASE_* * [in] memref[1].buffer APDU header. * [in] memref[1].size APDU header length. * [in] memref[2].buffer request (APDU raw frame). * [in] memref[2].size request length. * [out] memref[3].buffer response (APDU raw frame). * [out] memref[3].size response length. * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented * TEE_ERROR_GENERIC - Invoke command failure */ #define PTA_CMD_TXRX_APDU_RAW_FRAME 0 /* * Type identifier for the APDU message as described by Smart Card Standard * ISO7816-4 about ADPU message bodies decoding convention: * * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 */ #define PTA_APDU_TXRX_CASE_NO_HINT 0 #define PTA_APDU_TXRX_CASE_1 1 #define PTA_APDU_TXRX_CASE_2 2 #define PTA_APDU_TXRX_CASE_2E 3 #define PTA_APDU_TXRX_CASE_3 4 #define PTA_APDU_TXRX_CASE_3E 5 #define PTA_APDU_TXRX_CASE_4 6 #define PTA_APDU_TXRX_CASE_4E 7 #endif /* __PTA_APDU_H */ optee_client-4.1.0/libseteec/src/pta_scp03.h000066400000000000000000000015401455150071200206610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (C) 2020, Foundries Limited */ #ifndef __PTA_SCP03_H #define __PTA_SCP03_H #define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \ { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } } /* * Enable SCP03 support on the SE * * [in] value[0].a Use session keys PTA_SCP03_SESSION_* * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented * TEE_ERROR_GENERIC - Invoke command failure */ #define PTA_CMD_ENABLE_SCP03 0 /* Enable the session using the current keys in the Secure Element */ #define PTA_SCP03_SESSION_CURRENT_KEYS 0 /* Enable the session after replacing the current keys in the Secure Element */ #define PTA_SCP03_SESSION_ROTATE_KEYS 1 #endif /* __PTA_SCP03_H */ optee_client-4.1.0/libseteec/src/se.c000066400000000000000000000062261455150071200174750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Foundries.io Ltd */ #ifndef BINARY_PREFIX #define BINARY_PREFIX "seteec" #endif #include #include #include #include #include #include #include #include #include #include #include "pta_apdu.h" #include "pta_scp03.h" struct ta_context { pthread_mutex_t lock; TEEC_Context context; TEEC_Session session; TEEC_UUID uuid; bool open; }; static struct ta_context apdu_ta_ctx = { .lock = PTHREAD_MUTEX_INITIALIZER, .uuid = PTA_APDU_UUID, }; static struct ta_context scp03_ta_ctx = { .lock = PTHREAD_MUTEX_INITIALIZER, .uuid = PTA_SCP03_UUID, }; static bool open_session(struct ta_context *ctx) { TEEC_Result res = TEEC_SUCCESS; if (pthread_mutex_lock(&ctx->lock)) return false; if (!ctx->open) { res = TEEC_InitializeContext(NULL, &ctx->context); if (!res) { res = TEEC_OpenSession(&ctx->context, &ctx->session, &ctx->uuid, TEEC_LOGIN_PUBLIC, NULL, NULL, NULL); if (!res) ctx->open = true; } } return !pthread_mutex_unlock(&ctx->lock) && !res; } static SE_RV do_scp03(uint32_t cmd) { TEEC_Operation op = { 0 }; if (!open_session(&scp03_ta_ctx)) return SER_CANT_OPEN_SESSION; op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, 0, 0, 0); op.params[0].value.a = cmd; if (TEEC_InvokeCommand(&scp03_ta_ctx.session, PTA_CMD_ENABLE_SCP03, &op, NULL)) return SER_ERROR_GENERIC; return SER_OK; } SE_RV se_scp03_enable(void) { return do_scp03(PTA_SCP03_SESSION_CURRENT_KEYS); } SE_RV se_scp03_rotate_keys_and_enable(void) { return do_scp03(PTA_SCP03_SESSION_ROTATE_KEYS); } SE_RV se_apdu_request(enum se_apdu_type apdu_type, unsigned char *hdr, size_t hdr_len, unsigned char *src, size_t src_len, unsigned char *dst, size_t *dst_len) { uint32_t type = PTA_APDU_TXRX_CASE_NO_HINT; TEEC_Operation op = { 0 }; switch (apdu_type) { case SE_APDU_NO_HINT: type = PTA_APDU_TXRX_CASE_NO_HINT; break; case SE_APDU_CASE_1: type = PTA_APDU_TXRX_CASE_1; break; case SE_APDU_CASE_2: type = PTA_APDU_TXRX_CASE_2; break; case SE_APDU_CASE_2E: type = PTA_APDU_TXRX_CASE_2E; break; case SE_APDU_CASE_3: type = PTA_APDU_TXRX_CASE_3; break; case SE_APDU_CASE_3E: type = PTA_APDU_TXRX_CASE_3E; break; case SE_APDU_CASE_4: type = PTA_APDU_TXRX_CASE_4; break; case SE_APDU_CASE_4E: type = PTA_APDU_TXRX_CASE_4E; break; default: return SER_ERROR_GENERIC; } if (!open_session(&apdu_ta_ctx)) return SER_CANT_OPEN_SESSION; op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT); op.params[0].value.a = type; op.params[1].tmpref.buffer = hdr; op.params[1].tmpref.size = hdr_len; op.params[2].tmpref.buffer = src; op.params[2].tmpref.size = src_len; op.params[3].tmpref.buffer = dst; op.params[3].tmpref.size = *dst_len; if (TEEC_InvokeCommand(&apdu_ta_ctx.session, PTA_CMD_TXRX_APDU_RAW_FRAME, &op, NULL)) return SER_ERROR_GENERIC; *dst_len = op.params[3].tmpref.size; return SER_OK; } optee_client-4.1.0/libteeacl/000077500000000000000000000000001455150071200161125ustar00rootroot00000000000000optee_client-4.1.0/libteeacl/CMakeLists.txt000066400000000000000000000031121455150071200206470ustar00rootroot00000000000000project(teeacl VERSION 0.1.0 LANGUAGES C ) include(GNUInstallDirs) ################################################################################ # Source files ################################################################################ set(SRC src/group.c src/tee_uuid.c ) ################################################################################ # Built library ################################################################################ add_library(teeacl ${SRC}) set_target_properties(teeacl PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) ################################################################################ # Flags always set ################################################################################ target_compile_definitions(teeacl PRIVATE -D_GNU_SOURCE PRIVATE -DBINARY_PREFIX="LT" ) ################################################################################ # Public and private header and library dependencies ################################################################################ target_include_directories(teeacl PUBLIC $ $ ) target_link_libraries(teeacl PUBLIC PkgConfig::uuid ) ################################################################################ # Install targets ################################################################################ install(TARGETS teeacl DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") optee_client-4.1.0/libteeacl/Makefile000066400000000000000000000042611455150071200175550ustar00rootroot00000000000000include ../flags.mk include ../config.mk OUT_DIR := $(OO)/libteeacl .PHONY: all libteeacl check-libuuid clean all: libteeacl install: libteeacl LIB_NAME := libteeacl MAJOR_VERSION := 0 MINOR_VERSION := 1 PATCH_VERSION := 0 LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) LIBTEEACL_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) LIBTEEACL_AR_LIBRARY := $(LIB_NAME).a LIBTEEACL_SRC_DIR := src LIBTEEACL_SRCS = group.c LIBTEEACL_SRCS += tee_uuid.c LIBTEEACL_INCLUDES = ${CURDIR}/include LIBTEEACL_CFLAGS := $(addprefix -I, $(LIBTEEACL_INCLUDES)) \ $(shell $(PKG_CONFIG) --cflags uuid) \ $(CFLAGS) -D_GNU_SOURCE -fPIC LIBTEEACL_LFLAGS := $(LDFLAGS) $(shell $(PKG_CONFIG) --libs uuid) LIBTEEACL_OBJ_DIR := $(OUT_DIR) LIBTEEACL_OBJS := $(patsubst %.c,$(LIBTEEACL_OBJ_DIR)/%.o, $(LIBTEEACL_SRCS)) $(LIBTEEACL_OBJ_DIR)/%.o: ${LIBTEEACL_SRC_DIR}/%.c $(VPREFIX)mkdir -p $(LIBTEEACL_OBJ_DIR) @echo " CC $<" $(VPREFIX)$(CC) $(LIBTEEACL_CFLAGS) -c $< -o $@ libteeacl: check-libuuid check-libuuid: @echo " Finding uuid.pc" $(VPREFIX)$(PKG_CONFIG) --atleast-version=2.34 uuid libteeacl: $(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY) $(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY): $(LIBTEEACL_OBJS) @echo " LINK $@" $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIBTEEACL_SO_LIBRARY) -o $@ $+ $(LIBTEEACL_LFLAGS) @echo "" libteeacl: $(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY) $(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY): $(LIBTEEACL_OBJS) @echo " AR $@" $(VPREFIX)$(AR) rcs $@ $+ libteeacl: $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so ################################################################################ # Cleaning up configuration ################################################################################ clean: $(RM) $(LIBTEEACL_OBJS) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) $(RM) $(OUT_DIR)/$(LIB_MAJOR) $(RM) $(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY) $(RM) $(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY) $(call rmdir,$(OUT_DIR)) optee_client-4.1.0/libteeacl/include/000077500000000000000000000000001455150071200175355ustar00rootroot00000000000000optee_client-4.1.0/libteeacl/include/teeacl.h000066400000000000000000000047351455150071200211540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Vaisala Oyj. */ /* * Definitions for configuring and using Access Control List (ACL) * based login methods. */ #ifndef TEEACL_H #define TEEACL_H #include #include #ifdef __cplusplus extern "C" { #endif // TEE Client UUID name space identifier (UUIDv4) // same as `tee_client_uuid_ns` in linux kernel drivers/tee/tee_core.c #define KERNEL_NAMESPACE "58ac9ca0-2086-4683-a1b8-ec4bc08e01b6" /* * len UUID = 36 characters * * Prefixes: * public * user: * group: * * + '\0' character totals 43, roundup. */ /** * Required length for UUID char buffers */ #define TEEACL_L_UUID 48 /** * teeacl_gid_from_name - Try to resolve gid_t for a given `group_name`. * * If a matching group is found, zero is returned and `gid_out` will be set to * the found value. * If no group is found, -ENOENT is returned. * If memory allocation fails, -ENOMEM is returned. * For other failures, errno is returned. * * @param gid_out Ptr to gid result. Will be set to group id if a matching * group is found. * @param group_name Name of group to resolve. * @return 0 if a matching group is found, see detailed description for other * cases. */ int teeacl_gid_from_name(gid_t *gid_out, const char *group_name); /** * teeacl_group_acl_uuid() - Encode a group login ACL string to the * provided uuid_buf * * @param uuid_buf A buffer of length TEEACL_L_UUID. * @param group Group id to encode for login. * @return 0 on success, otherwise a negative number is returned in case of failure. */ int teeacl_group_acl_uuid(char uuid_buf[TEEACL_L_UUID], gid_t group); /** * The possible return values of the *_user_is_member_of functions. */ enum rv_groupmember { NOT_MEMBER, IS_MEMBER, E_MEMORY, /**< Failed to allocate memory. */ E_GROUPLIST /**< Failed to read group listing. */ }; /** * teeacl_current_user_is_member_of() - Check if the effective user ID of * the process is a member in `group`. * * @param group Group id to check membership of. * @return enum rv_groupmember form result. */ enum rv_groupmember teeacl_current_user_is_member_of(gid_t group); /** * teeacl_user_is_member_of() - Check if `user` is a member in `group`. * * @param user Username string. * @param group Group id to check membership of. * @return enum rv_groupmember form result. */ enum rv_groupmember teeacl_user_is_member_of(const char *user, gid_t group); #ifdef __cplusplus } // extern "C" #endif #endif /* TEEACL_H */ optee_client-4.1.0/libteeacl/src/000077500000000000000000000000001455150071200167015ustar00rootroot00000000000000optee_client-4.1.0/libteeacl/src/group.c000066400000000000000000000035451455150071200202100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Vaisala Oyj. */ #include #include #include #include #include #include #include static long teeacl_getgr_r_size_max(void) { long s = sysconf(_SC_GETGR_R_SIZE_MAX); if (s == -1) return 1024; return s; }; int teeacl_gid_from_name(gid_t *gid_out, const char *group_name) { struct group grp = { 0 }; char *buffer = NULL; struct group *result = NULL; size_t b_size = 0; int rv = 0; b_size = teeacl_getgr_r_size_max(); buffer = calloc(1, b_size); if (!buffer) return -ENOMEM; rv = getgrnam_r(group_name, &grp, buffer, b_size, &result); free(buffer); if (!result) { if (rv == 0) return -ENOENT; else return rv; } else { *gid_out = grp.gr_gid; return 0; } } enum rv_groupmember teeacl_current_user_is_member_of(gid_t group) { char username[L_cuserid] = { 0 }; cuserid(username); return teeacl_user_is_member_of(username, group); } enum rv_groupmember teeacl_user_is_member_of(const char *user, gid_t group) { enum rv_groupmember result = E_MEMORY; int ret = 0; int i = 0; int grouplistsize = 8; /* initial guess */ gid_t *p_groups = NULL; gid_t *groups = calloc(grouplistsize, sizeof(gid_t)); if (!groups) return E_MEMORY; ret = getgrouplist(user, group, groups, &grouplistsize); if (ret == -1) { p_groups = groups; /* we use realloc, since uClibc does not implement reallocarray */ groups = realloc(groups, grouplistsize * sizeof(gid_t)); if (!groups) { free(p_groups); return E_MEMORY; } ret = getgrouplist(user, group, groups, &grouplistsize); if (ret == -1) { result = E_GROUPLIST; goto out; } } for (i = 0; i < grouplistsize; ++i) { if (group == groups[i]) { result = IS_MEMBER; goto out; } } result = NOT_MEMBER; out: free(groups); return result; } optee_client-4.1.0/libteeacl/src/tee_uuid.c000066400000000000000000000014001455150071200206430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Vaisala Oyj. */ #include #include #include #include int teeacl_group_acl_uuid(char uuid_buf[TEEACL_L_UUID], gid_t group) { uuid_t g_uuid = { 0 }; uuid_t k_uuid = { 0 }; char gid_buf[TEEACL_L_UUID] = { 0 }; size_t gid_buf_len = 0; uint gstr_len = 6; int rv = snprintf(gid_buf, TEEACL_L_UUID, "gid=%x", group); if (rv < 0) return rv; if (rv >= TEEACL_L_UUID) return -1; rv = uuid_parse(KERNEL_NAMESPACE, k_uuid); if (rv < 0) return rv; gid_buf_len = strnlen(gid_buf, TEEACL_L_UUID); uuid_generate_sha1(g_uuid, k_uuid, gid_buf, gid_buf_len); memcpy(uuid_buf, "group:", gstr_len); uuid_unparse(g_uuid, uuid_buf + gstr_len); return 0; } optee_client-4.1.0/libteec/000077500000000000000000000000001455150071200155755ustar00rootroot00000000000000optee_client-4.1.0/libteec/CMakeLists.txt000066400000000000000000000057331455150071200203450ustar00rootroot00000000000000project(libteec VERSION 1.0.0 LANGUAGES C) ################################################################################ # Packages ################################################################################ find_package(Threads REQUIRED) if(NOT THREADS_FOUND) message(FATAL_ERROR "Threads not found") endif() ################################################################################ # Configuration flags always included ################################################################################ option(CFG_TEE_BENCHMARK "Build with benchmark support" OFF) set(CFG_TEE_CLIENT_LOG_LEVEL "1" CACHE STRING "libteec log level") set(CFG_TEE_CLIENT_LOG_FILE "/data/tee/teec.log" CACHE STRING "Location of libteec log") ################################################################################ # Source files ################################################################################ set(SRC src/tee_client_api.c src/teec_trace.c ) if(CFG_TEE_BENCHMARK) set(SRC ${SRC} src/teec_benchmark.c) endif() ################################################################################ # Built library ################################################################################ add_library(teec ${SRC}) set(libteectgt teec) configure_file(libteec.pc.in libteec.pc @ONLY) set_target_properties(teec PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) ################################################################################ # Flags always set ################################################################################ target_compile_definitions(teec PRIVATE -D_GNU_SOURCE PRIVATE -DDEBUGLEVEL_${CFG_TEE_CLIENT_LOG_LEVEL} PRIVATE -DTEEC_LOG_FILE="${CFG_TEE_CLIENT_LOG_FILE}" PRIVATE -DBINARY_PREFIX="LT" ) ################################################################################ # Optional flags ################################################################################ if(CFG_TEE_BENCHMARK) target_compile_definitions(teec PRIVATE -DCFG_TEE_BENCHMARK) endif() ################################################################################ # Public and private header and library dependencies ################################################################################ target_include_directories(teec PUBLIC include PRIVATE src ) target_link_libraries(teec PUBLIC ${CMAKE_THREAD_LIBS_INIT} # this is pthreads ) ################################################################################ # Install targets ################################################################################ # FIXME: This should in someway harmonize with CFG_TEE_CLIENT_LOAD_PATH # FIXME: Should we change this to /usr/local/lib? install(TARGETS teec LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") install(DIRECTORY include DESTINATION ${CMAKE_INSTALL_PREFIX} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libteec.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" ) optee_client-4.1.0/libteec/Makefile000066400000000000000000000040751455150071200172430ustar00rootroot00000000000000include ../flags.mk include ../config.mk OUT_DIR := $(OO)/libteec .PHONY: all libteec clean all: libteec ################################################################################ # Teec configuration ################################################################################ MAJOR_VERSION := 1 MINOR_VERSION := 0 PATCH_VERSION := 0 LIB_NAME := libteec.so LIB_MAJOR := $(LIB_NAME).$(MAJOR_VERSION) LIB_MAJ_MIN := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION) LIB_MAJ_MIN_P := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) TEEC_SRCS := tee_client_api.c \ teec_trace.c ifeq ($(CFG_TEE_BENCHMARK),y) TEEC_SRCS += teec_benchmark.c endif TEEC_SRC_DIR := src TEEC_OBJ_DIR := $(OUT_DIR) TEEC_OBJS := $(patsubst %.c,$(TEEC_OBJ_DIR)/%.o, $(TEEC_SRCS)) TEEC_INCLUDES := \ ${CURDIR}/include \ ${CURDIR}/src TEEC_CFLAGS := $(addprefix -I, $(TEEC_INCLUDES)) $(CFLAGS) -D_GNU_SOURCE \ -DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) \ -DBINARY_PREFIX=\"TEEC\" ifeq ($(CFG_TEE_BENCHMARK),y) TEEC_CFLAGS += -DCFG_TEE_BENCHMARK endif TEEC_LFLAGS := $(LDFLAGS) -lpthread TEEC_LIBRARY := $(OUT_DIR)/$(LIB_MAJ_MIN_P) libteec: $(TEEC_LIBRARY) $(OUT_DIR)/libteec.a $(VPREFIX)ln -sf $(LIB_MAJ_MIN_P) $(OUT_DIR)/$(LIB_MAJOR) $(VPREFIX)ln -sf $(LIB_MAJ_MIN_P) $(OUT_DIR)/$(LIB_MAJ_MIN) $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME) $(TEEC_LIBRARY): $(TEEC_OBJS) @echo " LINK $@" $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(TEEC_LFLAGS) @echo "" $(OUT_DIR)/libteec.a: $(TEEC_OBJS) @echo " AR $@" $(VPREFIX)$(AR) rcs $@ $+ $(TEEC_OBJ_DIR)/%.o: ${TEEC_SRC_DIR}/%.c $(VPREFIX)mkdir -p $(TEEC_OBJ_DIR) @echo " CC $<" $(VPREFIX)$(CC) $(TEEC_CFLAGS) -c $< -o $@ ################################################################################ # Cleaning up configuration ################################################################################ clean: $(RM) $(TEEC_OBJS) $(TEEC_LIBRARY) $(OUT_DIR)/$(LIB_MAJOR) \ $(OUT_DIR)/$(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_NAME) $(RM) $(OUT_DIR)/libteec.a $(call rmdir,$(OUT_DIR)) optee_client-4.1.0/libteec/include/000077500000000000000000000000001455150071200172205ustar00rootroot00000000000000optee_client-4.1.0/libteec/include/tee_bench.h000066400000000000000000000053321455150071200213100ustar00rootroot00000000000000/* * 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 */ optee_client-4.1.0/libteec/include/tee_client_api.h000066400000000000000000000553641455150071200223520ustar00rootroot00000000000000/* * 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_RegisteredMemoryReference. 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. * TEE_ERROR_EXTERNAL_CANCEL Defined by the Trusted User Interface * specification: An external event has caused a * User Interface operation to be aborted. * TEEC_ERROR_EXTERNAL_CANCEL Deprecated: not specified in client API, use * TEE_ERROR_EXTERNAL_CANCEL intead. * TEE_ERROR_OVERFLOW Internal TEE error – documented for completeness * TEE_ERROR_TARGET_DEAD The Trusted Application has terminated. * TEEC_ERROR_TARGET_DEAD The Trusted Application has terminated. * TEE_ERROR_STORAGE_NO_SPACE Internal TEE error – documented for completeness * TEEC_ERROR_STORAGE_NO_SPACE Deprecated: not specified in client API, use * TEE_ERROR_STORAGE_NO_SPACE instead. * TEE_ERROR_MAC_INVALID Internal TEE error – documented for completeness * TEE_ERROR_SIGNATURE_INVALID Internal TEE error – documented for completeness * TEE_ERROR_TIME_NOT_SET Internal TEE error – documented for completeness * TEE_ERROR_TIME_NEEDS_RESET Internal TEE error – documented for completeness */ /** * 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 TEE_ERROR_EXTERNAL_CANCEL 0xFFFF0011 #define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011 #define TEE_ERROR_OVERFLOW 0xFFFF300F #define TEE_ERROR_TARGET_DEAD 0xFFFF3024 #define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 #define TEE_ERROR_STORAGE_NO_SPACE 0xFFFF3041 #define TEEC_ERROR_STORAGE_NO_SPACE 0xFFFF3041 #define TEE_ERROR_MAC_INVALID 0xFFFF3071 #define TEE_ERROR_SIGNATURE_INVALID 0xFFFF3072 #define TEE_ERROR_TIME_NOT_SET 0xFFFF5000 #define TEE_ERROR_TIME_NEEDS_RESET 0xFFFF5001 /** * 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 optee_client-4.1.0/libteec/include/tee_client_api_extensions.h000066400000000000000000000043731455150071200246230ustar00rootroot00000000000000/* * 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 */ optee_client-4.1.0/libteec/include/tee_plugin_method.h000066400000000000000000000007471455150071200230740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Open Mobile Platform LLC */ #ifndef TEE_PLUGIN_METHOD_H #define TEE_PLUGIN_METHOD_H #include #include struct plugin_method { const char *name; /* short friendly name of the plugin */ TEEC_UUID uuid; TEEC_Result (*init)(void); TEEC_Result (*invoke)(unsigned int cmd, unsigned int sub_cmd, void *data, size_t in_len, size_t *out_len); }; #endif /* TEE_PLUGIN_METHOD_H */ optee_client-4.1.0/libteec/include/teec_trace.h000066400000000000000000000112001455150071200214610ustar00rootroot00000000000000/* * 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 #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 optee_client-4.1.0/libteec/libteec.pc.in000066400000000000000000000006421455150071200201370ustar00rootroot00000000000000prefix="@CMAKE_INSTALL_PREFIX@" exec_prefix="${prefix}" libdir="${prefix}/lib" includedir="${prefix}/include" Name: @PROJECT_NAME@ Description: @CMAKE_PROJECT_DESCRIPTION@ URL: @CMAKE_PROJECT_HOMEPAGE_URL@ Version: @PROJECT_VERSION@ Requires: @pc_req_public@ Requires.private: @pc_req_private@ Cflags: -I"${includedir}" Libs: -L"${libdir}" -l@libteectgt@ Libs.private: -L"${libdir}" -l@libteectgt@ @pc_libs_private@ optee_client-4.1.0/libteec/src/000077500000000000000000000000001455150071200163645ustar00rootroot00000000000000optee_client-4.1.0/libteec/src/linux/000077500000000000000000000000001455150071200175235ustar00rootroot00000000000000optee_client-4.1.0/libteec/src/linux/tee.h000066400000000000000000000326731455150071200204640ustar00rootroot00000000000000/* * 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*/ optee_client-4.1.0/libteec/src/tee_client_api.c000066400000000000000000000570571455150071200215120ustar00rootroot00000000000000/* * 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; size_t page_sz = sysconf(_SC_PAGESIZE); size_t aligned_sz = ((sz + page_sz - 1) / page_sz) * page_sz; if (aligned_sz >= sz && !posix_memalign(&p, page_sz, aligned_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; } optee_client-4.1.0/libteec/src/teec_benchmark.c000066400000000000000000000131661455150071200214710ustar00rootroot00000000000000/* * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "teec_benchmark.h" struct tee_ts_global *bench_ts_global; static const TEEC_UUID pta_benchmark_uuid = PTA_BENCHMARK_UUID; static TEEC_Context bench_ctx; static TEEC_Session bench_sess; static pthread_mutex_t teec_bench_mu = PTHREAD_MUTEX_INITIALIZER; /* Cycle counter */ static inline uint64_t read_ccounter(void) { uint64_t ccounter = 0; #ifdef __aarch64__ asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(ccounter)); #else asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(ccounter)); #endif return ccounter * TEE_BENCH_DIVIDER; } static TEEC_Result benchmark_pta_open(void) { TEEC_Result res = TEEC_ERROR_GENERIC; uint32_t ret_orig = 0; res = TEEC_InitializeContext(NULL, &bench_ctx); if (res != TEEC_SUCCESS) return res; res = TEEC_OpenSession(&bench_ctx, &bench_sess, &pta_benchmark_uuid, TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig); if (res != TEEC_SUCCESS) { TEEC_FinalizeContext(&bench_ctx); return res; } return res; } static void benchmark_pta_close(void) { TEEC_CloseSession(&bench_sess); TEEC_FinalizeContext(&bench_ctx); } static TEEC_Result benchmark_get_bench_buf_paddr(uint64_t *paddr_ts_buf, uint64_t *size) { TEEC_Result res = TEEC_ERROR_GENERIC; uint32_t ret_orig = 0; TEEC_Operation op; memset(&op, 0, sizeof(op)); res = benchmark_pta_open(); if (res != TEEC_SUCCESS) return res; op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); res = TEEC_InvokeCommand(&bench_sess, BENCHMARK_CMD_GET_MEMREF, &op, &ret_orig); if (res != TEEC_SUCCESS) return res; *paddr_ts_buf = op.params[0].value.a; *size = op.params[0].value.b; benchmark_pta_close(); return res; } static void *mmap_paddr(intptr_t paddr, uint64_t size) { int devmem = 0; off_t offset = 0; off_t page_addr = 0; intptr_t *hw_addr = NULL; devmem = open("/dev/mem", O_RDWR); if (!devmem) return NULL; offset = (off_t)paddr % getpagesize(); page_addr = (off_t)(paddr - offset); hw_addr = (intptr_t *)mmap(0, size + offset, PROT_READ|PROT_WRITE, MAP_SHARED, devmem, page_addr); if (hw_addr == MAP_FAILED) { close(devmem); return NULL; } close(devmem); return (hw_addr + offset); } /* check if we are in benchmark mode */ static bool benchmark_check_mode(void) { uint64_t ts_buf_raw = 0; uint64_t ts_buf_size = 0; bool res = true; if (!bench_ts_global) { /* receive buffer from Benchmark PTA and register it */ benchmark_get_bench_buf_paddr(&ts_buf_raw, &ts_buf_size); if (ts_buf_raw && ts_buf_size) { bench_ts_global = mmap_paddr(ts_buf_raw, ts_buf_size); res = (bench_ts_global) ? true : false; } else { res = false; } } return res; } /* Adding timestamp to buffer */ void bm_timestamp(void) { struct tee_ts_cpu_buf *cpu_buf = NULL; uint64_t ts_i = 0; void *ret_addr = NULL; uint32_t cur_cpu = 0; int ret = 0; cpu_set_t cpu_set_old; cpu_set_t cpu_set_tmp; struct tee_time_st ts_data; memset(&cpu_set_old, 0, sizeof(cpu_set_old)); memset(&cpu_set_tmp, 0, sizeof(cpu_set_tmp)); memset(&ts_data, 0, sizeof(ts_data)); if (pthread_mutex_trylock(&teec_bench_mu)) return; if (!benchmark_check_mode()) goto error; CPU_ZERO(&cpu_set_old); ret = sched_getaffinity(0, sizeof(cpu_set_old), &cpu_set_old); if (ret) goto error; /* stick to the same core while putting timestamp */ cur_cpu = sched_getcpu(); CPU_ZERO(&cpu_set_tmp); CPU_SET(cur_cpu, &cpu_set_tmp); ret = sched_setaffinity(0, sizeof(cpu_set_tmp), &cpu_set_tmp); if (ret) goto error; /* fill timestamp data */ if (cur_cpu >= bench_ts_global->cores) { ret = sched_setaffinity(0, sizeof(cpu_set_old), &cpu_set_old); goto error; } ret_addr = __builtin_return_address(0); cpu_buf = &bench_ts_global->cpu_buf[cur_cpu]; ts_i = __sync_fetch_and_add(&cpu_buf->head, 1); ts_data.cnt = read_ccounter(); ts_data.addr = (uintptr_t)ret_addr; ts_data.src = TEE_BENCH_CLIENT; cpu_buf->stamps[ts_i & TEE_BENCH_MAX_MASK] = ts_data; /* set back affinity mask */ sched_setaffinity(0, sizeof(cpu_set_old), &cpu_set_old); error: pthread_mutex_unlock(&teec_bench_mu); } optee_client-4.1.0/libteec/src/teec_benchmark.h000066400000000000000000000030311455150071200214640ustar00rootroot00000000000000/* * 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 */ optee_client-4.1.0/libteec/src/teec_trace.c000066400000000000000000000067501455150071200206360ustar00rootroot00000000000000/* * 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 optee_client-4.1.0/scripts/000077500000000000000000000000001455150071200156555ustar00rootroot00000000000000optee_client-4.1.0/scripts/checkpatch_inc.sh000066400000000000000000000026031455150071200211400ustar00rootroot00000000000000#!/bin/bash # SPDX-License-Identifier: BSD-2-Clause CHECKPATCH="${CHECKPATCH:-checkpatch.pl}" # checkpatch.pl will ignore the following paths CHECKPATCH_IGNORE=$(echo ) _CP_EXCL=$(for p in $CHECKPATCH_IGNORE; do echo ":(exclude)$p" ; done) function _checkpatch() { # Use --typedefsfile if supported by the checkpatch tool typedefs_opt="--typedefsfile typedefs.checkpatch" $CHECKPATCH --help 2>&1 | grep -q -- --typedefsfile || \ typedefs_opt=""; # Ignore NOT_UNIFIED_DIFF in case patch has no diff # (e.g., all paths filtered out) $CHECKPATCH --quiet --ignore FILE_PATH_CHANGES \ --ignore GERRIT_CHANGE_ID \ --ignore NOT_UNIFIED_DIFF \ --ignore CAMELCASE \ --ignore PREFER_KERNEL_TYPES \ --ignore CONCATENATED_STRING \ --no-tree \ --strict \ $typedefs_opt \ - } function checkpatch() { git show --oneline --no-patch $1 # The first git 'format-patch' shows the commit message # The second one produces the diff (might be empty if _CP_EXCL # filters out all diffs) (git format-patch $1^..$1 --stdout | sed -n '/^diff --git/q;p'; \ git format-patch $1^..$1 --stdout -- $_CP_EXCL . | \ sed -n '/^diff --git/,$p') | _checkpatch } function checkstaging() { git diff --cached -- . $_CP_EXCL | _checkpatch } function checkworking() { git diff -- . $_CP_EXCL | _checkpatch } function checkdiff() { git diff $1...$2 -- . $_CP_EXCL | _checkpatch } optee_client-4.1.0/tee-supplicant/000077500000000000000000000000001455150071200171235ustar00rootroot00000000000000optee_client-4.1.0/tee-supplicant/CMakeLists.txt000066400000000000000000000075441455150071200216750ustar00rootroot00000000000000project(tee-supplicant C) ################################################################################ # Configuration flags always included ################################################################################ option(RPMB_EMU "Enable tee-supplicant to emulate RPMB" ON) option(CFG_TA_GPROF_SUPPORT "Enable tee-supplicant support for TAs instrumented with gprof" ON) option(CFG_FTRACE_SUPPORT "Enable tee-supplicant support for TAs instrumented with ftrace" ON) option(CFG_TEE_SUPP_PLUGINS "Enable tee-supplicant plugin support" ON) set(CFG_TEE_SUPP_LOG_LEVEL "1" CACHE STRING "tee-supplicant log level") # FIXME: Question is, is this really needed? Should just use defaults from # GNUInstallDirs? set(CFG_TEE_CLIENT_LOAD_PATH "/lib" CACHE STRING "Colon-separated list of paths where to look for TAs (see also --ta-dir)") set(CFG_TEE_FS_PARENT_PATH "/data/tee" CACHE STRING "Location of TEE filesystem (secure storage)") # FIXME: Why do we have if defined(CFG_GP_SOCKETS) && CFG_GP_SOCKETS == 1 in the c-file? set(CFG_GP_SOCKETS "1" CACHE STRING "Enable GlobalPlatform Socket API support") set(CFG_TEE_PLUGIN_LOAD_PATH "/usr/lib/tee-supplicant/plugins/" CACHE STRING "tee-supplicant's plugins path") if(CFG_TEE_SUPP_PLUGINS) set(CMAKE_INSTALL_RPATH "${CFG_TEE_PLUGIN_LOAD_PATH}") endif() ################################################################################ # Source files ################################################################################ set(SRC src/handle.c src/hmac_sha2.c src/rpmb.c src/sha2.c src/tee_supp_fs.c src/tee_supplicant.c src/teec_ta_load.c ) if(CFG_GP_SOCKETS) set(SRC ${SRC} src/tee_socket.c) endif() if(CFG_TA_GPROF_SUPPORT OR CFG_FTRACE_SUPPORT) set(SRC ${SRC} src/prof.c) endif() if(CFG_TEE_SUPP_PLUGINS) set(SRC ${SRC} src/plugin.c) endif() ################################################################################ # Built binary ################################################################################ add_executable(${PROJECT_NAME} ${SRC}) ################################################################################ # Flags always set ################################################################################ target_compile_definitions(${PROJECT_NAME} PRIVATE -DDEBUGLEVEL_${CFG_TEE_SUPP_LOG_LEVEL} PRIVATE -DTEEC_LOAD_PATH="${CFG_TEE_CLIENT_LOAD_PATH}" PRIVATE -DTEE_FS_PARENT_PATH="${CFG_TEE_FS_PARENT_PATH}" PRIVATE -DBINARY_PREFIX="TSUP" ) ################################################################################ # Optional flags ################################################################################ if(CFG_GP_SOCKETS) target_compile_definitions(${PROJECT_NAME} PRIVATE -DCFG_GP_SOCKETS=${CFG_GP_SOCKETS}) endif() if(RPMB_EMU) target_compile_definitions(${PROJECT_NAME} PRIVATE -DRPMB_EMU=1) endif() if(CFG_TA_GPROF_SUPPORT) target_compile_definitions(${PROJECT_NAME} PRIVATE -DCFG_TA_GPROF_SUPPORT) endif() if(CFG_FTRACE_SUPPORT) target_compile_definitions(${PROJECT_NAME} PRIVATE -DCFG_FTRACE_SUPPORT) endif() if(CFG_TEE_SUPP_PLUGINS) target_compile_definitions(${PROJECT_NAME} PRIVATE -DTEE_SUPP_PLUGINS PRIVATE -DTEE_PLUGIN_LOAD_PATH="${CFG_TEE_PLUGIN_LOAD_PATH}" ) endif() ################################################################################ # Public and private header and library dependencies ################################################################################ target_include_directories(${PROJECT_NAME} PRIVATE src PRIVATE ../libteec/src ) target_link_libraries(${PROJECT_NAME} PRIVATE teec ) if(CFG_TEE_SUPP_PLUGINS) target_link_libraries(${PROJECT_NAME} PRIVATE dl ) endif() ################################################################################ # Install targets ################################################################################ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}) optee_client-4.1.0/tee-supplicant/Makefile000066400000000000000000000050461455150071200205700ustar00rootroot00000000000000include ../flags.mk include ../config.mk OUT_DIR := $(OO)/tee-supplicant # Emulate RPMB ioctl's by default RPMB_EMU ?= 1 .PHONY: all tee-supplicant clean all: tee-supplicant ################################################################################ # Teec configuration ################################################################################ PACKAGE_NAME := tee-supplicant TEES_SRCS := tee_supplicant.c \ teec_ta_load.c \ tee_supp_fs.c \ rpmb.c \ handle.c ifeq ($(CFG_GP_SOCKETS),y) TEES_SRCS += tee_socket.c endif ifeq ($(RPMB_EMU),1) TEES_SRCS += sha2.c hmac_sha2.c endif ifneq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) TEES_SRCS += prof.c endif ifeq ($(CFG_TEE_SUPP_PLUGINS),y) TEES_SRCS += plugin.c endif TEES_SRC_DIR := src TEES_OBJ_DIR := $(OUT_DIR) TEES_OBJS := $(patsubst %.c,$(TEES_OBJ_DIR)/%.o, $(TEES_SRCS)) TEES_INCLUDES := ${CURDIR}/../libteec/include \ ${CURDIR}/src \ ${CURDIR}/../libteec/src \ TEES_CFLAGS := $(addprefix -I, $(TEES_INCLUDES)) $(CFLAGS) \ -DDEBUGLEVEL_$(CFG_TEE_SUPP_LOG_LEVEL) \ -DBINARY_PREFIX=\"TEES\" \ -DTEE_FS_PARENT_PATH=\"$(CFG_TEE_FS_PARENT_PATH)\" \ -DTEEC_LOAD_PATH=\"$(CFG_TEE_CLIENT_LOAD_PATH)\" \ ifeq ($(CFG_GP_SOCKETS),y) TEES_CFLAGS += -DCFG_GP_SOCKETS=1 endif ifeq ($(RPMB_EMU),1) TEES_CFLAGS += -DRPMB_EMU=1 endif TEES_FILE := $(OUT_DIR)/$(PACKAGE_NAME) TEES_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec ifeq ($(CFG_TA_GPROF_SUPPORT),y) TEES_CFLAGS += -DCFG_TA_GPROF_SUPPORT endif ifeq ($(CFG_FTRACE_SUPPORT),y) TEES_CFLAGS += -DCFG_FTRACE_SUPPORT endif ifeq ($(CFG_TEE_SUPP_PLUGINS),y) TEES_CFLAGS += -DTEE_SUPP_PLUGINS \ -DTEE_PLUGIN_LOAD_PATH=\"$(CFG_TEE_PLUGIN_LOAD_PATH)\" endif TEES_LFLAGS += -lpthread # Needed to get clock_gettime() for for glibc versions before 2.17 TEES_LFLAGS += -lrt ifeq ($(CFG_TEE_SUPP_PLUGINS),y) # Needed to dynamically load user plugins TEES_LFLAGS += -ldl # Needed for dlopen() TEES_LFLAGS += -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) endif tee-supplicant: $(TEES_FILE) $(TEES_FILE): $(TEES_OBJS) @echo " LINK $@" $(VPREFIX)$(CC) -o $@ $+ $(TEES_LFLAGS) @echo "" $(TEES_OBJ_DIR)/%.o: $(TEES_SRC_DIR)/%.c $(VPREFIX)mkdir -p $(dir $@) @echo " CC $<" $(VPREFIX)$(CC) $(TEES_CFLAGS) $(TEES_CFLAGS_$(notdir $<)) -c $< -o $@ ################################################################################ # Cleaning up configuration ################################################################################ clean: $(RM) $(TEES_OBJS) $(TEES_FILE) $(call rmdir,$(OUT_DIR)) optee_client-4.1.0/tee-supplicant/src/000077500000000000000000000000001455150071200177125ustar00rootroot00000000000000optee_client-4.1.0/tee-supplicant/src/__tee_ipsocket.h000066400000000000000000000031161455150071200230400ustar00rootroot00000000000000/* * Copyright (c) 2016-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_IPSOCKET_H #define ____TEE_IPSOCKET_H typedef enum TEE_ipSocket_ipVersion_e { TEE_IP_VERSION_DC = 0, /* don’t care */ TEE_IP_VERSION_4 = 1, TEE_IP_VERSION_6 = 2 } TEE_ipSocket_ipVersion; #endif /*____TEE_IPSOCKET_H*/ optee_client-4.1.0/tee-supplicant/src/__tee_isocket_defines.h000066400000000000000000000035141455150071200243570ustar00rootroot00000000000000/* * Copyright (c) 2016-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_ISOCKET_DEFINES_H #define ____TEE_ISOCKET_DEFINES_H #define TEE_ISOCKET_VERSION 0x01000000 #define TEE_ISOCKET_ERROR_PROTOCOL 0xF1007001 #define TEE_ISOCKET_ERROR_REMOTE_CLOSED 0xF1007002 #define TEE_ISOCKET_ERROR_TIMEOUT 0xF1007003 #define TEE_ISOCKET_ERROR_OUT_OF_RESOURCES 0xF1007004 #define TEE_ISOCKET_ERROR_LARGE_BUFFER 0xF1007005 #define TEE_ISOCKET_WARNING_PROTOCOL 0xF1007006 #define TEE_ISOCKET_ERROR_HOSTNAME 0xF1007007 #endif /*____TEE_ISOCKET_DEFINES_H*/ optee_client-4.1.0/tee-supplicant/src/__tee_tcpsocket_defines.h000066400000000000000000000031621455150071200247140ustar00rootroot00000000000000/* * Copyright (c) 2016-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_TCPSOCKET_DEFINES_H #define ____TEE_TCPSOCKET_DEFINES_H /* Protocol identifier */ #define TEE_ISOCKET_PROTOCOLID_TCP 0x65 /* Instance specific errors */ #define TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1010002 #endif /*____TEE_TCPSOCKET_DEFINES_H*/ optee_client-4.1.0/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h000066400000000000000000000031711455150071200271730ustar00rootroot00000000000000/* * Copyright (c) 2016-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_TCPSOCKET_DEFINES_EXTENSIONS_H #define ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H /* Instance and implementation specific ioctl functions */ #define TEE_TCP_SET_RECVBUF 0x65f00000 #define TEE_TCP_SET_SENDBUF 0x65f00001 #endif /*____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H*/ optee_client-4.1.0/tee-supplicant/src/__tee_udpsocket_defines.h000066400000000000000000000033521455150071200247170ustar00rootroot00000000000000/* * Copyright (c) 2016-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_UDPSOCKET_DEFINES_H #define ____TEE_UDPSOCKET_DEFINES_H /* Protocol identifier */ #define TEE_ISOCKET_PROTOCOLID_UDP 0x66 /* Instance specific errors */ #define TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1020002 /* Instance specific ioctl functions */ #define TEE_UDP_CHANGEADDR 0x66000001 #define TEE_UDP_CHANGEPORT 0x66000002 #endif /*____TEE_UDPSOCKET_DEFINES_H*/ optee_client-4.1.0/tee-supplicant/src/handle.c000066400000000000000000000074571455150071200213260ustar00rootroot00000000000000/* * Copyright (c) 2014, 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 "handle.h" /* * Define the initial capacity of the database. It should be a low number * multiple of 2 since some databases a likely to only use a few handles. * Since the algorithm is to doubles up when growing it shouldn't cause a * noticable overhead on large databases. */ #define HANDLE_DB_INITIAL_MAX_PTRS 4 static void mutex_lock(struct handle_db *db) { if (db->mu) pthread_mutex_lock(db->mu); } static void mutex_unlock(struct handle_db *db) { if (db->mu) pthread_mutex_unlock(db->mu); } void handle_db_set_mutex(struct handle_db *db, pthread_mutex_t *mu) { db->mu = mu; } void handle_db_destroy(struct handle_db *db) { if (db) { mutex_lock(db); free(db->ptrs); db->ptrs = NULL; db->max_ptrs = 0; mutex_unlock(db); } } int handle_get(struct handle_db *db, void *ptr) { size_t n = 0; void *p = NULL; size_t new_max_ptrs = 0; int ret = 0; if (!db || !ptr) return -1; mutex_lock(db); /* Try to find an empty location */ for (n = 0; n < db->max_ptrs; n++) { if (!db->ptrs[n]) { db->ptrs[n] = ptr; ret = n; goto out; } } /* No location available, grow the ptrs array */ if (db->max_ptrs) new_max_ptrs = db->max_ptrs * 2; else new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); if (!p) { ret = -1; goto out; } db->ptrs = p; memset(db->ptrs + db->max_ptrs, 0, (new_max_ptrs - db->max_ptrs) * sizeof(void *)); db->max_ptrs = new_max_ptrs; /* Since n stopped at db->max_ptrs there is an empty location there */ db->ptrs[n] = ptr; ret = n; out: mutex_unlock(db); return ret; } void *handle_put(struct handle_db *db, int handle) { void *p = NULL; if (!db || handle < 0) return NULL; mutex_lock(db); if ((size_t)handle >= db->max_ptrs) { p = NULL; goto out; } p = db->ptrs[handle]; db->ptrs[handle] = NULL; out: mutex_unlock(db); return p; } void *handle_lookup(struct handle_db *db, int handle) { void *p = NULL; if (!db || handle < 0) return NULL; mutex_lock(db); if ((size_t)handle >= db->max_ptrs) { p = NULL; goto out; } p = db->ptrs[handle]; out: mutex_unlock(db); return p; } void handle_foreach_put(struct handle_db *db, void (*cb)(int handle, void *ptr, void *arg), void *arg) { size_t n = 0; if (!db || !cb) return; mutex_lock(db); for (n = 0; n < db->max_ptrs; n++) { if (db->ptrs[n]) { cb(n, db->ptrs[n], arg); db->ptrs[n] = NULL; } } mutex_unlock(db); } optee_client-4.1.0/tee-supplicant/src/handle.h000066400000000000000000000054231455150071200213220ustar00rootroot00000000000000/* * Copyright (c) 2014, 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 HANDLE_H #define HANDLE_H #include #include struct handle_db { void **ptrs; size_t max_ptrs; pthread_mutex_t *mu; }; #define HANDLE_DB_INITIALIZER { NULL, 0, NULL } #define HANDLE_DB_INITIALIZER_WITH_MUTEX(mu) { NULL, 0, (mu) } /* * Assigns a mutex for the database. If mu != NULL the mutex will be * acquired before each access to the database and released when * the operation is done. */ void handle_db_set_mutex(struct handle_db *db, pthread_mutex_t *mu); /* * Frees all internal data structures of the database, but does not free * the db pointer. The database is safe to reuse after it's destroyed, it * just be empty again. The assigned mutex is also preserved. */ void handle_db_destroy(struct handle_db *db); /* * Allocates a new handle and assigns the supplied pointer to it, * ptr must not be NULL. * The function returns * >= 0 on success and * -1 on failure */ int handle_get(struct handle_db *db, void *ptr); /* * Deallocates a handle. Returns the assiciated pointer of the handle * the the handle was valid or NULL if it's invalid. */ void *handle_put(struct handle_db *db, int handle); /* * Returns the assiciated pointer of the handle if the handle is a valid * handle. * Returns NULL on failure. */ void *handle_lookup(struct handle_db *db, int handle); void handle_foreach_put(struct handle_db *db, void (*cb)(int handle, void *ptr, void *arg), void *arg); #endif /*HANDLE_H*/ optee_client-4.1.0/tee-supplicant/src/hmac_sha2.c000066400000000000000000000105611455150071200217060ustar00rootroot00000000000000/* * HMAC-SHA-224/256/384/512 implementation * Last update: 06/15/2005 * Issue date: 06/15/2005 * * Copyright (C) 2005 Olivier Gay * All rights reserved. * * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "hmac_sha2.h" /* HMAC-SHA-256 functions */ void hmac_sha256_init(hmac_sha256_ctx *ctx, const unsigned char *key, unsigned int key_size) { unsigned int fill = 0; unsigned int num = 0; const unsigned char *key_used = NULL; unsigned char key_temp[SHA256_DIGEST_SIZE] = { 0 }; int i = 0; if (key_size == SHA256_BLOCK_SIZE) { key_used = key; num = SHA256_BLOCK_SIZE; } else { if (key_size > SHA256_BLOCK_SIZE){ num = SHA256_DIGEST_SIZE; sha256(key, key_size, key_temp); key_used = key_temp; } else { /* key_size > SHA256_BLOCK_SIZE */ key_used = key; num = key_size; } fill = SHA256_BLOCK_SIZE - num; memset(ctx->block_ipad + num, 0x36, fill); memset(ctx->block_opad + num, 0x5c, fill); } for (i = 0; i < (int) num; i++) { ctx->block_ipad[i] = key_used[i] ^ 0x36; ctx->block_opad[i] = key_used[i] ^ 0x5c; } sha256_init(&ctx->ctx_inside); sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE); sha256_init(&ctx->ctx_outside); sha256_update(&ctx->ctx_outside, ctx->block_opad, SHA256_BLOCK_SIZE); /* for hmac_reinit */ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, sizeof(sha256_ctx)); memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, sizeof(sha256_ctx)); } void hmac_sha256_reinit(hmac_sha256_ctx *ctx) { memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, sizeof(sha256_ctx)); memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, sizeof(sha256_ctx)); } void hmac_sha256_update(hmac_sha256_ctx *ctx, const unsigned char *message, unsigned int message_len) { sha256_update(&ctx->ctx_inside, message, message_len); } void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, unsigned int mac_size) { unsigned char digest_inside[SHA256_DIGEST_SIZE] = { 0 }; unsigned char mac_temp[SHA256_DIGEST_SIZE] = { 0 }; sha256_final(&ctx->ctx_inside, digest_inside); sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE); sha256_final(&ctx->ctx_outside, mac_temp); memcpy(mac, mac_temp, mac_size); } void hmac_sha256(const unsigned char *key, unsigned int key_size, const unsigned char *message, unsigned int message_len, unsigned char *mac, unsigned mac_size) { hmac_sha256_ctx ctx; memset(&ctx, 0, sizeof(ctx)); hmac_sha256_init(&ctx, key, key_size); hmac_sha256_update(&ctx, message, message_len); hmac_sha256_final(&ctx, mac, mac_size); } optee_client-4.1.0/tee-supplicant/src/hmac_sha2.h000066400000000000000000000053401455150071200217120ustar00rootroot00000000000000/* * HMAC-SHA-224/256/384/512 implementation * Last update: 06/15/2005 * Issue date: 06/15/2005 * * Copyright (C) 2005 Olivier Gay * All rights reserved. * * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 HMAC_SHA2_H #define HMAC_SHA2_H #include "sha2.h" #ifdef __cplusplus extern "C" { #endif typedef struct { sha256_ctx ctx_inside; sha256_ctx ctx_outside; /* for hmac_reinit */ sha256_ctx ctx_inside_reinit; sha256_ctx ctx_outside_reinit; unsigned char block_ipad[SHA256_BLOCK_SIZE]; unsigned char block_opad[SHA256_BLOCK_SIZE]; } hmac_sha256_ctx; void hmac_sha256_init(hmac_sha256_ctx *ctx, const unsigned char *key, unsigned int key_size); void hmac_sha256_reinit(hmac_sha256_ctx *ctx); void hmac_sha256_update(hmac_sha256_ctx *ctx, const unsigned char *message, unsigned int message_len); void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, unsigned int mac_size); void hmac_sha256(const unsigned char *key, unsigned int key_size, const unsigned char *message, unsigned int message_len, unsigned char *mac, unsigned mac_size); #ifdef __cplusplus } #endif #endif /* !HMAC_SHA2_H */ optee_client-4.1.0/tee-supplicant/src/optee_msg_supplicant.h000066400000000000000000000200411455150071200243040ustar00rootroot00000000000000/* * Copyright (c) 2016-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 __OPTEE_MSG_SUPPLICANT_H #define __OPTEE_MSG_SUPPLICANT_H /* * Load a TA into memory */ #define OPTEE_MSG_RPC_CMD_LOAD_TA 0 /* * Replay Protected Memory Block access */ #define OPTEE_MSG_RPC_CMD_RPMB 1 /* * File system access */ #define OPTEE_MSG_RPC_CMD_FS 2 /* * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_FS and first * parameter has the attribute OPTEE_MSG_ATTR_TYPE_VALUE_INPUT. */ /* * Open a file * * [in] param[0].u.value.a OPTEE_MRF_OPEN * [in] param[1].u.tmem a string holding the file name * [out] param[2].u.value.a file descriptor of open file */ #define OPTEE_MRF_OPEN 0 /* * Create a file * * [in] param[0].u.value.a OPTEE_MRF_CREATE * [in] param[1].u.tmem a string holding the file name * [out] param[2].u.value.a file descriptor of open file */ #define OPTEE_MRF_CREATE 1 /* * Close a file * * [in] param[0].u.value.a OPTEE_MRF_CLOSE * [in] param[0].u.value.b file descriptor of open file. */ #define OPTEE_MRF_CLOSE 2 /* * Read from a file * * [in] param[0].u.value.a OPTEE_MRF_READ * [in] param[0].u.value.b file descriptor of open file * [in] param[0].u.value.c offset into file * [out] param[1].u.tmem buffer to hold returned data */ #define OPTEE_MRF_READ 3 /* * Write to a file * * [in] param[0].u.value.a OPTEE_MRF_WRITE * [in] param[0].u.value.b file descriptor of open file * [in] param[0].u.value.c offset into file * [in] param[1].u.tmem buffer holding data to be written */ #define OPTEE_MRF_WRITE 4 /* * Truncate a file * * [in] param[0].u.value.a OPTEE_MRF_TRUNCATE * [in] param[0].u.value.b file descriptor of open file * [in] param[0].u.value.c length of file. */ #define OPTEE_MRF_TRUNCATE 5 /* * Remove a file * * [in] param[0].u.value.a OPTEE_MRF_REMOVE * [in] param[1].u.tmem a string holding the file name */ #define OPTEE_MRF_REMOVE 6 /* * Rename a file * * [in] param[0].u.value.a OPTEE_MRF_RENAME * [in] param[0].u.value.b true if existing target should be removed * [in] param[1].u.tmem a string holding the old file name * [in] param[2].u.tmem a string holding the new file name */ #define OPTEE_MRF_RENAME 7 /* * Opens a directory for file listing * * [in] param[0].u.value.a OPTEE_MRF_OPENDIR * [in] param[1].u.tmem a string holding the name of the directory * [out] param[2].u.value.a handle to open directory */ #define OPTEE_MRF_OPENDIR 8 /* * Closes a directory handle * * [in] param[0].u.value.a OPTEE_MRF_CLOSEDIR * [in] param[0].u.value.b handle to open directory */ #define OPTEE_MRF_CLOSEDIR 9 /* * Read next file name of directory * * * [in] param[0].u.value.a OPTEE_MRF_READDIR * [in] param[0].u.value.b handle to open directory * [out] param[1].u.tmem a string holding the file name */ #define OPTEE_MRF_READDIR 10 /* * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_FS */ /* * Command Ids 3, 4 and 5 of OPTEE_MSG_RPC_CMD_xxx macros are reserved for use * by the kernel driver. */ /* * Shared memory allocation */ #define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 #define OPTEE_MSG_RPC_CMD_SHM_FREE 7 /* * Was OPTEE_MSG_RPC_CMD_SQL_FS, which isn't supported any longer */ #define OPTEE_MSG_RPC_CMD_SQL_FS_RESERVED 8 /* * GPROF support management commands */ #define OPTEE_MSG_RPC_CMD_GPROF 9 /* * Socket commands */ #define OPTEE_MSG_RPC_CMD_SOCKET 10 /* * Function tracing support management commands */ #define OPTEE_MSG_RPC_CMD_FTRACE 11 /* * Plugin commands */ #define OPTEE_MSG_RPC_CMD_PLUGIN 12 /* * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET */ #define OPTEE_MRC_SOCKET_TIMEOUT_NONBLOCKING 0 #define OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING 0xffffffff /* * Open socket * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_OPEN * [in] param[0].u.value.b TA instance id * [in] param[1].u.value.a server port number * [in] param[1].u.value.b protocol, TEE_ISOCKET_PROTOCOLID_* * [in] param[1].u.value.c ip version TEE_IP_VERSION_* from tee_ipsocket.h * [in] param[2].u.tmem server address * [out] param[3].u.value.a socket handle (32-bit) */ #define OPTEE_MRC_SOCKET_OPEN 0 /* * Close socket * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE * [in] param[0].u.value.b TA instance id * [in] param[0].u.value.c socket handle */ #define OPTEE_MRC_SOCKET_CLOSE 1 /* * Close all sockets * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE_ALL * [in] param[0].u.value.b TA instance id */ #define OPTEE_MRC_SOCKET_CLOSE_ALL 2 /* * Send data on socket * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_SEND * [in] param[0].u.value.b TA instance id * [in] param[0].u.value.c socket handle * [in] param[1].u.tmem buffer to transmit * [in] param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_* * [out] param[2].u.value.b number of transmitted bytes */ #define OPTEE_MRC_SOCKET_SEND 3 /* * Receive data on socket * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_RECV * [in] param[0].u.value.b TA instance id * [in] param[0].u.value.c socket handle * [out] param[1].u.tmem buffer to receive * [in] param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_* */ #define OPTEE_MRC_SOCKET_RECV 4 /* * Perform IOCTL on socket * * [in] param[0].u.value.a OPTEE_MRC_SOCKET_IOCTL * [in] param[0].u.value.b TA instance id * [in] param[0].u.value.c socket handle * [in/out] param[1].u.tmem buffer * [in] param[2].u.value.a ioctl command */ #define OPTEE_MRC_SOCKET_IOCTL 5 /* * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET */ /* * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_PLUGIN */ /* * Invoke a tee-supplicant plugin. * * [in] param[0].u.value.a OPTEE_INVOKE_PLUGIN * [in] param[0].u.value.b uuid.d1 * [in] param[0].u.value.c uuid.d2 * [in] param[1].u.value.a uuid.d3 * [in] param[1].u.value.b uuid.d4 * [in] param[1].u.value.c cmd for plugin * [in] param[2].u.value.a sub_cmd for plugin * [out] param[2].u.value.b length of the outbuf (param[3]), * if out is needed. * [in/out] param[3].u.tmem buffer holding data for plugin * * UUID serialized into octets: * b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 * d1 | d2 | d3 | d4 * * The endianness of words d1, d2, d3 and d4 from SWd is little-endian. * d1 word contains [b3 b2 b1 b0] * d2 word contains [b7 b6 b5 b4] * d3 word contains [b11 b10 b9 b8] * d4 word contains [b15 b14 b13 b12] */ #define OPTEE_INVOKE_PLUGIN 0 /* * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_PLUGIN */ #endif /*__OPTEE_MSG_SUPPLICANT_H*/ optee_client-4.1.0/tee-supplicant/src/plugin.c000066400000000000000000000122321455150071200213540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Open Mobile Platform LLC */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "optee_msg_supplicant.h" #ifndef __aligned #define __aligned(x) __attribute__((__aligned__(x))) #endif #include /* internal possible returned values */ enum plugin_err { PLUGIN_OK = 0, PLUGIN_DL_OPEN_ERR = -1, PLUGIN_DL_SYM_ERR = -2, }; static struct plugin *plugin_list_head; /* returns 0, if u1 and u2 are equal */ static int uuid_cmp(TEEC_UUID *u1, TEEC_UUID *u2) { if (!memcmp(u1, u2, sizeof(TEEC_UUID))) return 0; return 1; } static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN]) { d->timeLow = ((uint32_t)s[0] << 24) | ((uint32_t)s[1] << 16) | ((uint32_t)s[2] << 8) | s[3]; d->timeMid = ((uint32_t)s[4] << 8) | s[5]; d->timeHiAndVersion = ((uint32_t)s[6] << 8) | s[7]; memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); } static void push_plugin(struct plugin *p) { p->next = plugin_list_head; plugin_list_head = p; } static struct plugin *find_plugin(TEEC_UUID *u) { struct plugin *p = plugin_list_head; while (p) { if (!uuid_cmp(&p->method->uuid, u)) return p; p = p->next; } return NULL; } static enum plugin_err load_plugin(const char *name, struct plugin *p) { void *handle = NULL; struct plugin_method *m = NULL; handle = dlopen(name, RTLD_LAZY); if (!handle) return PLUGIN_DL_OPEN_ERR; m = (struct plugin_method *)dlsym(handle, "plugin_method"); if (!m || !m->name || !m->invoke) { dlclose(handle); return PLUGIN_DL_SYM_ERR; } p->handle = handle; p->method = m; return PLUGIN_OK; } static TEEC_Result plugin_invoke(TEEC_UUID *u, unsigned int cmd, unsigned int sub_cmd, void *data, size_t in_len, size_t *out_len) { struct plugin *p = NULL; p = find_plugin(u); if (!p) return TEEC_ERROR_ITEM_NOT_FOUND; assert(p->method->invoke); return p->method->invoke(cmd, sub_cmd, data, in_len, out_len); } TEEC_Result plugin_load_all(void) { DIR *dir = NULL; enum plugin_err res = PLUGIN_OK; TEEC_Result teec_res = TEEC_SUCCESS; struct dirent *entry = NULL; char path[PATH_MAX] = { 0 }; dir = opendir(supplicant_params.plugin_load_path); if (!dir) { IMSG("could not open directory %s", supplicant_params.plugin_load_path); /* don't generate error if there is no the dir */ return TEEC_SUCCESS; } while ((entry = readdir(dir))) { struct plugin *p; int r; if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, ".")) continue; p = calloc(1, sizeof(struct plugin)); if (!p) { EMSG("allocate mem for plugin <%s> failed", entry->d_name); closedir(dir); return TEEC_ERROR_OUT_OF_MEMORY; } r = snprintf(path, sizeof(path), "%s/%s", supplicant_params.plugin_load_path, entry->d_name); if (r < 0 || r >= (int)sizeof(path)) { EMSG("assemble of full path for plugin <%s> failed", entry->d_name); closedir(dir); return TEEC_ERROR_GENERIC ; } res = load_plugin(path, p); switch (res) { case PLUGIN_DL_OPEN_ERR: EMSG("open plugin <%s> failed: %s", entry->d_name, dlerror()); free(p); continue; case PLUGIN_DL_SYM_ERR: EMSG("find 'plugin_method' sym in <%s> failed: %s", entry->d_name, dlerror()); free(p); continue; default: DMSG("loading the <%s> plugin were successful", p->method->name); break; } /* Init the plugin */ if (p->method->init) { teec_res = p->method->init(); if (teec_res) { EMSG("init the <%s> plugin failed with 0x%x", p->method->name, teec_res); free(p); continue; } } push_plugin(p); } closedir(dir); return TEEC_SUCCESS; } TEEC_Result plugin_process(size_t num_params, struct tee_ioctl_param *params) { unsigned int cmd = 0; unsigned int sub_cmd = 0; void *data = NULL; uint32_t data_len = 0; TEEC_UUID uuid = { }; uint32_t uuid_words[4] = { }; size_t outlen = 0; TEEC_Result res = TEEC_ERROR_NOT_SUPPORTED; if (num_params != 4 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || (params[3].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) return TEEC_ERROR_BAD_PARAMETERS; uuid_words[0] = params[0].b; uuid_words[1] = params[0].c; uuid_words[2] = params[1].a; uuid_words[3] = params[1].b; uuid_from_octets(&uuid, (const uint8_t *)uuid_words); cmd = params[1].c; sub_cmd = params[2].a; data = tee_supp_param_to_va(params + 3); data_len = MEMREF_SIZE(params + 3); if (data_len && !data) return TEEC_ERROR_BAD_PARAMETERS; switch (params[0].a) { case OPTEE_INVOKE_PLUGIN: res = plugin_invoke(&uuid, cmd, sub_cmd, data, data_len, &outlen); params[2].b = outlen; default: break; } return res; } optee_client-4.1.0/tee-supplicant/src/plugin.h000066400000000000000000000020361455150071200213620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Open Mobile Platform LLC */ #ifndef PLUGIN_H #define PLUGIN_H #include #include #include struct tee_ioctl_param; /* This structure describes one plugin for the supplicant */ struct plugin { void *handle; struct plugin_method *method; /* Implemented in the plugin */ struct plugin *next; }; #ifdef TEE_SUPP_PLUGINS /* * Loads all shared objects from 'CFG_TEE_PLUGIN_LOAD_PATH' * and binds all functions. * * @return 'TEEC_SUCCESS' if all plugins were successfully loaded. */ TEEC_Result plugin_load_all(void); /* Plugin RPC handler */ TEEC_Result plugin_process(size_t num_params, struct tee_ioctl_param *params); #else static inline TEEC_Result plugin_load_all(void) { return TEEC_SUCCESS; } static inline TEEC_Result plugin_process(size_t num_params, struct tee_ioctl_param *params) { (void)num_params; (void)params; return TEEC_ERROR_NOT_SUPPORTED; } #endif /*TEE_SUPP_PLUGINS*/ #endif /* PLUGIN_H */ optee_client-4.1.0/tee-supplicant/src/prof.c000066400000000000000000000074441455150071200210350ustar00rootroot00000000000000/* * 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. */ #include #include #include #include #include #include #include #include #include #include "prof.h" #ifndef __aligned #define __aligned(x) __attribute__((__aligned__(x))) #endif #include TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params, const char *prefix) { char vers[5] = ""; char path[255] = { 0 }; size_t bufsize = 0; TEEC_UUID *u = NULL; int fd = -1; void *buf = NULL; int flags = 0; int id = 0; int st = 0; int n = 0; if (num_params != 3 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) return TEEC_ERROR_BAD_PARAMETERS; id = params[0].a; if (MEMREF_SIZE(params + 1) != sizeof(TEEC_UUID)) return TEEC_ERROR_BAD_PARAMETERS; u = tee_supp_param_to_va(params + 1); if (!u) return TEEC_ERROR_BAD_PARAMETERS; buf = tee_supp_param_to_va(params + 2); if (!buf) return TEEC_ERROR_BAD_PARAMETERS; bufsize = MEMREF_SIZE(params + 2); if (id < 0 || id > 100) return TEEC_ERROR_BAD_PARAMETERS; flags = O_APPEND | O_WRONLY; if (!id) { /* id == 0 means create file */ flags |= O_CREAT | O_EXCL; id = 1; } for (;;) { if (id > 1) { /* * id == 1 is file 0 (no suffix), id == 2 is file .1 * etc. */ if (id > 100) id = 100; /* Avoid GCC truncation warning */ snprintf(vers, sizeof(vers), ".%d", id - 1); } n = snprintf(path, sizeof(path), "/tmp/%s" "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" "%s.out", prefix, u->timeLow, u->timeMid, u->timeHiAndVersion, u->clockSeqAndNode[0], u->clockSeqAndNode[1], u->clockSeqAndNode[2], u->clockSeqAndNode[3], u->clockSeqAndNode[4], u->clockSeqAndNode[5], u->clockSeqAndNode[6], u->clockSeqAndNode[7], vers); if ((n < 0) || (n >= (int)sizeof(path))) break; fd = open(path, flags, 0644); if (fd >= 0) { do { st = write(fd, buf, bufsize); } while (st < 0 && errno == EINTR); close(fd); if (st < 0 || st != (int)bufsize) break; params[0].a = id; goto success; } if (errno != EEXIST) break; if (id++ == 100) break; } /* An error occurred */ return TEEC_ERROR_GENERIC; success: return TEEC_SUCCESS; } optee_client-4.1.0/tee-supplicant/src/prof.h000066400000000000000000000036061455150071200210360ustar00rootroot00000000000000/* * 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 PROF_H #define PROF_H #include struct tee_ioctl_param; #if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params, const char *prefix); #else static inline TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params, const char *prefix) { (void)num_params; (void)params; (void)prefix; return TEEC_ERROR_NOT_SUPPORTED; } #endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ #endif /* PROF_H */ optee_client-4.1.0/tee-supplicant/src/rpmb.c000066400000000000000000000576441455150071200210360ustar00rootroot00000000000000/* * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RPMB_EMU #include #include "hmac_sha2.h" #else #include #endif /* * Request and response definitions must be in sync with the secure side */ /* Request */ struct rpmb_req { uint16_t cmd; #define RPMB_CMD_DATA_REQ 0x00 #define RPMB_CMD_GET_DEV_INFO 0x01 uint16_t dev_id; uint16_t block_count; /* Optional data frames (rpmb_data_frame) follow */ }; #define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1)) #define RPMB_CID_SZ 16 /* Response to device info request */ struct rpmb_dev_info { uint8_t cid[RPMB_CID_SZ]; uint8_t rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */ uint8_t rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */ /* Count */ uint8_t ret_code; #define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 #define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 }; /* * This structure is shared with OP-TEE and the MMC ioctl layer. * It is the "data frame for RPMB access" defined by JEDEC, minus the * start and stop bits. */ struct rpmb_data_frame { uint8_t stuff_bytes[196]; uint8_t key_mac[32]; uint8_t data[256]; uint8_t nonce[16]; uint32_t write_counter; uint16_t address; uint16_t block_count; uint16_t op_result; #define RPMB_RESULT_OK 0x00 #define RPMB_RESULT_GENERAL_FAILURE 0x01 #define RPMB_RESULT_AUTH_FAILURE 0x02 #define RPMB_RESULT_ADDRESS_FAILURE 0x04 #define RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 uint16_t msg_type; #define RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001 #define RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ 0x0002 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004 #define RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005 #define RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100 #define RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400 }; static pthread_mutex_t rpmb_mutex = PTHREAD_MUTEX_INITIALIZER; /* * ioctl() interface * Comes from: uapi/linux/major.h, linux/mmc/core.h */ #define MMC_BLOCK_MAJOR 179 /* mmc_ioc_cmd.opcode */ #define MMC_READ_MULTIPLE_BLOCK 18 #define MMC_WRITE_MULTIPLE_BLOCK 25 /* mmc_ioc_cmd.flags */ #define MMC_RSP_PRESENT (1 << 0) #define MMC_RSP_136 (1 << 1) /* 136 bit response */ #define MMC_RSP_CRC (1 << 2) /* Expect valid CRC */ #define MMC_RSP_OPCODE (1 << 4) /* Response contains opcode */ #define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) #define MMC_CMD_ADTC (1 << 5) /* Addressed data transfer command */ /* mmc_ioc_cmd.write_flag */ #define MMC_CMD23_ARG_REL_WR (1 << 31) /* CMD23 reliable write */ /* Maximum number of commands used in a multiple ioc command request */ #define RPMB_MAX_IOC_MULTI_CMDS 3 #ifndef RPMB_EMU #define IOCTL(fd, request, ...) \ ({ \ int ret; \ ret = ioctl((fd), (request), ##__VA_ARGS__); \ if (ret < 0) \ EMSG("ioctl ret=%d errno=%d", ret, errno); \ ret; \ }) /* Open and/or return file descriptor to RPMB partition of device dev_id */ static int mmc_rpmb_fd(uint16_t dev_id) { static int id; static int fd = -1; char path[PATH_MAX] = { 0 }; DMSG("dev_id = %u", dev_id); if (fd < 0) { #ifdef __ANDROID__ snprintf(path, sizeof(path), "/dev/mmcblk%urpmb", dev_id); #else snprintf(path, sizeof(path), "/dev/mmcblk%urpmb", dev_id); #endif fd = open(path, O_RDWR); if (fd < 0) { EMSG("Could not open %s (%s)", path, strerror(errno)); return -1; } id = dev_id; } if (id != dev_id) { EMSG("Only one MMC device is supported"); return -1; } return fd; } /* * Read @n bytes from @fd, takes care of short reads and EINTR. * Adapted from “Advanced Programming In the UNIX Environment” by W. Richard * Stevens and Stephen A. Rago, 2013, 3rd Edition, Addison-Wesley * (EINTR handling was added) */ static ssize_t readn(int fd, void *ptr, size_t n) { size_t nleft = n; ssize_t nread = 0; uint8_t *p = ptr; while (nleft > 0) { if ((nread = read(fd, p, nleft)) < 0) { if (errno == EINTR) continue; if (nleft == n) return -1; /* error, nothing read, return -1 */ else break; /* error, return amount read so far */ } else if (nread == 0) { break; /* EOF */ } nleft -= nread; p += nread; } return n - nleft; /* return >= 0 */ } /* Size of CID printed in hexadecimal */ #define CID_STR_SZ (2 * RPMB_CID_SZ) static TEEC_Result read_cid_str(uint16_t dev_id, char cid[CID_STR_SZ + 1]) { TEEC_Result res = TEEC_ERROR_GENERIC; char path[48] = { 0 }; int fd = 0; int st = 0; snprintf(path, sizeof(path), "/sys/class/mmc_host/mmc%u/mmc%u:0001/cid", dev_id, dev_id); fd = open(path, O_RDONLY); if (fd < 0) return TEEC_ERROR_ITEM_NOT_FOUND; st = readn(fd, cid, CID_STR_SZ); if (st != CID_STR_SZ) { EMSG("Read CID error"); if (errno) EMSG("%s", strerror(errno)); res = TEEC_ERROR_NO_DATA; goto out; } res = TEEC_SUCCESS; out: close(fd); return res; } static int hexchar2int(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static int hexbyte2int(char *hex) { int v1 = hexchar2int(hex[0]); int v2 = hexchar2int(hex[1]); if (v1 < 0 || v2 < 0) return -1; return 16 * v1 + v2; } /* Device Identification (CID) register is 16 bytes. It is read from sysfs. */ static TEEC_Result read_cid(uint16_t dev_id, uint8_t *cid) { TEEC_Result res = TEEC_ERROR_GENERIC; char cid_str[CID_STR_SZ + 1] = { }; int i = 0; int v = 0; res = read_cid_str(dev_id, cid_str); if (res) return res; for (i = 0; i < RPMB_CID_SZ; i++) { v = hexbyte2int(cid_str + 2 * i); if (v < 0) { EMSG("Invalid CID string: %s", cid_str); return TEEC_ERROR_NO_DATA; } cid[i] = v; } return TEEC_SUCCESS; } static TEEC_Result read_mmc_sysfs_hex(uint16_t dev_id, const char *file, uint8_t *value) { TEEC_Result status = TEEC_SUCCESS; char path[255] = { 0 }; char buf[255] = { 0 }; char *endp = buf; int fd = 0; int ret = 0; snprintf(path, sizeof(path), "/sys/class/mmc_host/mmc%u/mmc%u:0001/%s", dev_id, dev_id, file); fd = open(path, O_RDONLY); if (fd < 0) { EMSG("Could not open %s (%s)", path, strerror(errno)); return TEEC_ERROR_ITEM_NOT_FOUND; } ret = readn(fd, buf, sizeof(buf)); if (ret < 0) { EMSG("Read error (%s)", strerror(errno)); status = TEEC_ERROR_NO_DATA; goto out; } errno = 0; *value = strtol(buf, &endp, 16); if (errno || endp == buf) status = TEEC_ERROR_GENERIC; out: close(fd); return status; } static TEEC_Result read_size_mult(uint16_t dev_id, uint8_t *value) { return read_mmc_sysfs_hex(dev_id, "raw_rpmb_size_mult", value); } static TEEC_Result read_rel_wr_sec_c(uint16_t dev_id, uint8_t *value) { return read_mmc_sysfs_hex(dev_id, "rel_sectors", value); } /* * - If --rpmb-cid is given, find the eMMC RPMB device number with the specified * CID, cache the number, copy it to @ndev_id and return true. If not found * return false. * - If --rpmb-cid is not given, copy @dev_id to @ndev_id and return true. */ static bool remap_rpmb_dev_id(uint16_t dev_id, uint16_t *ndev_id) { TEEC_Result res = TEEC_ERROR_GENERIC; static bool found = false; static bool err = false; static uint16_t id = 0; char cid[CID_STR_SZ + 1] = { }; struct dirent *dent = NULL; DIR *dir = NULL; int num = 0; if (err || found) goto out; if (!supplicant_params.rpmb_cid) { id = dev_id; found = true; goto out; } dir = opendir("/sys/class/mmc_host"); if (!dir) { EMSG("Could not open /sys/class/mmc_host (%s)", strerror(errno)); err = true; goto out; } while ((dent = readdir(dir))) { if (sscanf(dent->d_name, "%*[^0123456789]%d", &num) != 1) continue; if (num > UINT16_MAX) { EMSG("Too many MMC devices"); err = true; break; } id = (uint16_t)num; res = read_cid_str(id, cid); if (res) continue; if (strcmp(cid, supplicant_params.rpmb_cid)) continue; IMSG("RPMB device %s is at /dev/mmcblk%urpmb\n", cid, id); found = true; break; } closedir(dir); if (!found) err = true; out: if (found) *ndev_id = id; return found; } #else /* RPMB_EMU */ #define IOCTL(fd, request, ...) ioctl_emu((fd), (request), ##__VA_ARGS__) /* Emulated rel_wr_sec_c value (reliable write size, *256 bytes) */ #define EMU_RPMB_REL_WR_SEC_C 1 /* Emulated rpmb_size_mult value (RPMB size, *128 kB) */ #define EMU_RPMB_SIZE_MULT 2 #define EMU_RPMB_SIZE_BYTES (EMU_RPMB_SIZE_MULT * 128 * 1024) /* Emulated eMMC device state */ struct rpmb_emu { uint8_t buf[EMU_RPMB_SIZE_BYTES]; size_t size; uint8_t key[32]; bool key_set; uint8_t nonce[16]; uint32_t write_counter; struct { uint16_t msg_type; uint16_t op_result; uint16_t address; } last_op; }; static struct rpmb_emu rpmb_emu = { .size = EMU_RPMB_SIZE_BYTES }; static struct rpmb_emu *mem_for_fd(int fd) { static int sfd = -1; if (sfd == -1) sfd = fd; if (sfd != fd) { EMSG("Emulating more than 1 RPMB partition is not supported"); return NULL; } return &rpmb_emu; } #if (DEBUGLEVEL >= TRACE_FLOW) static void dump_blocks(size_t startblk, size_t numblk, uint8_t *ptr, bool to_mmc) { char msg[100] = { 0 }; size_t i = 0; for (i = 0; i < numblk; i++) { snprintf(msg, sizeof(msg), "%s MMC block %zu", to_mmc ? "Write" : "Read", startblk + i); dump_buffer(msg, ptr, 256); ptr += 256; } } #else static void dump_blocks(size_t startblk, size_t numblk, uint8_t *ptr, bool to_mmc) { (void)startblk; (void)numblk; (void)ptr; (void)to_mmc; } #endif #define CUC(x) ((const unsigned char *)(x)) static void hmac_update_frm(hmac_sha256_ctx *ctx, struct rpmb_data_frame *frm) { hmac_sha256_update(ctx, CUC(frm->data), 256); hmac_sha256_update(ctx, CUC(frm->nonce), 16); hmac_sha256_update(ctx, CUC(&frm->write_counter), 4); hmac_sha256_update(ctx, CUC(&frm->address), 2); hmac_sha256_update(ctx, CUC(&frm->block_count), 2); hmac_sha256_update(ctx, CUC(&frm->op_result), 2); hmac_sha256_update(ctx, CUC(&frm->msg_type), 2); } static bool is_hmac_valid(struct rpmb_emu *mem, struct rpmb_data_frame *frm, size_t nfrm) { uint8_t mac[32] = { 0 }; size_t i = 0; hmac_sha256_ctx ctx; memset(&ctx, 0, sizeof(ctx)); if (!mem->key_set) { EMSG("Cannot check MAC (key not set)"); return false; } hmac_sha256_init(&ctx, mem->key, sizeof(mem->key)); for (i = 0; i < nfrm; i++, frm++) hmac_update_frm(&ctx, frm); frm--; hmac_sha256_final(&ctx, mac, 32); if (memcmp(mac, frm->key_mac, 32)) { EMSG("Invalid MAC"); return false; } return true; } static uint16_t gen_msb1st_result(uint8_t byte) { return (uint16_t)byte << 8; } static uint16_t compute_hmac(struct rpmb_emu *mem, struct rpmb_data_frame *frm, size_t nfrm) { size_t i = 0; hmac_sha256_ctx ctx; memset(&ctx, 0, sizeof(ctx)); if (!mem->key_set) { EMSG("Cannot compute MAC (key not set)"); return gen_msb1st_result(RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED); } hmac_sha256_init(&ctx, mem->key, sizeof(mem->key)); for (i = 0; i < nfrm; i++, frm++) hmac_update_frm(&ctx, frm); frm--; hmac_sha256_final(&ctx, frm->key_mac, 32); return gen_msb1st_result(RPMB_RESULT_OK); } static uint16_t ioctl_emu_mem_transfer(struct rpmb_emu *mem, struct rpmb_data_frame *frm, size_t nfrm, int to_mmc) { size_t start = mem->last_op.address * 256; size_t size = nfrm * 256; size_t i = 0; uint8_t *memptr = NULL; if (start > mem->size || start + size > mem->size) { EMSG("Transfer bounds exceeed emulated memory"); return gen_msb1st_result(RPMB_RESULT_ADDRESS_FAILURE); } if (to_mmc && !is_hmac_valid(mem, frm, nfrm)) return gen_msb1st_result(RPMB_RESULT_AUTH_FAILURE); DMSG("Transferring %zu 256-byte data block%s %s MMC (block offset=%zu)", nfrm, (nfrm > 1) ? "s" : "", to_mmc ? "to" : "from", start / 256); for (i = 0; i < nfrm; i++) { memptr = mem->buf + start + i * 256; if (to_mmc) { memcpy(memptr, frm[i].data, 256); mem->write_counter++; frm[i].write_counter = htonl(mem->write_counter); frm[i].msg_type = htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE); } else { memcpy(frm[i].data, memptr, 256); frm[i].msg_type = htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_READ); frm[i].address = htons(mem->last_op.address); frm[i].block_count = nfrm; memcpy(frm[i].nonce, mem->nonce, 16); } frm[i].op_result = gen_msb1st_result(RPMB_RESULT_OK); } dump_blocks(mem->last_op.address, nfrm, mem->buf + start, to_mmc); if (!to_mmc) compute_hmac(mem, frm, nfrm); return gen_msb1st_result(RPMB_RESULT_OK); } static void ioctl_emu_get_write_result(struct rpmb_emu *mem, struct rpmb_data_frame *frm) { frm->msg_type = htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE); frm->op_result = mem->last_op.op_result; frm->address = htons(mem->last_op.address); frm->write_counter = htonl(mem->write_counter); compute_hmac(mem, frm, 1); } static uint16_t ioctl_emu_setkey(struct rpmb_emu *mem, struct rpmb_data_frame *frm) { if (mem->key_set) { EMSG("Key already set"); return gen_msb1st_result(RPMB_RESULT_GENERAL_FAILURE); } dump_buffer("Setting key", frm->key_mac, 32); memcpy(mem->key, frm->key_mac, 32); mem->key_set = true; return gen_msb1st_result(RPMB_RESULT_OK); } static void ioctl_emu_get_keyprog_result(struct rpmb_emu *mem, struct rpmb_data_frame *frm) { frm->msg_type = htons(RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM); frm->op_result = mem->last_op.op_result; } static void ioctl_emu_read_ctr(struct rpmb_emu *mem, struct rpmb_data_frame *frm) { DMSG("Reading counter"); frm->msg_type = htons(RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ); frm->write_counter = htonl(mem->write_counter); memcpy(frm->nonce, mem->nonce, 16); frm->op_result = compute_hmac(mem, frm, 1); } static uint32_t read_cid(uint16_t dev_id, uint8_t *cid) { /* Taken from an actual eMMC chip */ static const uint8_t test_cid[] = { /* MID (Manufacturer ID): Micron */ 0xfe, /* CBX (Device/BGA): BGA */ 0x01, /* OID (OEM/Application ID) */ 0x4e, /* PNM (Product name) "MMC04G" */ 0x4d, 0x4d, 0x43, 0x30, 0x34, 0x47, /* PRV (Product revision): 4.2 */ 0x42, /* PSN (Product serial number) */ 0xc8, 0xf6, 0x55, 0x2a, /* * MDT (Manufacturing date): * June, 2014 */ 0x61, /* (CRC7 (0xA) << 1) | 0x1 */ 0x15 }; (void)dev_id; memcpy(cid, test_cid, sizeof(test_cid)); return TEEC_SUCCESS; } /* A crude emulation of the MMC ioc commands we need for RPMB */ static int ioctl_emu_cmd(int fd, struct mmc_ioc_cmd *cmd) { struct rpmb_data_frame *frm = NULL; uint16_t msg_type = 0; struct rpmb_emu *mem = mem_for_fd(fd); if (!mem) return -1; switch (cmd->opcode) { case MMC_WRITE_MULTIPLE_BLOCK: frm = (struct rpmb_data_frame *)(uintptr_t)cmd->data_ptr; msg_type = ntohs(frm->msg_type); switch (msg_type) { case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: mem->last_op.msg_type = msg_type; mem->last_op.op_result = ioctl_emu_setkey(mem, frm); break; case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: mem->last_op.msg_type = msg_type; mem->last_op.address = ntohs(frm->address); mem->last_op.op_result = ioctl_emu_mem_transfer(mem, frm, cmd->blocks, 1); break; case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: memcpy(mem->nonce, frm->nonce, 16); mem->last_op.msg_type = msg_type; mem->last_op.address = ntohs(frm->address); break; default: break; } break; case MMC_READ_MULTIPLE_BLOCK: frm = (struct rpmb_data_frame *)(uintptr_t)cmd->data_ptr; msg_type = ntohs(frm->msg_type); switch (mem->last_op.msg_type) { case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: ioctl_emu_get_keyprog_result(mem, frm); break; case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: ioctl_emu_get_write_result(mem, frm); break; case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: ioctl_emu_read_ctr(mem, frm); break; case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: ioctl_emu_mem_transfer(mem, frm, cmd->blocks, 0); break; default: EMSG("Unexpected"); break; } break; default: EMSG("Unsupported ioctl opcode 0x%08x", cmd->opcode); return -1; } return 0; } static int ioctl_emu(int fd, unsigned long request, ...) { struct mmc_ioc_multi_cmd *mcmd = NULL; struct mmc_ioc_cmd *cmd = NULL; size_t i = 0; int res = 0; va_list ap; if (request == MMC_IOC_CMD) { va_start(ap, request); cmd = va_arg(ap, struct mmc_ioc_cmd *); va_end(ap); res = ioctl_emu_cmd(fd, cmd); } else if (request == MMC_IOC_MULTI_CMD) { va_start(ap, request); mcmd = va_arg(ap, struct mmc_ioc_multi_cmd *); va_end(ap); for (i = 0; i < mcmd->num_of_cmds; i++) { res = ioctl_emu_cmd(fd, &mcmd->cmds[i]); if (res) return res; } } else { EMSG("Unsupported ioctl: 0x%lx", request); return -1; } return res; } static int mmc_rpmb_fd(uint16_t dev_id) { (void)dev_id; /* Any value != -1 will do in test mode */ return 0; } static TEEC_Result read_size_mult(uint16_t dev_id, uint8_t *value) { (void)dev_id; *value = EMU_RPMB_SIZE_MULT; return TEEC_SUCCESS; } static TEEC_Result read_rel_wr_sec_c(uint16_t dev_id, uint8_t *value) { (void)dev_id; *value = EMU_RPMB_REL_WR_SEC_C; return TEEC_SUCCESS; } static bool remap_rpmb_dev_id(uint16_t dev_id, uint16_t *ndev_id) { *ndev_id = dev_id; return true; } #endif /* RPMB_EMU */ static inline void set_mmc_io_cmd(struct mmc_ioc_cmd *cmd, unsigned int blocks, __u32 opcode, int write_flag) { cmd->blksz = 512; cmd->blocks = blocks; cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd->opcode = opcode; cmd->write_flag = write_flag; } static uint32_t rpmb_data_req(int fd, struct rpmb_data_frame *req_frm, size_t req_nfrm, struct rpmb_data_frame *rsp_frm, size_t rsp_nfrm) { TEEC_Result res = TEEC_SUCCESS; int st = 0; size_t i = 0; uint16_t msg_type = ntohs(req_frm->msg_type); struct mmc_ioc_multi_cmd *mcmd = NULL; struct mmc_ioc_cmd *cmd = NULL; for (i = 1; i < req_nfrm; i++) { if (req_frm[i].msg_type != msg_type) { EMSG("All request frames shall be of the same type"); return TEEC_ERROR_BAD_PARAMETERS; } } DMSG("Req: %zu frame(s) of type 0x%04x", req_nfrm, msg_type); DMSG("Rsp: %zu frame(s)", rsp_nfrm); mcmd = (struct mmc_ioc_multi_cmd *) calloc(1, sizeof(struct mmc_ioc_multi_cmd) + RPMB_MAX_IOC_MULTI_CMDS * sizeof(struct mmc_ioc_cmd)); if (!mcmd) return TEEC_ERROR_OUT_OF_MEMORY; switch(msg_type) { case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: if (rsp_nfrm != 1) { EMSG("Expected only one response frame"); res = TEEC_ERROR_BAD_PARAMETERS; goto out; } mcmd->num_of_cmds = 3; /* Send write request frame(s) */ cmd = &mcmd->cmds[0]; set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, 1 | MMC_CMD23_ARG_REL_WR); /* * Black magic: tested on a HiKey board with a HardKernel eMMC * module. When postsleep values are zero, the kernel logs * random errors: "mmc_blk_ioctl_cmd: Card Status=0x00000E00" * and ioctl() fails. */ cmd->postsleep_min_us = 20000; cmd->postsleep_max_us = 50000; mmc_ioc_cmd_set_data((*cmd), (uintptr_t)req_frm); /* Send result request frame */ cmd = &mcmd->cmds[1]; set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, 1); memset(rsp_frm, 0, 1); rsp_frm->msg_type = htons(RPMB_MSG_TYPE_REQ_RESULT_READ); mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); /* Read response frame */ cmd = &mcmd->cmds[2]; set_mmc_io_cmd(cmd, rsp_nfrm, MMC_READ_MULTIPLE_BLOCK, 0); mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); break; case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: if (rsp_nfrm != 1) { EMSG("Expected only one response frame"); res = TEEC_ERROR_BAD_PARAMETERS; goto out; } #if __GNUC__ > 6 __attribute__((fallthrough)); #endif case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: if (req_nfrm != 1) { EMSG("Expected only one request frame"); res = TEEC_ERROR_BAD_PARAMETERS; goto out; } mcmd->num_of_cmds = 2; /* Send request frame */ cmd = &mcmd->cmds[0]; set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, 1); mmc_ioc_cmd_set_data((*cmd), (uintptr_t)req_frm); /* Read response frames */ cmd = &mcmd->cmds[1]; set_mmc_io_cmd(cmd, rsp_nfrm, MMC_READ_MULTIPLE_BLOCK, 0); mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); break; default: EMSG("Unsupported message type: %d", msg_type); res = TEEC_ERROR_GENERIC; goto out; } st = IOCTL(fd, MMC_IOC_MULTI_CMD, mcmd); if (st < 0) res = TEEC_ERROR_GENERIC; out: free(mcmd); return res; } static uint32_t rpmb_get_dev_info(uint16_t dev_id, struct rpmb_dev_info *info) { TEEC_Result res = TEEC_SUCCESS; uint8_t rpmb_size_mult = 0; uint8_t rel_wr_sec_c = 0; res = read_cid(dev_id, info->cid); if (res != TEEC_SUCCESS) return res; res = read_size_mult(dev_id, &rpmb_size_mult); if (res != TEEC_SUCCESS) return res; info->rpmb_size_mult = rpmb_size_mult; res = read_rel_wr_sec_c(dev_id, &rel_wr_sec_c); if (res != TEEC_SUCCESS) return res; info->rel_wr_sec_c = rel_wr_sec_c; info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK; return res; } /* * req is one struct rpmb_req followed by one or more struct rpmb_data_frame * rsp is either one struct rpmb_dev_info or one or more struct rpmb_data_frame */ static uint32_t rpmb_process_request_unlocked(void *req, size_t req_size, void *rsp, size_t rsp_size) { struct rpmb_req *sreq = req; size_t req_nfrm = 0; size_t rsp_nfrm = 0; uint16_t dev_id = 0; uint32_t res = 0; int fd = 0; if (req_size < sizeof(*sreq)) return TEEC_ERROR_BAD_PARAMETERS; if (!remap_rpmb_dev_id(sreq->dev_id, &dev_id)) return TEEC_ERROR_ITEM_NOT_FOUND; switch (sreq->cmd) { case RPMB_CMD_DATA_REQ: req_nfrm = (req_size - sizeof(struct rpmb_req)) / 512; rsp_nfrm = rsp_size / 512; fd = mmc_rpmb_fd(dev_id); if (fd < 0) return TEEC_ERROR_BAD_PARAMETERS; res = rpmb_data_req(fd, RPMB_REQ_DATA(req), req_nfrm, rsp, rsp_nfrm); break; case RPMB_CMD_GET_DEV_INFO: if (req_size != sizeof(struct rpmb_req) || rsp_size != sizeof(struct rpmb_dev_info)) { EMSG("Invalid req/rsp size"); return TEEC_ERROR_BAD_PARAMETERS; } res = rpmb_get_dev_info(dev_id, (struct rpmb_dev_info *)rsp); break; default: EMSG("Unsupported RPMB command: %d", sreq->cmd); res = TEEC_ERROR_BAD_PARAMETERS; break; } return res; } uint32_t rpmb_process_request(void *req, size_t req_size, void *rsp, size_t rsp_size) { uint32_t res = 0; tee_supp_mutex_lock(&rpmb_mutex); res = rpmb_process_request_unlocked(req, req_size, rsp, rsp_size); tee_supp_mutex_unlock(&rpmb_mutex); return res; } optee_client-4.1.0/tee-supplicant/src/rpmb.h000066400000000000000000000030261455150071200210240ustar00rootroot00000000000000/* * 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 RPMB_H #define RPMB_H #include #include uint32_t rpmb_process_request(void *req, size_t req_size, void *rsp, size_t rsp_size); #endif /* RPMB_H */ optee_client-4.1.0/tee-supplicant/src/sha2.c000066400000000000000000000201271455150071200207150ustar00rootroot00000000000000/* * FIPS 180-2 SHA-224/256/384/512 implementation * Last update: 02/02/2007 * Issue date: 04/30/2005 * * Copyright (C) 2005, 2007 Olivier Gay * All rights reserved. * * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 "sha2.h" #define SHFR(x, n) (x >> n) #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) #define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) #define CH(x, y, z) ((x & y) ^ (~x & z)) #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) #define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) #define UNPACK32(x, str) \ { \ *((str) + 3) = (uint8) ((x) ); \ *((str) + 2) = (uint8) ((x) >> 8); \ *((str) + 1) = (uint8) ((x) >> 16); \ *((str) + 0) = (uint8) ((x) >> 24); \ } #define PACK32(str, x) \ { \ *(x) = ((uint32) *((str) + 3) ) \ | ((uint32) *((str) + 2) << 8) \ | ((uint32) *((str) + 1) << 16) \ | ((uint32) *((str) + 0) << 24); \ } #define UNPACK64(x, str) \ { \ *((str) + 7) = (uint8) ((x) ); \ *((str) + 6) = (uint8) ((x) >> 8); \ *((str) + 5) = (uint8) ((x) >> 16); \ *((str) + 4) = (uint8) ((x) >> 24); \ *((str) + 3) = (uint8) ((x) >> 32); \ *((str) + 2) = (uint8) ((x) >> 40); \ *((str) + 1) = (uint8) ((x) >> 48); \ *((str) + 0) = (uint8) ((x) >> 56); \ } #define PACK64(str, x) \ { \ *(x) = ((uint64) *((str) + 7) ) \ | ((uint64) *((str) + 6) << 8) \ | ((uint64) *((str) + 5) << 16) \ | ((uint64) *((str) + 4) << 24) \ | ((uint64) *((str) + 3) << 32) \ | ((uint64) *((str) + 2) << 40) \ | ((uint64) *((str) + 1) << 48) \ | ((uint64) *((str) + 0) << 56); \ } #define SHA256_SCR(i) \ { \ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \ + SHA256_F3(w[i - 15]) + w[i - 16]; \ } uint32 sha256_h0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; uint32 sha256_k[64] = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; /* SHA-256 functions */ static void sha256_transf(sha256_ctx *ctx, const unsigned char *message, unsigned int block_nb) { uint32 w[64] = { 0 }; uint32 wv[8] = { 0 }; uint32 t1 = 0; uint32 t2 = 0; const unsigned char *sub_block = NULL; int i = 0; int j = 0; for (i = 0; i < (int) block_nb; i++) { sub_block = message + (i << 6); for (j = 0; j < 16; j++) { PACK32(&sub_block[j << 2], &w[j]); } for (j = 16; j < 64; j++) { SHA256_SCR(j); } for (j = 0; j < 8; j++) { wv[j] = ctx->h[j]; } for (j = 0; j < 64; j++) { t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j]; t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); wv[7] = wv[6]; wv[6] = wv[5]; wv[5] = wv[4]; wv[4] = wv[3] + t1; wv[3] = wv[2]; wv[2] = wv[1]; wv[1] = wv[0]; wv[0] = t1 + t2; } for (j = 0; j < 8; j++) { ctx->h[j] += wv[j]; } } } void sha256(const unsigned char *message, unsigned int len, unsigned char *digest) { sha256_ctx ctx; memset(&ctx, 0, sizeof(ctx)); sha256_init(&ctx); sha256_update(&ctx, message, len); sha256_final(&ctx, digest); } void sha256_init(sha256_ctx *ctx) { int i = 0; for (i = 0; i < 8; i++) { ctx->h[i] = sha256_h0[i]; } ctx->len = 0; ctx->tot_len = 0; } void sha256_update(sha256_ctx *ctx, const unsigned char *message, unsigned int len) { unsigned int block_nb = 0; unsigned int new_len = 0; unsigned int rem_len = 0; unsigned int tmp_len = 0; const unsigned char *shifted_message = NULL; tmp_len = SHA256_BLOCK_SIZE - ctx->len; rem_len = len < tmp_len ? len : tmp_len; memcpy(&ctx->block[ctx->len], message, rem_len); if (ctx->len + len < SHA256_BLOCK_SIZE) { ctx->len += len; return; } new_len = len - rem_len; block_nb = new_len / SHA256_BLOCK_SIZE; shifted_message = message + rem_len; sha256_transf(ctx, ctx->block, 1); sha256_transf(ctx, shifted_message, block_nb); rem_len = new_len % SHA256_BLOCK_SIZE; memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len); ctx->len = rem_len; ctx->tot_len += (block_nb + 1) << 6; } void sha256_final(sha256_ctx *ctx, unsigned char *digest) { unsigned int block_nb = 0; unsigned int pm_len = 0; unsigned int len_b = 0; int i = 0; block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE))); len_b = (ctx->tot_len + ctx->len) << 3; pm_len = block_nb << 6; memset(ctx->block + ctx->len, 0, pm_len - ctx->len); ctx->block[ctx->len] = 0x80; UNPACK32(len_b, ctx->block + pm_len - 4); sha256_transf(ctx, ctx->block, block_nb); for (i = 0 ; i < 8; i++) { UNPACK32(ctx->h[i], &digest[i << 2]); } } optee_client-4.1.0/tee-supplicant/src/sha2.h000066400000000000000000000050061455150071200207210ustar00rootroot00000000000000/* * FIPS 180-2 SHA-224/256/384/512 implementation * Last update: 02/02/2007 * Issue date: 04/30/2005 * * Copyright (C) 2005, 2007 Olivier Gay * All rights reserved. * * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 SHA2_H #define SHA2_H #define SHA256_DIGEST_SIZE ( 256 / 8) #define SHA256_BLOCK_SIZE ( 512 / 8) #ifndef SHA2_TYPES #define SHA2_TYPES typedef unsigned char uint8; typedef unsigned int uint32; typedef unsigned long long uint64; #endif #ifdef __cplusplus extern "C" { #endif typedef struct { unsigned int tot_len; unsigned int len; unsigned char block[2 * SHA256_BLOCK_SIZE]; uint32 h[8]; } sha256_ctx; typedef sha256_ctx sha224_ctx; void sha256_init(sha256_ctx * ctx); void sha256_update(sha256_ctx *ctx, const unsigned char *message, unsigned int len); void sha256_final(sha256_ctx *ctx, unsigned char *digest); void sha256(const unsigned char *message, unsigned int len, unsigned char *digest); #ifdef __cplusplus } #endif #endif /* !SHA2_H */ optee_client-4.1.0/tee-supplicant/src/tee_socket.c000066400000000000000000000501401455150071200222030ustar00rootroot00000000000000/* * Copyright (c) 2016-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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "handle.h" #include "__tee_isocket_defines.h" #include "__tee_ipsocket.h" #include "__tee_tcpsocket_defines.h" #include "__tee_tcpsocket_defines_extensions.h" #include "__tee_udpsocket_defines.h" #ifndef __aligned #define __aligned(x) __attribute__((__aligned__(x))) #endif #include /* * Used when checking how much data we have queued. * * For SOCK_DGRAM we try to be accurate up to 4096 bytes as * that's our arbitrary chosen sensible upper size (with * some margin). Larger size doesn't make much sense since * anything larger than the MTU is bound to cause trouble * on a congested network. * * For SOCK_STREAM we chose the same upper limit for * simplicity. It doesn't matter if there's more queued, * no data will be lost. */ #define SUPP_MAX_PEEK_LEN 4096 struct sock_instance { uint32_t id; struct handle_db db; TAILQ_ENTRY(sock_instance) link; }; static pthread_mutex_t sock_mutex = PTHREAD_MUTEX_INITIALIZER; TAILQ_HEAD(, sock_instance) sock_instances = TAILQ_HEAD_INITIALIZER(sock_instances); static void sock_lock(void) { pthread_mutex_lock(&sock_mutex); } static void sock_unlock(void) { pthread_mutex_unlock(&sock_mutex); } static struct sock_instance *sock_instance_find(uint32_t instance_id) { struct sock_instance *si = NULL; TAILQ_FOREACH(si, &sock_instances, link) { if (si->id == instance_id) return si; } return NULL; } static void *fd_to_handle_ptr(int fd) { uintptr_t ptr = 0; assert(fd >= 0); ptr = fd + 1; return (void *)ptr; } static int handle_ptr_to_fd(void *ptr) { assert(ptr); return (uintptr_t)ptr - 1; } static int sock_handle_get(uint32_t instance_id, int fd) { int handle = -1; struct sock_instance *si = NULL; sock_lock(); si = sock_instance_find(instance_id); if (!si) { si = calloc(1, sizeof(*si)); if (!si) goto out; si->id = instance_id; TAILQ_INSERT_TAIL(&sock_instances, si, link); } handle = handle_get(&si->db, fd_to_handle_ptr(fd)); out: sock_unlock(); return handle; } static int sock_handle_to_fd(uint32_t instance_id, uint32_t handle) { int fd = -1; struct sock_instance *si = NULL; sock_lock(); si = sock_instance_find(instance_id); if (si) fd = handle_ptr_to_fd(handle_lookup(&si->db, handle)); sock_unlock(); return fd; } static void sock_handle_put(uint32_t instance_id, uint32_t handle) { struct sock_instance *si = NULL; sock_lock(); si = sock_instance_find(instance_id); if (si) handle_put(&si->db, handle); sock_unlock(); } static bool chk_pt(struct tee_ioctl_param *param, uint32_t type) { return (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) == type; } static int fd_flags_add(int fd, int flags) { int val = 0; val = fcntl(fd, F_GETFD, 0); if (val == -1) return -1; val |= flags; return fcntl(fd, F_SETFL, val); } static TEEC_Result sock_connect(uint32_t ip_vers, unsigned int protocol, const char *server, uint16_t port, int *ret_fd) { TEEC_Result r = TEEC_ERROR_GENERIC; struct addrinfo *res0 = NULL; struct addrinfo *res = NULL; int fd = -1; char port_name[10] = { 0 }; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); snprintf(port_name, sizeof(port_name), "%" PRIu16, port); switch (ip_vers) { case TEE_IP_VERSION_DC: hints.ai_family = AF_UNSPEC; break; case TEE_IP_VERSION_4: hints.ai_family = AF_INET; break; case TEE_IP_VERSION_6: hints.ai_family = AF_INET6; break; default: return TEEC_ERROR_BAD_PARAMETERS; } if (protocol == TEE_ISOCKET_PROTOCOLID_TCP) hints.ai_socktype = SOCK_STREAM; else if (protocol == TEE_ISOCKET_PROTOCOLID_UDP) hints.ai_socktype = SOCK_DGRAM; else return TEEC_ERROR_BAD_PARAMETERS; if (getaddrinfo(server, port_name, &hints, &res0)) return TEE_ISOCKET_ERROR_HOSTNAME; for (res = res0; res; res = res->ai_next) { fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (fd == -1) { if (errno == ENOMEM || errno == ENOBUFS) r = TEE_ISOCKET_ERROR_OUT_OF_RESOURCES; else r = TEEC_ERROR_GENERIC; continue; } if (connect(fd, res->ai_addr, res->ai_addrlen)) { if (errno == ETIMEDOUT) r = TEE_ISOCKET_ERROR_TIMEOUT; else r = TEEC_ERROR_COMMUNICATION; close(fd); fd = -1; continue; } if (fd_flags_add(fd, O_NONBLOCK)) { close(fd); fd = -1; r = TEEC_ERROR_GENERIC; break; } r = TEEC_SUCCESS; break; } freeaddrinfo(res0); *ret_fd = fd; return r; } static TEEC_Result tee_socket_open(size_t num_params, struct tee_ioctl_param *params) { TEEC_Result res = TEEC_ERROR_GENERIC; int handle = 0; int fd = 0; uint32_t instance_id = 0; char *server = NULL; uint32_t ip_vers = 0; uint16_t port = 0; uint32_t protocol = 0; if (num_params != 4 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) || !chk_pt(params + 3, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; port = params[1].a; protocol = params[1].b; ip_vers = params[1].c; server = tee_supp_param_to_va(params + 2); if (!server || server[MEMREF_SIZE(params + 2) - 1] != '\0') return TEE_ISOCKET_ERROR_HOSTNAME; res = sock_connect(ip_vers, protocol, server, port, &fd); if (res != TEEC_SUCCESS) return res; handle = sock_handle_get(instance_id, fd); if (handle < 0) { close(fd); return TEEC_ERROR_OUT_OF_MEMORY; } params[3].a = handle; return TEEC_SUCCESS; } static TEEC_Result tee_socket_close(size_t num_params, struct tee_ioctl_param *params) { int handle = 0; uint32_t instance_id = 0; int fd = 0; if (num_params != 1 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; handle = params[0].c; fd = sock_handle_to_fd(instance_id, handle); if (fd < 0) return TEEC_ERROR_BAD_PARAMETERS; sock_handle_put(instance_id, handle); if (close(fd)) { EMSG("tee_socket_close: close(%d): %s", fd, strerror(errno)); return TEEC_ERROR_GENERIC; } return TEEC_SUCCESS; } static void sock_close_cb(int handle, void *ptr, void *arg) { struct sock_instance *si = arg; int fd = handle_ptr_to_fd(ptr); if (close(fd)) EMSG("sock_close_cb instance_id %d handle %d fd %d: %s", si->id, handle, fd, strerror(errno)); } static TEEC_Result tee_socket_close_all(size_t num_params, struct tee_ioctl_param *params) { uint32_t instance_id = 0; struct sock_instance *si = NULL; if (num_params != 1 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; sock_lock(); si = sock_instance_find(instance_id); if (si) handle_foreach_put(&si->db, sock_close_cb, si); sock_unlock(); return TEEC_SUCCESS; } #define TS_NSEC_PER_SEC 1000000000 static void ts_add(const struct timespec *a, const struct timespec *b, struct timespec *res) { res->tv_sec = a->tv_sec + b->tv_sec; res->tv_nsec = a->tv_nsec + b->tv_nsec; if (res->tv_nsec >= TS_NSEC_PER_SEC) { res->tv_sec++; res->tv_nsec -= TS_NSEC_PER_SEC; } } static int ts_diff_to_polltimeout(const struct timespec *a, const struct timespec *b) { struct timespec diff; memset(&diff, 0, sizeof(diff)); diff.tv_sec = a->tv_sec - b->tv_sec; diff.tv_nsec = a->tv_nsec - b->tv_nsec; if (a->tv_nsec < b->tv_nsec) { diff.tv_nsec += TS_NSEC_PER_SEC; diff.tv_sec--; } if ((diff.tv_sec - 1) > (INT_MAX / 1000)) return INT_MAX; return diff.tv_sec * 1000 + diff.tv_nsec / (TS_NSEC_PER_SEC / 1000); } static void ts_delay_from_millis(uint32_t millis, struct timespec *res) { res->tv_sec = millis / 1000; res->tv_nsec = (millis % 1000) * (TS_NSEC_PER_SEC / 1000); } static TEEC_Result poll_with_timeout(struct pollfd *pfd, nfds_t nfds, uint32_t timeout) { int to = 0; int r = 0; struct timespec now; struct timespec until; memset(&now, 0, sizeof(now)); memset(&until, 0, sizeof(until)); if (timeout == OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING) { to = -1; } else { struct timespec delay; memset(&delay, 0, sizeof(delay)); ts_delay_from_millis(timeout, &delay); if (clock_gettime(CLOCK_REALTIME, &now)) return TEEC_ERROR_GENERIC; ts_add(&now, &delay, &until); } while (true) { if (to != -1) to = ts_diff_to_polltimeout(&until, &now); r = poll(pfd, nfds, to); if (!r) return TEE_ISOCKET_ERROR_TIMEOUT; if (r == -1) { /* * If we're interrupted by a signal treat * recalculate the timeout (if needed) and wait * again. */ if (errno == EINTR) { if (to != -1 && clock_gettime(CLOCK_REALTIME, &now)) return TEEC_ERROR_GENERIC; continue; } return TEEC_ERROR_BAD_PARAMETERS; } return TEEC_SUCCESS; } } static TEEC_Result write_with_timeout(int fd, const void *buf, size_t *blen, uint32_t timeout) { TEEC_Result res = TEEC_ERROR_GENERIC; struct pollfd pfd = { .fd = fd, .events = POLLOUT }; ssize_t r = 0; res = poll_with_timeout(&pfd, 1, timeout); if (res != TEEC_SUCCESS) return res; r = write(fd, buf, *blen); if (r == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return TEE_ISOCKET_ERROR_TIMEOUT; return TEEC_ERROR_BAD_PARAMETERS; } *blen = r; return TEEC_SUCCESS; } static TEEC_Result tee_socket_send(size_t num_params, struct tee_ioctl_param *params) { TEEC_Result res = TEEC_ERROR_GENERIC; int handle = 0; int fd = 0; uint32_t instance_id = 0; void *buf = NULL; size_t bytes = 0; if (num_params != 3 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) || !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; handle = params[0].c; fd = sock_handle_to_fd(instance_id, handle); if (fd < 0) return TEEC_ERROR_BAD_PARAMETERS; buf = tee_supp_param_to_va(params + 1); bytes = MEMREF_SIZE(params + 1); res = write_with_timeout(fd, buf, &bytes, params[2].a); if (res == TEEC_SUCCESS) params[2].b = bytes; return res; } static ssize_t recv_with_out_flags(int fd, void *buf, size_t len, int inflags, int *out_flags) { ssize_t r = 0; while (true) { struct iovec iov = { .iov_base = buf, .iov_len = len, }; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, }; r = recvmsg(fd, &msg, inflags); if (r < 0) { /* * If the syscall was just interrupted by a signal * delivery, try again. */ if (errno == EINTR) continue; return r; } *out_flags = msg.msg_flags; return r; } } static TEEC_Result read_with_timeout(int fd, void *buf, size_t *blen, uint32_t timeout) { TEEC_Result res = TEEC_ERROR_GENERIC; struct pollfd pfd = { .fd = fd, .events = POLLIN }; int socktype = 0; socklen_t l = sizeof(socktype); size_t peek_len = 0; int out_flags = 0; ssize_t r = 0; int e = 0; if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &l)) return TEEC_ERROR_BAD_PARAMETERS; if (*blen) { /* If *blen == 0, the timeout parameter has no effect. */ res = poll_with_timeout(&pfd, 1, timeout); if (res != TEEC_SUCCESS) return res; } if ((socktype == SOCK_DGRAM && *blen < SUPP_MAX_PEEK_LEN) || !*blen) { /* Check how much data we have queued. */ void *b = malloc(SUPP_MAX_PEEK_LEN); if (!b) return TEEC_ERROR_OUT_OF_MEMORY; r = recv_with_out_flags(fd, b, SUPP_MAX_PEEK_LEN, MSG_PEEK | MSG_DONTWAIT, &out_flags); e = errno; free(b); if (r < 0) goto err; /* * If the message was truncated we know that it's at least * one byte larger. */ if (out_flags & MSG_TRUNC) r++; if (!*blen) { *blen = r; return TEEC_SUCCESS; } peek_len = r; } r = recv_with_out_flags(fd, buf, *blen, MSG_DONTWAIT, &out_flags); if (r == -1) { e = errno; goto err; } if (socktype == SOCK_DGRAM && (out_flags & MSG_TRUNC)) { /* * The datagram has been truncated, return the best length * we have to indicate that. */ if (peek_len > (size_t)r) *blen = peek_len; else *blen = r + 1; } else { *blen = r; } return TEEC_SUCCESS; err: if (e == EAGAIN || e == EWOULDBLOCK) { /* * If *blen is supplied as 0 then we're not supposed wait * for data so the call to poll has been skipped. In case * there is no data available recvmsg() will return an * error with errno set to EAGAIN or EWOULDBLOCK. */ if (!*blen) return TEEC_SUCCESS; return TEE_ISOCKET_ERROR_TIMEOUT; } return TEEC_ERROR_BAD_PARAMETERS; } static TEEC_Result tee_socket_recv(size_t num_params, struct tee_ioctl_param *params) { TEEC_Result res = TEEC_ERROR_GENERIC; int handle = 0; int fd = 0; uint32_t instance_id = 0; void *buf = NULL; size_t bytes = 0; if (num_params != 3 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) || !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; handle = params[0].c; fd = sock_handle_to_fd(instance_id, handle); if (fd < 0) return TEEC_ERROR_BAD_PARAMETERS; buf = tee_supp_param_to_va(params + 1); bytes = MEMREF_SIZE(params + 1); res = read_with_timeout(fd, buf, &bytes, params[2].a); if (res == TEEC_SUCCESS) MEMREF_SIZE(params + 1) = bytes; return res; } static TEEC_Result tee_socket_ioctl_tcp(int fd, uint32_t command, void *buf, size_t *blen) { switch (command) { case TEE_TCP_SET_RECVBUF: if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, buf, *blen)) return TEEC_ERROR_BAD_PARAMETERS; return TEEC_SUCCESS; case TEE_TCP_SET_SENDBUF: if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, buf, *blen)) return TEEC_ERROR_BAD_PARAMETERS; return TEEC_SUCCESS; default: return TEEC_ERROR_NOT_SUPPORTED; } } static TEEC_Result sa_set_port(struct sockaddr *sa, socklen_t slen, uint16_t port) { if (sa->sa_family == AF_INET) { struct sockaddr_in *sain = (void *)sa; if (slen < (socklen_t)sizeof(*sain)) return TEEC_ERROR_BAD_PARAMETERS; sain->sin_port = htons(port); return TEEC_SUCCESS; } if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sain6 = (void *)sa; if (slen < (socklen_t)sizeof(*sain6)) return TEEC_ERROR_BAD_PARAMETERS; sain6->sin6_port = htons(port); return TEEC_SUCCESS; } return TEEC_ERROR_BAD_PARAMETERS; } static TEEC_Result sa_get_port(struct sockaddr *sa, socklen_t slen, uint16_t *port) { if (sa->sa_family == AF_INET) { struct sockaddr_in *sain = (void *)sa; if (slen < (socklen_t)sizeof(*sain)) return TEEC_ERROR_BAD_PARAMETERS; *port = ntohs(sain->sin_port); return TEEC_SUCCESS; } if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sain6 = (void *)sa; if (slen < (socklen_t)sizeof(*sain6)) return TEEC_ERROR_BAD_PARAMETERS; *port = ntohs(sain6->sin6_port); return TEEC_SUCCESS; } return TEEC_ERROR_BAD_PARAMETERS; } static TEEC_Result udp_changeaddr(int fd, int family, const char *server, uint16_t port) { TEEC_Result r = TEE_ISOCKET_ERROR_HOSTNAME; struct addrinfo *res0 = NULL; struct addrinfo *res = NULL; char port_name[10] = { 0 }; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); snprintf(port_name, sizeof(port_name), "%" PRIu16, port); hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; if (getaddrinfo(server, port_name, &hints, &res0)) return TEE_ISOCKET_ERROR_HOSTNAME; for (res = res0; res; res = res->ai_next) { if (connect(fd, res->ai_addr, res->ai_addrlen)) { if (errno == ETIMEDOUT) r = TEE_ISOCKET_ERROR_TIMEOUT; else r = TEEC_ERROR_COMMUNICATION; continue; } r = TEEC_SUCCESS; break; } freeaddrinfo(res0); return r; } static TEEC_Result tee_socket_ioctl_udp(int fd, uint32_t command, void *buf, size_t *blen) { TEEC_Result res = TEEC_ERROR_GENERIC; uint16_t port = 0; struct sockaddr_storage sass; struct sockaddr *sa = (struct sockaddr *)&sass; socklen_t len = sizeof(sass); memset(&sass, 0, sizeof(sass)); if (getpeername(fd, sa, &len)) return TEEC_ERROR_BAD_PARAMETERS; switch (command) { case TEE_UDP_CHANGEADDR: res = sa_get_port(sa, len, &port); if (res != TEEC_SUCCESS) return res; if (!blen || *((char *)buf + *blen - 1) != '\0') return TEE_ISOCKET_ERROR_HOSTNAME; return udp_changeaddr(fd, sa->sa_family, buf, port); case TEE_UDP_CHANGEPORT: if (*blen != sizeof(port)) return TEEC_ERROR_BAD_PARAMETERS; memcpy(&port, buf, sizeof(port)); res = sa_set_port(sa, len, port); if (res != TEEC_SUCCESS) return res; if (connect(fd, sa, len)) return TEEC_ERROR_GENERIC; return TEEC_SUCCESS; default: return TEEC_ERROR_NOT_SUPPORTED; } } static TEEC_Result tee_socket_ioctl(size_t num_params, struct tee_ioctl_param *params) { TEEC_Result res = TEEC_ERROR_GENERIC; int handle = 0; int fd = 0; uint32_t instance_id = 0; uint32_t command = 0; void *buf = NULL; int socktype = 0; socklen_t l = 0; size_t sz = 0; if (num_params != 3 || !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) || !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) return TEEC_ERROR_BAD_PARAMETERS; instance_id = params[0].b; handle = params[0].c; command = params[2].a; fd = sock_handle_to_fd(instance_id, handle); if (fd < 0) return TEEC_ERROR_BAD_PARAMETERS; l = sizeof(socktype); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &l)) return TEEC_ERROR_BAD_PARAMETERS; buf = tee_supp_param_to_va(params + 1); switch (socktype) { case SOCK_STREAM: sz = MEMREF_SIZE(params + 1); res = tee_socket_ioctl_tcp(fd, command, buf, &sz); MEMREF_SIZE(params + 1) = sz; return res; case SOCK_DGRAM: sz = MEMREF_SIZE(params + 1); res = tee_socket_ioctl_udp(fd, command, buf, &sz); MEMREF_SIZE(params + 1) = sz; return res; default: return TEEC_ERROR_BAD_PARAMETERS; } } TEEC_Result tee_socket_process(size_t num_params, struct tee_ioctl_param *params) { if (!num_params || !tee_supp_param_is_value(params)) return TEEC_ERROR_BAD_PARAMETERS; switch (params->a) { case OPTEE_MRC_SOCKET_OPEN: return tee_socket_open(num_params, params); case OPTEE_MRC_SOCKET_CLOSE: return tee_socket_close(num_params, params); case OPTEE_MRC_SOCKET_CLOSE_ALL: return tee_socket_close_all(num_params, params); case OPTEE_MRC_SOCKET_SEND: return tee_socket_send(num_params, params); case OPTEE_MRC_SOCKET_RECV: return tee_socket_recv(num_params, params); case OPTEE_MRC_SOCKET_IOCTL: return tee_socket_ioctl(num_params, params); default: return TEEC_ERROR_BAD_PARAMETERS; } } optee_client-4.1.0/tee-supplicant/src/tee_socket.h000066400000000000000000000034521455150071200222140ustar00rootroot00000000000000/* * Copyright (c) 2016-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_SOCKET_H #define __TEE_SOCKET_H #include struct tee_ioctl_param; #if defined(CFG_GP_SOCKETS) && CFG_GP_SOCKETS == 1 TEEC_Result tee_socket_process(size_t num_params, struct tee_ioctl_param *params); #else static inline TEEC_Result tee_socket_process(size_t num_params, struct tee_ioctl_param *params) { (void)num_params; (void)params; return TEEC_ERROR_NOT_SUPPORTED; } #endif #endif /*__SOCKET_H*/ optee_client-4.1.0/tee-supplicant/src/tee_supp_fs.c000066400000000000000000000406551455150071200224040ustar00rootroot00000000000000/* * 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 #include #include #include #include #include #include #include #include #ifndef __aligned #define __aligned(x) __attribute__((__aligned__(x))) #endif #include #ifndef PATH_MAX #define PATH_MAX 255 #endif /* Path to all secure storage files. */ static char tee_fs_root[PATH_MAX]; #define TEE_FS_FILENAME_MAX_LENGTH 150 static pthread_mutex_t dir_handle_db_mutex = PTHREAD_MUTEX_INITIALIZER; static struct handle_db dir_handle_db = HANDLE_DB_INITIALIZER_WITH_MUTEX(&dir_handle_db_mutex); static TEEC_Result errno_to_teec(int err) { switch (err) { case ENOSPC: return TEEC_ERROR_STORAGE_NO_SPACE; case ENOENT: return TEEC_ERROR_ITEM_NOT_FOUND; default: break; } return TEEC_ERROR_GENERIC; } static size_t tee_fs_get_absolute_filename(char *file, char *out, size_t out_size) { int s = 0; if (!file || !out || (out_size <= strlen(tee_fs_root) + 1)) return 0; s = snprintf(out, out_size, "%s%s", tee_fs_root, file); if (s < 0 || (size_t)s >= out_size) return 0; /* Safe to cast since we have checked that sizes are OK */ return (size_t)s; } static void fs_fsync(void) { int fd = 0; fd = open(tee_fs_root, O_RDONLY | O_DIRECTORY); if (fd > 0) { fsync(fd); close(fd); } } static int do_mkdir(const char *path, mode_t mode) { struct stat st; memset(&st, 0, sizeof(st)); if (mkdir(path, mode) != 0 && errno != EEXIST) return -1; if (stat(path, &st) != 0 && !S_ISDIR(st.st_mode)) return -1; fs_fsync(); return 0; } static int mkpath(const char *path, mode_t mode) { int status = 0; char *subpath = strdup(path); char *prev = subpath; char *curr = NULL; while (status == 0 && (curr = strchr(prev, '/')) != 0) { /* * Check for root or double slash */ if (curr != prev) { *curr = '\0'; status = do_mkdir(subpath, mode); *curr = '/'; } prev = curr + 1; } if (status == 0) status = do_mkdir(path, mode); free(subpath); return status; } static int tee_supp_fs_init(void) { size_t n = 0; mode_t mode = 0700; n = snprintf(tee_fs_root, sizeof(tee_fs_root), "%s/", supplicant_params.fs_parent_path); if (n >= sizeof(tee_fs_root)) return -1; if (mkpath(tee_fs_root, mode) != 0) return -1; return 0; } static int open_wrapper(const char *fname, int flags) { int fd = 0; while (true) { fd = open(fname, flags | O_SYNC, 0600); if (fd >= 0 || errno != EINTR) return fd; } } static TEEC_Result ree_fs_new_open(size_t num_params, struct tee_ioctl_param *params) { char abs_filename[PATH_MAX] = { 0 }; char *fname = NULL; int fd = 0; if (num_params != 3 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) return TEEC_ERROR_BAD_PARAMETERS; fname = tee_supp_param_to_va(params + 1); if (!fname) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(fname, abs_filename, sizeof(abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; fd = open_wrapper(abs_filename, O_RDWR); if (fd < 0) { /* * In case the problem is the filesystem is RO, retry with the * open flags restricted to RO. */ fd = open_wrapper(abs_filename, O_RDONLY); if (fd < 0) return TEEC_ERROR_ITEM_NOT_FOUND; } params[2].a = fd; return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_create(size_t num_params, struct tee_ioctl_param *params) { char abs_filename[PATH_MAX] = { 0 }; char abs_dir[PATH_MAX] = { 0 }; char *fname = NULL; char *d = NULL; int fd = 0; const int flags = O_RDWR | O_CREAT | O_TRUNC; if (num_params != 3 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) return TEEC_ERROR_BAD_PARAMETERS; fname = tee_supp_param_to_va(params + 1); if (!fname) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(fname, abs_filename, sizeof(abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; fd = open_wrapper(abs_filename, flags); if (fd >= 0) goto out; if (errno != ENOENT) return errno_to_teec(errno); /* Directory for file missing, try make to it */ strncpy(abs_dir, abs_filename, sizeof(abs_dir)); abs_dir[sizeof(abs_dir) - 1] = '\0'; d = dirname(abs_dir); if (!mkdir(d, 0700)) { int err = 0; fd = open_wrapper(abs_filename, flags); if (fd >= 0) goto out; /* * The directory was made but the file could still not be * created. */ err = errno; rmdir(d); return errno_to_teec(err); } if (errno != ENOENT) return errno_to_teec(errno); /* Parent directory for file missing, try to make it */ d = dirname(d); if (mkdir(d, 0700)) return errno_to_teec(errno); /* Try to make directory for file again */ strncpy(abs_dir, abs_filename, sizeof(abs_dir)); abs_dir[sizeof(abs_dir) - 1] = '\0'; d = dirname(abs_dir); if (mkdir(d, 0700)) { int err = errno; d = dirname(d); rmdir(d); return errno_to_teec(err); } fd = open_wrapper(abs_filename, flags); if (fd < 0) { int err = errno; rmdir(d); d = dirname(d); rmdir(d); return errno_to_teec(err); } out: fs_fsync(); params[2].a = fd; return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_close(size_t num_params, struct tee_ioctl_param *params) { int fd = 0; if (num_params != 1 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) return TEEC_ERROR_BAD_PARAMETERS; fd = params[0].b; while (close(fd)) { if (errno != EINTR) return errno_to_teec(errno); } return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_read(size_t num_params, struct tee_ioctl_param *params) { uint8_t *buf = NULL; size_t len = 0; off_t offs = 0; int fd = 0; ssize_t r = 0; size_t s = 0; if (num_params != 2 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) return TEEC_ERROR_BAD_PARAMETERS; fd = params[0].b; offs = params[0].c; buf = tee_supp_param_to_va(params + 1); if (!buf) return TEEC_ERROR_BAD_PARAMETERS; len = MEMREF_SIZE(params + 1); s = 0; r = -1; while (r && len) { r = pread(fd, buf, len, offs); if (r < 0) { if (errno == EINTR) continue; return errno_to_teec(errno); } assert((size_t)r <= len); buf += r; len -= r; offs += r; s += r; } MEMREF_SIZE(params + 1) = s; return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_write(size_t num_params, struct tee_ioctl_param *params) { uint8_t *buf = NULL; size_t len = 0; off_t offs = 0; int fd = 0; ssize_t r = 0; if (num_params != 2 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) return TEEC_ERROR_BAD_PARAMETERS; fd = params[0].b; offs = params[0].c; buf = tee_supp_param_to_va(params + 1); if (!buf) return TEEC_ERROR_BAD_PARAMETERS; len = MEMREF_SIZE(params + 1); while (len) { r = pwrite(fd, buf, len, offs); if (r < 0) { if (errno == EINTR) continue; return errno_to_teec(errno); } assert((size_t)r <= len); buf += r; len -= r; offs += r; } return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_truncate(size_t num_params, struct tee_ioctl_param *params) { size_t len = 0; int fd = 0; if (num_params != 1 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) return TEEC_ERROR_BAD_PARAMETERS; fd = params[0].b; len = params[0].c; while (ftruncate(fd, len)) { if (errno != EINTR) return errno_to_teec(errno); } return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_remove(size_t num_params, struct tee_ioctl_param *params) { char abs_filename[PATH_MAX] = { 0 }; char *fname = NULL; char *d = NULL; if (num_params != 2 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) return TEEC_ERROR_BAD_PARAMETERS; fname = tee_supp_param_to_va(params + 1); if (!fname) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(fname, abs_filename, sizeof(abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; if (unlink(abs_filename)) return errno_to_teec(errno); /* If a file is removed, maybe the directory can be removed to? */ d = dirname(abs_filename); if (!rmdir(d)) { /* * If the directory was removed, maybe the parent directory * can be removed too? */ d = dirname(d); rmdir(d); } return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_rename(size_t num_params, struct tee_ioctl_param *params) { char old_abs_filename[PATH_MAX] = { 0 }; char new_abs_filename[PATH_MAX] = { 0 }; char *old_fname = NULL; char *new_fname = NULL; bool overwrite = false; if (num_params != 3 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) return TEEC_ERROR_BAD_PARAMETERS; overwrite = !!params[0].b; old_fname = tee_supp_param_to_va(params + 1); if (!old_fname) return TEEC_ERROR_BAD_PARAMETERS; new_fname = tee_supp_param_to_va(params + 2); if (!new_fname) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(old_fname, old_abs_filename, sizeof(old_abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(new_fname, new_abs_filename, sizeof(new_abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; if (!overwrite) { struct stat st; if (!stat(new_abs_filename, &st)) return TEEC_ERROR_ACCESS_CONFLICT; } if (rename(old_abs_filename, new_abs_filename)) { if (errno == ENOENT) return TEEC_ERROR_ITEM_NOT_FOUND; } fs_fsync(); return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_opendir(size_t num_params, struct tee_ioctl_param *params) { char abs_filename[PATH_MAX] = { 0 }; char *fname = NULL; DIR *dir = NULL; int handle = 0; struct dirent *dent = NULL; bool empty = true; if (num_params != 3 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) return TEEC_ERROR_BAD_PARAMETERS; fname = tee_supp_param_to_va(params + 1); if (!fname) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_get_absolute_filename(fname, abs_filename, sizeof(abs_filename))) return TEEC_ERROR_BAD_PARAMETERS; dir = opendir(abs_filename); if (!dir) return TEEC_ERROR_ITEM_NOT_FOUND; /* * Ignore empty directories. Works around an issue when the * data path is mounted over NFS. Due to the way OP-TEE implements * TEE_CloseAndDeletePersistentObject1() currently, tee-supplicant * still has a file descriptor open to the file when it's removed in * ree_fs_new_remove(). In this case the NFS server may create a * temporary reference called .nfs????, and the rmdir() call fails * so that the TA directory is left over. Checking this special case * here avoids that TEE_StartPersistentObjectEnumerator() returns * TEE_SUCCESS when it should return TEEC_ERROR_ITEM_NOT_FOUND. * Test case: "xtest 6009 6010". */ while ((dent = readdir(dir))) { if (dent->d_name[0] == '.') continue; empty = false; break; } if (empty) { closedir(dir); return TEEC_ERROR_ITEM_NOT_FOUND; } rewinddir(dir); handle = handle_get(&dir_handle_db, dir); if (handle < 0) { closedir(dir); return TEEC_ERROR_OUT_OF_MEMORY; } params[2].a = handle; return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_closedir(size_t num_params, struct tee_ioctl_param *params) { DIR *dir = NULL; if (num_params != 1 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) return TEEC_ERROR_BAD_PARAMETERS; dir = handle_put(&dir_handle_db, params[0].b); if (!dir) return TEEC_ERROR_BAD_PARAMETERS; closedir(dir); return TEEC_SUCCESS; } static TEEC_Result ree_fs_new_readdir(size_t num_params, struct tee_ioctl_param *params) { DIR *dir = NULL; struct dirent *dirent = NULL; char *buf = NULL; size_t len = 0; size_t fname_len = 0; if (num_params != 2 || (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) return TEEC_ERROR_BAD_PARAMETERS; buf = tee_supp_param_to_va(params + 1); if (!buf) return TEEC_ERROR_BAD_PARAMETERS; len = MEMREF_SIZE(params + 1); dir = handle_lookup(&dir_handle_db, params[0].b); if (!dir) return TEEC_ERROR_BAD_PARAMETERS; while (true) { dirent = readdir(dir); if (!dirent) return TEEC_ERROR_ITEM_NOT_FOUND; if (dirent->d_name[0] != '.') break; } fname_len = strlen(dirent->d_name) + 1; MEMREF_SIZE(params + 1) = fname_len; if (fname_len > len) return TEEC_ERROR_SHORT_BUFFER; memcpy(buf, dirent->d_name, fname_len); return TEEC_SUCCESS; } TEEC_Result tee_supp_fs_process(size_t num_params, struct tee_ioctl_param *params) { if (!num_params || !tee_supp_param_is_value(params)) return TEEC_ERROR_BAD_PARAMETERS; if (!tee_fs_root[0]) { if (tee_supp_fs_init() != 0) { EMSG("error tee_supp_fs_init: failed to create %s/", tee_fs_root); memset(tee_fs_root, 0, sizeof(tee_fs_root)); return TEEC_ERROR_STORAGE_NOT_AVAILABLE; } } switch (params->a) { case OPTEE_MRF_OPEN: return ree_fs_new_open(num_params, params); case OPTEE_MRF_CREATE: return ree_fs_new_create(num_params, params); case OPTEE_MRF_CLOSE: return ree_fs_new_close(num_params, params); case OPTEE_MRF_READ: return ree_fs_new_read(num_params, params); case OPTEE_MRF_WRITE: return ree_fs_new_write(num_params, params); case OPTEE_MRF_TRUNCATE: return ree_fs_new_truncate(num_params, params); case OPTEE_MRF_REMOVE: return ree_fs_new_remove(num_params, params); case OPTEE_MRF_RENAME: return ree_fs_new_rename(num_params, params); case OPTEE_MRF_OPENDIR: return ree_fs_new_opendir(num_params, params); case OPTEE_MRF_CLOSEDIR: return ree_fs_new_closedir(num_params, params); case OPTEE_MRF_READDIR: return ree_fs_new_readdir(num_params, params); default: return TEEC_ERROR_BAD_PARAMETERS; } } optee_client-4.1.0/tee-supplicant/src/tee_supp_fs.h000066400000000000000000000030621455150071200224000ustar00rootroot00000000000000/* * 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 TEE_SUPP_FS_H #define TEE_SUPP_FS_H #include struct tee_ioctl_param; TEEC_Result tee_supp_fs_process(size_t num_params, struct tee_ioctl_param *params); #endif optee_client-4.1.0/tee-supplicant/src/tee_supplicant.c000066400000000000000000000537621455150071200231120ustar00rootroot00000000000000/* * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "optee_msg_supplicant.h" #ifndef __aligned #define __aligned(x) __attribute__((__aligned__(x))) #endif #include #define RPC_NUM_PARAMS 5 #define DEFAULT_TA_DIR "optee_armtz" #define RPC_BUF_SIZE (sizeof(struct tee_iocl_supp_send_arg) + \ RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param)) char **ta_path; union tee_rpc_invoke { uint64_t buf[(RPC_BUF_SIZE - 1) / sizeof(uint64_t) + 1]; struct tee_iocl_supp_recv_arg recv; struct tee_iocl_supp_send_arg send; }; struct tee_shm { int id; void *p; size_t size; bool registered; int fd; struct tee_shm *next; }; struct thread_arg { int fd; uint32_t gen_caps; bool abort; size_t num_waiters; pthread_mutex_t mutex; }; struct param_value { uint64_t a; uint64_t b; uint64_t c; }; static pthread_mutex_t shm_mutex = PTHREAD_MUTEX_INITIALIZER; static struct tee_shm *shm_head; struct tee_supplicant_params supplicant_params = { #ifdef TEE_PLUGIN_LOAD_PATH .plugin_load_path = TEE_PLUGIN_LOAD_PATH, #endif .fs_parent_path = TEE_FS_PARENT_PATH, }; static void *thread_main(void *a); static size_t num_waiters_inc(struct thread_arg *arg) { size_t ret = 0; tee_supp_mutex_lock(&arg->mutex); arg->num_waiters++; assert(arg->num_waiters); ret = arg->num_waiters; tee_supp_mutex_unlock(&arg->mutex); return ret; } static size_t num_waiters_dec(struct thread_arg *arg) { size_t ret = 0; tee_supp_mutex_lock(&arg->mutex); assert(arg->num_waiters); arg->num_waiters--; ret = arg->num_waiters; tee_supp_mutex_unlock(&arg->mutex); return ret; } static void *paged_aligned_alloc(size_t sz) { void *p = NULL; if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz)) return p; return NULL; } static int get_value(size_t num_params, struct tee_ioctl_param *params, const uint32_t idx, struct param_value **value) { if (idx >= num_params) return -1; switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: *value = (void *)¶ms[idx].a; return 0; default: return -1; } } static struct tee_shm *find_tshm(int id) { struct tee_shm *tshm = NULL; tee_supp_mutex_lock(&shm_mutex); tshm = shm_head; while (tshm && tshm->id != id) tshm = tshm->next; tee_supp_mutex_unlock(&shm_mutex); return tshm; } static struct tee_shm *pop_tshm(int id) { struct tee_shm *tshm = NULL; struct tee_shm *prev = NULL; tee_supp_mutex_lock(&shm_mutex); tshm = shm_head; if (!tshm) goto out; if (tshm->id == id) { shm_head = tshm->next; goto out; } do { prev = tshm; tshm = tshm->next; if (!tshm) goto out; } while (tshm->id != id); prev->next = tshm->next; out: tee_supp_mutex_unlock(&shm_mutex); return tshm; } static void push_tshm(struct tee_shm *tshm) { tee_supp_mutex_lock(&shm_mutex); tshm->next = shm_head; shm_head = tshm; tee_supp_mutex_unlock(&shm_mutex); } /* Get parameter allocated by secure world */ static int get_param(size_t num_params, struct tee_ioctl_param *params, const uint32_t idx, TEEC_SharedMemory *shm) { struct tee_shm *tshm = NULL; size_t offs = 0; size_t sz = 0; if (idx >= num_params) return -1; switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: break; default: return -1; } memset(shm, 0, sizeof(*shm)); tshm = find_tshm(MEMREF_SHM_ID(params + idx)); if (!tshm) { /* * It doesn't make sense to query required size of an * input buffer. */ if ((params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) == TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) return -1; /* * Buffer isn't found, the caller is querying required size * of the buffer. */ return 0; } sz = MEMREF_SIZE(params + idx); offs = MEMREF_SHM_OFFS(params + idx); if ((sz + offs) < sz) return -1; if ((sz + offs) > tshm->size) return -1; shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; shm->size = sz; shm->id = MEMREF_SHM_ID(params + idx); shm->buffer = (uint8_t *)tshm->p + offs; return 0; } static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN]) { d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; d->timeMid = (s[4] << 8) | s[5]; d->timeHiAndVersion = (s[6] << 8) | s[7]; memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); } static uint32_t load_ta(size_t num_params, struct tee_ioctl_param *params) { int ta_found = 0; size_t size = 0; struct param_value *val_cmd = NULL; TEEC_UUID uuid; TEEC_SharedMemory shm_ta; memset(&uuid, 0, sizeof(uuid)); memset(&shm_ta, 0, sizeof(shm_ta)); if (num_params != 2 || get_value(num_params, params, 0, &val_cmd) || get_param(num_params, params, 1, &shm_ta)) return TEEC_ERROR_BAD_PARAMETERS; uuid_from_octets(&uuid, (void *)val_cmd); size = shm_ta.size; ta_found = TEECI_LoadSecureModule(&uuid, shm_ta.buffer, &size); if (ta_found != TA_BINARY_FOUND) { EMSG(" TA not found"); return TEEC_ERROR_ITEM_NOT_FOUND; } MEMREF_SIZE(params + 1) = size; /* * If a buffer wasn't provided, just tell which size it should be. * If it was provided but isn't big enough, report an error. */ if (shm_ta.buffer && size > shm_ta.size) return TEEC_ERROR_SHORT_BUFFER; return TEEC_SUCCESS; } static struct tee_shm *alloc_shm(int fd, size_t size) { struct tee_shm *shm = NULL; struct tee_ioctl_shm_alloc_data data; memset(&data, 0, sizeof(data)); shm = calloc(1, sizeof(*shm)); if (!shm) return NULL; data.size = size; shm->fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data); if (shm->fd < 0) { free(shm); return NULL; } shm->p = mmap(NULL, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->fd, 0); if (shm->p == (void *)MAP_FAILED) { close(shm->fd); free(shm); return NULL; } shm->id = data.id; shm->registered = false; return shm; } static struct tee_shm *register_local_shm(int fd, size_t size) { struct tee_shm *shm = NULL; void *buf = NULL; struct tee_ioctl_shm_register_data data; memset(&data, 0, sizeof(data)); buf = paged_aligned_alloc(size); if (!buf) return NULL; shm = calloc(1, sizeof(*shm)); if (!shm) { free(buf); return NULL; } data.addr = (uintptr_t)buf; data.length = size; shm->fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data); if (shm->fd < 0) { free(shm); free(buf); return NULL; } shm->p = buf; shm->registered = true; shm->id = data.id; return shm; } static uint32_t process_alloc(struct thread_arg *arg, size_t num_params, struct tee_ioctl_param *params) { struct param_value *val = NULL; struct tee_shm *shm = NULL; if (num_params != 1 || get_value(num_params, params, 0, &val)) return TEEC_ERROR_BAD_PARAMETERS; if (arg->gen_caps & TEE_GEN_CAP_REG_MEM) shm = register_local_shm(arg->fd, val->b); else shm = alloc_shm(arg->fd, val->b); if (!shm) return TEEC_ERROR_OUT_OF_MEMORY; shm->size = val->b; val->c = shm->id; push_tshm(shm); return TEEC_SUCCESS; } static uint32_t process_free(size_t num_params, struct tee_ioctl_param *params) { struct param_value *val = NULL; struct tee_shm *shm = NULL; int id = 0; if (num_params != 1 || get_value(num_params, params, 0, &val)) return TEEC_ERROR_BAD_PARAMETERS; id = val->b; shm = pop_tshm(id); if (!shm) return TEEC_ERROR_BAD_PARAMETERS; close(shm->fd); if (shm->registered) { free(shm->p); } else { if (munmap(shm->p, shm->size) != 0) { EMSG("munmap(%p, %zu) failed - Error = %s", shm->p, shm->size, strerror(errno)); free(shm); return TEEC_ERROR_BAD_PARAMETERS; } } free(shm); return TEEC_SUCCESS; } /* How many device sequence numbers will be tried before giving up */ #define MAX_DEV_SEQ 10 static int open_dev(const char *devname, 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)) goto err; /* Only OP-TEE supported */ if (vers.impl_id != TEE_IMPL_ID_OPTEE) goto err; if (gen_caps) *gen_caps = vers.gen_caps; DMSG("using device \"%s\"", devname); return fd; err: close(fd); return -1; } static int get_dev_fd(uint32_t *gen_caps) { int fd = 0; char name[PATH_MAX] = { 0 }; size_t n = 0; for (n = 0; n < MAX_DEV_SEQ; n++) { snprintf(name, sizeof(name), "/dev/teepriv%zu", n); fd = open_dev(name, gen_caps); if (fd >= 0) return fd; } return -1; } static int usage(int status) { fprintf(stderr, "Usage: tee-supplicant [options] []\n"); fprintf(stderr, "\t-h, --help: this help\n"); fprintf(stderr, "\t-d, --daemonize: run as a daemon (fork and return " "after child has opened the TEE device or on error)\n"); fprintf(stderr, "\t-f, --fs-parent-path: secure fs parent path [%s]\n", supplicant_params.fs_parent_path); fprintf(stderr, "\t-l, --ta-path: TA load path\n"); fprintf(stderr, "\t-t, --ta-dir: TAs dirname under %s [%s]" " (deprecated, cannot be used with --ta-path)\n", TEEC_LOAD_PATH, DEFAULT_TA_DIR); fprintf(stderr, "\t-p, --plugin-path: plugin load path [%s]\n", supplicant_params.plugin_load_path); fprintf(stderr, "\t-r, --rpmb-cid: RPMB device identification register " "(CID) in hexadecimal\n"); return status; } static uint32_t process_rpmb(size_t num_params, struct tee_ioctl_param *params) { TEEC_SharedMemory req; TEEC_SharedMemory rsp; memset(&req, 0, sizeof(req)); memset(&rsp, 0, sizeof(rsp)); if (get_param(num_params, params, 0, &req) || get_param(num_params, params, 1, &rsp)) return TEEC_ERROR_BAD_PARAMETERS; return rpmb_process_request(req.buffer, req.size, rsp.buffer, rsp.size); } static bool read_request(int fd, union tee_rpc_invoke *request) { struct tee_ioctl_buf_data data; memset(&data, 0, sizeof(data)); data.buf_ptr = (uintptr_t)request; data.buf_len = sizeof(*request); if (ioctl(fd, TEE_IOC_SUPPL_RECV, &data)) { EMSG("TEE_IOC_SUPPL_RECV: %s", strerror(errno)); return false; } return true; } static bool write_response(int fd, union tee_rpc_invoke *request) { struct tee_ioctl_buf_data data; memset(&data, 0, sizeof(data)); data.buf_ptr = (uintptr_t)&request->send; data.buf_len = sizeof(struct tee_iocl_supp_send_arg) + sizeof(struct tee_ioctl_param) * (__u64)request->send.num_params; if (ioctl(fd, TEE_IOC_SUPPL_SEND, &data)) { EMSG("TEE_IOC_SUPPL_SEND: %s", strerror(errno)); return false; } return true; } static bool find_params(union tee_rpc_invoke *request, uint32_t *func, size_t *num_params, struct tee_ioctl_param **params, size_t *num_meta) { struct tee_ioctl_param *p = NULL; size_t n = 0; p = (struct tee_ioctl_param *)(&request->recv + 1); /* Skip meta parameters in the front */ for (n = 0; n < request->recv.num_params; n++) if (!(p[n].attr & TEE_IOCTL_PARAM_ATTR_META)) break; *func = request->recv.func; *num_params = request->recv.num_params - n; *params = p + n; *num_meta = n; /* Make sure that no meta parameters follows a non-meta parameter */ for (; n < request->recv.num_params; n++) { if (p[n].attr & TEE_IOCTL_PARAM_ATTR_META) { EMSG("Unexpected meta parameter"); return false; } } return true; } static bool spawn_thread(struct thread_arg *arg) { int e = 0; pthread_t tid; memset(&tid, 0, sizeof(tid)); DMSG("Spawning a new thread"); /* * Increase number of waiters now to avoid starting another thread * before this thread has been scheduled. */ num_waiters_inc(arg); e = pthread_create(&tid, NULL, thread_main, arg); if (e) { EMSG("pthread_create: %s", strerror(e)); num_waiters_dec(arg); return false; } e = pthread_detach(tid); if (e) EMSG("pthread_detach: %s", strerror(e)); return true; } static bool process_one_request(struct thread_arg *arg) { size_t num_params = 0; size_t num_meta = 0; struct tee_ioctl_param *params = NULL; uint32_t func = 0; uint32_t ret = 0; union tee_rpc_invoke request; memset(&request, 0, sizeof(request)); DMSG("looping"); request.recv.num_params = RPC_NUM_PARAMS; /* Let it be known that we can deal with meta parameters */ params = (struct tee_ioctl_param *)(&request.send + 1); params->attr = TEE_IOCTL_PARAM_ATTR_META; num_waiters_inc(arg); if (!read_request(arg->fd, &request)) return false; if (!find_params(&request, &func, &num_params, ¶ms, &num_meta)) return false; if (num_meta && !num_waiters_dec(arg) && !spawn_thread(arg)) return false; switch (func) { case OPTEE_MSG_RPC_CMD_LOAD_TA: ret = load_ta(num_params, params); break; case OPTEE_MSG_RPC_CMD_FS: ret = tee_supp_fs_process(num_params, params); break; case OPTEE_MSG_RPC_CMD_RPMB: ret = process_rpmb(num_params, params); break; case OPTEE_MSG_RPC_CMD_SHM_ALLOC: ret = process_alloc(arg, num_params, params); break; case OPTEE_MSG_RPC_CMD_SHM_FREE: ret = process_free(num_params, params); break; case OPTEE_MSG_RPC_CMD_GPROF: ret = prof_process(num_params, params, "gmon-"); break; case OPTEE_MSG_RPC_CMD_SOCKET: ret = tee_socket_process(num_params, params); break; case OPTEE_MSG_RPC_CMD_FTRACE: ret = prof_process(num_params, params, "ftrace-"); break; case OPTEE_MSG_RPC_CMD_PLUGIN: ret = plugin_process(num_params, params); break; default: EMSG("Cmd [0x%" PRIx32 "] not supported", func); /* Not supported. */ ret = TEEC_ERROR_NOT_SUPPORTED; break; } request.send.ret = ret; return write_response(arg->fd, &request); } static void *thread_main(void *a) { struct thread_arg *arg = a; /* * Now that this thread has been scheduled, compensate for the * initial increase in spawn_thread() before. */ num_waiters_dec(arg); while (!arg->abort) { if (!process_one_request(arg)) arg->abort = true; } return NULL; } static void set_ta_path(void) { char *ta_path_str = NULL; char *p = NULL; char *saveptr = NULL; char *new_path = NULL; size_t n = 0; const char *path = supplicant_params.ta_load_path; int path_len = -1; if (!path) path = TEEC_LOAD_PATH; ta_path_str = strdup(path); if (!ta_path_str) goto err; p = ta_path_str; while (strtok_r(p, ":", &saveptr)) { p = NULL; n++; } n++; /* NULL terminator */ ta_path = malloc(n * sizeof(char *)); if (!ta_path) goto err; n = 0; strcpy(ta_path_str, path); p = ta_path_str; while ((new_path = strtok_r(p, ":", &saveptr))) { if (!supplicant_params.ta_load_path) { char full_path[PATH_MAX] = { 0 }; path_len = snprintf(full_path, PATH_MAX, "%s/%s", new_path, supplicant_params.ta_dir); if (path_len < 0 || path_len >= PATH_MAX) goto err_path; ta_path[n++] = strdup(full_path); } else { path_len = strnlen(new_path, PATH_MAX); if (path_len == PATH_MAX) goto err_path; ta_path[n++] = strdup(new_path); } p = NULL; } free(ta_path_str); return; err: EMSG("out of memory"); exit(EXIT_FAILURE); err_path: EMSG("Path exceeds maximum path length"); exit(EXIT_FAILURE); } /* * Similar to the standard libc function daemon(0, 0) but the parent process * issues a blocking read on pipefd[0] before exiting. * Returns 0 on success, <0 on error. */ static int make_daemon(int pipefd[2]) { int fd = 0; char c = 0; int n = 0; switch (fork()) { case -1: return -1; case 0: /* In child */ close(pipefd[0]); break; default: /* In parent */ close(pipefd[1]); n = read(pipefd[0], &c, 1); close(pipefd[0]); if (!n) { /* * Nothing has been read: child has closed without * writing (either exited on error or crashed) */ return -1; } /* Child is done with the opening of the TEE device */ _exit(EXIT_SUCCESS); } if (setsid() < 0) return -2; if (chdir("/") < 0) return -3; fd = open("/dev/null", O_RDWR); if (fd < 0) return -4; dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); return 0; } int main(int argc, char *argv[]) { struct thread_arg arg = { .fd = -1 }; int pipefd[2] = { 0, }; bool daemonize = false; char *dev = NULL; int e = 0; int long_index = 0; int opt = 0; e = pthread_mutex_init(&arg.mutex, NULL); if (e) { EMSG("pthread_mutex_init: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } static struct option long_options[] = { /* long name | has argument | flag | short value */ { "help", no_argument, 0, 'h' }, { "daemonize", no_argument, 0, 'd' }, { "fs-parent-path", required_argument, 0, 'f' }, { "ta-path", required_argument, 0, 'l' }, { "ta-dir", required_argument, 0, 't' }, { "plugin-path", required_argument, 0, 'p' }, { "rpmb-cid", required_argument, 0, 'r' }, { 0, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "hdf:l:t:p:r:", long_options, &long_index )) != -1) { switch (opt) { case 'h' : return usage(EXIT_SUCCESS); break; case 'd': daemonize = true; break; case 'f': supplicant_params.fs_parent_path = optarg; break; case 'l': supplicant_params.ta_load_path = optarg; break; case 't': supplicant_params.ta_dir = optarg; break; case 'p': supplicant_params.plugin_load_path = optarg; break; case 'r': supplicant_params.rpmb_cid = optarg; break; default: return usage(EXIT_FAILURE); } } /* check for non option argument, which is device name */ if (argv[optind]) { fprintf(stderr, "Using device %s.\n", argv[optind]); dev = argv[optind]; /* check that we do not have too many arguments */ if (argv[optind + 1]) { fprintf(stderr, "Too many arguments passed: extra argument: %s.\n", argv[optind+1]); return usage(EXIT_FAILURE); } } if (!supplicant_params.ta_dir && !supplicant_params.ta_load_path) { supplicant_params.ta_dir = DEFAULT_TA_DIR; } else if (supplicant_params.ta_dir && supplicant_params.ta_load_path) { fprintf(stderr, "Cannot use --ta-path and --ta-dir at the same time\n"); return usage(EXIT_FAILURE); } set_ta_path(); if (plugin_load_all() != 0) { EMSG("failed to load plugins"); exit(EXIT_FAILURE); } if (daemonize) { if (pipe(pipefd) < 0) { EMSG("pipe(): %s", strerror(errno)); exit(EXIT_FAILURE); } e = make_daemon(pipefd); if (e < 0) { EMSG("make_daemon(): %d", e); exit(EXIT_FAILURE); } } if (dev) { arg.fd = open_dev(dev, &arg.gen_caps); if (arg.fd < 0) { EMSG("failed to open \"%s\"", argv[1]); exit(EXIT_FAILURE); } } else { arg.fd = get_dev_fd(&arg.gen_caps); if (arg.fd < 0) { EMSG("failed to find an OP-TEE supplicant device"); exit(EXIT_FAILURE); } } if (daemonize) { /* Release parent */ if (write(pipefd[1], "", 1) != 1) { EMSG("write(): %s", strerror(errno)); exit(EXIT_FAILURE); } close(pipefd[1]); } while (!arg.abort) { if (!process_one_request(&arg)) arg.abort = true; } close(arg.fd); return EXIT_FAILURE; } bool tee_supp_param_is_memref(struct tee_ioctl_param *param) { switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: return true; default: return false; } } bool tee_supp_param_is_value(struct tee_ioctl_param *param) { switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: return true; default: return false; } } void *tee_supp_param_to_va(struct tee_ioctl_param *param) { struct tee_shm *tshm = NULL; size_t end_offs = 0; if (!tee_supp_param_is_memref(param)) return NULL; end_offs = MEMREF_SIZE(param) + MEMREF_SHM_OFFS(param); if (end_offs < MEMREF_SIZE(param) || end_offs < MEMREF_SHM_OFFS(param)) return NULL; tshm = find_tshm(MEMREF_SHM_ID(param)); if (!tshm) return NULL; if (end_offs > tshm->size) return NULL; return (uint8_t *)tshm->p + MEMREF_SHM_OFFS(param); } void tee_supp_mutex_lock(pthread_mutex_t *mu) { int e = pthread_mutex_lock(mu); if (e) { EMSG("pthread_mutex_lock: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } } void tee_supp_mutex_unlock(pthread_mutex_t *mu) { int e = pthread_mutex_unlock(mu); if (e) { EMSG("pthread_mutex_unlock: %s", strerror(e)); EMSG("terminating..."); exit(EXIT_FAILURE); } } optee_client-4.1.0/tee-supplicant/src/tee_supplicant.h000066400000000000000000000043751455150071200231130ustar00rootroot00000000000000/* * Copyright (c) 2016, Linaro Limited * 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 TEE_SUPPLICANT_H #define TEE_SUPPLICANT_H #include #include /* 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) struct tee_ioctl_param; /* Global tee-supplicant parameters */ struct tee_supplicant_params { const char *ta_dir; const char *ta_load_path; const char *plugin_load_path; const char *fs_parent_path; const char *rpmb_cid; }; extern struct tee_supplicant_params supplicant_params; bool tee_supp_param_is_memref(struct tee_ioctl_param *param); bool tee_supp_param_is_value(struct tee_ioctl_param *param); void *tee_supp_param_to_va(struct tee_ioctl_param *param); void tee_supp_mutex_lock(pthread_mutex_t *mu); void tee_supp_mutex_unlock(pthread_mutex_t *mu); #endif /*TEE_SUPPLICANT_H*/ optee_client-4.1.0/tee-supplicant/src/teec_ta_load.c000066400000000000000000000116401455150071200224630ustar00rootroot00000000000000/* * 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 #include #ifndef PATH_MAX #define PATH_MAX 255 #endif struct tee_rpc_cmd { void *buffer; uint32_t size; uint32_t type; int fd; }; /* * Based on the uuid this function will try to find a TA-binary on the * filesystem and return it back to the caller in the parameter ta. * * @param: ta_load_path Where to load the TA from. The full path to the TA * binary is @ta_load_path/@destination.ta. * @param: destination The uuid of the TA we are searching for. * @param: ta A pointer which this function will allocate and copy * the TA from the filesystem to the pointer itself. It is * the callers responsibility to free the pointer. * @param: ta_size The size of the TA found on file system. It will be 0 * if no TA was not found. * * @return 0 if TA was found, otherwise -1. */ static int try_load_secure_module(const char *ta_load_path, const TEEC_UUID *destination, void *ta, size_t *ta_size) { char fname[PATH_MAX] = { 0 }; FILE *file = NULL; bool first_try = true; size_t s = 0; long l = 0; int n = 0; if (!ta_size || !destination) { DMSG("wrong inparameter to TEECI_LoadSecureModule"); return TA_BINARY_NOT_FOUND; } /* * We expect the TA binary to be named after the UUID as per RFC4122, * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta * If the file cannot be open, try the deprecated format: * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta */ again: n = snprintf(fname, PATH_MAX, "%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta", ta_load_path, destination->timeLow, destination->timeMid, destination->timeHiAndVersion, destination->clockSeqAndNode[0], destination->clockSeqAndNode[1], first_try ? "-" : "", destination->clockSeqAndNode[2], destination->clockSeqAndNode[3], destination->clockSeqAndNode[4], destination->clockSeqAndNode[5], destination->clockSeqAndNode[6], destination->clockSeqAndNode[7]); DMSG("Attempt to load %s", fname); if ((n < 0) || (n >= PATH_MAX)) { EMSG("wrong TA path [%s]", fname); return TA_BINARY_NOT_FOUND; } file = fopen(fname, "r"); if (file == NULL) { DMSG("failed to open the ta %s TA-file", fname); if (first_try) { first_try = false; goto again; } return TA_BINARY_NOT_FOUND; } if (fseek(file, 0, SEEK_END) != 0) { fclose(file); return TA_BINARY_NOT_FOUND; } l = ftell(file); if (l < 0) { DMSG("failed to ftell the ta %s TA-file", fname); fclose(file); return TA_BINARY_NOT_FOUND; } s = l; if (s > *ta_size || !ta) { /* * Buffer isn't large enough, return the required size to * let the caller increase the size of the buffer and try * again. */ goto out; } if (fseek(file, 0, SEEK_SET) != 0) { fclose(file); return TA_BINARY_NOT_FOUND; } if (s != fread(ta, 1, s, file)) { DMSG("failed to fread the ta %s TA-file", fname); fclose(file); return TA_BINARY_NOT_FOUND; } out: *ta_size = s; fclose(file); return TA_BINARY_FOUND; } int TEECI_LoadSecureModule(const TEEC_UUID *destination, void *ta, size_t *ta_size) { int res = TA_BINARY_NOT_FOUND; char **path = NULL; for (path = ta_path; *path; path++) { res = try_load_secure_module(*path, destination, ta, ta_size); if (res == TA_BINARY_FOUND) break; } return res; } optee_client-4.1.0/tee-supplicant/src/teec_ta_load.h000066400000000000000000000043201455150071200224650ustar00rootroot00000000000000/* * 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_TA_LOAD_H #define _TEEC_TA_LOAD_H #include #define TA_BINARY_FOUND 0 #define TA_BINARY_NOT_FOUND -1 /* NULL-terminated list of paths */ extern char **ta_path; /** * Based on the uuid this function will try to find a TA-binary on the * filesystem and return it back to the caller in the parameter ta. * * @param: destination The uuid of the TA we are searching for. * @param: ta A pointer which this function will copy * the TA from the filesystem to if *@ta_size i large * enough. * @param: ta_size The size of the TA found on file system. It will be 0 * if no TA was not found. * * @return 0 if TA was found, otherwise -1. */ int TEECI_LoadSecureModule(const TEEC_UUID *destination, void *ta, size_t *ta_size); #endif optee_client-4.1.0/tee-supplicant/tee_supplicant_android.mk000066400000000000000000000033441455150071200241770ustar00rootroot00000000000000################################################################################ # Build tee supplicant # ################################################################################ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS += $(optee_CFLAGS) LOCAL_CFLAGS += -DDEBUGLEVEL_$(CFG_TEE_SUPP_LOG_LEVEL) \ -DBINARY_PREFIX=\"TEES\" \ -DTEE_FS_PARENT_PATH=\"$(CFG_TEE_FS_PARENT_PATH)\" \ -DTEEC_LOAD_PATH=\"$(CFG_TEE_CLIENT_LOAD_PATH)\" LOCAL_SRC_FILES += src/tee_supplicant.c \ src/teec_ta_load.c \ src/tee_supp_fs.c \ src/rpmb.c \ src/handle.c ifeq ($(CFG_GP_SOCKETS),y) LOCAL_SRC_FILES += src/tee_socket.c LOCAL_CFLAGS += -DCFG_GP_SOCKETS=1 endif RPMB_EMU ?= 1 ifeq ($(RPMB_EMU),1) LOCAL_SRC_FILES += src/sha2.c src/hmac_sha2.c LOCAL_CFLAGS += -DRPMB_EMU=1 endif ifneq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) LOCAL_SRC_FILES += src/prof.c endif ifeq ($(CFG_TA_GPROF_SUPPORT),y) LOCAL_CFLAGS += -DCFG_TA_GPROF_SUPPORT endif ifeq ($(CFG_TEE_SUPP_PLUGINS),y) LOCAL_SRC_FILES += src/plugin.c LOCAL_CFLAGS += -DTEE_SUPP_PLUGINS \ -DTEE_PLUGIN_LOAD_PATH=\"$(CFG_TEE_PLUGIN_LOAD_PATH)\" # Needed to dynamically load user plugins LOCAL_LDFLAGS += -ldl # Needed for dlopen() LOCAL_LDFLAGS += -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) endif LOCAL_CFLAGS += -pthread ifeq ($(CFG_FTRACE_SUPPORT),y) LOCAL_CFLAGS += -DCFG_FTRACE_SUPPORT endif LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libteec/src \ $(LOCAL_PATH)/../libteec/include \ $(LOCAL_PATH)/src LOCAL_SHARED_LIBRARIES := libteec LOCAL_MODULE := tee-supplicant LOCAL_MODULE_TAGS := optional LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) optee_client-4.1.0/typedefs.checkpatch000066400000000000000000000024631455150071200200350ustar00rootroot00000000000000# Note: please keep the entries in this file sorted in reverse alphabetical # order (sort -r) TEEC_Result TEEC_Context TEEC_UUID TEEC_SharedMemory TEEC_TempMemoryReference TEEC_RegisteredMemoryReference TEEC_Value TEEC_Parameter TEEC_Session TEEC_Operation CK_VOID_PTR_PTR CK_VOID_PTR CK_VERSION_PTR CK_VERSION CK_UTF8CHAR_PTR CK_UTF8CHAR CK_USER_TYPE CK_UNLOCKMUTEX CK_ULONG_PTR CK_ULONG CK_TOKEN_INFO_PTR CK_TOKEN_INFO CK_STATE CK_SLOT_INFO_PTR CK_SLOT_INFO CK_SLOT_ID_PTR CK_SLOT_ID CK_SESSION_INFO_PTR CK_SESSION_INFO CK_SESSION_HANDLE_PTR CK_SESSION_HANDLE CK_RV CK_OBJECT_HANDLE_PTR CK_OBJECT_HANDLE CK_OBJECT_CLASS_PTR CK_OBJECT_CLASS CK_NOTIFY CK_NOTIFICATION CK_MECHANISM_TYPE_PTR CK_MECHANISM_TYPE CK_MECHANISM_PTR CK_MECHANISM_INFO_PTR CK_MECHANISM_INFO CK_MECHANISM CK_MAC_GENERAL_PARAMS_PTR CK_MAC_GENERAL_PARAMS CK_LONG CK_LOCKMUTEX CK_KEY_TYPE_PTR CK_KEY_TYPE CK_INFO_PTR CK_INFO CK_GCM_PARAMS_PTR CK_GCM_PARAMS CK_FUNCTION_LIST_PTR_PTR CK_FUNCTION_LIST_PTR CK_FUNCTION_LIST CK_FLAGS CK_DESTROYMUTEX CK_DATE_PTR CK_DATE CK_CREATEMUTEX CK_C_INITIALIZE_ARGS_PTR CK_C_INITIALIZE_ARGS CK_CHAR_PTR CK_CHAR CK_CCM_PARAMS_PTR CK_CCM_PARAMS CK_BYTE_PTR CK_BYTE CK_BBOOL CK_ATTRIBUTE_TYPE CK_ATTRIBUTE_PTR CK_ATTRIBUTE CK_AES_CTR_PARAMS_PTR CK_AES_CTR_PARAMS CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS