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 the CSR using a custom extension [1]

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 [2] for optee-client reference.

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

[1] "1.3.6.1.4.1.294.1.00"
[2] OP-TEE/optee_client#352

Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
  • Loading branch information
ldts committed Aug 29, 2023
1 parent d281ad3 commit f8f913c
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 10 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 */
7 changes: 7 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,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
88 changes: 83 additions & 5 deletions src/openssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
*
* SPDX-License-Identifier: MIT
*/

#include <device_register.h>

#define CUSTOM_EXT_MPROTECT_KEY_OID ((const char *)"1.3.6.1.4.1.294.1.00")

#define leave \
({ cerr << "Error !"<< endl; \
cerr << " Commit : " << GIT_COMMIT << endl; \
Expand All @@ -25,6 +26,31 @@ static int add_ext(STACK_OF(X509_EXTENSION)*sk, int nid, char *value)
return 0;
}

static int add_custom_ext(STACK_OF(X509_EXTENSION)*sk, const char *objectid,
string data)
{
if (data.empty())
return 0;

ASN1_OBJECT *oid = OBJ_txt2obj(objectid, 1);
if (!oid)
return -1;

ASN1_OCTET_STRING *str = ASN1_OCTET_STRING_new();
ASN1_OCTET_STRING_set(str, (const unsigned char *)data.c_str(),
(int)data.size());

X509_EXTENSION *ex = X509_EXTENSION_create_by_OBJ(NULL, oid, 0, str);
if (!ex)
return -1;

sk_X509_EXTENSION_push(sk, ex);

ASN1_OBJECT_free(oid);
ASN1_OCTET_STRING_free(str);
return 0;
}

/* Use external keys (not created with OpenSSL) to generate a CSR */
int openssl_gen_csr(const lmp_options &opt, EVP_PKEY *pub, EVP_PKEY *priv,
string &csr)
Expand Down Expand Up @@ -67,6 +93,9 @@ int openssl_gen_csr(const lmp_options &opt, EVP_PKEY *pub, EVP_PKEY *priv,
if (add_ext(ext, NID_ext_key_usage, (char *)"clientAuth"))
leave;

if (add_custom_ext(ext, CUSTOM_EXT_MPROTECT_KEY_OID, opt.mprotect_key))
leave;

if (X509_REQ_add_extensions(req, ext) != 1)
leave;

Expand All @@ -91,7 +120,7 @@ int openssl_gen_csr(const lmp_options &opt, EVP_PKEY *pub, EVP_PKEY *priv,
return 0;
}

int openssl_create_csr(const lmp_options &options, string &pkey, string &csr)
int openssl_create_csr(const lmp_options &opt, string &pkey, string &csr)
{
STACK_OF(X509_EXTENSION) *ext = NULL;
X509_NAME *name = NULL;
Expand All @@ -110,16 +139,16 @@ int openssl_create_csr(const lmp_options &options, string &pkey, string &csr)

if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(const unsigned char *)
options.uuid.c_str(), -1, -1, 0) != 1)
opt.uuid.c_str(), -1, -1, 0) != 1)
leave;

if (X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC,
(const unsigned char *)
options.factory.c_str(), -1, -1, 0) != 1)
opt.factory.c_str(), -1, -1, 0) != 1)
leave;


if (options.production) {
if (opt.production) {
if (X509_NAME_add_entry_by_txt(name, LN_businessCategory,
MBSTRING_ASC,
(const unsigned char *)
Expand All @@ -135,6 +164,9 @@ int openssl_create_csr(const lmp_options &options, string &pkey, string &csr)
if (add_ext(ext, NID_ext_key_usage, (char *)"clientAuth"))
leave;

if (add_custom_ext(ext, CUSTOM_EXT_MPROTECT_KEY_OID, opt.mprotect_key))
leave;

if (X509_REQ_add_extensions(req, ext) != 1)
leave;

Expand Down Expand Up @@ -185,3 +217,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 f8f913c

Please sign in to comment.