Skip to content

Commit a55223a

Browse files
committed
inplace encryption inside csp packet
1 parent f8a76bf commit a55223a

File tree

3 files changed

+94
-12
lines changed

3 files changed

+94
-12
lines changed

include/crypto/crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ extern param_t rx_decrypt;
1212
void crypto_key_generate(param_t * param, int idx);
1313
int16_t crypto_decrypt(uint8_t * msg_out, uint8_t * ciphertext_in, uint16_t ciphertext_len, uint8_t crypto_key);
1414
int16_t crypto_encrypt(uint8_t * msg_out, uint8_t * msg_in, uint16_t msg_len);
15+
int16_t crypto_encrypt_inplace(csp_packet_t * packet);
1516
void crypto_init();

src/crypto/crypto.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
#endif
1414

1515
#include "crypto/crypto_param.h"
16+
#define CSP_ID2_HEADER_SIZE 6
1617

1718
#define NONCE_SIZE (sizeof(uint64_t) + sizeof(uint8_t))
1819

20+
_Static_assert(CSP_PACKET_PADDING_BYTES > crypto_secretbox_ZEROBYTES + CSP_ID2_HEADER_SIZE, "Not enough padding before csp packet for in-place encryption!");
21+
1922
uint8_t _crypto_beforenm[CRYPTO_NUM_KEYS][crypto_secretbox_KEYBYTES];
2023

