@@ -39,17 +39,49 @@ void crypto_key_generate(param_t * param, int idx) {
3939 param_get_data (& crypto_key3 , _crypto_beforenm [2 ], sizeof (_crypto_beforenm [2 ]));
4040}
4141
42- /*
43- There is a 32-octet padding requirement on the plaintext buffer that you pass to crypto_box.
44- Internally, the NaCl implementation uses this space to avoid having to allocate memory or
45- use static memory that might involve a cache hit (see Bernstein's paper on cache timing
46- side-channel attacks for the juicy details).
47-
48- Similarly, the crypto_box_open call requires 16 octets of zero padding before the start
49- of the actual ciphertext. This is used in a similar fashion. These padding octets are not
50- part of either the plaintext or the ciphertext, so if you are sending ciphertext across the
51- network, don't forget to remove them!
52- */
42+ /**
43+ * @brief Decrypts a CSP packet payload in-place using NaCl/libsodium.
44+ *
45+ * This function verifies the Message Authentication Code (MAC) and decrypts the
46+ * payload contained in the packet structure. It also performs replay protection
47+ * by validating the received Nonce against a stored high-water mark.
48+ *
49+ * The function modifies the packet's data buffer directly, stripping the
50+ * protocol overhead (MAC, padding, Nonce) to restore the original plaintext
51+ * payload.
52+ *
53+ * **Memory Layout Transformation:**
54+ *
55+ * **Before:**
56+ * @code
57+ * [ MAC (16) ] [ Encrypted Payload (N) ] [ 0x00 (16) ] [ Nonce (8) ] [ TX ID (1) ]
58+ * ^
59+ * frame_begin
60+ * @endcode
61+ *
62+ * **After:**
63+ * @code
64+ * [ Headroom ] [ Plaintext Payload (N) ] [ Tailroom ]
65+ * ^
66+ * frame_begin
67+ * @endcode
68+ *
69+ * **Validation Steps:**
70+ * 1. Checks if the packet is long enough to contain the necessary crypto overhead.
71+ * 2. Extracts the Nonce from the end of the packet.
72+ * 3. Prepends the required zerofill padding (`crypto_secretbox_BOXZEROBYTES`) to the start.
73+ * 4. Performs authenticated decryption using `crypto_box_open_afternm`.
74+ * 5. Verifies the Nonce counter is strictly greater than the last received Nonce for that group (Replay Protection).
75+ *
76+ * @param[in,out] packet Pointer to the CSP packet structure containing the encrypted frame.
77+ * On success, `frame_begin` and `frame_length` are updated to point
78+ * to the decrypted plaintext.
79+ * @param[in] crypto_key The index of the pre-shared key to use for decryption (1-based index).
80+ *
81+ * @return
82+ * - \b CSP_ERR_NONE: Decryption successful and Nonce is valid.
83+ * - \b -1: Decryption failed (Authentication error, invalid key, packet too short, or replay detected).
84+ */
5385int16_t crypto_decrypt (csp_packet_t * packet , uint8_t crypto_key ) {
5486
5587 if (crypto_key == 0 || crypto_key > CRYPTO_NUM_KEYS ) {
@@ -79,8 +111,8 @@ int16_t crypto_decrypt(csp_packet_t * packet, uint8_t crypto_key) {
79111 /* Message successfully decrypted, check for valid nonce */
80112 uint64_t nonce_counter ;
81113 memcpy (& nonce_counter , decrypt_nonce , sizeof (uint64_t ));
82- uint8_t nounce_group = decrypt_nonce [sizeof (uint64_t )];
83- uint64_t nonce_rx = param_get_uint64_array (& crypto_nonce_rx_count , nounce_group );
114+ uint8_t nonce_group = decrypt_nonce [sizeof (uint64_t )];
115+ uint64_t nonce_rx = param_get_uint64_array (& crypto_nonce_rx_count , nonce_group );
84116 if (nonce_counter <= nonce_rx ) {
85117 param_set_uint16 (& crypto_fail_nonce_count , param_get_uint16 (& crypto_fail_nonce_count ) + 1 );
86118 return -1 ;
@@ -91,7 +123,7 @@ int16_t crypto_decrypt(csp_packet_t * packet, uint8_t crypto_key) {
91123 packet -> frame_begin += crypto_secretbox_ZEROBYTES ;
92124
93125 /* Update counter with received value so that next sent value is higher */
94- param_set_uint64_array (& crypto_nonce_rx_count , nounce_group , nonce_counter );
126+ param_set_uint64_array (& crypto_nonce_rx_count , nonce_group , nonce_counter );
95127
96128 return CSP_ERR_NONE ;
97129}
0 commit comments