Tracing the same function multiple times in one `recv_plain` call

Let’s say I want to have multiple traces of one function/functioncall, while only sending the data that I want to have an input to the function once. So consider a function like this:

uint8_t recv_plain(uint8_t cmd, uint8_t scmd, uint8_t len, uint8_t* pt) {
[..]
static volatile return_value; //static volatile to prevent optimizations
trigger_high();
return_value = functioncall(input);
trigger_low();
[...]
trigger_high();
return_value =functioncall(input);
trigger_low();
[...]
}

And so on. I have multiple questions here:

  1. In python, I then call capture() and then get_last_trace()[:scope.adc.trig_count] - I except that if I divide the resulting trace into equal parts, then each of those parts should represent the trace for a function call. Is this correct?
  2. Considering a manage to get rid of compiler optimizations so that the assembly between the trigger_high and the trigger_low function always looks the same. Can I then expect the trace for two chain function calls to be twice as long as the one for function call? For example, can I expect the trace for the code example above to be twice as long as if I were to call the function just once:
uint8_t recv_plain(uint8_t cmd, uint8_t scmd, uint8_t len, uint8_t* pt) {
[..]
static volatile return_value; //static volatile to prevent optimizations
trigger_high();
return_value = functioncall(input);
trigger_low();
[...]
}

Because this does not seem to be the case and I would like to get more understanding as to why this is not the case.

Thank you so much!
Vincent

Hi Vincent,

  1. It’ll be close, but not quite. The actual trigger happens at the end of trigger_high(), so your first trace
    will have the return from trigger_high(), all of functioncall(), and the call into and most of trigger_low(). Your second partition will have that, plus the return from trigger_low() and the call into and most of trigger_high(). I’d recommend taking a look at the .lss file generated during the build, as this has the assembly and your .c file.
  2. Your might be running into some of what I described above. How much does the length differ from what you expect?

Alex

Thanks! I think the differences where in some compiler optimization I missed – If I put the trigger_high and trigger_low inside the called function itself the assembly seems to be exactly the same and I get the trace length I expect.

Is this the right approach though? Or can there be other side effects the make two traces gathered in one uart communication this way incomparable to two “separate” traces?

So long as the instructions are the same, the traces should look the same. More complicated devices might have things like caching and branch prediction that could disrupt things, but I don’t think
the devices we generally deal with have too much of that.

Alex

Thank you! I was wondering if the following problem could arise: If I trace the function multiple times in a row, then the values for certain registers could stay the same . For example, imagine that in the first function call register r0 is set to to value 2 (and this change results in some power consumption), while in the second function call the value is also set to value 2, but since this is no change, this would not result in an as-high power consumption. I am concerned about this effect changing the measurement results - may I ask for you take on this?

Everything in the function call itself will be the same, as the assembly for the function will push all the registers it’s using onto the stack, then pop them off at the end. The registers, therefore, will be exactly the same before and after the function call, barring the registers used for passing arguments to/from the function.

Additionally, loading the same value multiple times into the register should result in roughly the same power consumption, as the registers are being set to an intermediate value. This saves power in the general case, though obviously not in this particular one, and it what allows us to use Hamming weight instead of Hamming distance for CPA attacks.

Alex

Thank you very much for your reply! I got one more question, because I stumbled into another problem, for which I created a minimum working example (attached).

Basically, if I run a code statement repeatedly N times in a row, enclosed by only trigger_high and trigger_low call, the trace length does not increase by the same amount if I execute the code statement one more time (for example, the increase in trace length is 36 when I run the code 3 times vs. 2 times, but 28 when I run the code 4 times vs. 3 times). I fail to understand why this is the case. Details follow.

In the minimum example, I run the following code N times, enclosed by the trigger_high() and trigger_low() calls.

__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");

For example, when I want to run the code two times I execute:

trigger_high();
__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");
__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");
trigger_low();

When I want to run the code three times I call:

trigger_high();
__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");
__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");
__asm__("mov r1, 5; mov r2, 10; add r0, r1, r2");
trigger_low();

I confirmed in assembly that between the trigger_high() and trigger_low() statements only these assembly instruction and a ldmia.w sp!, {r3, lr} just before the trigger_low() are executed. Now, I would have expected that the trace length increases by the exact same amount each time I execute the respective assembly code. But the results do not confirm this:

Execute 1 times trace_len 208 difference to 0: 208
Execute 2 times trace_len 216 difference to 1: 8
Execute 3 times trace_len 252 difference to 2: 36
Execute 4 times trace_len 280 difference to 3: 28
Execute 5 times trace_len 316 difference to 4: 36

How come the increase is not always the same? I am working the CW308_STM32F4 target.

The minimum example: n_times_tracing_example.zip (27.1 KB) – The zip directory contains the C code, the .lss file, and the python code I ran to get the traces.

Again, thank you very much for your support!