What is the function of .textout?

Hi,
I am trying to implement a cipher, for which implementation is not available in chipwhisperer\hardware\victims\firmware\crypto\avrcryptolib folder.
I have created referred simpleserial-aes.c and replaced the aes functions with what I desired to implement.

import chipwhisperer as cw
scope = cw.scope()
scope.default_setup()
scope.adc.samples=95000

SCOPETYPE = 'OPENADC'
VERSION = 'HARDWARE'
target=cw.target(scope,  cw.targets.SimpleSerial)

%%bash -s "$PLATFORM" "$CRYPTO_TARGET"
cd ../hardware/victims/firmware/simpleserial-cipherother
make PLATFORM=CWLITEXMEGA  CRYPTO_TARGET=AVRCRYPTOLIB SS_VER=SS_VER_1_1 


cw.program_target(scope, cw.programmers.XMEGAProgrammer,"../hardware/victims/firmware/simpleserial-cipherother/simpleserial-cipherother-CWLITEXMEGA.hex" )


proj = cw.create_project("Other", overwrite=True)

from tqdm import tnrange
import numpy as np
import time
keyd1=[0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255]
textd1=[0,0,0,0,0,0,0,0]


text=bytearray(textd1)
key=bytearray(keyd1)


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

Now when I read the value of ct, which must be the cipher text, is not as expected. I am trying to debug this but left clueless. So, from what register/parameter does this cw.capture_trace(scope,target,text,key).textout takes the value? Any steps that I can follow for debugging?

textout is simply the output that the target returns. In our simpleserial-aes example, we return the result of the AES encryption:

Are you doing the same in your implementation?

Yes @jpthibault, I am using the same function,
I have attached the simpleserial file modified used below:


#include "hal.h"
#include "simpleserial.h"
#include "other_independant.h"
#include <stdint.h>
#include <stdlib.h>


uint8_t get_key(uint8_t* k, uint8_t len)
{

	
	other_indep_key(k);
	return 0x00;
}

uint8_t get_pt(uint8_t* pt1, uint8_t len)
{
	
    unsigned char pt[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    other_indep_enc_pretrigger(pt);

	trigger_high();

  	other_indep_enc(pt); /* encrypting the data block */
	trigger_low();

    other_indep_enc_posttrigger(pt);

	simpleserial_put('r', 16, pt); 
	return 0x00;
}

uint8_t reset(uint8_t* x, uint8_t len)
{
    // Reset key here if needed
	return 0x00;
}

int main(void)
{
	uint8_t tmp[KEY_LENGTH] = {DEFAULT_KEY};
    
    platform_init();
    init_uart();
    trigger_setup();

	other_indep_init();
	other_indep_key(tmp);

    /* Uncomment this to get a HELLO message for debug */

/*
    putch('h');
    putch('e');
    putch('l');
    putch('l');
    putch('o');
    putch('\n');
  
*/
	simpleserial_init();
    
    simpleserial_addcmd('k', 16, get_key);
    simpleserial_addcmd('p', 16,  get_pt);  
    simpleserial_addcmd('x',  0,   reset);
   
    while(1)
        simpleserial_get();
}

I worked further on it today, and came to know that the plaintext is always treated as "all 0’s " irrespective of the value given as in previous post through jupyter notebook.

So I tried to hard code the pt value within the uint8_t get_pt() function. But that too didn’t work.

I am getting ct value only for the combination of key entered through jupyter notebook and for plaintext with all 0’s.

One more thing I noticed is, the trace that I plot after capturing is similar to the one that I get in running tinyaes.

I would start debugging this by confirming whether basic communication is working properly. Make pt some fixed pattern in get_pt() and simply return that, and verify that you get this same pattern when you run cw.capture_trace().

Hi @jpthibault , as suggested I have made the simpleserial.c file as follows,

#include "hal.h"
#include "simpleserial.h"
#include <stdint.h>
#include <stdlib.h>

uint8_t get_pt(uint8_t* pt1, uint8_t len)
{
	
    //unsigned char pt[16] = {0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,0x00, 0xff, 0x00, 0xff,0x00, 0xff, 0x00, 0xff};
	//unsigned char pt[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00};
unsigned char pt[16] = {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,0x11, 0x00, 0x11, 0x00,0x11, 0x00, 0x11, 0x00};
    
	trigger_high();

   
	simpleserial_put('r', 16, pt); //value returned from the target
	trigger_low();

   
	
	return 0x00;
}

uint8_t reset(uint8_t* x, uint8_t len)
{
    
	return 0x00;
}

int main(void)
{
	 
    platform_init();
    init_uart();
    trigger_setup();

	simpleserial_init();
    
    simpleserial_addcmd('p', 16,  get_pt);  //plaintext is 64bits and key is 128 bits
    simpleserial_addcmd('x',  0,   reset);
	
    while(1)
        simpleserial_get();
}
  1. I tried hard coding pt values inside the get_pt function with following values,
    a) unsigned char pt[16] = {0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,0x00, 0xff, 0x00, 0xff,0x00, 0xff, 0x00, 0xff};
    b) unsigned char pt[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00};
    c) unsigned char pt[16] = {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,0x11, 0x00, 0x11, 0x00,0x11, 0x00, 0x11, 0x00};

  2. I didn’t hard code the pt value instead, I gave it through the jupyter notebook generated by ktp function.
    In both the scenarios, I can read the pt as it is, which means I hope the simpleserial communication is working fine.

In jupyter notebook through the following commands, I can read the same pt value as hard coded/given trough jupyter notebook with same traces when plotted(no much difference).
trace3=cw.capture_trace(scope,target,text)
ct=trace3.textout

Following is the .ipynb file used:

import chipwhisperer as cw
scope = cw.scope()
scope.default_setup()
scope.adc.samples=95000

SCOPETYPE = 'OPENADC'
#PLATFORM = 'CWLITEXMEGA'
#CRYPTO_TARGET = 'AVRCRYPTOLIB'
VERSION = 'HARDWARE'
target=cw.target(scope,  cw.targets.SimpleSerial)

%%bash -s "$PLATFORM" "$CRYPTO_TARGET"
cd ../hardware/victims/firmware/simpleserial-communication-check
make PLATFORM=CWLITEXMEGA  CRYPTO_TARGET=AVRCRYPTOLIB SS_VER=SS_VER_1_1 

cw.program_target(scope, cw.programmers.XMEGAProgrammer,"../hardware/victims/firmware/simpleserial-communication-check/simpleserial-comm-CWLITEXMEGA.hex" )

print(target.read())

#to set text length as 8/16 byte
ktp=cw.ktp.Basic()
#ktp.text_len=16
key,text=ktp.next()

from tqdm import tnrange
import numpy as np
import time
trace3=cw.capture_trace(scope,target,text)
ct=trace3.textout

%matplotlib notebook
import matplotlib.pylab as plt
plt.plot(trace3[0])
plt.show()

ct

I have attached the screenshot of the captured trace

So this confirms that you are communicating with the target FW correctly. If I understood your original post correctly, you now need to figure out why your target isn’t returning the expected result.
Have you tried using a debugger to see what’s going on? If you don’t have an external debugger, you can now use ChipWhisperer itself for that: Debugging with ChipWhisperer — ChipWhisperer 5.6.1 documentation
(the 5.6.1 release hasn’t happened yet; it should be any day now; in the meantime you need to use our develop branch to get access to this new functionality. Make sure to update your CW firmware.)

I didn’t use debugger yet. I will follow the shared link as suggested.
Thank you @jpthibault.