2124
void crypto_key_generate(param_t * param, int idx) {
@@ -107,6 +110,79 @@ int16_t crypto_encrypt(uint8_t * msg_out, uint8_t * msg_in, uint16_t msg_len) {
107110
return msg_len + crypto_secretbox_KEYBYTES + NONCE_SIZE;
108111
}
109112

113+
/**
114+
* @brief Encrypts a CSP packet payload in-place using NaCl/libsodium.
115+
*
116+
* This function performs authenticated encryption on the data contained in the
117+
* packet structure. It modifies the packet's data buffer directly, adjusting
118+
* the `frame_begin` pointer and `frame_length` to account for the prepended
119+
* Message Authentication Code (MAC) and the appended Nonce.
120+
*
121+
* **Memory Layout Transformation:**
122+
*
123+
* **Before:**
124+
* @code
125+
* [ Headroom ] [ Payload (N) ] [ Tailroom ]
126+
* ^
127+
* frame_begin
128+
* @endcode
129+
*
130+
* **After:**
131+
* @code
132+
* [ MAC (16) ] [ Encrypted Payload (N) ] [ 0x00 (16) ] [ Nonce (8) ] [ TX ID (1) ]
133+
* ^
134+
* frame_begin
135+
* @endcode
136+
*
137+
* @pre **Compile-time Check:** `CSP_PACKET_PADDING_BYTES` must be greater than
138+
* `crypto_secretbox_ZEROBYTES + CSP_ID2_HEADER_SIZE`. This is enforced by a
139+
* `_Static_assert` to ensure safe headless padding.
140+
*
141+
* @param[in,out] packet Pointer to the CSP packet structure. The `frame_begin`,
142+
* `frame_length`, and buffer contents will be modified.
143+
*
144+
* @return
145+
* - \b CSP_ERR_NONE: Encryption successful.
146+
* - \b CSP_ERR_INVAL: Packet buffer too small for prepending nonce and zerofill.
147+
*/
148+
int16_t crypto_encrypt_inplace(csp_packet_t * packet) {
149+
150+
/* Check that there is enough space to postpend nonce and 16 byte zerofill */
151+
if(packet->length + NONCE_SIZE + crypto_secretbox_BOXZEROBYTES > CSP_BUFFER_SIZE) {
152+
return CSP_ERR_INVAL;
153+
}
154+
155+
/* Update and get transmit nonce */
156+
uint64_t tx_nonce = param_get_uint64(&crypto_nonce_tx_count) + 1;
157+
param_set_uint64(&crypto_nonce_tx_count, tx_nonce);
158+
159+
/* Pack nonce into 24-bytes format, expected by NaCl */
160+
unsigned char nonce[crypto_box_NONCEBYTES] = {};
161+
memcpy(nonce, &tx_nonce, sizeof(uint64_t));
162+
/* Add nonce ID to nonce */
163+
nonce[sizeof(uint64_t)] = param_get_uint8(&crypto_nonce_tx_id);
164+
165+
/* Make room for zerofill at the beginning of message */
166+
uint8_t * padding_begin = packet->frame_begin - crypto_secretbox_ZEROBYTES;
167+
memset(padding_begin, 0, crypto_secretbox_ZEROBYTES);
168+
169+
/* Encryption only returns -1 if mlen < 32 */
170+
crypto_box_afternm(padding_begin, padding_begin, packet->frame_length + crypto_secretbox_ZEROBYTES, nonce, _crypto_beforenm[param_get_uint8(&tx_encrypt)-1]);
171+
172+
/* Adjust packet pointers and length for the prepended MAC */
173+
packet->frame_begin -= crypto_secretbox_MACBYTES;
174+
packet->frame_length += crypto_secretbox_MACBYTES;
175+
176+
/* Zero out the 16 bytes between the end of the encrypted data and the nonce for backwards compatibility */
177+
memset(packet->frame_begin + packet->frame_length, 0, crypto_secretbox_BOXZEROBYTES);
178+
179+
/* Add nonce at the end of the packet plus 16 bytes for backwards compatibility */
180+
memcpy(packet->frame_begin + (crypto_secretbox_BOXZEROBYTES + packet->frame_length), nonce, NONCE_SIZE);
181+
packet->frame_length += NONCE_SIZE + crypto_secretbox_BOXZEROBYTES;
182+
183+
return CSP_ERR_NONE;
184+
}
185+
110186
void crypto_init() {
111187

112188
crypto_key_generate(NULL, -1);

src/csp_if_cblk.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,28 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int
5959
csp_hex_dump("tx_frame", packet->frame_begin, packet->frame_length);
6060
}
6161

62-
uint16_t frame_length = packet->frame_length;
63-
uint8_t* frame_begin = packet->frame_begin;
64-
65-
ifdata->cblk_tx_lock(iface);
6662

6763
if (param_get_uint8(&tx_encrypt)) {
68-
frame_length = crypto_encrypt(ifdata->packet_enc, packet->frame_begin, packet->frame_length);
69-
frame_begin = &ifdata->packet_enc[CRYPTO_PREAMP];
64+
65+
if(crypto_encrypt_inplace(packet) < 0) {
66+
csp_buffer_free(packet);
67+
if (_cblk_tx_debug >= 2) {
68+
printf("Encryption fail: packet too large to encrypt\n");
69+
}
70+
return CSP_ERR_INVAL;
71+
}
7072

7173
if (_cblk_tx_debug >= 3) {
72-
csp_hex_dump("tx_enc", frame_begin, frame_length);
74+
csp_hex_dump("tx_enc", packet->frame_begin, packet->frame_length);
7375
}
7476
}
7577

76-
uint16_t bytes_remain = frame_length;
77-
for (int8_t frame_cnt = 0; frame_cnt < num_ccsds_from_csp(frame_length); frame_cnt++) {
78+
uint16_t bytes_remain = packet->frame_length;
79+
uint8_t num_frames = num_ccsds_from_csp(packet->frame_length);
80+
81+
for (int8_t frame_cnt = 0; frame_cnt < num_frames; frame_cnt++) {
7882

83+
ifdata->cblk_tx_lock(iface);
7984
cblk_frame_t * tx_ccsds_buf = ifdata->cblk_tx_buffer_get(iface);
8085
if (tx_ccsds_buf == NULL) {
8186
ifdata->cblk_tx_unlock(iface);
@@ -87,15 +92,15 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int
8792

8893
tx_ccsds_buf->hdr.csp_packet_idx = iface->tx;
8994
tx_ccsds_buf->hdr.ccsds_frame_idx = frame_cnt;
90-
tx_ccsds_buf->hdr.data_length = htobe16(frame_length);
95+
tx_ccsds_buf->hdr.data_length = htobe16(packet->frame_length);
9196
tx_ccsds_buf->hdr.nacl_crypto_key = param_get_uint8(&tx_encrypt);
9297

9398
if (_cblk_tx_debug >= 1) {
94-
printf("TX CCSDS header: %u %u %u\n", tx_ccsds_buf->hdr.csp_packet_idx, frame_cnt, frame_length);
99+
printf("TX CCSDS header: %u %u %u\n", tx_ccsds_buf->hdr.csp_packet_idx, frame_cnt, packet->frame_length);
95100
}
96101
uint16_t segment_len = (CBLK_DATA_LEN < bytes_remain) ? CBLK_DATA_LEN : bytes_remain;
97102

98-
memcpy(tx_ccsds_buf->data, frame_begin+(frame_length-bytes_remain), segment_len);
103+
memcpy(tx_ccsds_buf->data, packet->frame_begin+(packet->frame_length-bytes_remain), segment_len);
99104
bytes_remain -= segment_len;
100105

101106
if (ifdata->cblk_tx_send(iface, tx_ccsds_buf) < 0) {

0 commit comments

Comments
 (0)