Situation: I am working with a crypto library called embedded disco, I have a demo working on my PC but when porting it over to the MCU I get a hard fault when executing a library procedure. In the faulting code, the library is trying to simply copy the content of one strobe_s
struct into another strobe_s
. This is done twice: once for s1
and once for s2
. For s1
, the library simply assigns the dest. struct to the source struct. For s2
however, such an assign gave a hard fault. As the Cortex-M ISA requires aligned memory accesses, I reckoned that replacing the assignment with a memcpy should fix the problem. Nevertheless, simply stepping into memcpy using the debugger results in a hard fault! I.e. I have a breakpoint at the line with the memcpy and when stepping inside the fault handler is called! I have used memcpy to fix misaligned memory accesses in other parts of the code just fine...
MCU: STM32L552ZET6QU
Faulting code:
The code below is my modification of the original library code where the assignment to *s2
was replaced by a memcpy. The original code from the library's github was:
// s1 = our current strobe state
*s1 = ss->strobe;
if (!half_duplex) {
// s2 = s1
*s2 = ss->strobe;
}
My modified version:
// s1 = our current strobe state
*s1 = ss->strobe;
if (!half_duplex) {
// s2 = s1
// WARNING: The below code will give a HARD FAULT ON THE STM32L552ZE!
// *s2 = ss->strobe;
// Fix I tried: Use memcpy instead!
memcpy((void*) s2, (void*)(&(ss -> strobe)), sizeof(strobe_s));
}
Parameter values of memcpy:
Right before the execution of memcpy, the debugger shows me the following values for the variables in question:
Expr. Type Value
----------------------------------------------------
s1 strobe_s * 0x800c374
s2 strobe_s * 0x800a497 <_fflush_r+66>
ss symmetricState * 0x2002f988
&s1 strobe_s ** 0x2002f690
&s2 strobe_s ** 0x2002f68c
&ss symmetricState ** 0x2002f694
Typedefs:
typedef struct symmetricState_ {
strobe_s strobe;
bool isKeyed;
} symmetricState;
/** Keccak's domain: 25 words of size b/25, or b/8 bytes. */
typedef union {
kword_t w[25];
uint8_t b[25 * sizeof(kword_t) / sizeof(uint8_t)];
} kdomain_s;
/** The main strobe state object. */
typedef struct strobe_s_ {
kdomain_s state;
uint8_t position;
uint8_t pos_begin;
uint8_t flags;
uint8_t initiator;
uint8_t initialized; // strobe is initialized if this value is set to 111.
// This is because we cannot assume that a boolean would
// be set to false initially (C stuff). A uint8_t is a
// short value but here we do not care about security
// much, rather catching bugs early in a development
// environement.
} strobe_s;
Questions:
Here:
s2 strobe_s * 0x800a497 <_fflush_r+66>
s2
is a flash (read-only) address. Copying to read-only memory is both semantically erroneous and may trigger an MPU fault if the region were set to read-only.
It is not clear to me how the original code worked or indeed how:
*s1 = ss->strobe;
is not causing a problem too however. Certainly it won't work as intended even if there were no exception.