Command error while reading from the target

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.

My simpleserial main function looks like:

platform_init();
init_uart();
trigger_setup();
simpleserial_init();
simpleserial_addcmd('k', 16, get_key);
simpleserial_addcmd('a', 16, ascon_encrypt_own);
simpleserial_addcmd('x', 0, reset);
while(1)
		simpleserial_get();

In my encryption function, I return the tag with:

simpleserial_put('r', 16, tag);

I run my Python code as:

key=bytearray([0xcb,0x4e,0x8a,0xfe,0x47,0x50,0xd4,0xb6,0x2c,0x1b,0x0a,0xb0,0x43,0x82,0x9e,0x0f])
nonce=bytearray([0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff])

scope.arm()
target.simpleserial_write('k', key)
target.simpleserial_write('a', nonce)
ret = scope.capture()
if ret:
    print("Target timed out!")
response = target.simpleserial_read('r', 16)
print(response)

But get the error

WARNING:ChipWhisperer Target:Unexpected start to command: z

Do you know what could be causing this ?

Thanks in advance

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.

Alex

Thank you so much ! That was exactly it ! What a satisfaction to have your own crypto working on the chip !

Have a great week end !

1 Like

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();
}

The python code is

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) 
print(response)

The output is CWbytearray(b’00 6a 75 e3 11 09 01 ff’) as desired

but when the following is executed

trace3=cw.capture_trace(scope,target,text,key)

results in

 WARNING:ChipWhisperer Target:Unexpected start to command: 

printing trace3 results in the following with textout = None :

Trace(wave=array([ 0.08007812, -0.125 , -0.15625 , …, -0.0078125 ,
0.02832031, 0.02246094]), textin=CWbytearray(b’ff ff ff ff ff ff ff ff’), textout=None, key=CWbytearray(b’00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00’))

I have earlier posted the related query in

were it was suggested to run

scope.adc.trig_count

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

trace3=cw.capture_trace(scope,target,text,key)
trace3

I get the warning
WARNING:ChipWhisperer Target:Unexpected start to command:
along with the output

Trace(wave=array([ 0.08300781, -0.09863281, -0.15332031, ..., -0.1328125 ,
       -0.13476562, -0.10839844]), textin=CWbytearray(b'00 00 00 00 00 00 00 01'), textout=None, key=CWbytearray(b'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'))

In the above output

  1. the first bytearray of Trace is ‘wave’ the trace captured,
  2. the second byte array is ‘textin’ the plaintext input
  3. the third byte array is ‘textout’ which is the ciphertext…but it is None (which is expected to give the ciphertext value as output)
  4. 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.

  1. 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.

  2. 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