Good afternoon,
I’m currently working on an Ascon implementation on the Chipwhisperer.
I’m sending a 16 bytes key and a 16 bytes nonce to the target, process an encryption and return the tag.
Try adding a target.simpleserial_wait_ack() after target.simpleserial_write('k', key). The C return code gets sent back as z<RTN>\n, which is probably what you’re seeing when you try to read the response from the target.
Hi,
I am currently trying to implement a crypto algorithm in Chipwhisperer 1200 XMEGA platform.
The inputs are plaintext (64 bits) and key (128 bits). The cipher text output is also 64 bits.
So based on the previous discussions I have made my simpleserial.c file as
#include "hal.h"
#include "simpleserial.h"
#include "newcrypto_independant.h"
#include <stdint.h>
#include <stdlib.h>
uint8_t get_key(uint8_t* k, uint8_t len)
{
newcrypto_indep_key(k);
return 0x00;
}
uint8_t get_pt(uint8_t* pt, uint8_t len)
{
newcrypto_indep_enc_pretrigger(pt);
trigger_high();
#ifdef ADD_JITTER
for (volatile uint8_t k = 0; k < (*pt & 0x0F); k++);
#endif
newcrypto_indep_enc(pt); /* encrypting the data block */
trigger_low();
newcrypto_indep_enc_posttrigger(pt);
simpleserial_put('r', 8, pt); //value returned from the target pt is updated and returned
return 0x00;
}
uint8_t reset(uint8_t* x, uint8_t len)
{
return 0x00;
}
int main(void)
{
platform_init();
init_uart();
trigger_setup();
newcrypto_indep_init();
simpleserial_init();
simpleserial_addcmd('k', 16, get_key);
simpleserial_addcmd('p', 8, get_pt); //plaintext is 64bits and key is 128 bits
simpleserial_addcmd('x', 0, reset);
while(1)
simpleserial_get();
}
So the output is 16554520 (which I found to be varying)
And I the earlier suggestion was the warning is because the encryption takes longer time. And yes I have replaced the component in encryption algorithm with three more additional functions. Now how can I increase the timeout period to read the generated cipher text?
Also the encryption operation was able to produce output through response = target.simpleserial_read(‘r’, 8,timeout=10000) but why not the same output through cw.capture_trace(scope,target,text,key) ?
capture_trace() has a call to simpleserial_read() using the default timeout of 250ms: https://github.com/newaetech/chipwhisperer/blob/350561ea41e7a392e32bb9841391ee2b1ff56def/software/chipwhisperer/init.py#L505
Your target operation runs for ~16M cycles; assuming it’s clocked at the default 7.37 MHz, that’s over 2 seconds.
You can simply define your own capture_trace function as you have above. The simpleserial_read timeout is defined in ms, so something around 3000 should work for you. Add wave = scope.get_last_trace() to obtain the power trace.
Hi @jpthibault,
I have tried response = target.simpleserial_read('r', 8,timeout=3100) as suggested and I am able to get the desired output.
Also I have used wave = scope.get_last_trace() to obtain the power trace successfully after the capture command.
when I run
the first bytearray of Trace is ‘wave’ the trace captured,
the second byte array is ‘textin’ the plaintext input
the third byte array is ‘textout’ which is the ciphertext…but it is None (which is expected to give the ciphertext value as output)
the second byte array is ‘key’
I can understand that the capture_trace() function calls simpleserial_read() function with default timeout of 250ms but for my design I understand it requires 3100ms to get time out. And, I believe, the textout value turns to be None because of this time out issue.
So, how to pass the timeout value for simpleserial_read() so that I could get the value of cipher text in ‘textout’ variable instead of None.
And does the power trace captured corresponds to the complete cryptographic operation? eventhough, the ‘textout’ variable is None?
The unexpected start to command error occurs because the simpleserial_read times out and so the response obtained is invalid (doesn’t start with r as expected because it hasn’t been received yet). The Trace textout attribute is obtained from that simpleserial_read, so it won’t have a proper value if the read was not successful (i.e. because it timed out).
There is no mechanism to change the default timeout. The reason for this is to keep things simple: in most cases no changes to the timeout are needed, because we wait for the power trace to be captured before attempting the simpleserial_read. This works under the assumption that you’re capturing the full power trace, e.g. in your case this means setting scope.adc.samples to around 16M samples (which requires CW-Pro or Husky, since CW-Lite has a maximum of 24K samples).
The workaround is to not call capture_trace(), but instead do as you had a few posts above:
# your code as before:
keyd1=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
textd1=[0,0,0,0,0,0,0,0]
text=bytearray(textd1)
key=bytearray(keyd1)
scope.arm()
target.simpleserial_write('k', key)
target.simpleserial_write('p', text)
target.simpleserial_wait_ack()
ret = scope.capture()
if ret:
print("Target timed out!")
response = target.simpleserial_read('r', 8,timeout=10000)
# new code:
wave = scope.get_last_trace()
if len(wave) >= 1:
trace = Trace(wave, text, response, key)
else:
trace = None
# return trace
Thank You @jpthibault, I can get clarified at this point.
If I am not wrong, the timeout issue to read the ciphertext, doesn’t affect the power trace captured using the scope.get_last_trace() function. The power trace corresponds to the crypto function getting operated in the target only? Here the issue is just the response couldn’t get read through simpleserial_read() ?
That’s correct. If there was an issue with the power trace capture (e.g. timeout because no trigger is seen), you would get a different message indicating that.
The power trace is collected when the target raises the trigger line high; if you follow our AES example, this is done when the cryptographic activity begins.
Jean-Pierre