diff --git a/platforms/common/include/px4_platform_common/crypto.h b/platforms/common/include/px4_platform_common/crypto.h index 554b6d4891..94016e0fa6 100644 --- a/platforms/common/include/px4_platform_common/crypto.h +++ b/platforms/common/include/px4_platform_common/crypto.h @@ -208,6 +208,8 @@ public: size_t get_min_blocksize(uint8_t key_idx); + static int crypto_ioctl(unsigned int cmd, unsigned long arg); + private: crypto_session_handle_t _crypto_handle; static px4_sem_t _lock; diff --git a/platforms/common/include/px4_platform_common/crypto_backend.h b/platforms/common/include/px4_platform_common/crypto_backend.h index 1b1df6e87b..5093933679 100644 --- a/platforms/common/include/px4_platform_common/crypto_backend.h +++ b/platforms/common/include/px4_platform_common/crypto_backend.h @@ -39,6 +39,7 @@ extern "C" { #include #include +#include #include #include "crypto_backend_definitions.h" @@ -181,6 +182,63 @@ bool crypto_encrypt_data(crypto_session_handle_t handle, size_t crypto_get_min_blocksize(crypto_session_handle_t handle, uint8_t key_idx); + +/* Crypto IOCTLs, to access backend from user space */ + +#define _CRYPTOIOC(_n) (_IOC(_CRYPTOIOCBASE, _n)) + +#define CRYPTOIOCOPEN _CRYPTOIOC(1) +typedef struct cryptoiocopen { + px4_crypto_algorithm_t algorithm; + crypto_session_handle_t *handle; +} cryptoiocopen_t; + +#define CRYPTOIOCCLOSE _CRYPTOIOC(2) + +#define CRYPTOIOCENCRYPT _CRYPTOIOC(3) +typedef struct cryptoiocencrypt { + crypto_session_handle_t *handle; + uint8_t key_index; + const uint8_t *message; + size_t message_size; + uint8_t *cipher; + size_t *cipher_size; + bool ret; +} cryptoiocencrypt_t; + +#define CRYPTOIOCGENKEY _CRYPTOIOC(4) +typedef struct cryptoiocgenkey { + crypto_session_handle_t *handle; + uint8_t idx; + bool persistent; + bool ret; +} cryptoiocgenkey_t; + +#define CRYPTOIOCGETNONCE _CRYPTOIOC(5) +typedef struct cryptoiocgetnonce { + crypto_session_handle_t *handle; + uint8_t *nonce; + size_t *nonce_len; + bool ret; +} cryptoiocgetnonce_t; + +#define CRYPTOIOCGETKEY _CRYPTOIOC(6) +typedef struct cryptoiocgetkey { + crypto_session_handle_t *handle; + uint8_t key_idx; + uint8_t *key; + size_t *max_len; + uint8_t encryption_key_idx; + bool ret; +} cryptoiocgetkey_t; + +#define CRYPTOIOCGETBLOCKSZ _CRYPTOIOC(7) +typedef struct cryptoiocgetblocksz { + crypto_session_handle_t *handle; + uint8_t key_idx; + size_t ret; +} cryptoiocgetblocksz_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 6ae4e8f7ea..b14c5782b6 100644 --- a/platforms/nuttx/src/px4/common/px4_crypto.cpp +++ b/platforms/nuttx/src/px4/common/px4_crypto.cpp @@ -35,6 +35,8 @@ #include #include +#include +#include extern "C" { #include @@ -63,6 +65,11 @@ void PX4Crypto::px4_crypto_init() // initialize actual crypto algoritms crypto_init(); + // initialize user ioctl interface for crypto +#if !defined(CONFIG_BUILD_FLAT) + px4_register_boardct_ioctl(_CRYPTOIOCBASE, crypto_ioctl); +#endif + PX4Crypto::_initialized = true; } @@ -146,4 +153,63 @@ size_t PX4Crypto::get_min_blocksize(uint8_t key_idx) return crypto_get_min_blocksize(_crypto_handle, key_idx); } +#if !defined(CONFIG_BUILD_FLAT) +int PX4Crypto::crypto_ioctl(unsigned int cmd, unsigned long arg) +{ + int ret = PX4_OK; + + switch (cmd) { + case CRYPTOIOCOPEN: { + cryptoiocopen_t *data = (cryptoiocopen_t *)arg; + *(data->handle) = crypto_open(data->algorithm); + } + break; + + case CRYPTOIOCCLOSE: { + crypto_close((crypto_session_handle_t *)arg); + } + break; + + case CRYPTOIOCENCRYPT: { + cryptoiocencrypt_t *data = (cryptoiocencrypt_t *)arg; + data->ret = crypto_encrypt_data(*(data->handle), data->key_index, data->message, data->message_size, data->cipher, + data->cipher_size); + } + break; + + case CRYPTOIOCGENKEY: { + cryptoiocgenkey_t *data = (cryptoiocgenkey_t *)arg; + data->ret = crypto_generate_key(*(data->handle), data->idx, data->persistent); + } + break; + + case CRYPTOIOCGETNONCE: { + cryptoiocgetnonce_t *data = (cryptoiocgetnonce_t *)arg; + data->ret = crypto_get_nonce(*(data->handle), data->nonce, data->nonce_len); + + } + break; + + case CRYPTOIOCGETKEY: { + cryptoiocgetkey_t *data = (cryptoiocgetkey_t *)arg; + data->ret = crypto_get_encrypted_key(*(data->handle), data->key_idx, data->key, data->max_len, + data->encryption_key_idx); + } + break; + + case CRYPTOIOCGETBLOCKSZ: { + cryptoiocgetblocksz_t *data = (cryptoiocgetblocksz_t *)arg; + data->ret = crypto_get_min_blocksize(*(data->handle), data->key_idx); + } + break; + + default: + ret = PX4_ERROR; + break; + } + + return ret; +} +#endif // !defined(CONFIG_BUILD_FLAT) + #endif diff --git a/platforms/nuttx/src/px4/common/px4_protected_layers.cmake b/platforms/nuttx/src/px4/common/px4_protected_layers.cmake index a3ab4a6931..424e29c236 100644 --- a/platforms/nuttx/src/px4/common/px4_protected_layers.cmake +++ b/platforms/nuttx/src/px4/common/px4_protected_layers.cmake @@ -12,6 +12,7 @@ add_library(px4_layer ${PX4_SOURCE_DIR}/platforms/posix/src/px4/common/cpuload.cpp usr_hrt.cpp px4_userspace_init.cpp + px4_usr_crypto.cpp ) target_link_libraries(px4_layer @@ -55,6 +56,7 @@ target_link_libraries(px4_kernel_layer if (DEFINED PX4_CRYPTO) target_link_libraries(px4_kernel_layer PUBLIC crypto_backend) + target_link_libraries(px4_layer PUBLIC crypto_backend_interface) endif() target_compile_options(px4_kernel_layer PRIVATE -D__KERNEL__) diff --git a/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp b/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp new file mode 100644 index 0000000000..bb48cad6aa --- /dev/null +++ b/platforms/nuttx/src/px4/common/px4_usr_crypto.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** + * + * Copyright (c) 2021 Technology Innovation Institute. 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. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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 OWNER 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. + * + ****************************************************************************/ + +#if defined(PX4_CRYPTO) + +#include +#include +#include + +bool PX4Crypto::_initialized = false; + +void PX4Crypto::px4_crypto_init() +{ + PX4Crypto::_initialized = true; +} + +PX4Crypto::PX4Crypto() +{ + // Initialize an empty handle + crypto_session_handle_init(&_crypto_handle); +} + +PX4Crypto::~PX4Crypto() +{ + close(); +} + +bool PX4Crypto::open(px4_crypto_algorithm_t algorithm) +{ + // HW specific crypto already open? Just close before proceeding + close(); + + // Open the HW specific crypto handle + cryptoiocopen_t data = {algorithm, &_crypto_handle}; + boardctl(CRYPTOIOCOPEN, reinterpret_cast(&data)); + + return crypto_session_handle_valid(_crypto_handle); +} + +void PX4Crypto::close() +{ + if (!crypto_session_handle_valid(_crypto_handle)) { + return; + } + + boardctl(CRYPTOIOCCLOSE, reinterpret_cast(&_crypto_handle)); +} + +bool PX4Crypto::encrypt_data(uint8_t key_index, + const uint8_t *message, + size_t message_size, + uint8_t *cipher, + size_t *cipher_size) +{ + cryptoiocencrypt_t data = {&_crypto_handle, key_index, message, message_size, cipher, cipher_size, false}; + boardctl(CRYPTOIOCENCRYPT, reinterpret_cast(&data)); + return data.ret; +} + +bool PX4Crypto::generate_key(uint8_t idx, + bool persistent) +{ + cryptoiocgenkey_t data = {&_crypto_handle, idx, persistent, false}; + boardctl(CRYPTOIOCGENKEY, reinterpret_cast(&data)); + return data.ret; +} + +bool PX4Crypto::get_nonce(uint8_t *nonce, + size_t *nonce_len) +{ + cryptoiocgetnonce_t data = {&_crypto_handle, nonce, nonce_len, false}; + boardctl(CRYPTOIOCGETNONCE, reinterpret_cast(&data)); + return data.ret; +} + +bool PX4Crypto::get_encrypted_key(uint8_t key_idx, + uint8_t *key, + size_t *key_len, + uint8_t encryption_key_idx) +{ + cryptoiocgetkey_t data = {&_crypto_handle, key_idx, key, key_len, encryption_key_idx, false}; + boardctl(CRYPTOIOCGETKEY, reinterpret_cast(&data)); + return data.ret; +} + +size_t PX4Crypto::get_min_blocksize(uint8_t key_idx) +{ + cryptoiocgetblocksz_t data = {&_crypto_handle, key_idx, 0}; + boardctl(CRYPTOIOCGETBLOCKSZ, reinterpret_cast(&data)); + return data.ret; +} + +#endif