Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libptateec: manufacturing protection PTA #352

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ if(WITH_TEEACL)
add_subdirectory (libteeacl)
endif(WITH_TEEACL)
add_subdirectory (libseteec)
add_subdirectory (libptateec)
16 changes: 13 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ includedir ?= $(INCLUDEDIR)
WITH_TEEACL ?= 1

.PHONY: all build build-libteec build-libckteec build-libseteec \
build-libteeacl install copy_export clean cscope \
build-libteeacl built-libptateec install copy_export clean cscope \
clean-cscope \
checkpatch-pre-req checkpatch-modified-patch checkpatch-modified-file \
checkpatch-last-commit-patch checkpatch-last-commit-file \
Expand All @@ -40,7 +40,7 @@ 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
build: build-libteec build-tee-supplicant build-libckteec build-libseteec build-libptateec
ifeq ($(WITH_TEEACL),1)
build: build-libteeacl
endif
Expand All @@ -57,10 +57,14 @@ build-libteeacl:
@echo "Building libteeacl.so"
@$(MAKE) --directory=libteeacl --no-print-directory --no-builtin-variables

build-libptateec: build-libteec
@echo "Building libptateec.so"
@$(MAKE) --directory=libptateec --no-print-directory --no-builtin-variables

install: copy_export

clean: clean-libteec clean-tee-supplicant clean-cscope clean-libckteec \
clean-libseteec
clean-libseteec clean-libptateec
ifeq ($(WITH_TEEACL),1)
clean: clean-libteeacl
endif
Expand All @@ -80,6 +84,9 @@ clean-libseteec:
clean-libteeacl:
@$(MAKE) --directory=libteeacl --no-print-directory clean

clean-libptateec:
@$(MAKE) --directory=libptateec --no-print-directory clean

