Henry Case 3 лет назад
committed by Kris Kwiatkowski
Родитель
Сommit
71733d10fb
33 измененных файлов: 1983 добавлений и 235 удалений
  1. +3
    -0
      .gitmodules
  2. +1
    -0
      3rd/gbench
  3. +8
    -6
      3rd/openssl-cmake/CMakeLists.txt
  4. +110
    -48
      CMakeLists.txt
  5. +9
    -0
      README.md
  6. +1
    -0
      cfg/certs/10e22dbc.0
  7. +13
    -0
      cfg/certs/ca.cert
  8. +8
    -0
      cfg/certs/ca.key
  9. +1
    -0
      cfg/certs/ca.srl
  10. +14
    -0
      cfg/certs/client.cert
  11. +7
    -0
      cfg/certs/client.csr
  12. +8
    -0
      cfg/certs/client.key
  13. +1
    -0
      cfg/certs/f40a0c39.0
  14. +18
    -0
      cfg/certs/server.cert
  15. +8
    -0
      cfg/certs/server.csr
  16. +8
    -0
      cfg/certs/server.key
  17. +83
    -0
      cfg/create_certs.sh
  18. +137
    -0
      cfg/openssl.cnf
  19. +366
    -0
      cfg/openssl_optee.cnf
  20. +22
    -0
      cfg/openvpn_cli.conf
  21. +19
    -0
      cfg/openvpn_srv.conf
  22. +33
    -0
      optee-patches/0001-openvpn-2.4.9-to-2.5.0.patch
  23. +47
    -0
      optee-patches/0002_build_enable_openvpn.patch
  24. +271
    -148
      src/optee_engine/back.c
  25. +5
    -5
      src/optee_engine/back.h
  26. +4
    -10
      src/optee_engine/front.c
  27. +243
    -0
      src/optee_engine/keymgnt.c
  28. +101
    -0
      src/optee_engine/speed.cc
  29. +1
    -18
      src/optee_engine/utils.h
  30. +19
    -0
      src/ta/Makefile
  31. +345
    -0
      src/ta/delegator_tz.c
  32. +67
    -0
      src/ta/include/user_ta_header_defines.h
  33. +2
    -0
      src/ta/sub.mk

+ 3
- 0
.gitmodules Просмотреть файл

@@ -4,3 +4,6 @@
[submodule "3rd/openssl"]
path = 3rd/openssl
url = https://github.com/openssl/openssl.git
[submodule "3rd/gbench"]
path = 3rd/gbench
url = git@github.com:henrydcase/benchmark.git

+ 1
- 0
3rd/gbench

@@ -0,0 +1 @@
Subproject commit 048ddbb65d00a923d09be7e18616c09ac7153c29

+ 8
- 6
3rd/openssl-cmake/CMakeLists.txt Просмотреть файл

@@ -17,6 +17,8 @@ set(OPENSSL_INCLUDE_DIR ${OPENSSL_BUILD_INSTALL_ROOT}/include)
# ${OPENSSL_PREFIX_OPENSSLDIR}
set(OPENSSL_PREFIX_OPENSSLDIR ${CMAKE_INSTALL_PREFIX}${PQSDK_INSTALL_DIR}/openssl)
include(libdefs.cmake)
set(OPENSSL_CONFIG_CMD "config" CACHE STRING "Command used to configure OpenSSL (default ./config)")
set(OPENSSL_CONFIG_TARGET "" CACHE STRING "Platform for which OpenSSL should be compiled (default native)")

message("OpenSSL root dir: ${OPENSSL_ROOT_DIR}")
message("OpenSSL install dir: ${OPENSSL_BUILD_INSTALL_ROOT}")
@@ -24,7 +26,7 @@ message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}")
message("OpenSSL crypto lib: ${OPENSSL_LIB_CRYPTO}")
message("OpenSSL ssl lib: ${OPENSSL_LIB_SSL}")
# TODO: add no-deprecated. Need to get rid of ERR_load_crypto_strings and OBJ_cleanup first
set(OPENSSL_CONFIG_ARGS no-shared shared threads)
set(OPENSSL_CONFIG_ARGS no-shared shared threads no-md2 no-md4 no-sm2 no-sm3 no-sm4)

if(DEBUG)
set(OPENSSL_CONFIG_ARGS ${OPENSSL_CONFIG_ARGS} -d -g3 -O0 no-asm -fno-omit-frame-pointer -fno-inline-functions)
@@ -44,14 +46,14 @@ add_dependencies(
ExternalProject_Add(OpenSSL
SOURCE_DIR ${OPENSSL_ROOT_DIR}
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-build
CONFIGURE_COMMAND <SOURCE_DIR>/config -debug ${OPENSSL_CONFIG_ARGS} --prefix=${OPENSSL_PREFIX_OPENSSLDIR} --openssldir=${OPENSSL_PREFIX_OPENSSLDIR} --strict-warnings
CONFIGURE_COMMAND <SOURCE_DIR>/${OPENSSL_CONFIG_CMD} ${OPENSSL_CONFIG_TARGET} ${OPENSSL_CONFIG_ARGS} --prefix=${OPENSSL_PREFIX_OPENSSLDIR} --openssldir=${OPENSSL_PREFIX_OPENSSLDIR} --strict-warnings
BUILD_COMMAND ${MAKE_PROGRAM} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_LINKER}
INSTALL_DIR /
INSTALL_COMMAND make DESTDIR=${OPENSSL_BUILD_INSTALL_ROOT} install
)

install(DIRECTORY ${OPENSSL_BUILD_INSTALL_ROOT}/${OPENSSL_PREFIX_OPENSSLDIR}/.. DESTINATION ${OPENSSL_PREFIX_OPENSSLDIR})
install(DIRECTORY ${OPENSSL_BUILD_INSTALL_ROOT}${OPENSSL_PREFIX_OPENSSLDIR}/bin/ DESTINATION
${OPENSSL_PREFIX_OPENSSLDIR}/bin
FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
#install(DIRECTORY ${OPENSSL_BUILD_INSTALL_ROOT}/${OPENSSL_PREFIX_OPENSSLDIR}/.. DESTINATION ${OPENSSL_PREFIX_OPENSSLDIR})
#install(DIRECTORY ${OPENSSL_BUILD_INSTALL_ROOT}${OPENSSL_PREFIX_OPENSSLDIR}/bin/ DESTINATION
# ${OPENSSL_PREFIX_OPENSSLDIR}/bin
# FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
set_property(GLOBAL PROPERTY openssl_build_dir_property ${OPENSSL_BUILD_DIR})

+ 110
- 48
CMakeLists.txt Просмотреть файл

@@ -10,45 +10,36 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "~/.cmake/Modules")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
set(OPTEE_ENGINE_INSTALL_DIR /usr/local/softs)
set(OPTEE_ENGINE_INSTALL_DIR /opt)

# --- Configuration ---

# Arch settings
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CLANG 1)
# OP-TEE
if (NOT OPTEE_BUILD_DIR)
message(FATAL_ERROR "Must specify -DOPTEE_BUILD_DIR")
endif()

if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_C_COMPILER /usr/bin/cc CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER /usr/bin/c++ CACHE PATH "" FORCE)
set(OPTEE_ENG_LD_FLAGS "-Wl")
else()
set(OPTEE_ENG_LD_FLAGS "-W")
if (NOT PLATFORM)
message(FATAL_ERROR "Must specify -DPLATFORM=V where V is either qemu or hikey960")
endif()
set(OPTEE_ROOT_DIR ${OPTEE_BUILD_DIR})
set(OPTEE_REE_LIB_DIR ${OPTEE_ROOT_DIR}/out-br/target/usr/lib)
set(OPTEE_REE_INCLUDE_DIR ${OPTEE_ROOT_DIR}/optee_client/public)
set(CMAKE_C_COMPILER ${OPTEE_ROOT_DIR}/toolchains/aarch64/bin/aarch64-linux-gnu-gcc CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER ${OPTEE_ROOT_DIR}/toolchains/aarch64/bin/aarch64-linux-gnu-g++ CACHE PATH "" FORCE)

# Build OpenSSL if not provided, otherwise define
# OpenSSL_ssl_shared and OpenSSL_crypto_shared
if (BUILD_OPENSSL)
add_subdirectory(3rd/openssl-cmake)
else()
if (NOT OPENSSL_INSTALL_DIR)
message(FATAL_ERROR "Must specify -DOPENSSL_INSTALL_DIR")
endif()
set(OPENSSL_BUILD_INSTALL_ROOT ${OPENSSL_INSTALL_DIR})
set(OPENSSL_PREFIX_OPENSSLDIR ${CMAKE_INSTALL_PREFIX}${OPTEE_ENGINE_INSTALL_DIR}/openssl)
include(3rd/openssl-cmake/libdefs.cmake)
endif()
# 3rd Parties

# OpenSSL config targets
set(OPENSSL_CONFIG_CMD "Configure" CACHE STRING "Command used to configure OpenSSL (default ./config)")
set(OPENSSL_CONFIG_TARGET "linux-aarch64" CACHE STRING "Platform for which OpenSSL should be compiled (default native)")

add_subdirectory(3rd/openssl-cmake)
# Gtest
add_subdirectory(3rd/gtest)
get_property(OPENSSL_INSTALL_DIR GLOBAL PROPERTY openssl_build_install_dir_property)
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include)

# Trusted Application sources
set(TA_DELEGATOR_ROOT ${CMAKE_SOURCE_DIR}/src/ta)

# Build gtest
add_subdirectory(3rd/gtest)

