mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-16 20:03:35 +08:00
Take crypto interfaces into use in logger, to encrypt ulog data
- Generate a symmetric encryption key and a nonce value - Use a public key in keystore to encrypt the symmteric key - Write the encrypted key and the nonce value to disk into .ulgk, name matching with the encrypted log file - use quick stream encryption to crypt the .ulg file contents Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>
This commit is contained in:
committed by
Beat Küng
parent
6b22fe99b7
commit
9472f79307
@@ -40,10 +40,15 @@
|
||||
|
||||
#include <mathlib/mathlib.h>
|
||||
#include <px4_platform_common/posix.h>
|
||||
#include <px4_platform_common/crypto.h>
|
||||
#ifdef __PX4_NUTTX
|
||||
#include <systemlib/hardfault_log.h>
|
||||
#endif /* __PX4_NUTTX */
|
||||
|
||||
// TODO: how to define the key slots/product?
|
||||
// this depends on the keystore as well
|
||||
#define LOGGER_CRYPTO_KEY_IDX 2
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
|
||||
@@ -81,6 +86,116 @@ LogWriterFile::~LogWriterFile()
|
||||
pthread_cond_destroy(&_cv);
|
||||
}
|
||||
|
||||
#if defined(PX4_CRYPTO)
|
||||
bool LogWriterFile::init_logfile_encryption(const char *filename)
|
||||
{
|
||||
// open a crypto session // TODO: use a parameter for algorithm
|
||||
if (!_crypto.open(CRYPTO_XCHACHA20)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the minimum block size for which the encryption can be performed
|
||||
_min_blocksize = _crypto.get_min_blocksize(_key_idx);
|
||||
|
||||
// Generate a crypto key and store it to the keystore.
|
||||
|
||||
// TODO: use parameter for alogrithm? Or product specific macro?
|
||||
// TODO: how to define key index to the keystore? Product macro? parameter?
|
||||
if (!_crypto.generate_key(LOGGER_CRYPTO_KEY_IDX, false)) {
|
||||
PX4_ERR("Can't generate crypto key");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the generated key, encrypted with RSA_OAEP. Open another temporary session for this.
|
||||
PX4Crypto rsa_crypto;
|
||||
|
||||
if (!rsa_crypto.open(CRYPTO_RSA_OAEP)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: define the public key used for key exchange. Now hardcoded to 1
|
||||
|
||||
/* Get the size of an encrypted key and nonce */
|
||||
|
||||
size_t key_size;
|
||||
size_t nonce_size;
|
||||
|
||||
if (!rsa_crypto.get_encrypted_key(LOGGER_CRYPTO_KEY_IDX,
|
||||
NULL,
|
||||
&key_size,
|
||||
1) ||
|
||||
!_crypto.get_nonce(NULL, &nonce_size) ||
|
||||
key_size == 0) {
|
||||
rsa_crypto.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allocate space and get key + nonce */
|
||||
uint8_t *key = (uint8_t *)malloc(key_size + nonce_size);
|
||||
|
||||
if (!key ||
|
||||
!rsa_crypto.get_encrypted_key(
|
||||
LOGGER_CRYPTO_KEY_IDX,
|
||||
key,
|
||||
&key_size,
|
||||
1) ||
|
||||
!_crypto.get_nonce(
|
||||
key + key_size, &nonce_size)) {
|
||||
PX4_ERR("Can't get & encrypt the key");
|
||||
free(key);
|
||||
rsa_crypto.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
rsa_crypto.close();
|
||||
|
||||
// Write the encrypted key to the disk
|
||||
|
||||
// Allocate a buffer for filename
|
||||
size_t fnlen = strlen(filename);
|
||||
char *tmp_buf = (char *)malloc(fnlen + 1);
|
||||
|
||||
if (!tmp_buf) {
|
||||
PX4_ERR("out of memory");
|
||||
free(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the original logfile name, and append 'k' to the filename
|
||||
|
||||
memcpy(tmp_buf, filename, fnlen + 1);
|
||||
tmp_buf[fnlen - 1] = 'k';
|
||||
tmp_buf[fnlen] = 0;
|
||||
|
||||
int key_fd = ::open((const char *)tmp_buf, O_CREAT | O_WRONLY, PX4_O_MODE_666);
|
||||
|
||||
// The file name is no longer needed, free it
|
||||
free(tmp_buf);
|
||||
tmp_buf = nullptr;
|
||||
|
||||
if (key_fd < 0) {
|
||||
PX4_ERR("Can't open key file, errno: %d", errno);
|
||||
free(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t written = ::write(key_fd, key, key_size + nonce_size);
|
||||
|
||||
// Free temporary memory allocations
|
||||
free(key);
|
||||
::close(key_fd);
|
||||
|
||||
// Check that writing to the disk succeeded
|
||||
if (written != key_size + nonce_size) {
|
||||
PX4_ERR("Writing the encryption key to disk fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // PX4_CRYPTO
|
||||
|
||||
|
||||
void LogWriterFile::start_log(LogType type, const char *filename)
|
||||
{
|
||||
// At this point we don't expect the file to be open, but it can happen for very fast consecutive stop & start
|
||||
@@ -107,6 +222,18 @@ void LogWriterFile::start_log(LogType type, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
#if PX4_CRYPTO
|
||||
// TODO: use parameter to check if logfile crypto is enabled
|
||||
bool enc_init = init_logfile_encryption(filename);
|
||||
|
||||
if (!enc_init) {
|
||||
PX4_ERR("Failed to start encrypted logging");
|
||||
_crypto.close();
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (_buffers[(int)type].start_log(filename)) {
|
||||
PX4_INFO("Opened %s log file: %s", log_type_str(type), filename);
|
||||
notify();
|
||||
@@ -183,7 +310,6 @@ void LogWriterFile::thread_stop()
|
||||
if (ret) {
|
||||
PX4_WARN("join failed: %d", ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *LogWriterFile::run_helper(void *context)
|
||||
@@ -247,10 +373,39 @@ void LogWriterFile::run()
|
||||
LogFileBuffer &buffer = _buffers[i];
|
||||
size_t available = buffer.get_read_ptr(&read_ptr, &is_part);
|
||||
|
||||
#if defined(PX4_CRYPTO)
|
||||
// Split into min blocksize chunks, so it is good for encrypting in pieces
|
||||
available = (available / _min_blocksize) * _min_blocksize;
|
||||
#endif
|
||||
|
||||
/* if sufficient data available or partial read or terminating, write data */
|
||||
if (available >= min_available[i] || is_part || (!buffer._should_run && available > 0)) {
|
||||
pthread_mutex_unlock(&_mtx);
|
||||
|
||||
#if defined(PX4_CRYPTO)
|
||||
/* This makes the following assumptions:
|
||||
* - the chipher size is always the
|
||||
same as the input size
|
||||
* - the encryption can be done in
|
||||
place. This is always taken care
|
||||
by the px4 crypto interfaces
|
||||
*/
|
||||
|
||||
// TODO: use parameter to check if logfile crypto is enabled
|
||||
size_t out = available;
|
||||
_crypto.encrypt_data(
|
||||
LOGGER_CRYPTO_KEY_IDX, // key
|
||||
(uint8_t *)read_ptr,
|
||||
available,
|
||||
(uint8_t *)read_ptr,
|
||||
&out);
|
||||
|
||||
if (out != available) {
|
||||
PX4_ERR("Encryption output size mismatch, logfile corrupted");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
written = buffer.write_to_file(read_ptr, available, call_fsync);
|
||||
|
||||
/* buffer.mark_read() requires _mtx to be locked */
|
||||
@@ -289,6 +444,12 @@ void LogWriterFile::run()
|
||||
|
||||
if (_buffers[0].fd() < 0 && _buffers[1].fd() < 0) {
|
||||
// stop when both files are closed
|
||||
#if defined(PX4_CRYPTO)
|
||||
/* close the crypto session */
|
||||
|
||||
_crypto.close();
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -424,6 +585,7 @@ void LogWriterFile::LogFileBuffer::write_no_check(void *ptr, size_t size)
|
||||
|
||||
// now: n = bytes already written
|
||||
size_t p = size - n; // number of bytes to write
|
||||
|
||||
memcpy(&(_buffer[_head]), &(buffer_c[n]), p);
|
||||
_head = (_head + p) % _buffer_size;
|
||||
_count += size;
|
||||
|
||||
Reference in New Issue
Block a user