Skip to content

Commit

Permalink
options: tee: manufacturing protection
Browse files Browse the repository at this point in the history
This option allows lmp-device-register to interrogate the CAAM hardware
for an EC public key (256 bits usually)

The key will be stored in /var/sota in PEM format (for reference) and
passed to the gateway.

Afer registration aktualizer-lite should periodically request the CAAM
hardware to sign random strings and send these signatures to the gateway
along with the message.

See [1] for optee-client reference.

Upon receiving these digests, the gateway shall verify them using the
board associated public key

[1] OP-TEE/optee_client#352

Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
  • Loading branch information
ldts committed Aug 28, 2023
1 parent d281ad3 commit e5d8d5b
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 6 deletions.
25 changes: 20 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,29 @@ pkg_search_module(GLIB REQUIRED glib-2.0)
# Use C++11, but without GNU or other extensions
set(CMAKE_CXX_STANDARD 11)

set(LMP_SRCS src/main.cpp src/options.cpp src/auth.cpp src/openssl.cpp)
set(LMP_LIBS ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS} ${OPENSSL_LIBRARIES})
set(LMP_INCS PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> ${GLIB_INCLUDE_DIRS})

# PKCS11 configuration
if(DISABLE_PKCS11)
add_executable(lmp-device-register src/main.cpp src/options.cpp src/auth.cpp src/pkcs11_stub.cpp src/openssl.cpp)
target_link_libraries(lmp-device-register ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS} ${OPENSSL_LIBRARIES})
set(LMP_SRCS ${LMP_SRCS} src/pkcs11_stub.cpp)
else(DISABLE_PKCS11)
pkg_check_modules(LIBP11 REQUIRED libp11)
add_executable(lmp-device-register src/main.cpp src/options.cpp src/auth.cpp src/pkcs11.cpp src/openssl.cpp)
target_link_libraries(lmp-device-register ${CURL_LIBRARIES} ${Boost_LIBRARIES} ${GLIB_LDFLAGS} ${OPENSSL_LIBRARIES} ${LIBP11_LIBRARIES})
set(LMP_SRCS ${LMP_SRCS} src/pkcs11.cpp)
set(LMP_LIBS ${LMP_LIBS} ${LIBP11_LIBRARIES})
endif(DISABLE_PKCS11)

target_include_directories(lmp-device-register PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc> ${GLIB_INCLUDE_DIRS})
# OPTEE_CLIENT configuration
if(ENABLE_TEE)
set(LMP_SRCS ${LMP_SRCS} src/tee.cpp)
set(LMP_LIBS ${LMP_LIBS} ptateec)
set(LMP_INCS ${LMP_INCS} ${OPTEE_TEST_SDK}/host_include)
else(ENABLE_TEE)
set(LMP_SRCS ${LMP_SRCS} src/tee_stub.cpp)
endif(ENABLE_TEE)

add_executable(lmp-device-register ${LMP_SRCS})
target_link_libraries(lmp-device-register ${LMP_LIBS})
target_include_directories(lmp-device-register ${LMP_INCS} )
install(TARGETS lmp-device-register RUNTIME DESTINATION bin)
10 changes: 10 additions & 0 deletions inc/device_register.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
#include <unistd.h>

#include <openssl/pem.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/encoder.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/buffer.h>
#include <openssl/buffer.h>
#include <openssl/param_build.h>

#include <boost/algorithm/string.hpp>
#include <boost/beast/core/detail/base64.hpp>
Expand Down Expand Up @@ -87,8 +91,10 @@ struct lmp_options {
string hsm_pin;
string sota_dir;
string pacman_tags;
string mprotect_key;
bool start_daemon;
bool use_server;
bool mprotect;
bool production;
bool mlock;
bool vuuid;
Expand All @@ -109,9 +115,13 @@ int options_parse(int argc, char **argv, lmp_options &options);
int openssl_create_csr(const lmp_options &options, string &key, string &csr);
int openssl_gen_csr(const lmp_options &options, EVP_PKEY *pub, EVP_PKEY *priv,
string &csr);
int openssl_ec_raw_to_pem(string &raw, string &pem);

int pkcs11_create_csr(const lmp_options &options, string &key, string &csr);
int pkcs11_store_cert(lmp_options &opt, X509 *cert);
int pkcs11_get_uuid(lmp_options &options);
int pkcs11_check_hsm(lmp_options &opt);

int tee_imx_get_mprotect_pubkey(lmp_options &opt);

#endif
35 changes: 35 additions & 0 deletions inc/pta_imx_manufacturing_protection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright 2018-2019, 2023 NXP
*/
#ifndef PTA_IMX_MANUFACTURING_PROTECTION_H
#define PTA_IMX_MANUFACTURING_PROTECTION_H

#define PTA_MANUFACT_PROTEC_UUID { 0x83268b7c, 0x85e3, 0x11e8, \
{ 0xad, 0xc0, 0xfa, 0x7a, 0xe0, 0x1b, 0xbe, 0xbc} }

/*
* Sign the given message with the manufacturing protection private key
*
* [in] memref[0].buffer Message buffer
* [in] memref[0].size Message size
* [out] memref[1].buffer Signature buffer
* [out] memref[1].size Signature size
* [out] memref[2].buffer MPMR buffer
* [out] memref[2].size MPMR size
*/
#define PTA_IMX_MP_CMD_SIGNATURE_MPMR 0