# Global configuration
set(C_CXX_FLAGS "\
-Wno-ignored-qualifiers \
@@ -60,12 +51,6 @@ set(C_CXX_FLAGS "\
-Wundef \
-Wunused-result")

if(CLANG)
set(C_CXX_FLAGS
"-Wconditional-uninitialized \
-Wmissing-variable-declarations")
endif()

# Control Debug/Release mode
IF(${CMAKE_BUILD_TYPE} MATCHES "Debug")
set(C_CXX_FLAGS "${C_CXX_FLAGS} -g3 -O0 -Wno-unused")
@@ -73,22 +58,8 @@ else()
set(C_CXX_FLAGS "${C_CXX_FLAGS} -O3")
endif()

# Add possibility to build Client Application with ASAN
if(ASAN)
set(CLANG 1)
set(C_CXX_FLAGS "${C_CXX_FLAGS} -fsanitize=undefined,address,leak -fno-omit-frame-pointer")
set(LDFLAGS "${LDFLAGS} -fsanitize=undefined,address,leak")
endif()

set(CMAKE_C_FLAGS ${C_CXX_FLAGS})
set(CMAKE_CXX_FLAGS ${C_CXX_FLAGS})
if(CLANG)
if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang" OR NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(FATAL_ERROR "Clang required for this build")
endif()

set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof -fcolor-diagnostics")
endif()

# --- Build targets ---

@@ -133,8 +104,99 @@ target_link_directories(
target_link_libraries(
optee_eng
OpenSSL_crypto_shared
teec
${CMAKE_DL_LIBS})

IF(${CMAKE_BUILD_TYPE} MATCHES "Debug")
target_compile_definitions(optee_eng PRIVATE BUILD_DEBUG)
endif()

# Key management app
add_executable(
optee_keymgnt
src/optee_engine/keymgnt.c
)
target_include_directories(
optee_keymgnt PRIVATE
${OPENSSL_INCLUDE_DIR}
${OPTEE_REE_INCLUDE_DIR}
${TA_DELEGATOR_ROOT}/include)
target_link_directories(
optee_keymgnt PRIVATE
${OPTEE_REE_LIB_DIR})
target_link_libraries(
optee_keymgnt
OpenSSL_crypto_shared
teec
${OPTEE_ENG_LD_FLAGS}
${CMAKE_DL_LIBS})

ExternalProject_Add(optee_eng_ta
SOURCE_DIR ${TA_DELEGATOR_ROOT}
CONFIGURE_COMMAND ""
BUILD_COMMAND OPTEE_ROOT=${OPTEE_BUILD_DIR} O=${CMAKE_CURRENT_BINARY_DIR} ${MAKE_PROGRAM}
BUILD_IN_SOURCE TRUE
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/ta
INSTALL_COMMAND ""
BUILD_ALWAYS TRUE
)

# Google benchmark settings
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
# Target for benchmark - it also builds gtest library
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "Enable testing of the benchmark library." FORCE)
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable benchmark tests" FORCE)
set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/3rd/gtest" CACHE PATH "Path to the gtest sources" FORCE)
set(BENCHMARK_OS_WINDOWS OFF CACHE BOOL "" FORCE)
set(HAVE_POSIX_REGEX OFF CACHE BOOL "" FORCE)
set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
add_subdirectory(3rd/gbench)
add_executable(
speed
src/optee_engine/speed.cc)
target_include_directories(
speed PRIVATE
${OPENSSL_INCLUDE_DIR}
)
target_link_libraries(
speed
gtest
pthread
OpenSSL_crypto_shared
benchmark::benchmark)

# Install copies needed files to the buildroot overlay.

# OpenVPN config
install(FILES ${PROJECT_SOURCE_DIR}/cfg/openvpn_cli.conf
DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/etc/openvpn/
RENAME client.conf)
install(FILES
${PROJECT_SOURCE_DIR}/cfg/certs/ca.cert
${PROJECT_SOURCE_DIR}/cfg/certs/client.cert
${PROJECT_SOURCE_DIR}/cfg/certs/client.key
DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/etc/openvpn/certs/)
# OpenSSL config
install(FILES ${PROJECT_SOURCE_DIR}/cfg/openssl_optee.cnf
DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/etc/ssl/
RENAME openssl.cnf)
# OpTEE engine
install(TARGETS optee_eng
LIBRARY DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/opt/
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
# TA
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/8aaaf200-2450-11e4-0060-0dc0ffee0000.ta
DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/lib/optee_armtz)
# Must be empty and have same name as the TEE key ID
install(FILES /dev/null
DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/etc/openvpn/
RENAME vpn.testlab.com)
# Key management app
install(TARGETS optee_keymgnt
RUNTIME DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/usr/bin/
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ)
# Speed app
install(TARGETS speed
RUNTIME DESTINATION ${OPTEE_ROOT_DIR}/build/br-ext/board/${PLATFORM}/overlay/usr/bin/
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ)

+ 9
- 0
README.md Просмотреть файл

@@ -0,0 +1,9 @@
# OPTEE OpenSSL ENGINE for TLS

Typically, a TLS server uses an X509 Certificate and associated Private Key to sign TLS session. Both certificate and private key used for signing the certificate form an asymmetric cryptographic key-pair. Revealing the traffic-private-key makes it possible to perform men-in-the-middle type of attacks. Typically private-key is stored on the server’s hard disk. Even if it is stored in encrypted form, at some point HTTPS server needs to have a possibility to decrypt it to use for signing. It means that at runtime the key in the plaintext will be available in memory of an HTTPS process. In the case of software errors, attackers may be able to steal a private key (see [Heartbleed](https://heartbleed.com/)). From the other hand, in multiple domains, there is a need for binding of secret keys to the hardware on which software is running comes with multiple (IoT devices, software deployments on the edge networks).

Secure Trusted Execution Environments may address those needs. The repository provides a PoC implementation of Trusted Application that can be run in the ARM's TrustZone and be used for storing secret key of a TLS server as well as perform signing operation with that key. The implementation uses [OPTEE](https://www.op-tee.org/) as an implementation of the TEE. The secret key is stored in the encrypted form on secure storage. The secure storage is encrypted with device Device Unique Key (HUK) and hence it can be only used by any other hardware after being copied from one device to the other.

The plugin to OpenSSL provides integration between Trusted Application running in Trust Zone and TLS stack. Namely, the plugin implements OpenSSL ENGINE API and hence it can be dynamically loaded by OpenSSL, eliminating a need to modify OpenSSL source code.

The idea was initially described on a blog [here](https://www.amongbytes.com/post/201904-tee-sign-delegator/). The main improvement provided by software in this repository is the implementation of the OpenSSL plugin.

+ 1
- 0
cfg/certs/10e22dbc.0 Просмотреть файл

@@ -0,0 +1 @@
server.cert

+ 13
- 0
cfg/certs/ca.cert Просмотреть файл

@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB4jCCAYegAwIBAgIUUAWISiMN6taMN9o92ZeCmvF/hWEwCgYIKoZIzj0EAwIw
PjElMCMGA1UECgwcQW1vbmcgQnl0ZXMsIHZwbi50ZXN0bGFiLmNvbTEVMBMGA1UE
AwwMUm9vdCBDZXJ0IEcxMB4XDTIxMDIwNzIzNDQ0NFoXDTQ4MDYyNDIzNDQ0NFow
PjElMCMGA1UECgwcQW1vbmcgQnl0ZXMsIHZwbi50ZXN0bGFiLmNvbTEVMBMGA1UE
AwwMUm9vdCBDZXJ0IEcxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELti1AngN
Z5mpgfL/IEfwP4d28l5qqj3qagHproif80C0L7mkGmseO7gdLQHyU7UlelGxAFZD
vC4NOufG2c6fS6NjMGEwHQYDVR0OBBYEFI+sqwD8xeuHR2qtcnS/hBPfUA4vMB8G
A1UdIwQYMBaAFI+sqwD8xeuHR2qtcnS/hBPfUA4vMA8GA1UdEwEB/wQFMAMBAf8w
DgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0kAMEYCIQCn4bViwS6ALu7HtXjp
SaEJgkSjLj/Fw/5/XohAx/ta/QIhAJrdETBDyaqN7kZjT3mI12vOb1vdA2oHYCZw
OsL1I5yO
-----END CERTIFICATE-----

+ 8
- 0
cfg/certs/ca.key Просмотреть файл

@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIM2kewhtexp7AZonkZqAYKk4pNTImjxDpX5GeGxkb0IDoAoGCCqGSM49
AwEHoUQDQgAELti1AngNZ5mpgfL/IEfwP4d28l5qqj3qagHproif80C0L7mkGmse
O7gdLQHyU7UlelGxAFZDvC4NOufG2c6fSw==
-----END EC PRIVATE KEY-----

+ 1
- 0
cfg/certs/ca.srl Просмотреть файл

@@ -0,0 +1 @@
725588E0FAE750D03BC5D4B1254454A2C85ECBBB

+ 14
- 0
cfg/certs/client.cert Просмотреть файл

@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICNTCCAdygAwIBAgIUclWI4PrnUNA7xdSxJURUoshey7swCgYIKoZIzj0EAwIw
PjElMCMGA1UECgwcQW1vbmcgQnl0ZXMsIHZwbi50ZXN0bGFiLmNvbTEVMBMGA1UE
AwwMUm9vdCBDZXJ0IEcxMB4XDTIxMDIwNzIzNDQ0NFoXDTQ4MDYyNDIzNDQ0NFow
MTEZMBcGA1UECgwQQ2VydCBUZXN0aW5nIE9SRzEUMBIGA1UEAwwLQ2xpZW50IENl
cnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQU41Tkm38N15yBrlUdrrIhcfXO
aav9SY+OHoEYpR6FvZvvhEtmSLMe0tBlXLq/SBwWDERMwCb4ksnMYuRk81wko4HE
MIHBMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMDIGCWCGSAGG+EIBDQQl
FiNBbW9uZyBCeXRlcywgTGFiIFRlc3RuZywgVExTIENsaWVudDAdBgNVHQ4EFgQU
TfNbUInWGruGey7vUaXiWdZUBIcwHwYDVR0jBBgwFoAUj6yrAPzF64dHaq1ydL+E
E99QDi8wDgYDVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEF
BQcDBDAKBggqhkjOPQQDAgNHADBEAiAaN2sorsRKG9GeEcqUSag/FS+cRVt70vG/
AN+3XKlmeAIgKKSwTm8JuHYJO1bHQzVBJOFtjQQvc1NINEE3yIvTc6M=
-----END CERTIFICATE-----

+ 7
- 0
cfg/certs/client.csr Просмотреть файл

@@ -0,0 +1,7 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHsMIGTAgEAMDExGTAXBgNVBAoMEENlcnQgVGVzdGluZyBPUkcxFDASBgNVBAMM
C0NsaWVudCBDZXJ0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFONU5Jt/Ddec
ga5VHa6yIXH1zmmr/UmPjh6BGKUehb2b74RLZkizHtLQZVy6v0gcFgxETMAm+JLJ
zGLkZPNcJKAAMAoGCCqGSM49BAMCA0gAMEUCIQCvWl41LYMmGyfsGMKoNrc3kXac
4/vTZbt/3F5N3MnfIAIgKhkxJ8K8leLqsUnasAINKqV7goVXdOncZXFZWB3Z/zs=
-----END CERTIFICATE REQUEST-----

+ 8
- 0
cfg/certs/client.key Просмотреть файл

@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEINy9shU4Xzqh+R47QxCvTFkaAWK5V35J1ynaPU29LlRKoAoGCCqGSM49
AwEHoUQDQgAEFONU5Jt/Ddecga5VHa6yIXH1zmmr/UmPjh6BGKUehb2b74RLZkiz
HtLQZVy6v0gcFgxETMAm+JLJzGLkZPNcJA==
-----END EC PRIVATE KEY-----

+ 1
- 0
cfg/certs/f40a0c39.0 Просмотреть файл

@@ -0,0 +1 @@
ca.cert

+ 18
- 0
cfg/certs/server.cert Просмотреть файл

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC0TCCAnegAwIBAgIUclWI4PrnUNA7xdSxJURUoshey7owCgYIKoZIzj0EAwIw
PjElMCMGA1UECgwcQW1vbmcgQnl0ZXMsIHZwbi50ZXN0bGFiLmNvbTEVMBMGA1UE
AwwMUm9vdCBDZXJ0IEcxMB4XDTIxMDIwNzIzNDQ0NFoXDTQ4MDYyNDIzNDQ0NFow
NTEZMBcGA1UECgwQQ2VydCBUZXN0aW5nIE9SRzEYMBYGA1UEAwwPdnBuLnRlc3Rs
YWIuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQKMXJu5XByLVq1Mo7oek
MzDLQWBulUcDH6CXxXJSRVDOHapNMTNsjEIzLvManD7tXRaxDNINXvAJ/ze6eA+0
FaOCAVowggFWMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDIGCWCGSAGG
+EIBDQQlFiNBbW9uZyBCeXRlcywgTGFiIFRlc3RuZywgVExTIFNlcnZlcjAdBgNV
HQ4EFgQUFzD2JhWfK/YeOd9Yd5h9aONsFigweQYDVR0jBHIwcIAUj6yrAPzF64dH
aq1ydL+EE99QDi+hQqRAMD4xJTAjBgNVBAoMHEFtb25nIEJ5dGVzLCB2cG4udGVz
dGxhYi5jb20xFTATBgNVBAMMDFJvb3QgQ2VydCBHMYIUUAWISiMN6taMN9o92ZeC
mvF/hWEwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMEMGA1Ud
EQQ8MDqCDXd3dy5wcXNkay5jb22CDWlvdC5wcXNkay5jb22CDXZwbi5wcXNkay5j
b22CCyoucHFzZGsuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDKpmDVh3TTkojSMDLV
Fzq6kk7RSvD48lG2FTMwWtE0NAIgdPeRd9DQcuCBCT8/kHxevfcoBXI60o5MVpNo
sY8hFVo=
-----END CERTIFICATE-----

+ 8
- 0
cfg/certs/server.csr Просмотреть файл

@@ -0,0 +1,8 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHwMIGXAgEAMDUxGTAXBgNVBAoMEENlcnQgVGVzdGluZyBPUkcxGDAWBgNVBAMM
D3Zwbi50ZXN0bGFiLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABECjFybu
Vwci1atTKO6HpDMwy0FgbpVHAx+gl8VyUkVQzh2qTTEzbIxCMy7zGpw+7V0WsQzS
DV7wCf83ungPtBWgADAKBggqhkjOPQQDAgNIADBFAiEAwoYmOPkC6fHjInldqob/
sIkBNQoQG3IG50JZNaXDQ94CIByydf2CoqABEjMJ49/YhgikQ8Cp88qw23M0uCdZ
avEs
-----END CERTIFICATE REQUEST-----

+ 8
- 0
cfg/certs/server.key Просмотреть файл

@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIGS/md9a764Wd2z6+eaIpT+c4pcxMOPY5+KCeZ88xdbEoAoGCCqGSM49
AwEHoUQDQgAEQKMXJu5XByLVq1Mo7oekMzDLQWBulUcDH6CXxXJSRVDOHapNMTNs
jEIzLvManD7tXRaxDNINXvAJ/ze6eA+0FQ==
-----END EC PRIVATE KEY-----

+ 83
- 0
cfg/create_certs.sh Просмотреть файл

@@ -0,0 +1,83 @@
#!/bin/sh

# Re-creates certificates for server and client VPN
OPENSSL_BIN=openssl
OPENSSL_REHASH_BIN=c_rehash
TMP_DIR=certs
set -x

create_openvpn_pki()
{
# Create CA key and certificate
${OPENSSL_BIN} ecparam \
-name secp256r1 \
-genkey \
-out ${TMP_DIR}/ca.key || exit;
${OPENSSL_BIN} req \
-new \
-config openssl.cnf \
-x509 \
-extensions v3_ca \
-key ${TMP_DIR}/ca.key \
-out ${TMP_DIR}/ca.cert \
-days 9999 \
-subj "/O=Among Bytes, vpn.testlab.com/CN=Root Cert G1" \
-batch || exit;

# Create server certificate
${OPENSSL_BIN} ecparam \
-name secp256r1 \
-genkey \
-out ${TMP_DIR}/server.key || exit;
${OPENSSL_BIN} req \
-new \
-config openssl.cnf \
-key ${TMP_DIR}/server.key \
-out ${TMP_DIR}/server.csr \
-subj "/O=Cert Testing ORG/CN=vpn.testlab.com" \
-batch || exit;
${OPENSSL_BIN} x509 \
-extfile openssl.cnf \
-extensions server_cert \
-req \
-CA ${TMP_DIR}/ca.cert \
-CAkey ${TMP_DIR}/ca.key \
-CAcreateserial \
-in ${TMP_DIR}/server.csr \
-out ${TMP_DIR}/server.cert \
-days 9999 || exit;
OPENSSL=${OPENSSL_BIN} ${OPENSSL_REHASH_BIN} ${TMP_DIR}
${OPENSSL_BIN} verify \
-CApath ${TMP_DIR} \
${TMP_DIR}/server.cert || exit;

# Create client certificate
${OPENSSL_BIN} ecparam \
-name secp256r1 \
-genkey \
-out ${TMP_DIR}/client.key || exit;
${OPENSSL_BIN} req \
-new \
-config openssl.cnf \
-key ${TMP_DIR}/client.key \
-out ${TMP_DIR}/client.csr \
-subj "/O=Cert Testing ORG/CN=Client Cert" \
-batch || exit;
${OPENSSL_BIN} x509 \
-extfile openssl.cnf \
-extensions client_cert \
-req \
-CA ${TMP_DIR}/ca.cert \
-CAkey ${TMP_DIR}/ca.key \
-CAcreateserial \
-in ${TMP_DIR}/client.csr \
-out ${TMP_DIR}/client.cert \
-days 9999 || exit;
${OPENSSL_BIN} verify \
-CApath ${TMP_DIR}/ \
${TMP_DIR}/client.cert || exit;
}

rm -rf ${TMP_DIR}
mkdir -p ${TMP_DIR}
create_openvpn_pki

+ 137
- 0
cfg/openssl.cnf Просмотреть файл

@@ -0,0 +1,137 @@
[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir = .
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand

# The root key and root certificate.
private_key = $dir/root.key
certificate = $dir/root.pem

# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256

name_opt = ca_default
cert_opt = ca_default
default_days = 9999
preserve = no
policy = policy_loose

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name

stateOrProvinceName_default = City of London
countryName_default = UK
localityName_default = London
organizationalUnitName_default = Among Bytes, Lab Testng
commonName_default = www.pqsdk.com
commonName_max = 64

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = serverAuth, clientAuth

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = 'Among Bytes, Lab Testng, Intermediate Cert'
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = 'Among Bytes, Lab Testng, TLS Server'
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[ client_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = 'Among Bytes, Lab Testng, TLS Client'
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier = keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

[alt_names]
DNS.1 = www.pqsdk.com
DNS.2 = iot.pqsdk.com
DNS.3 = vpn.pqsdk.com
DNS.4 = *.pqsdk.com

+ 366
- 0
cfg/openssl_optee.cnf Просмотреть файл

@@ -0,0 +1,366 @@
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#

# Note that you can include other files from the main configuration
# file using the .include directive.
#.include filename

# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .

# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids

# System default
openssl_conf = default_conf

# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)

[ new_oids ]

# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6

# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

####################################################################
[ ca ]
default_ca = CA_default # The default ca section

####################################################################
[ CA_default ]

dir = /etc/ssl # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.

certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key

x509_extensions = usr_cert # The extensions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext

default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match

# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert

# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret

# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
string_mask = utf8only

# req_extensions = v3_req # The extensions to add to a certificate request

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name

[ usr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.

# This is OK for an SSL server.
# nsCertType = server

# For an object signing certificate this would be used.
# nsCertType = objsign

# For normal client use this is typical
# nsCertType = client, email

# and for everything including object signing:
# nsCertType = client, email, objsign

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move

# Copy subject details
# issuerAltName=issuer:copy

#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName

# This is required for TSA certificates.
# extendedKeyUsage = critical,timeStamping

[ v3_req ]

# Extensions to add to a certificate request

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]


# Extensions for a typical CA


# PKIX recommendation.

subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer

basicConstraints = critical,CA:true

# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign

# Some might want this also
# nsCertType = sslCA, emailCA

# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy

# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF

[ crl_ext ]

# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.

# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always

[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.

# This is OK for an SSL server.
# nsCertType = server

# For an object signing certificate this would be used.
# nsCertType = objsign

# For normal client use this is typical
# nsCertType = client, email

# and for everything including object signing:
# nsCertType = client, email, objsign

# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move

# Copy subject details
# issuerAltName=issuer:copy

#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName

# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

####################################################################
[ tsa ]

default_tsa = tsa_config1 # the default TSA section

[ tsa_config1 ]

# These are used by the TSA reply generation only.
dir = /etc/ssl # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
signer_digest = sha256 # Signing digest to use. (Optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
ess_cert_id_alg = sha1 # algorithm to compute certificate
# identifier (optional, default: sha1)
#
#

[default_conf]
engines = engine_section

[engine_section]
optee = optee_section

[optee_section]
engine_id = optee
dynamic_path = /opt/liboptee_eng.so
init = 1

+ 22
- 0
cfg/openvpn_cli.conf Просмотреть файл

@@ -0,0 +1,22 @@
client
proto udp4
# Deliberatelly same IP as tun0 on a host system, to easily connect from QEMU
remote 172.16.0.1 1194
# remote vpn.testlab.com 1194
dev tun
resolv-retry infinite
nobind
dh none
remote-cert-tls server
cipher AES-256-GCM
persist-key
persist-tun
verb 3

# Certificates
ca certs/ca.cert
cert certs/client.cert
key vpn.testlab.com

# Load 'optee' engine, to perform private key operation in the TEE
engine optee

+ 19
- 0
cfg/openvpn_srv.conf Просмотреть файл

@@ -0,0 +1,19 @@
port 1194
proto udp4
dev tun
dh none
topology subnet
server 172.16.0.0 255.255.0.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
cipher AES-256-GCM
persist-key
persist-tun
status openvpn-status.log
verb 1
explicit-exit-notify 1

# Certificates
ca certs/ca.cert
cert certs/server.cert
key certs/server.key

+ 33
- 0
optee-patches/0001-openvpn-2.4.9-to-2.5.0.patch Просмотреть файл

@@ -0,0 +1,35 @@
From ff9a4702a79d2e10156f5ce748a542b98abfae4d Mon Sep 17 00:00:00 2001
From: Kris Kwiatkowski <contact@amongbytes.com>
Date: Wed, 13 Jan 2021 15:44:20 +0000
Subject: [PATCH] openvpn 2.4.9 -> 2.5.0 because of engine support

---
package/openvpn/openvpn.hash | 2 +-
package/openvpn/openvpn.mk | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package/openvpn/openvpn.hash b/package/openvpn/openvpn.hash
index b9b0a4d..1a16d90 100644
--- a/package/openvpn/openvpn.hash
@@ -1,3 +1,3 @@
# Locally calculated after checking signature
-sha256 641f3add8694b2ccc39fd4fd92554e4f089ad16a8db6d2b473ec284839a5ebe2 openvpn-2.4.9.tar.xz
+sha256 029a426e44d656cb4e1189319c95fe6fc9864247724f5599d99df9c4c3478fbd openvpn-2.5.0.tar.xz
sha256 1fcb78d7e478bb8a9408010bdc91b36e213b1facfad093df3f7ce7e28af19043 COPYRIGHT.GPL
diff --git a/package/openvpn/openvpn.mk b/package/openvpn/openvpn.mk
index 4234675..9881426 100644
--- a/package/openvpn/openvpn.mk
@@ -4,7 +4,7 @@
#
################################################################################
-OPENVPN_VERSION = 2.4.9
+OPENVPN_VERSION = 2.5.0
OPENVPN_SOURCE = openvpn-$(OPENVPN_VERSION).tar.xz
OPENVPN_SITE = http://swupdate.openvpn.net/community/releases
OPENVPN_DEPENDENCIES = host-pkgconf openssl
--
2.28.0


+ 47
- 0
optee-patches/0002_build_enable_openvpn.patch Просмотреть файл

@@ -0,0 +1,48 @@
diff --git a/common.mk b/common.mk
index 169b99c..361405f 100644
--- a/common.mk
@@ -74,23 +74,23 @@ endif
# # Then in QEMU, run:
# # $ mount -t 9p -o trans=virtio host <mount_point>
# # Or enable QEMU_VIRTFS_AUTOMOUNT
-QEMU_VIRTFS_ENABLE ?= n
-QEMU_VIRTFS_HOST_DIR ?= $(ROOT)
+QEMU_VIRTFS_ENABLE ?= n
+QEMU_VIRTFS_HOST_DIR ?= $(ROOT)
# Persistent Secure Storage via shared folder
# # Set QEMU_PSS_ENABLE to 'y' and adjust QEMU_PSS_HOST_DIR
# # Then in QEMU, run:
# # $ mount -t 9p -o trans=virtio secure /data/tee
# # Or enable QEMU_PSS_AUTOMOUNT
-QEMU_PSS_ENABLE ?= n
-QEMU_PSS_HOST_DIR ?= /tmp/qemu-data-tee
+QEMU_PSS_ENABLE ?= y
+QEMU_PSS_HOST_DIR ?= /tmp/
# Warning: when these variables are modified, you must remake the buildroot
# target directory. This can be done without rebuilding everything as follows:
# rm -rf ../out-br/target; find ../out-br/ -name .stamp_target_installed | xargs rm
# make <flags> run
-QEMU_VIRTFS_AUTOMOUNT ?= n
-QEMU_PSS_AUTOMOUNT ?= n
+QEMU_VIRTFS_AUTOMOUNT ?= y
+QEMU_PSS_AUTOMOUNT ?= y
# Mount point for the shared directory inside QEMU
# Used by the post-build script, this is written to /etc/fstab as the mount
# point of the shared directory
@@ -246,9 +246,12 @@ BUILDROOT_TOOLCHAIN=toolchain-aarch$(COMPILE_NS_USER)-legacy
endif
endif
+BR2_PACKAGE_OPENSSL ?= y
+BR2_PACKAGE_OPENVPN ?= y
BR2_PACKAGE_LIBOPENSSL ?= y
+BR2_PACKAGE_LIBOPENSSL_BIN ?= y
+BR2_PACKAGE_LIBOPENSSL_ENGINES ?= y
BR2_PACKAGE_MMC_UTILS ?= y
-BR2_PACKAGE_OPENSSL ?= y
BR2_PACKAGE_OPTEE_BENCHMARK_EXT ?= $(CFG_TEE_BENCHMARK)
BR2_PACKAGE_OPTEE_BENCHMARK_EXT_SITE ?= $(BENCHMARK_APP_PATH)
BR2_PACKAGE_OPTEE_CLIENT_EXT_SITE ?= $(OPTEE_CLIENT_PATH)

+ 271
- 148
src/optee_engine/back.c Просмотреть файл

@@ -1,171 +1,184 @@
#include <string.h>
#include <assert.h>
#include <err.h>

// OpenSSL
#include <openssl/engine.h>
#include <openssl/evp.h>

// OpTEE
#include <tee_client_api.h>
#include <user_ta_header_defines.h>

#include "back.h"
#include "log.h"
#include "utils.h"

// Only ECDSA/p256 scheme is supported
#define CURVE_ID NID_X9_62_prime256v1
// Coordinate byte size in the NIST-P256
#define ECC_POINT_BSZ 32

// Extended data index for EC key
static int ec_ex_index = 0;

// OZAPTF: remove
static const EC_POINT *ec_pub_key;
static const BIGNUM *ec_prv_key;

// Context
struct tee_ctx_t {
// Stores hash of key ID of a key stored in the TEE
uint8_t key_id[32];
// OZAPTF: remove
const BIGNUM *prv;
struct session_t {
// TEE session context
TEEC_Context ctx;
// Handle to the TEE session
TEEC_Session tee_sess;
// SHA-256 hash of a key ID, used for key indexing inside TEE
uint8_t key_id[SHA256_SIZE];
};

// OZAPTF helper to remove
static int parse_key_from_file(const char *path) {
int ret = 0;

BIO *bp;
EVP_PKEY *key;
EC_KEY *ec_key;
const EC_GROUP *group;
BIGNUM *x, *y;

bp = BIO_new(BIO_s_file());
if (!bp) {
// Creates session with the TEE. On success, sets the sess and returns
// true, otherwise false.
static bool create_tee_session(struct session_t *sess) {
TEEC_Result res;
uint32_t err_origin;
TEEC_UUID uuid = TA_UUID;

// Initialize a context connecting us to the TEE
res = TEEC_InitializeContext(NULL, &sess->ctx);
if (res != TEEC_SUCCESS) {
info("TEEC_InitializeContext failed with code 0x%x", res);
goto end;
}

if (!BIO_read_filename(bp, path)) {
fprintf(stderr, "Failed to open private key file %s", path);
// Open a session with TEE
res = TEEC_OpenSession(&sess->ctx, &sess->tee_sess, &uuid,
TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
if (res != TEEC_SUCCESS) {
info("TEEC_Opensession failed with code 0x%x origin 0x%x",
res, err_origin);
goto end;
}

key = PEM_read_bio_PrivateKey(bp, 0, 0, 0);
if (!key) {
goto end;
}

BN_CTX *ctx = BN_CTX_new();
if (!ctx) goto end;

// Get curve
ec_key = EVP_PKEY_get1_EC_KEY(key);
if (!ec_key) goto end;

ec_pub_key = EC_KEY_get0_public_key(ec_key);
if (!ec_pub_key) goto end;

// Get private key
ec_prv_key = EC_KEY_get0_private_key(ec_key);
ret = 1;
end:
BIO_free(bp);
return ret;
return res == TEEC_SUCCESS;
}

int OPTEE_ENG_evp_cb_sign(
EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *sigsz,
const unsigned char *tb, size_t tbsz) {
ENTRY;
// Creates session with the TEE. Returns true on success, otherwise false.
static void close_tee_session(struct session_t *sess) {
if(!sess) {
return;
}
TEEC_CloseSession(&sess->tee_sess);
TEEC_FinalizeContext(&sess->ctx);
}

EC_KEY *ec = 0;
EVP_MD *md = 0;
EVP_PKEY *pkey = 0;
const EC_GROUP *group = 0;
struct tee_ctx_t *op_ctx = 0;
unsigned int sltmp;
int ret = 0;
// Load public key. This implementation loads it from TEE
static const EC_POINT* get_public_ec_point_from_tee(
struct session_t *sess) {
ENTRY;

// OZAPTF: not sure if 64
static const size_t max_signature_length = 64;
const EC_POINT *ec_pub_key = 0;
uint8_t coord_x[ECC_POINT_BSZ] = {0};
uint8_t coord_y[ECC_POINT_BSZ] = {0};
BIGNUM *x_bn = 0, *y_bn = 0;
EC_POINT *point = 0;
EC_GROUP *group = 0;
EC_KEY *ec_key = 0;
BN_CTX *ctx = 0;
int res;
uint32_t err_origin;
TEEC_Operation op;

memset(&op, 0, sizeof(op));
op.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_INOUT,
TEEC_MEMREF_TEMP_INOUT,
TEEC_NONE);
op.params[0].tmpref.buffer = sess->key_id;
op.params[0].tmpref.size = ARRAY_SIZE(sess->key_id);
op.params[1].tmpref.buffer = coord_x;
op.params[1].tmpref.size = ECC_POINT_BSZ;
op.params[2].tmpref.buffer = coord_y;
op.params[2].tmpref.size = ECC_POINT_BSZ;
if (!create_tee_session(sess)) {
crit("TEE session: can't create");
return 0;
}
res = TEEC_InvokeCommand(&sess->tee_sess, TA_GET_PUB_KEY, &op, &err_origin);
close_tee_session(sess);

// if sig not set, return maximum length of the signature buffer
if (!sig && sigsz) {
*sigsz = max_signature_length;
ret = 0;
goto end;
if (res != TEEC_SUCCESS) {
crit("TEE session: TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
res, err_origin);
return 0;
}

if (*sigsz < max_signature_length) {
/* Signature buffer is to small. The documentation, here:
https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_sign.html
doesn't specify what to do in this case. The choices are
either fail or return truncated signature. I'll just fail
as truncated ECDSA signature can't be verified. */
*sigsz = 0;
goto end;
if ((op.params[1].tmpref.size != ECC_POINT_BSZ) ||
(op.params[2].tmpref.size != ECC_POINT_BSZ)) {
crit("Wrong length of public key received");
return 0;
}

pkey = EVP_PKEY_CTX_get0_pkey(ctx);
TEST_NULL(pkey);
// Convert received affine coordinate into EC public key
ctx = BN_CTX_new();
group = EC_GROUP_new_by_curve_name(CURVE_ID);
point = EC_POINT_new(group);
ec_key = EC_KEY_new();

if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
info("Only ECDSA supported for signing");
ret = -2; // doc says to set -2 in this case
TEST_NULL(ctx);
TEST_NULL(group);
TEST_NULL(point);
TEST_NULL(ec_key);

x_bn = BN_bin2bn(op.params[1].tmpref.buffer,
op.params[1].tmpref.size, x_bn);
y_bn = BN_bin2bn(op.params[2].tmpref.buffer,
op.params[2].tmpref.size, y_bn);
if (!x_bn||!y_bn) {
crit("Can't convert octet strings to BN");
goto end;
}

if (!EVP_PKEY_CTX_get_signature_md(ctx, &md) ||
(md != EVP_sha256())) {
// We only support ECDSA+P-256+SHA256
info("Only SHA256 supported for signing");
ret = -2;
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x_bn, y_bn, ctx)) {
crit("Can't convert BN to point");
goto end;
}

ec = EVP_PKEY_get1_EC_KEY(pkey);
TEST_NULL(ec);

group = EC_KEY_get0_group(ec);
TEST_NULL(group);

if (NID_X9_62_prime256v1 != EC_GROUP_get_curve_name(group)) {
info("Only p-256 supported");
ret = -2;
if (!EC_KEY_set_group(ec_key, group) ||
!EC_KEY_set_public_key(ec_key, point)) {
crit("Can't set public key");
goto end;
}

// Get TEE context as crypto extended data and set it as signing key
op_ctx = EC_KEY_get_ex_data(ec, ec_ex_index);
TEST_NULL(op_ctx);
TEST_OSSL(
EC_KEY_set_private_key(ec, ec_prv_key),
INVALID_KEY);

TEST_OSSL(
ECDSA_sign(NID_sha256, tb, tbsz, sig, &sltmp, ec),
CANNOT_SIGN);
*sigsz = sltmp;
ec_pub_key = EC_KEY_get0_public_key(ec_key);

// That's all, folks!
ret = 1;
end:
if (ec) EC_KEY_free(ec);
return ret;
BN_free(x_bn);
BN_free(y_bn);
EC_POINT_free(point);
EC_GROUP_free(group);
BN_CTX_free(ctx);
return ec_pub_key;
}

// generate key pair for the ECC key and
static EVP_PKEY* get_ecc_key_pair(
ENGINE *e,
struct tee_ctx_t *op,
int ecc_group_id) {
// Construct EVP_PKEY with private key stored in the TEE
static EVP_PKEY* load_key_pair_ec(
struct session_t *sess,
ENGINE *e) {

ENTRY;

const EC_POINT *ec_pub_key = 0;
EVP_PKEY_CTX *evp_ctx = 0;
EVP_PKEY *evp_key = 0;
EC_KEY *ec_key = 0;
uint8_t *hash_key_id = 0;
int ret = 0;

// Generate parameters for ECDSA-P256
evp_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, e);
TEST_NULL(evp_ctx);
TEST_OSSL(
EVP_PKEY_paramgen_init(evp_ctx),
BAD_PARAMETERS);
// Generate parameters for ECDSA-P256
TEST_OSSL(
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(evp_ctx, ecc_group_id),
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(evp_ctx, CURVE_ID),
BAD_PARAMETERS);
TEST_OSSL(
EVP_PKEY_paramgen(evp_ctx, &evp_key),
@@ -189,27 +202,25 @@ static EVP_PKEY* get_ecc_key_pair(
* Normal World, on Client Application request. Second option is
* implemented here, as that's easier.
*/
// OZAPTF: set public key received from TEE
ec_pub_key = get_public_ec_point_from_tee(sess);
TEST_NULL(ec_pub_key);
TEST_OSSL(
EC_KEY_set_public_key(ec_key, ec_pub_key),
BAD_PARAMETERS);

// Set handle to private key, stored in the TEE
EC_KEY_set_ex_data(ec_key, ec_ex_index, op);
// Set ID of a private key, stored in the TEE
hash_key_id = (void*)malloc(SHA256_SIZE);
TEST_NULL(hash_key_id);
memcpy(hash_key_id, sess->key_id, SHA256_SIZE);
EC_KEY_set_ex_data(ec_key, ec_ex_index, hash_key_id);
TEST_OSSL(
EVP_PKEY_set1_engine(evp_key, e),
INTERNAL);

ret = 1;
end:
if (ec_key) {
// must be "free'd" as EVP_PKEY_get1 was used
EC_KEY_free(ec_key);
}
if (evp_ctx) {
EVP_PKEY_CTX_free(evp_ctx);
}
EC_KEY_free(ec_key);
EVP_PKEY_CTX_free(evp_ctx);
if (!ret && evp_key) {
EVP_PKEY_free(evp_key);
evp_key = 0;
@@ -217,41 +228,33 @@ end:
return evp_key;
}

// ENGINE_set_load_privkey_function callback. Retrieves public key
// from TEE and sets a handler for the private key stored in the TEE.
EVP_PKEY* OPTEE_ENG_load_private_key(
ENGINE *e, const char *key_name, UI_METHOD *ui_method,
void *callback_data) {
ENTRY;

NOP(callback_data), NOP(ui_method);

struct tee_ctx_t *op_ctx = 0;
EVP_PKEY_CTX *evp_ctx = 0;
ENTRY;
EVP_PKEY *evp_key = 0;
uint8_t key_digest[32] = {0};
struct session_t sess;
int ret = 0;

/* read key from file */
// OZAPTF
TEST_OSSL(
parse_key_from_file(getenv("PRV_KEY")),
BAD_PARAMETERS);

// Calculate key-id used internally. It is a sha256
// caller provided of key name.
TEST_OSSL(
EVP_Digest(key_name, strlen(key_name), key_digest, NULL, EVP_sha256(), NULL),
EVP_Digest(key_name,
strlen(key_name), sess.key_id, NULL, EVP_sha256(), NULL),
BAD_PARAMETERS);

// Create internal TEE context
op_ctx = malloc(sizeof(*op_ctx));
TEST_NULL(op_ctx);
op_ctx->prv = ec_prv_key;
memcpy(op_ctx->key_id, key_digest, ARRAY_SIZE(op_ctx->key_id));

// create EVP_PKEY_CTX object for ECDSA-P256 signing
evp_key = get_ecc_key_pair(e, op_ctx, NID_X9_62_prime256v1);
// Create EVP_PKEY object. Currently only ECDSA/p256 is supported.
// Normally it would be a switch-case for all supported methods.
evp_key = load_key_pair_ec(&sess, e);
TEST_NULL(evp_key);

// Some calls related to EVP_PKEY must be forwaded to
// OpTEE engine.
if (EVP_PKEY_set1_engine(evp_key, e) != 1) {
info("Can't set engine for EVP_PKEY");
EVP_PKEY_free(evp_key);
@@ -261,12 +264,132 @@ EVP_PKEY* OPTEE_ENG_load_private_key(

end:
if (!ret) {
if (op_ctx && !evp_key) {
free(op_ctx);
}
if (evp_key) {
EVP_PKEY_free(evp_key);
}
EVP_PKEY_free(evp_key);
}
return evp_key;
}

int OPTEE_ENG_evp_cb_sign(
EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sigsz,
const uint8_t *tb, size_t tbsz) {
ENTRY;

const EC_GROUP *group = 0;
EVP_PKEY *pkey = 0;
EC_KEY *ec = 0;
EVP_MD *md = 0;
ECDSA_SIG *sig_ob = 0;
BIGNUM *r = 0, *s = 0;
TEEC_Operation op;

uint8_t *hash_key_id = 0;
int ret = 0;
uint32_t err_origin;
struct session_t sess = {0};
uint8_t sign[64] = {0};

TEST_NULL(sigsz);

pkey = EVP_PKEY_CTX_get0_pkey(ctx);
TEST_NULL(pkey);

// Check if ECDSA/p256-SHA256 signature was requested
if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
info("Only ECDSA supported for signing");
ret = -2; // doc says to set -2 in this case
goto end;
}

if (!EVP_PKEY_CTX_get_signature_md(ctx, &md) ||
(md != EVP_sha256())) {
// We only support ECDSA+P-256+SHA256
info("Only SHA256 supported for signing");
ret = -2;
goto end;
}

ec = EVP_PKEY_get1_EC_KEY(pkey);
TEST_NULL(ec);
group = EC_KEY_get0_group(ec);
TEST_NULL(group);
if (CURVE_ID != EC_GROUP_get_curve_name(group)) {
info("Only NIST P-256 supported");
ret = -2;
goto end;
}

// Request message singing from TEE
memset(&op, 0, sizeof(op));
hash_key_id = EC_KEY_get_ex_data(ec, ec_ex_index);
TEST_NULL(hash_key_id);
op.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_INOUT,
TEEC_NONE);
op.params[0].tmpref.buffer = hash_key_id;
op.params[0].tmpref.size = SHA256_SIZE;
op.params[1].tmpref.buffer = (uint8_t*)tb;
op.params[1].tmpref.size = tbsz;
op.params[2].tmpref.buffer = sign;
op.params[2].tmpref.size = ARRAY_SIZE(sign);
if (!create_tee_session(&sess)) {
info("TEE session: can't create");
goto end;
}
ret = TEEC_InvokeCommand(&sess.tee_sess, TA_SIGN_ECC, &op, &err_origin);
close_tee_session(&sess);
if (ret != TEEC_SUCCESS) {
info("TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
ret, err_origin);
goto end;
}

// Convert raw ECDSA signature (r,s) into DER encoded signature.
const size_t h = ARRAY_SIZE(sign)/2;
r = BN_bin2bn(sign+0, h, r);
s = BN_bin2bn(sign+h, h, s);
if (!r||!s) {
info("Can't create r&s of ECDSA SIGN");
goto end;
}
sig_ob = ECDSA_SIG_new();
// r,s are not NULL, so this call never fails
(void)ECDSA_SIG_set0(sig_ob, r, s);

// if sig not set, return maximum length of the signature buffer
if (!sig && sigsz) {
*sigsz = i2d_ECDSA_SIG(sig_ob, 0);
goto end;
}

if (*sigsz < i2d_ECDSA_SIG(sig_ob, 0)) {
/* Signature buffer is to small. The documentation, here:
https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_sign.html
doesn't specify what to do in this case. The choices are
either fail or return truncated signature. I'll just fail
as truncated ECDSA signature can't be verified. */
goto end;
}

*sigsz = i2d_ECDSA_SIG(sig_ob, &sig);
if (!*sigsz) {
info("Can't DER encode signature");
goto end;
}

// That's all, folks!
ret = 1;
end:
if (ec) EC_KEY_free(ec);
if (!sig_ob) {
// Calling ECDSA_SIG_set0 transfers the ownership of
// r,s to the ECDSA_SIG object. The ECDSA_SIG_free
// takes care of freeing it.
ECDSA_SIG_free(sig_ob);
} else {
BN_free(r);
BN_free(s);
}
return ret;
}

+ 5
- 5
src/optee_engine/back.h Просмотреть файл

@@ -12,10 +12,10 @@ EVP_PKEY* OPTEE_ENG_load_private_key(
void * callback_data);

int OPTEE_ENG_evp_cb_sign(
EVP_PKEY_CTX * ctx,
unsigned char * sig,
size_t * sigsz,
const unsigned char *tb,
size_t tbsz);
EVP_PKEY_CTX * ctx,
uint8_t * sig,
size_t * sigsz,
const uint8_t *tb,
size_t tbsz);

#endif // BACK_H_

+ 4
- 10
src/optee_engine/front.c Просмотреть файл

@@ -10,7 +10,7 @@
#ifdef OPTEE_ENG_ENGINE_ID
#undef OPTEE_ENG_ENGINE_ID
#endif
#define OPTEE_ENG_ENGINE_ID "optee_eng"
#define OPTEE_ENG_ENGINE_ID "optee"

#ifdef OPTEE_ENG_ENGINE_NAME
#undef OPTEE_ENG_ENGINE_NAME
@@ -18,7 +18,6 @@
#define OPTEE_ENG_ENGINE_NAME "OpTEE OpenSSL ENGINE."

BIO *bio_err = NULL;
static bool is_initialized = false;
static int lib_code = 0;
static int error_loaded = 0;

@@ -118,11 +117,6 @@ static int OPTEE_ENG_pkey_meths(
return 1;
}

static int OPTEE_ENG_register_engine(ENGINE *e) {
ENGINE_set_pkey_meths(e, OPTEE_ENG_pkey_meths);
return 1;
}

static int OPTEE_ENG_bind(ENGINE *e, const char *id) {
if (!ERR_load_crypto_strings()) {
fprintf(stderr, "ERR_load_crypto_strings failed\n");
@@ -130,7 +124,7 @@ static int OPTEE_ENG_bind(ENGINE *e, const char *id) {
}

if (!OPENSSL_init_crypto(
OPENSSL_INIT_LOAD_CONFIG | OPENSSL_INIT_ENGINE_DYNAMIC, NULL)) {
OPENSSL_INIT_ENGINE_DYNAMIC, NULL)) {
fprintf(stderr, "OPENSSL_init_crypto failed\n");
return 0;
}
@@ -138,7 +132,7 @@ static int OPTEE_ENG_bind(ENGINE *e, const char *id) {
NOP(id);
TEST_P(OPTEE_ENG_err_strings());

/* we set logs here to get potential error traces
/* We set logs here to get potential error traces
* from library initialization. */
unsigned level = TEE_DEFAULT_LOG_LEVEL;
(void)get_env_log_level(&level);
@@ -150,7 +144,7 @@ static int OPTEE_ENG_bind(ENGINE *e, const char *id) {
TEST_P(ENGINE_set_name(e, OPTEE_ENG_ENGINE_NAME));
TEST_P(ENGINE_set_destroy_function(e, OPTEE_ENG_destroy));
TEST_P(ENGINE_set_load_privkey_function(e, OPTEE_ENG_load_private_key));
TEST_P(OPTEE_ENG_register_engine(e));
TEST_P(ENGINE_set_pkey_meths(e, OPTEE_ENG_pkey_meths));
debug("Registration done");

return 1;


+ 243
- 0
src/optee_engine/keymgnt.c Просмотреть файл

@@ -0,0 +1,243 @@
/*
* 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 <stdint.h>
#include <stdbool.h>

#include <err.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <assert.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/x509.h>
#include <openssl/obj_mac.h>

/* OP-TEE TEE client API (built by optee_client) */
#include <tee_client_api.h>

/* To the the UUID (found the the TA's h-file(s)) */
#include <user_ta_header_defines.h>

#define TEE_ECC_CURVE_NIST_P256 0x00000003

static uint32_t curve_openssl_to_tee(int openssl_id) {
if (openssl_id != NID_X9_62_prime256v1) {
return 0;
}
return TEE_ECC_CURVE_NIST_P256;
}

// kp_bncpy():
// * buf : either destination buffer or NULL. If NULL buffer is initialized
static void kp_bncpy(struct keybuf_t *b, const BIGNUM *bn) {
b->sz = BN_num_bytes(bn);
// Ensure field is not empty
assert(b->sz);
// Ensure allocation hasn't failed
(void)BN_bn2bin(bn, &b->b[0]);
}

static bool get_keypair(EVP_PKEY *key, struct keypair_t *keypair) {
switch (EVP_PKEY_type(EVP_PKEY_id(key))) {
case EVP_PKEY_EC: {
EC_KEY *ec_key;
const EC_POINT *ec_pub_key;
const EC_GROUP *group;
BIGNUM *x, *y;

keypair->type = KEYTYPE_ECC;
BN_CTX *ctx = BN_CTX_new();
if (!ctx) return false;

// Get curve
ec_key = EVP_PKEY_get1_EC_KEY(key);
if (!ec_key) return false;

ec_pub_key = EC_KEY_get0_public_key(ec_key);
if (!ec_pub_key) return false;

group = EC_KEY_get0_group(ec_key);
if (!group) return false;

// Get private key
const BIGNUM *bn = EC_KEY_get0_private_key(ec_key);
kp_bncpy(&keypair->u.ecc.scalar, bn);

// Get public key
keypair->u.ecc.curve_id
= curve_openssl_to_tee(EC_GROUP_get_curve_name(group));

x = BN_new(); y = BN_new();
if (!x || !y) return false;

if (!EC_POINT_get_affine_coordinates_GFp(group, ec_pub_key, x, y, ctx)) {
BN_free(x); BN_free(y);
return false;
}

kp_bncpy(&keypair->u.ecc.x, x);
kp_bncpy(&keypair->u.ecc.y, y);
OPENSSL_free(ctx);
BN_free(x); BN_free(y); // OMG, refactoring is necessairy

break;
}
default:
errx(1, "Unsupported key type");
return false;
}

return true;
}

// parse_key_from_file: adds a private key from a file location
static int parse_key_from_file(
const char *path,
struct keypair_t *kp) {

BIO *bp;
EVP_PKEY *key;
int ret = 0;

bp = BIO_new(BIO_s_file());
if (!bp) {
goto end;
}

if (!BIO_read_filename(bp, path)) {
errx(1, "Failed to open private key file %s", path);
goto end;
}

key = PEM_read_bio_PrivateKey(bp, 0, 0, 0);
if (!key) {
errx(1, "PEM_read_bio_PrivateKey: failed");
goto end;
}

if (!get_keypair(key, kp)) {
errx(1, "get_keypair: failed");
goto end;
}

ret = 1;
end:
BIO_free(bp);
return ret;
}

int main(int argc, char *argv[])
{
TEEC_Result res;
TEEC_Context ctx;
TEEC_Session sess;
TEEC_Operation op;
TEEC_UUID uuid = TA_UUID;
uint32_t cmd;
struct keypair_t kp = {0};
uint32_t err_origin;
uint8_t key_id[32];

// Initialize a context connecting us to the TEE
res = TEEC_InitializeContext(NULL, &ctx);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_InitializeContext failed with code 0x%x", res);

// Open a session to the TA identified by uuid
res = TEEC_OpenSession(&ctx, &sess, &uuid,
TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
if (res != TEEC_SUCCESS)
errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
res, err_origin);

/* Clear the TEEC_Operation struct */
memset(&op, 0, sizeof(op));

/*
* TA_INSTALL_KEYS is the actual function in the TA to be
* called.
*/
if (argc < 2) {
errx(1, "Key name not provided");
}

if (!EVP_Digest(argv[2], strlen(argv[2]), key_id, NULL, EVP_sha256(), NULL)) {
errx(1, "EVP_Digest");
}

if (!strncmp(argv[1], "put", 3)) {
cmd = TA_INSTALL_KEYS;
if (argc < 3) {
errx(1, "Filename missing\n");
}

if (!parse_key_from_file(argv[3], &kp)) {
errx(1, "parse_key_from_file() failed");
}

op.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_INPUT,
TEEC_NONE,
TEEC_NONE);
op.params[0].tmpref.buffer = (void*) &kp;
op.params[0].tmpref.size = sizeof(kp);
op.params[1].tmpref.buffer = key_id;
op.params[1].tmpref.size = 32;
} else if (!strncmp(argv[1], "del", 3)) {
cmd = TA_DEL_KEYS;
op.paramTypes = TEEC_PARAM_TYPES(
TEEC_MEMREF_TEMP_INPUT,
TEEC_NONE,
TEEC_NONE,
TEEC_NONE);
op.params[0].tmpref.buffer = key_id;
op.params[0].tmpref.size = 32;
} else {
errx(1, "E: Command must be 'put <key_name> filename' or 'del <key_name>'");
}

res = TEEC_InvokeCommand(&sess, cmd, &op, &err_origin);
if (res != TEEC_SUCCESS) {
errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
res, err_origin);
}

/*
* We're done with the TA, close the session and
* destroy the context.
*/
TEEC_CloseSession(&sess);
TEEC_FinalizeContext(&ctx);
return 0;
}

+ 101
- 0
src/optee_engine/speed.cc Просмотреть файл

@@ -0,0 +1,101 @@
#include <stdint.h>
#include <vector>

#include <gtest/gtest.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/engine.h>

#include <benchmark/benchmark.h>

// Size of the input message. It doesn't matter
// for speed as hashing is done in the REE anyway
#define MSG_SIZE 32

// Name of the key stored in the TEE
#define KEY_NAME "bench_key"

// Path to the engine library
#define OPTEE_ENG_PATH "/opt/liboptee_eng.so"

// Engine ID
#define OPTEE_ID "optee"

static void SignREE(benchmark::State& state) {

unsigned char msg[MSG_SIZE];
EVP_MD_CTX * mctx = EVP_MD_CTX_new();
EVP_PKEY * pkey = NULL, *params = NULL;
EVP_PKEY_CTX *pctx, *kctx;

ASSERT_TRUE(mctx);

// Initialize parameters for NIST P-256 curve
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, 0);
ASSERT_TRUE(pctx);
ASSERT_TRUE(EVP_PKEY_paramgen_init(pctx));
ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1));
ASSERT_TRUE(EVP_PKEY_paramgen(pctx, &params));
kctx = EVP_PKEY_CTX_new(params, NULL);
ASSERT_TRUE(kctx);

// Generate key with paramters stored in kctx
ASSERT_EQ(EVP_PKEY_keygen_init(kctx), 1);
ASSERT_EQ(EVP_PKEY_keygen(kctx, &pkey), 1);
ASSERT_TRUE(pkey);

// Setup buffer for signature
size_t siglen = EVP_PKEY_size(pkey);
std::vector<uint8_t> sig;
sig.reserve(siglen);

// Perform benchmarking for signing
ASSERT_EQ(EVP_DigestSignInit(mctx, NULL, 0, 0, pkey), 1);
for (auto _ : state) {
ASSERT_EQ(EVP_DigestSign(mctx, sig.data(), &siglen, msg, MSG_SIZE), 1);
siglen = EVP_PKEY_size(pkey);
}
EVP_MD_CTX_free(mctx);
EVP_PKEY_free(pkey);
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(pctx);
EVP_PKEY_CTX_free(kctx);
}

static void SignTEE(benchmark::State& state) {
const char key_name[] = "bench_key\0";
// load engine
unsigned char msg[MSG_SIZE];
EVP_PKEY * pkey = NULL;
EVP_MD_CTX * mctx = EVP_MD_CTX_new();
ENGINE *e = NULL;

ENGINE_load_dynamic();
e = ENGINE_by_id("dynamic");
ASSERT_TRUE(e);

ENGINE_ctrl_cmd_string(e, "SO_PATH", OPTEE_ENG_PATH, 0);
ENGINE_ctrl_cmd_string(e, "ID", OPTEE_ID, 0);
ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
ENGINE_set_default(e, ENGINE_METHOD_ALL);
ERR_clear_error();

pkey = ENGINE_load_private_key(e, key_name, 0, 0);
ASSERT_TRUE(pkey);

size_t siglen = EVP_PKEY_size(pkey);
std::vector<uint8_t> sig;
sig.reserve(siglen);

ASSERT_EQ(EVP_DigestSignInit(mctx, NULL, 0, 0, pkey), 1);
for (auto _ : state) {
EVP_DigestSign(mctx, sig.data(), &siglen, msg, sizeof msg);
siglen = EVP_PKEY_size(pkey);
}
EVP_MD_CTX_free(mctx);
EVP_PKEY_free(pkey);
}

BENCHMARK(SignREE);
BENCHMARK(SignTEE);
BENCHMARK_MAIN();

+ 1
- 18
src/optee_engine/utils.h Просмотреть файл

@@ -63,26 +63,9 @@ enum {
#define ERR_R_LIST(_) \
_(SUCCESS, "Success") \
_(GENERIC, "Generic") \
_(CANNOT_ALLOCATE_KEY, "key allocation") \
_(BAD_SIGNATURE, "bad signature") \
_(CANNOT_SIGN, "signing operation failed") \
_(CANNOT_GEN_KEY, "failed to generate keys") \
_(INVALID_ENCODING, "invalid encoding") \
_(INVALID_KEY, "invalid key") \
_(INVALID_PEER_KEY, "invalid peer key") \
_(WRONG_PRVKEY_BUF, "invalid private key") \
_(WRONG_PUBKEY_BUF, "invalid public key") \
_(KEYS_NOT_SET, "keys not set") \
_(MISSING_NID_DATA, "failed to get nid_data struct pointer") \
_(MISSING_PRIVATE_KEY, "missing private key") \
_(RNG_FAILED, "random number generation failed") \
_(BAD_PARAMETERS, "bad parameters found") \
_(PASSED_NULL_PARAMETER, "null pointer provided") \
_(NOT_SUPPORTED, "not supported") \
_(WRONG_LENGTH, "wrong length") \
_(OUT_OF_MEMORY, "not enough memory") \
_(INTERNAL, "internal error") \
_(VALUE_NOT_SET, "value not set")
_(INTERNAL, "internal error")

enum {
TEE_R_NONE = 100,


+ 19
- 0
src/ta/Makefile Просмотреть файл

@@ -0,0 +1,19 @@
# The UUID for the Trusted Application
BINARY=8aaaf200-2450-11e4-0060-0dc0ffee0000

CFG_TEE_TA_LOG_LEVEL = 4
CPPFLAGS += -O2 -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
TA_DEV_KIT_DIR=$(OPTEE_ROOT)/optee_os/out/arm/export-ta_arm64
TEEC_EXPORT=$(OPTEE_ROOT)/optee_client/public
HOST_CROSS_COMPILE=$(OPTEE_ROOT)/toolchains/aarch64/bin/aarch64-linux-gnu-
CROSS_COMPILE=${HOST_CROSS_COMPILE}

-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk

ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
clean:
@echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
@echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
rm -rf ${BINARY}.*
rm -rf *.o
endif

+ 345
- 0
src/ta/delegator_tz.c Просмотреть файл

@@ -0,0 +1,345 @@
#include <stdio.h>
#include <string.h>
#include <user_ta_header_defines.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>

#ifdef ATTR_REF
#undef ATTR_REF
#endif
#define ATTR_REF(CNT, ATTR, BUF) \
TEE_InitRefAttribute(&attrs[(CNT)++], (ATTR), (BUF).b, (BUF).sz)

#define LOG_RET(ret) \
if((ret)!=TEE_SUCCESS) { \
EMSG("ERR: %d %X", __LINE__, ret); \
return ret; \
}

// Calculates size of an array
#define ARRAY_SIZE(a) ((sizeof((a))) / sizeof((a)[0]))

/*
* Called when the instance of the TA is created. This is the first call in
* the TA.
*/
TEE_Result TA_CreateEntryPoint(void)
{
DMSG("has been called");
return TEE_SUCCESS;
}

/*
* Called when the instance of the TA is destroyed if the TA has not
* crashed or panicked. This is the last call in the TA.
*/
void TA_DestroyEntryPoint(void) {
DMSG("has been called");
}

/*
* Called when a new session is opened to the TA. *sess_ctx can be updated
* with a value to be able to identify this session in subsequent calls to the
* TA. In this function you will normally do the global initialization for the
* TA.
*/
TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
TEE_Param __maybe_unused params[4],
void __maybe_unused **sess_ctx) {

const uint32_t exp_param_types =
TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);

DMSG("has been called");
if (param_types != exp_param_types) {
return TEE_ERROR_BAD_PARAMETERS;
}

/* Unused parameters */
(void)&params;
(void)&sess_ctx;

/*
* The DMSG() macro is non-standard, TEE Internal API doesn't
* specify any means to logging from a TA.
*/
/* If return value != TEE_SUCCESS the session will not be created. */
return TEE_SUCCESS;
}

/*
* Called when a session is closed, sess_ctx hold the value that was
* assigned by TA_OpenSessionEntryPoint().
*/
void TA_CloseSessionEntryPoint(void __maybe_unused *sess_ctx)
{
(void)&sess_ctx; /* Unused parameter */
EMSG("Session closed\n");
}

// Creates new ECC key
static TEE_ObjectHandle create_ecc_key(struct keypair_t *kp) {
TEE_Result res;
TEE_ObjectHandle obj = TEE_HANDLE_NULL;
TEE_Attribute attrs[4];
struct ECC_t *ecc;
size_t cnt = 0;

ecc = &kp->u.ecc;
res = TEE_AllocateTransientObject(
TEE_TYPE_ECDSA_KEYPAIR,
ecc->x.sz * 8,
&obj);

if (res != TEE_SUCCESS) {
EMSG("E: TEE_AllocateTransientObject failed");
goto err;
}

ATTR_REF(cnt, TEE_ATTR_ECC_PRIVATE_VALUE, ecc->scalar);
ATTR_REF(cnt, TEE_ATTR_ECC_PUBLIC_VALUE_X, ecc->x);
ATTR_REF(cnt, TEE_ATTR_ECC_PUBLIC_VALUE_Y, ecc->y);
TEE_InitValueAttribute(&attrs[cnt++], TEE_ATTR_ECC_CURVE,ecc->curve_id, 0);
// TODO: ecc->scalar shouldn't be extractable, but we store it with
// the public key, and I need to be able to extract it.
// It would be better to store public and private key separately.
res = TEE_RestrictObjectUsage1(obj, TEE_USAGE_EXTRACTABLE|TEE_USAGE_SIGN);
if (res != TEE_SUCCESS ) {
EMSG("E: TEE_RestrictObjectUsage1 failed");
goto err;
}

res = TEE_PopulateTransientObject(obj, attrs, cnt);
if (res != TEE_SUCCESS) {
EMSG("E: TEE_PopulateTransientObject failed");
goto err;
}
return obj;

err:
TEE_FreeTransientObject(obj);
return TEE_HANDLE_NULL;
}

// Puts the key to the storage
static TEE_Result install_key(uint32_t param_types, TEE_Param params[4]) {
TEE_Result ret;
TEE_ObjectHandle transient_obj = TEE_HANDLE_NULL;
TEE_ObjectHandle persistant_obj = TEE_HANDLE_NULL;
uint32_t exp_param_types;
struct keypair_t *kp;
uint8_t key_id[SHA256_SIZE];

exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);

if (param_types != exp_param_types ||
params[1].memref.size != ARRAY_SIZE(key_id)) {
return TEE_ERROR_BAD_PARAMETERS;
}

kp = (struct keypair_t*)params[0].memref.buffer;
if (sizeof(*kp) != params[0].memref.size) {
EMSG("E: wrong size of keypair_t struct");
return TEE_ERROR_BAD_PARAMETERS;
}

// Only ECC supported
if (kp->type != KEYTYPE_ECC) {
EMSG("E: only ECC keys supported");
return TEE_ERROR_BAD_PARAMETERS;
}
transient_obj = create_ecc_key(kp);
if (transient_obj == TEE_HANDLE_NULL) {
EMSG("E: Can't create transient object");
return TEE_ERROR_BAD_PARAMETERS;
}

// Input TEE_CreatePersistentObject can't be NWd shared buffer
memcpy(key_id, params[1].memref.buffer, params[1].memref.size);
ret = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
key_id, ARRAY_SIZE(key_id),
TEE_DATA_FLAG_ACCESS_WRITE,
transient_obj,
NULL/*data*/, 0 /*data_len*/, &persistant_obj);
if (ret) {
EMSG("E: Create");
return ret;
}
IMSG("New key [%02X%02X%02X%02X%02X] registered",
key_id[0], key_id[1], key_id[2], key_id[3], key_id[4]);
TEE_FreeTransientObject(transient_obj);
TEE_CloseObject(persistant_obj);
return TEE_SUCCESS;
}

// Performs key deletion from the secure storage
static TEE_Result del_key(uint32_t param_types, TEE_Param params[4]) {
TEE_Result ret;
char key_id[SHA256_SIZE] = {0};
TEE_ObjectHandle obj = TEE_HANDLE_NULL;
const uint32_t exp_param_types =
TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);

if (param_types != exp_param_types)
return TEE_ERROR_BAD_PARAMETERS;

if (params[0].memref.size > sizeof(key_id)) {
EMSG("E: filename too long (>255)");
return TEE_ERROR_BAD_PARAMETERS;
}

memcpy(key_id, params[0].memref.buffer,
params[0].memref.size);

ret = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
key_id, params[0].memref.size,
TEE_DATA_FLAG_ACCESS_WRITE_META, &obj);
if (ret) {
EMSG("E: Can't open");
return ret;

}
IMSG("Key [%02X%02X%02X%02X%02X] unregistered",
key_id[0], key_id[1], key_id[2], key_id[3], key_id[4]);
TEE_CloseAndDeletePersistentObject(obj);
return TEE_SUCCESS;
}

// returns public key of installed key-pair to the normal world
static TEE_Result get_public_key(uint32_t param_types, TEE_Param params[4]) {
uint32_t exp_param_types;
char key_id[SHA256_SIZE] = {0};
TEE_Result ret;
TEE_ObjectHandle obj = TEE_HANDLE_NULL;

exp_param_types = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_NONE);

if (param_types != exp_param_types) {
EMSG("Unexpected params");
return TEE_ERROR_BAD_PARAMETERS;
}

if (params[0].memref.size < SHA256_SIZE) {
EMSG("key-id must be SHA256 hash");
return TEE_ERROR_BAD_PARAMETERS;
}

memcpy(key_id, params[0].memref.buffer, params[0].memref.size);
ret = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
key_id, ARRAY_SIZE(key_id),
TEE_DATA_FLAG_ACCESS_READ, &obj);

if (ret) {
EMSG("E: Open 0x%X", ret);
return ret;
}

ret = TEE_SUCCESS;
ret |= TEE_GetObjectBufferAttribute(obj, TEE_ATTR_ECC_PUBLIC_VALUE_X,
params[1].memref.buffer, &params[1].memref.size);
ret |= TEE_GetObjectBufferAttribute(obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y,
params[2].memref.buffer, &params[2].memref.size);

if (ret) {
EMSG("E: Can't extract public attributes for ECC key");
goto end;
}

IMSG("Public key for ID [%02X%02X%02X%02X%02X] returned",
key_id[0], key_id[1], key_id[2], key_id[3], key_id[4]);
end:
TEE_CloseObject(obj);
return TEE_SUCCESS;
}

// Performs ECDSA signing with a key from secure storage
static TEE_Result sign_ecdsa(uint32_t param_types, TEE_Param params[4]) {
TEE_Result ret;
TEE_OperationHandle op = TEE_HANDLE_NULL;
TEE_ObjectHandle obj = TEE_HANDLE_NULL;
uint8_t key_id[SHA256_SIZE];

const uint32_t exp_param_types =
TEE_PARAM_TYPES(
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_NONE);

if ((param_types != exp_param_types) ||
(params[0].memref.size > ARRAY_SIZE(key_id))) {
return TEE_ERROR_BAD_PARAMETERS;
}

// Must be local
memcpy(key_id, params[0].memref.buffer, params[0].memref.size);

IMSG("Sign for a key ID [%02X%02X%02X%02X%02X] requested",
key_id[0], key_id[1], key_id[2], key_id[3], key_id[4]);

ret = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
key_id, ARRAY_SIZE(key_id),
TEE_DATA_FLAG_ACCESS_READ, &obj);
if (ret) {
EMSG("E: Can't open");
return ret;
}

// perform ECDSA sigining
ret = TEE_AllocateOperation(&op, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, 256);
LOG_RET(ret);
ret = TEE_SetOperationKey(op, obj);
LOG_RET(ret);
ret = TEE_AsymmetricSignDigest(op, NULL, 0,
params[1].memref.buffer, params[1].memref.size,
params[2].memref.buffer, &params[2].memref.size);
LOG_RET(ret);

TEE_CloseObject(obj);
TEE_FreeOperation(op);

IMSG("Message signed with key ID [%02X%02X%02X%02X%02X]",
key_id[0], key_id[1], key_id[2], key_id[3], key_id[4]);
return TEE_SUCCESS;
}

/*
* Called when a TA is invoked. sess_ctx hold that value that was
* assigned by TA_OpenSessionEntryPoint(). The rest of the paramters
* comes from normal world.
*/
TEE_Result TA_InvokeCommandEntryPoint(void __maybe_unused *sess_ctx,
uint32_t cmd_id,
uint32_t param_types, TEE_Param params[4]) {
(void)&sess_ctx; /* Unused parameter */
switch (cmd_id) {
case TA_INSTALL_KEYS:
return install_key(param_types, params);
case TA_DEL_KEYS:
return del_key(param_types, params);
case TA_GET_PUB_KEY:
return get_public_key(param_types, params);
case TA_SIGN_ECC:
return sign_ecdsa(param_types, params);
default:
EMSG("Request not supported");
return TEE_ERROR_BAD_PARAMETERS;
}
}

+ 67
- 0
src/ta/include/user_ta_header_defines.h Просмотреть файл

@@ -0,0 +1,67 @@
#ifndef TA_DELEGATOR_TZ_H
#define TA_DELEGATOR_TZ_H

#include <stdint.h>
#include <stddef.h>

/*
* This UUID is generated with uuidgen
* the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
*/
#define TA_UUID \
{ 0x8aaaf200, 0x2450, 0x11e4, \
{ 0x00, 0x60, 0x0d, 0xc0, 0xff, 0xee, 0x00, 0x00}}

/*
* TA properties: multi-instance TA, no specific attribute
* TA_FLAG_EXEC_DDR is meaningless but mandated.
*/
#define TA_FLAGS TA_FLAG_EXEC_DDR

/* Provisioned stack size */
#define TA_STACK_SIZE (1 * 1024)

/* Provisioned heap size for TEE_Malloc() and friends */
#define TA_DATA_SIZE (1 * 1024)

/* Extra properties (give a version id and a string name) */
#define TA_CURRENT_TA_EXT_PROPERTIES \
{ "gp.ta.description", USER_TA_PROP_TYPE_STRING, "TLS signer TZ" }, \
{ "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } \
}

/* The function IDs implemented in this TA */
#define TA_INSTALL_KEYS 0
#define TA_DEL_KEYS 1
#define TA_SIGN_ECC 2
#define TA_GET_PUB_KEY 3

// SHA-256 output size
#define SHA256_SIZE 32

#define MAX_KEY_SIZE 512

struct keybuf_t {
uint8_t b[MAX_KEY_SIZE];
size_t sz;
};

typedef enum {
KEYTYPE_ECC = 1,
// ... RSA, PQ ...
} keytype_t;

struct keypair_t {
keytype_t type;
union {
struct ECC_t {
uint32_t curve_id;
struct keybuf_t scalar;
struct keybuf_t x;
struct keybuf_t y;
} ecc;
// rsa, pq, ...
} u;
};

#endif /*TA_DELEGATOR_TZ_H*/

+ 2
- 0
src/ta/sub.mk Просмотреть файл

@@ -0,0 +1,2 @@
global-incdirs-y += include
srcs-y += delegator_tz.c

Загрузка…
Отмена
Сохранить