crypto: fix strict aliasing for expandedKey in aesb.c
What changed, and why it matters
This commit fixes a C programming rule violation called 'strict aliasing' in Monero's AES encryption helper code. Previously, the code treated a byte buffer as if it were an array of 32-bit integers by casting the pointer directly. The patch copies the bytes into a properly typed local array first. This is a correctness and portability fix; under aggressive compiler optimization, the old code could theoretically produce wrong encryption results or expose subtle bugs, but there is no direct evidence it was exploitable as a security vulnerability.
Treat as a low-risk code-quality/hardening fix. Include in routine review and testing; no urgent security response required absent additional evidence of practical exploitability.
Security signals we found
Strict-aliasing rule violation removed via memcpy instead of pointer cast
Functions changed from static inline to non-static (linkage change)
Defensive code-quality fix in cryptographic primitive helper
Evidence from the diff
In src/crypto/aesb.c, aesb_single_round and aesb_pseudo_round previously cast uint8_t expandedKey to const uint32_t kp, violating C strict-aliasing rules. The patch removes the STATIC/INLINE macros, makes the functions externally visible, and replaces the pointer cast with a memcpy into a local uint32_t array (kp[4] and kp[40] respectively). This avoids undefined behavior that compilers may optimize unpredictably. The change is defensive/correctness-oriented; no buffer overflow, use-after-free, or direct control-flow issue is introduced or fixed.
Changed components
src/crypto/aesb.caesb_single_roundaesb_pseudo_roundInspect captured patch +5 / −12
diff --git a/src/crypto/aesb.c b/src/crypto/aesb.c
index 6d4905a..59b4c0a 100644
--- a/src/crypto/aesb.c
+++ b/src/crypto/aesb.c
@@ -19,6 +19,7 @@ Issue Date: 20/12/2007
*/
#include <stdint.h>
+#include <string.h>
#include "int-util.h"
#if defined(__cplusplus)
@@ -141,18 +142,10 @@ extern "C"
d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
-#if !defined(STATIC)
-#define STATIC
-#endif
-
-#if !defined(INLINE)
-#define INLINE
-#endif
-
-STATIC INLINE void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
+void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
{
uint32_t b0[4], b1[4];
- const uint32_t *kp = (uint32_t *) expandedKey;
+ uint32_t kp[4]; memcpy(kp, expandedKey, sizeof(kp));
state_in(b0, in);
round(fwd_rnd, b1, b0, kp);
@@ -160,10 +153,10 @@ STATIC INLINE void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *e
state_out(out, b1);
}
-STATIC INLINE void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
+void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
{
uint32_t b0[4], b1[4];
- const uint32_t *kp = (uint32_t *) expandedKey;
+ uint32_t kp[40]; memcpy(kp, expandedKey, sizeof(kp));
state_in(b0, in);
round(fwd_rnd, b1, b0, kp);
Why this scored 31/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.