cscope:
@echo " CSCOPE"
${VPREFIX}find ${CURDIR} -name "*.[chsS]" > cscope.files
Expand Down Expand Up @@ -172,3 +179,6 @@ endif
cp libseteec/include/*.h $(DESTDIR)$(includedir)
cp -d ${O}/libseteec/libseteec.so* $(DESTDIR)$(libdir)
cp -d ${O}/libseteec/libseteec.a $(DESTDIR)$(libdir)
cp libptateec/include/*.h $(DESTDIR)$(INCLUDEDIR)
cp -d ${O}/libptateec/libptateec.so* $(DESTDIR)$(LIBDIR)
cp -d ${O}/libptateec/libptateec.a $(DESTDIR)$(LIBDIR)
66 changes: 66 additions & 0 deletions libptateec/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
project(ptateec
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/pta.c
src/pta_imx_manufacturing_protection.c
)

################################################################################
# Built library
################################################################################
add_library (ptateec ${SRC})

set_target_properties (ptateec PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)

################################################################################
# Flags always set
################################################################################
target_compile_definitions (ptateec
PRIVATE -D_GNU_SOURCE
PRIVATE -DBINARY_PREFIX="LT"
)

################################################################################
# Optional flags
################################################################################

################################################################################
# Public and private header and library dependencies
################################################################################
target_include_directories(ptateec
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE src
)

target_link_libraries (ptateec
PRIVATE pthread
PRIVATE teec
)

################################################################################
# Install targets
################################################################################
install (TARGETS ptateec
DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

add_subdirectory(include)
71 changes: 71 additions & 0 deletions libptateec/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
include ../flags.mk
include ../config.mk

OUT_DIR := $(OO)/libptateec

.PHONY: all libptateec clean

all: libptateec
install: libptateec

LIB_NAME := libptateec
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)
LIBPTATEEC_SO_LIBRARY := $(LIB_MAJ_MIN_PAT)
LIBPTATEEC_AR_LIBRARY := $(LIB_NAME).a

LIBPTATEEC_SRC_DIR := src

LIBPTATEEC_SRCS = pta.c \
pta_imx_manufacturing_protection.c

LIBPTATEEC_INCLUDES = ${CURDIR}/include
LIBPTATEEC_INCLUDES += ${CURDIR}/../public

LIBPTATEEC_CFLAGS := $(addprefix -I, $(LIBPTATEEC_INCLUDES)) \
$(CFLAGS) -D_GNU_SOURCE -fPIC

LIBPTATEEC_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec -lpthread

LIBPTATEEC_OBJ_DIR := $(OUT_DIR)
LIBPTATEEC_OBJS := $(patsubst %.c,$(LIBPTATEEC_OBJ_DIR)/%.o, $(LIBPTATEEC_SRCS))

$(LIBPTATEEC_OBJ_DIR)/%.o: ${LIBPTATEEC_SRC_DIR}/%.c
$(VPREFIX)mkdir -p $(LIBPTATEEC_OBJ_DIR)
@echo " CC $<"
$(VPREFIX)$(CC) $(LIBPTATEEC_CFLAGS) -c $< -o $@

libptateec: $(OUT_DIR)/$(LIBPTATEEC_SO_LIBRARY)

$(OUT_DIR)/$(LIBPTATEEC_SO_LIBRARY): $(LIBPTATEEC_OBJS)
@echo " LINK $@"
$(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(LIBPTATEEC_LFLAGS)
@echo ""

libptateec: $(OUT_DIR)/$(LIBPTATEEC_AR_LIBRARY)

$(OUT_DIR)/$(LIBPTATEEC_AR_LIBRARY): $(LIBPTATEEC_OBJS)
@echo " AR $@"
$(VPREFIX)$(AR) rcs $@ $+

libptateec:
$(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) $(LIBPTATEEC_OBJS)
$(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT)
$(RM) $(OUT_DIR)/$(LIB_MAJ_MIN)
$(RM) $(OUT_DIR)/$(LIB_MAJOR)
$(RM) $(OUT_DIR)/$(LIBPTATEEC_SO_LIBRARY)
$(RM) $(OUT_DIR)/$(LIBPTATEEC_AR_LIBRARY)
$(call rmdir,$(OUT_DIR))
7 changes: 7 additions & 0 deletions libptateec/include/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project (libptateec-headers C)

FILE(GLOB INSTALL_HEADERS "*.h")

add_library(${PROJECT_NAME} INTERFACE)

install (FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
81 changes: 81 additions & 0 deletions libptateec/include/pta_tee.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2023, Foundries.io
*/

#ifndef PTA_TEE_H
#define PTA_TEE_H

#include <tee_client_api.h>
#include <unistd.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* pta_imx_mprotect_get_key() - Retrieves the iMX CAAM Manufacturing Protection
* EC public key. The components x,y are retrieved in RAW format and should
* be converted to DER or PEM as required.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you describe the arguments?

* For the 256 bit curve, this will generate two 32 byte components therefore
* requiring at least a 64 byte buffer.
*
* @key: [out] Public key in RAW format.
* @len: [in/out] Key length in bytes.
*
* @return TEEC_ERROR_BAD_PARAMETERS Invalid parameters provided on input.
* @return TEEC_ERROR_ACCESS_DENIED Error opening the TEE session.
* @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion.
* @return TEEC_ERROR_GENERIC Error unspecified.
* @return TEEC_ERROR_SHORT_BUFFER Error small buffer provided.
* @return TEEC_ERROR_COMMUNICATION Some other thread closed the connection.
* @return TEEC_SUCCESS On success.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add TEE_ERROR_OUT_OF_MEMORY
ditto for pta_imx_mprotect_sign().

*
*/
TEEC_Result pta_imx_mprotect_get_key(char *key, size_t *len);

