From 585f65b76c29ffea6f8e8a57e2805846aa11cc7d Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Wed, 27 Mar 2024 09:29:10 +0200 Subject: [PATCH] Add ed25519 signing support --- .../include/px4_platform_common/crypto.h | 25 +++++-- .../px4_platform_common/crypto_backend.h | 65 ++++++++++++++++--- platforms/nuttx/src/px4/common/px4_crypto.cpp | 33 +++++++++- .../nuttx/src/px4/common/px4_usr_crypto.cpp | 23 ++++++- src/drivers/sw_crypto/crypto.c | 52 ++++++++++++++- 5 files changed, 176 insertions(+), 22 deletions(-) diff --git a/platforms/common/include/px4_platform_common/crypto.h b/platforms/common/include/px4_platform_common/crypto.h index f82e5f1530d3..19cdc2bf2c90 100644 --- a/platforms/common/include/px4_platform_common/crypto.h +++ b/platforms/common/include/px4_platform_common/crypto.h @@ -97,17 +97,14 @@ class PX4Crypto /* * Generate a key pair for asymmetric-key encryption * - * algorithm: the key type * key_size: size of the key in bytes - * private_idx: the private key will be stored in this index in the keystore - * public_idx: the public key will be stored in this index in the keystore + * key_idx: the keys will be stored in this index in the keystore * persistent: whether the keys need to be stored persistently * returns true on success, false on failure */ bool generate_keypair(size_t key_size, - uint8_t private_idx, - uint8_t public_idx, + uint8_t key_idx, bool persistent); @@ -173,6 +170,20 @@ class PX4Crypto * PX4 Crypto API functions */ + /* + * Message signing + * + * key_index: private key index in keystore + * signature: pointer to the output signature + * message: pointer to the data to be signed + * message_size: size of the message in bytes + */ + + bool sign(uint8_t key_index, + uint8_t *signature, + const uint8_t *message, + size_t message_size); + /* * Verify signature * @@ -182,7 +193,7 @@ class PX4Crypto * message_size: size of the message in bytes */ - bool signature_check(uint8_t key_index, + bool signature_check(uint8_t key_index, const uint8_t *signature, const uint8_t *message, size_t message_size); @@ -203,7 +214,7 @@ class PX4Crypto * returns true on success, false on failure */ - bool encrypt_data(uint8_t key_index, + bool encrypt_data(uint8_t key_index, const uint8_t *message, size_t message_size, uint8_t *cipher, diff --git a/platforms/common/include/px4_platform_common/crypto_backend.h b/platforms/common/include/px4_platform_common/crypto_backend.h index da7d4998284f..6be3969131b1 100644 --- a/platforms/common/include/px4_platform_common/crypto_backend.h +++ b/platforms/common/include/px4_platform_common/crypto_backend.h @@ -137,6 +137,19 @@ bool crypto_generate_key(crypto_session_handle_t handle, uint8_t idx, bool persistent); +/* + * Generate key pair + * handle: Open handle for the crypto session. The key will be generated for + * the crypto algorithm used by this session + * key_size: size of the private key + * key_idx: The key index, by which the keys can be used + * persistent: if set to "true", the keys will be stored into the keystore + */ +bool crypto_generate_keypair(crypto_session_handle_t handle, + size_t key_size, + uint8_t key_idx, + bool persistent); + /* * Get a key from keystore, possibly encrypted * @@ -181,22 +194,39 @@ bool crypto_get_nonce(crypto_session_handle_t handle, uint8_t *nonce, size_t *nonce_len); + +/* + * Perform signing using an open session to crypto + * handle: session handle, returned by open + * key_index: index to the key used for signing + * signature: pointer to output signature data + * message: pointer to the data to be signed + * message_size: size of the data + */ + +bool crypto_signature_gen(crypto_session_handle_t handle, + uint8_t key_index, + uint8_t *signature, + const uint8_t *message, + size_t message_size); + /* * Perform signature check using an open session to crypto * handle: session handle, returned by open * key_index: index to the key used for signature check + * signature: pointer to the signature * message: pointer to the data to be checked * message_size: size of the data */ bool crypto_signature_check(crypto_session_handle_t handle, - uint8_t key_index, - const uint8_t *signature, + uint8_t key_index, + const uint8_t *signature, const uint8_t *message, size_t message_size); bool crypto_encrypt_data(crypto_session_handle_t handle, - uint8_t key_index, + uint8_t key_index, const uint8_t *message, size_t message_size, uint8_t *cipher, @@ -253,7 +283,7 @@ typedef struct cryptoiocopen { #define CRYPTOIOCENCRYPT _CRYPTOIOC(3) typedef struct cryptoiocencrypt { crypto_session_handle_t *handle; - uint8_t key_index; + uint8_t key_index; const uint8_t *message; size_t message_size; uint8_t *cipher; @@ -304,17 +334,27 @@ typedef struct cryptoiocrenewnonce { size_t ret; } cryptoiocrenewnonce_t; -#define CRYPTOIOCSIGNATURECHECK _CRYPTOIOC(9) +#define CRYPTOIOCSIGN _CRYPTOIOC(9) +typedef struct cryptoiocsign { + crypto_session_handle_t *handle; + uint8_t key_index; + uint8_t *signature; + const uint8_t *message; + size_t message_size; + size_t ret; +} cryptoiocsign_t; + +#define CRYPTOIOCSIGNATURECHECK _CRYPTOIOC(10) typedef struct cryptoiocsignaturecheck { crypto_session_handle_t *handle; - uint8_t key_index; - const uint8_t *signature; + uint8_t key_index; + const uint8_t *signature; const uint8_t *message; size_t message_size; size_t ret; } cryptoiocsignaturecheck_t; -#define CRYPTOIOCDECRYPTDATA _CRYPTOIOC(10) +#define CRYPTOIOCDECRYPTDATA _CRYPTOIOC(11) typedef struct cryptoiocdecryptdata { crypto_session_handle_t *handle; uint8_t key_index; @@ -327,6 +367,15 @@ typedef struct cryptoiocdecryptdata { size_t ret; } cryptoiocdecryptdata_t; +#define CRYPTOIOCGENKEYPAIR _CRYPTOIOC(12) +typedef struct cryptoiocgenkeypair { + crypto_session_handle_t *handle; + size_t key_size; + uint8_t key_idx; + bool persistent; + bool ret; +} cryptoiocgenkeypair_t; + #if defined(__cplusplus) } // extern "C" #endif diff --git a/platforms/nuttx/src/px4/common/px4_crypto.cpp b/platforms/nuttx/src/px4/common/px4_crypto.cpp index 6cafd9b250f3..c27e650cd68b 100644 --- a/platforms/nuttx/src/px4/common/px4_crypto.cpp +++ b/platforms/nuttx/src/px4/common/px4_crypto.cpp @@ -117,7 +117,15 @@ void PX4Crypto::close() unlock(); } -bool PX4Crypto::signature_check(uint8_t key_index, +bool PX4Crypto::sign(uint8_t key_index, + uint8_t *signature, + const uint8_t *message, + size_t message_size) +{ + return crypto_signature_gen(_crypto_handle, key_index, signature, message, message_size); +} + +bool PX4Crypto::signature_check(uint8_t key_index, const uint8_t *signature, const uint8_t *message, size_t message_size) @@ -125,7 +133,7 @@ bool PX4Crypto::signature_check(uint8_t key_index, return crypto_signature_check(_crypto_handle, key_index, signature, message, message_size); } -bool PX4Crypto::encrypt_data(uint8_t key_index, +bool PX4Crypto::encrypt_data(uint8_t key_index, const uint8_t *message, size_t message_size, uint8_t *cipher, @@ -154,6 +162,13 @@ bool PX4Crypto::generate_key(uint8_t idx, return crypto_generate_key(_crypto_handle, idx, persistent); } +bool PX4Crypto::generate_keypair(size_t key_size, + uint8_t key_idx, + bool persistent) +{ + return crypto_generate_keypair(_crypto_handle, key_size, key_idx, persistent); +} + bool PX4Crypto::renew_nonce(const uint8_t *nonce, size_t nonce_size) { @@ -209,6 +224,13 @@ int PX4Crypto::crypto_ioctl(unsigned int cmd, unsigned long arg) } break; + + case CRYPTOIOCGENKEYPAIR: { + cryptoiocgenkeypair_t *data = (cryptoiocgenkeypair_t *)arg; + data->ret = crypto_generate_keypair(*(data->handle), data->key_size, data->key_idx, data->persistent); + } + break; + case CRYPTOIOCRENEWNONCE: { cryptoiocrenewnonce_t *data = (cryptoiocrenewnonce_t *)arg; data->ret = crypto_renew_nonce(*(data->handle), data->nonce, data->nonce_size); @@ -229,6 +251,13 @@ int PX4Crypto::crypto_ioctl(unsigned int cmd, unsigned long arg) } break; + case CRYPTOIOCSIGN: { + cryptoiocsign_t *data = (cryptoiocsign_t *)arg; + data->ret = crypto_signature_gen(*(data->handle), data->key_index, data->signature, data->message, + data->message_size); + } + break; + case CRYPTOIOCSIGNATURECHECK: { cryptoiocsignaturecheck_t *data = (cryptoiocsignaturecheck_t *)arg; data->ret = crypto_signature_check(*(data->handle), data->key_index, data->signature, data->message, diff --git a/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp b/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp index 22f4bb113df5..a44567f7df85 100644 --- a/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp +++ b/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp @@ -77,7 +77,7 @@ void PX4Crypto::close() boardctl(CRYPTOIOCCLOSE, reinterpret_cast(&_crypto_handle)); } -bool PX4Crypto::signature_check(uint8_t key_index, +bool PX4Crypto::signature_check(uint8_t key_index, const uint8_t *signature, const uint8_t *message, size_t message_size) @@ -87,7 +87,17 @@ bool PX4Crypto::signature_check(uint8_t key_index, return data.ret; } -bool PX4Crypto::encrypt_data(uint8_t key_index, +bool PX4Crypto::sign(uint8_t key_index, + uint8_t *signature, + const uint8_t *message, + size_t message_size) +{ + cryptoiocsign_t data = {&_crypto_handle, key_index, signature, message, message_size, false}; + boardctl(CRYPTOIOCSIGN, reinterpret_cast(&data)); + return data.ret; +} + +bool PX4Crypto::encrypt_data(uint8_t key_index, const uint8_t *message, size_t message_size, uint8_t *cipher, @@ -121,6 +131,15 @@ bool PX4Crypto::generate_key(uint8_t idx, return data.ret; } +bool PX4Crypto::generate_keypair(size_t key_size, + uint8_t key_idx, + bool persistent) +{ + cryptoiocgenkeypair_t data = {&_crypto_handle, key_size, key_idx, persistent, false}; + boardctl(CRYPTOIOCGENKEYPAIR, reinterpret_cast(&data)); + return data.ret; +} + bool PX4Crypto::renew_nonce(const uint8_t *nonce, size_t nonce_size) { diff --git a/src/drivers/sw_crypto/crypto.c b/src/drivers/sw_crypto/crypto.c index 3ef3cc206aa3..136c250798ec 100644 --- a/src/drivers/sw_crypto/crypto.c +++ b/src/drivers/sw_crypto/crypto.c @@ -214,9 +214,47 @@ void crypto_close(crypto_session_handle_t *handle) handle->context = NULL; } +bool crypto_signature_gen(crypto_session_handle_t handle, + uint8_t key_index, + uint8_t *signature, + const uint8_t *message, + size_t message_size) +{ + bool ret = false; + size_t keylen = 0; + const uint8_t *private_key = NULL; + + if (crypto_session_handle_valid(handle)) { + private_key = crypto_get_key_ptr(handle.keystore_handle, key_index, &keylen); + } + + if (keylen == 0 || private_key == NULL) { + return false; + } + + switch (handle.algorithm) { + case CRYPTO_ED25519: + if (keylen >= 32) { + /* In the DER format ed25519 key the raw private key part is always the last 32 bytes. + * This simple "parsing" works for both "raw" key and DER format + */ + private_key += keylen - 32; + crypto_ed25519_sign(signature, private_key, 0, message, message_size); + ret = (signature != NULL); + } + + break; + + default: + ret = false; + } + + return ret; +} + bool crypto_signature_check(crypto_session_handle_t handle, - uint8_t key_index, - const uint8_t *signature, + uint8_t key_index, + const uint8_t *signature, const uint8_t *message, size_t message_size) { @@ -252,7 +290,7 @@ bool crypto_signature_check(crypto_session_handle_t handle, } bool crypto_encrypt_data(crypto_session_handle_t handle, - uint8_t key_idx, + uint8_t key_idx, const uint8_t *message, size_t message_size, uint8_t *cipher, @@ -330,6 +368,14 @@ bool crypto_encrypt_data(crypto_session_handle_t handle, return ret; } +bool crypto_generate_keypair(crypto_session_handle_t handle, + size_t key_size, uint8_t key_idx, + bool persistent) +{ + /* unimplemented */ + return false; +} + bool crypto_generate_key(crypto_session_handle_t handle, uint8_t idx, bool persistent) {