Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combined ulge file #820

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions Tools/decrypt_ulog.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,91 @@
#!/usr/bin/env python3

import sys

try:
from Crypto.Cipher import ChaCha20
except ImportError as e:
print("Failed to import crypto: " + str(e))
print("")
print("You may need to install it using:")
print(" pip3 install --user pycryptodome")
print("")
sys.exit(1)

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import ChaCha20
from Crypto.Hash import SHA256
import binascii
from pathlib import Path
import argparse
#from pathlib import Path
import sys


if __name__ == "__main__":

parser = argparse.ArgumentParser(description="""CLI tool to decrypt an ulog file\n""")
parser.add_argument("ulog_file", help=".ulog file", nargs='?', default=None)
parser.add_argument("ulog_key", help=".ulogk, encrypted key", nargs='?', default=None)
parser.add_argument("ulog_file", help=".ulge/.ulgc, encrypted log file", nargs='?', default=None)
parser.add_argument("ulog_key", help=".ulgk, legacy encrypted key (give empty string '' to ignore for .ulge)", nargs='?', default=None)
parser.add_argument("rsa_key", help=".pem format key for decrypting the ulog key", nargs='?', default=None)

args = parser.parse_args()

# Only generate a key pair, don't sign
if not args.ulog_file or not args.ulog_key or not args.rsa_key:
print('Need all arguments, the encrypted ulog file, the key and the key decryption key')
sys.exit(1);
# Check all arguments are given
if not args.rsa_key:
print('Need all arguments, the encrypted ulog file, key file (or empty string if not needed) and the key decryption key (.pem)')
sys.exit(1)

# Read the private RSA key to decrypt the cahcha key
with open(args.rsa_key, 'rb') as f:
r = RSA.importKey(f.read(), passphrase='')

# Read the encrypted xchacha key and the nonce
with open(args.ulog_key, 'rb') as f:
if args.ulog_key == "":
key_data_filename = args.ulog_file
magic = "ULogEnc"
else:
key_data_filename = args.ulog_key
magic = "ULogKey"

with open(key_data_filename, 'rb') as f:
# Read the encrypted xchacha key and the nonce
ulog_key_header = f.read(22)

# Parse the header
try:
# magic
if not ulog_key_header.startswith(bytearray("ULogKey".encode())):
if not ulog_key_header.startswith(bytearray(magic.encode())):
print("Incorrect header magic")
raise Exception()
# version
if ulog_key_header[7] != 1:
print("Unsupported header version")
raise Exception()
# expected key exchange algorithm (RSA_OAEP)
if ulog_key_header[16] != 4:
print("Unsupported key algorithm")
raise Exception()
key_size = ulog_key_header[19] << 8 | ulog_key_header[18];
nonce_size = ulog_key_header[21] << 8 | ulog_key_header[20];
key_size = ulog_key_header[19] << 8 | ulog_key_header[18]
nonce_size = ulog_key_header[21] << 8 | ulog_key_header[20]
ulog_key_cipher = f.read(key_size)
nonce = f.read(nonce_size)
except:
print("Keyfile format error")
sys.exit(1);
print("Keydata format error")
sys.exit(1)

if magic == "ULogEnc":
data_offset = 22 + key_size + nonce_size
else:
data_offset = 0

# Decrypt the xchacha key
cipher_rsa = PKCS1_OAEP.new(r,SHA256)
ulog_key = cipher_rsa.decrypt(ulog_key_cipher)
#print(binascii.hexlify(ulog_key))

# Read and decrypt the .ulgc
# Read and decrypt the ulog data
cipher = ChaCha20.new(key=ulog_key, nonce=nonce)

outfilename = Path(args.ulog_file).stem + ".ulog"
with open(args.ulog_file, 'rb') as f:
with open(args.ulog_file.rstrip(args.ulog_file[-1]), 'wb') as out:
if data_offset > 0:
f.seek(data_offset)
with open(outfilename, 'wb') as out:
out.write(cipher.decrypt(f.read()))
31 changes: 7 additions & 24 deletions src/modules/logger/log_writer_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,38 +149,17 @@ bool LogWriterFile::init_logfile_encryption(const char *filename)
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;
int key_fd = ::open((const char *)filename, O_CREAT | O_WRONLY | O_DIRECT | O_SYNC, PX4_O_MODE_666);

if (key_fd < 0) {
PX4_ERR("Can't open key file, errno: %d", errno);
free(key);
return false;
}

// write the header to the key exchange file
// write the header to the combined key exchange & cipherdata file
struct ulog_key_header_s keyfile_header = {
.magic = {'U', 'L', 'o', 'g', 'K', 'e', 'y'},
.magic = {'U', 'L', 'o', 'g', 'E', 'n', 'c'},
.hdr_ver = 1,
.timestamp = hrt_absolute_time(),
.exchange_algorithm = CRYPTO_RSA_OAEP,
Expand Down Expand Up @@ -651,7 +630,11 @@ size_t LogWriterFile::LogFileBuffer::get_read_ptr(void **ptr, bool *is_part)

bool LogWriterFile::LogFileBuffer::start_log(const char *filename)
{
#if defined(PX4_CRYPTO)
_fd = ::open(filename, O_APPEND | O_WRONLY, PX4_O_MODE_666);
#else
_fd = ::open(filename, O_CREAT | O_WRONLY, PX4_O_MODE_666);
#endif

if (_fd < 0) {
PX4_ERR("Can't open log file %s, errno: %d", filename, errno);
Expand Down
2 changes: 1 addition & 1 deletion src/modules/logger/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ int Logger::get_log_file_name(LogType type, char *file_name, size_t file_name_si
#if defined(PX4_CRYPTO)

if (_param_sdlog_crypto_algorithm.get() != 0) {
crypto_suffix = "c";
crypto_suffix = "e";
}

#endif
Expand Down
Loading