/**
* pta_imx_mprotect_sign() - Signs a message using the Manufacturing Protection
* EC private key.
*
* This function takes message data as input and outputs a signature over a
* message composed of the content of the MPMR, followed by the input-data
* message.
*
* @message: [in] Message to sign.
* @mlen: [in] Message length in bytes.
* @signature: [out] Generated signature.
* @slen: [in/out] Signature length in bytes.
* @mpmr: [out] MPMR data.
* @len: [in/out] MPMR length in bytes.
*
* @return TEEC_ERROR_BAD_PARAMETERS Invalid parameters provided on input.
* @return TEEC_ERROR_ACCESS_DENIED Error opening the TEE session.
* @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion.
* @return TEEC_ERROR_GENERIC Error unspecified.
* @return TEEC_ERROR_COMMUNICATION Some other thread closed the connection.
* @return TEEC_ERROR_SHORT_BUFFER Error small buffer provided.
* @return TEEC_SUCCESS On success.
*
*/
TEEC_Result pta_imx_mprotect_sign(char *message, size_t mlen, char *signature,
size_t *slen, char *mpmr, size_t *len);

/**
* pta_imx_mprotect_final() - Closes the OP-TEE session
*
* This function may fail with TEEC_ERROR_BUSY if there are unfulfilled calls
* pending.
*
* @return TEEC_ERROR_BUSY PTA is still in use.
* @return TEEC_SUCCESS On success.
*
*/
TEEC_Result pta_imx_mprotect_final(void);

#ifdef __cplusplus
}
#endif

#endif /*PTA_TEE_H*/
73 changes: 73 additions & 0 deletions libptateec/src/pta.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2023, Foundries.io Ltd
*/

#ifndef BINARY_PREFIX
#define BINARY_PREFIX "ptateec"
#endif

#include "pta.h"

TEEC_Result pta_open_session(struct pta_context *ctx)
{
TEEC_Result ret = TEEC_SUCCESS;

pthread_mutex_lock(&ctx->lock);
if (!ctx->open) {
ret = TEEC_InitializeContext(NULL, &ctx->context);
if (!ret) {
ret = TEEC_OpenSession(&ctx->context, &ctx->session,
&ctx->uuid, TEEC_LOGIN_PUBLIC,
NULL, NULL, NULL);
if (!ret)
ctx->open = true;
}
}
if (ctx->open)
atomic_fetch_add(&ctx->count, 1);
pthread_mutex_unlock(&ctx->lock);

return ret;
}

TEEC_Result pta_invoke_cmd(struct pta_context *ctx, uint32_t cmd_id,
TEEC_Operation *op, uint32_t *error_origin)
{
TEEC_Result ret = TEEC_SUCCESS;

pthread_mutex_lock(&ctx->lock);
if (!ctx->open) {
atomic_store(&ctx->count, 0);
pthread_mutex_unlock(&ctx->lock);

return TEEC_ERROR_COMMUNICATION;
}
pthread_mutex_unlock(&ctx->lock);
ret = TEEC_InvokeCommand(&ctx->session, cmd_id, op, error_origin);
atomic_fetch_sub(&ctx->count, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means 1 call to pta_open_session() must be balanced by a call to pta_invoke_cmd().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, I think there is no need to have 2 functions. A single call to pta_invoke_cmd() should be is sufficient to open the context session and invoke a PTA. It's a bit strange of a PTA API to require a call to open_session for each calls to invoke_command.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think it's a bit weird that a generic PTA invocation API requires each call to pta_open_session() be always followed by a single call to pta_invoke_cmd().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this session handling is a bit more complicated than needed with mutex and reference counter. Couldn't we skip it all and rely on the normal TEE Client primitives?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO being capable of rejecting a close request coming from some separate thread because an invoke is about to follow is a nice feature to have (it really only costs the mutex and reference counter and it has no impact on performance).

But sure I can remove it if you think it adds too much maintenance noise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove it then.


return ret;
}

TEEC_Result pta_final(struct pta_context *ctx)
{
TEEC_Result ret = TEEC_SUCCESS;

pthread_mutex_lock(&ctx->lock);
if (!ctx->open) {
pthread_mutex_unlock(&ctx->lock);
return TEEC_SUCCESS;
}

if (atomic_load(&ctx->count)) {
ret = TEEC_ERROR_BUSY;
} else {
TEEC_CloseSession(&ctx->session);
TEEC_FinalizeContext(&ctx->context);
ctx->open = false;
}
pthread_mutex_unlock(&ctx->lock);

return ret;
}
Loading