/*
* Get the manufacturing protection public key
*
* [out] memref[0].buffer Public key buffer
* [out] memref[0].size Public key size
*
* Return codes:
* TEE_SUCCESS - Invoke command success
* TEE_ERROR_BAD_PARAMETERS - Incorrect input param
*/
#define PTA_IMX_MP_CMD_GET_PUBLIC_KEY 1

#endif /* PTA_IMX_MANUFACTURING_PROTECTION_H */
11 changes: 11 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ static void get_device_info(const lmp_options &opt, string &csr, ptree &dev)
dev.put("uuid", opt.uuid);
dev.put("csr", csr);

/* Manufacturing Protect key */
if (!opt.mprotect_key.empty())
dev.put("mpkey", opt.mprotect_key);

/* HSM information */
put_hsm_info(opt, dev);

Expand Down Expand Up @@ -214,6 +218,13 @@ static int populate_sota_dir(lmp_options &opt, ptree &resp, string &pkey)
out.close();
}

if (!opt.mprotect_key.empty()) {
/* Write the MProtect public key */
std::ofstream out(opt.sota_dir + "/mprotect_key.pem");
out << opt.mprotect_key;
out.close();
}

stringstream sota_toml;
for (auto it: resp) {
string name = opt.sota_dir + "/" + it.first;
Expand Down
47 changes: 46 additions & 1 deletion src/openssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*
* SPDX-License-Identifier: MIT
*/

#include <device_register.h>

#define leave \
Expand Down Expand Up @@ -185,3 +184,49 @@ int openssl_create_csr(const lmp_options &options, string &pkey, string &csr)

return 0;
}

int openssl_ec_raw_to_pem(string &raw, string &key_pem)
{
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *key = NULL;
char *pem = nullptr;

OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();

OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
(char *)SN_X9_62_prime256v1, 0);

OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
raw.c_str(), raw.size());

OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);

ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
if (ctx == NULL ||
params == NULL ||
EVP_PKEY_fromdata_init(ctx) <= 0 ||
EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) <= 0)
leave;

BIO *pem_bio = BIO_new(BIO_s_mem());
if (!pem_bio)
leave;

if (PEM_write_bio_PUBKEY_ex(pem_bio, key, NULL, NULL) == 0)
leave;

int pem_len = BIO_get_mem_data(pem_bio, &pem);
if (pem_len < 0)
leave;

string pem_str(reinterpret_cast<char *>(pem), pem_len);
key_pem = pem_str;

/* Clean up */
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);

return 0;
}
12 changes: 12 additions & 0 deletions src/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ namespace po = boost::program_options;
#define TAGS_HELP \
"Configure " SOTA_CLIENT " to only apply updates from Targets with these tags."

#define MP_HELP \
"Enable iMX Manufacturing Protection feature: a board specific ECDSA public" \
"key will be obtained from the SoC and handled to the server."

#define DAEMON_HELP \
"Start the " SOTA_CLIENT " systemd service after registration."

Expand Down Expand Up @@ -134,6 +138,7 @@ static void set_default_options(lmp_options &opt, string factory, string tags,

("help", "print usage")
OPT_DEF_BOOL("use-ostree-server", opt.use_server, true, OSTREE_SRV_HELP)
OPT_DEF_BOOL("manufacturing-protection,w", opt.mprotect, false, MP_HELP)
OPT_DEF_BOOL("production,p", opt.production, prod, PRODUCTION_HELP)
OPT_DEF_BOOL("start-daemon", opt.start_daemon,true, DAEMON_HELP)
OPT_DEF_STR("sota-dir,d", opt.sota_dir, SOTA_DIR, SOTA_DIR_HELP)
Expand Down Expand Up @@ -323,6 +328,13 @@ int options_parse(int argc, char **argv, lmp_options &opt)
opt.name = opt.uuid;
}

if (opt.mprotect) {
if (tee_imx_get_mprotect_pubkey(opt)) {
cerr << "Error reading the MProtection key" << endl;
return -1;
}
}

if (opt.mlock) {
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
cout << "Error locking memory " << endl;
Expand Down
31 changes: 31 additions & 0 deletions src/tee.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2023 Foundries.io
*
* SPDX-License-Identifier: MIT
*/
#include <device_register.h>
#include <pta_tee.h>
#include <stdio.h>

int tee_imx_get_mprotect_pubkey(lmp_options &opt)
{
char key[257] = { 0 };
size_t key_len = sizeof(key) - 1;
string ec_raw;
PTA_RV res;

memset(key, '\0', sizeof(key));

/* Uncompressed format*/
key[0] = POINT_CONVERSION_UNCOMPRESSED;

res = pta_imx_mprotect_get_key(key + 1, &key_len);
if (res != PTAR_OK) {
cout << "Can't get the MProtect key (" << res << ")" << endl;
return -1;
}

ec_raw = string(key);

return openssl_ec_raw_to_pem(ec_raw, opt.mprotect_key);
}
20 changes: 20 additions & 0 deletions src/tee_stub.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2023 Foundries.io
*
* SPDX-License-Identifier: MIT
*/
#include <device_register.h>
#include <stdio.h>

int tee_imx_get_mprotect_pubkey(lmp_options &opt)
{
/* Taken from imx8mm */
string ec_raw = "8EE2ECDD46EEF367774F225E4EAD75A8"
"0FD71C8A1B03779H9H0808C053584C14"
"6FF5114EA17220A513C15F91D314766D"
"316840DF69740BBB8E48BC39C84887BE";

cout << "WARNING: using Manufacturing Protection stub" << endl;

return openssl_ec_raw_to_pem(ec_raw,opt.mprotect_key);
}

0 comments on commit e5d8d5b

Please sign in to comment.