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 in DER format.

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 24, 2023
1 parent d281ad3 commit ee54862
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 5 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)
9 changes: 9 additions & 0 deletions inc/device_register.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,13 @@ struct lmp_options {
string hsm_pin;
string sota_dir;
string pacman_tags;
struct {
string der;
string pem;
} mprotect_key;
bool start_daemon;
bool use_server;
bool mprotect;
bool production;
bool mlock;
bool vuuid;
Expand All @@ -109,9 +114,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_der(string &raw, string &pem, string &der);

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.der.empty())
dev.put("mpkey", opt.mprotect_key.der);

/* 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.pem.empty()) {
/* Write the MProtect public key */
std::ofstream out(opt.sota_dir + "/mprotect_key.pem");
out << opt.mprotect_key.pem;
out.close();
}

stringstream sota_toml;
for (auto it: resp) {
string name = opt.sota_dir + "/" + it.first;
Expand Down
61 changes: 61 additions & 0 deletions src/openssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,64 @@ int openssl_create_csr(const lmp_options &options, string &pkey, string &csr)

return 0;
}

int openssl_ec_raw_to_pem_der(string &raw, string &key_pem, string &key_der)
{
EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1);
EC_POINT *point = EC_POINT_new(group);
EC_KEY *ec_key = EC_KEY_new();
BIGNUM *x_bn = nullptr;
BIGNUM *y_bn = nullptr;
char *pem = nullptr;
char *der = nullptr;

x_bn = BN_bin2bn((unsigned char *)raw.c_str(),
raw.size() / 2, nullptr);

y_bn = BN_bin2bn((unsigned char *)raw.c_str() + raw.size() / 2,
raw.size() / 2, nullptr);

if (!EC_KEY_set_group(ec_key, group))
leave;

if (EC_POINT_set_affine_coordinates_GFp(group, point, x_bn, y_bn,
nullptr))
leave;

if (!EC_KEY_set_public_key(ec_key, point))
leave;

/* Convert the EC public key to DER format and put it in a string */
int der_len = i2d_EC_PUBKEY(ec_key, (unsigned char **)&der);
if (der_len < 0)
leave;

string der_str(reinterpret_cast<char*>(der), der_len);
key_der = der_str;

/* Convert the EC public key to PEM format and put it in a string */
BIO *pem_bio = BIO_new(BIO_s_mem());
if (pem_bio == nullptr)
leave;

if (PEM_write_bio_EC_PUBKEY(pem_bio, ec_key) == 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 */
OPENSSL_free(der);
EC_KEY_free(ec_key);
EC_POINT_free(point);
EC_GROUP_free(group);
BN_free(x_bn);
BN_free(y_bn);
BIO_free(pem_bio);

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
30 changes: 30 additions & 0 deletions src/tee.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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[256] = { 0 };
size_t len = sizeof(key);
string ec_raw;
PTA_RV res;

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

res = pta_imx_mprotect_get_key(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_der(ec_raw,
opt.mprotect_key.pem,
opt.mprotect_key.der);
}
21 changes: 21 additions & 0 deletions src/tee_stub.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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_der(ec_raw,opt.mprotect_key.pem,
opt.mprotect_key.der);
}

0 comments on commit ee54862

Please sign in to comment.