I have a telemetry stream that is passed through a hardware CRC generator appending the CRC to the end of each telemetry frame. Now I am trying to make something to verify the hardware generated CRC. I have old legacy code (see below) that computes the correct CRC (verified multiple times). However it is slow since each telemetry frame is 300+ bytes and there can be upwards of 10,000,000+ frames to process.
After some research I found some literature pointing me to a table driven approach. The legacy method uses a Poly of 0x8005, reverses the bit order of each byte before processing, and initializes the CRC to zero. However, after building tables for that poly with reversed and non-reversed input and just trying to work through even the first byte of data (0x10) I can not get anything to match what the legacy method is generating.
Inside the calcCRC16 function (below) the existing method checks the LSB where others seem to check the MSB ... and the bit shifts are to the right where other examples I have seen are to the left. I am getting lost in why this is especially since the bit order is swapped before passing it to this function. I have tried on-line calculators & manually doing the look-ups in tables switching the poly from 8005 to A001(reversed), normal and reversed input bytes, and every combination I can think of but can't get any table approach to match the legacy code which I know to be correct for our hardware implementation.
Can anyone help me out if I am missing something obvious? How would you go about creating a table based approach to create the same output? I am a novice at C++ and not really familiar with CRC generation and could be overlooking something fundamental. Sample code and output which was verified against the hardware CRC follows:
Sample Code: I just hard coded a few bytes out of a know telemetry stream as an example
/** ********************************************************************************
* TEST CRC METHOD
*******************************************************************************/
#include <iostream>
using namespace std;
unsigned char swapBits(unsigned char d);
void calcCRC16(unsigned int *CRCVal, unsigned char value);
/** **************************************************************************
* #function main
* TEST CRC METHOd
*******************************************************************************/
int main(int argc, char* argv[])
{
short dataLength = 5;
unsigned int givenCrc;
unsigned int calcCrc;
unsigned char byte[] = {0x10,0xbb,0x42,0x4d,0xfd};
/* Init CRC. */
calcCrc = 0;
cout << "Inital CRC = " << hex << calcCrc << "\n";
/* Read frame data. */
for (int i = 0; i < dataLength; i++)
{
cout << "byte = " << hex << static_cast<int16_t>(byte[i]) << " ";
calcCRC16(&calcCrc, swapBits(byte[i]));
cout << "calcCRC = " << hex << calcCrc << "\n";
}
}
/** ********************************************************************
* #function swapBits
* Swaps the bits so they match the order sent to CRC Gen Hardware
************************************************************************/
unsigned char swapBits(unsigned char d)
{
unsigned char t = 0;
int i = 0;
int n = 0x80;
for(i=0x01; i<0x100; i=i<<1)
{
if (d & i)
{
t|=n;
}
n=n>>1;
}
return t;
}
/** ********************************************************************
* #function calcCRC16
* WORKING METHOD VERIFIED AGAINST CRC HARDWARE
************************************************************************/
void calcCRC16(unsigned int *CRCVal, unsigned char value)
{
unsigned char lsb;
unsigned char bcnt;
for (bcnt=0 ; bcnt<8 ; bcnt++)
{
lsb = (value ^ *CRCVal) & 0x01;
*CRCVal >>= 1;
value >>= 1;
if (lsb != 0)
{
*CRCVal ^= 0x8005;
}
}
}
Output:
Inital CRC = 0
byte = 10 calcCRC = b804
byte = bb calcCRC = 1fb8
byte = 42 calcCRC = 461d
byte = 4d calcCRC = 3d47
byte = fd calcCRC = 683e
rev16(crc16(0, buf, len)) will give you the CRCs listed.
#include <stdio.h>
static unsigned short crc16_table[] = {
0x0000, 0xa001, 0xe003, 0x4002, 0x6007, 0xc006, 0x8004, 0x2005,
0xc00e, 0x600f, 0x200d, 0x800c, 0xa009, 0x0008, 0x400a, 0xe00b,
0x201d, 0x801c, 0xc01e, 0x601f, 0x401a, 0xe01b, 0xa019, 0x0018,
0xe013, 0x4012, 0x0010, 0xa011, 0x8014, 0x2015, 0x6017, 0xc016,
0x403a, 0xe03b, 0xa039, 0x0038, 0x203d, 0x803c, 0xc03e, 0x603f,
0x8034, 0x2035, 0x6037, 0xc036, 0xe033, 0x4032, 0x0030, 0xa031,
0x6027, 0xc026, 0x8024, 0x2025, 0x0020, 0xa021, 0xe023, 0x4022,
0xa029, 0x0028, 0x402a, 0xe02b, 0xc02e, 0x602f, 0x202d, 0x802c,
0x8074, 0x2075, 0x6077, 0xc076, 0xe073, 0x4072, 0x0070, 0xa071,
0x407a, 0xe07b, 0xa079, 0x0078, 0x207d, 0x807c, 0xc07e, 0x607f,
0xa069, 0x0068, 0x406a, 0xe06b, 0xc06e, 0x606f, 0x206d, 0x806c,
0x6067, 0xc066, 0x8064, 0x2065, 0x0060, 0xa061, 0xe063, 0x4062,
0xc04e, 0x604f, 0x204d, 0x804c, 0xa049, 0x0048, 0x404a, 0xe04b,
0x0040, 0xa041, 0xe043, 0x4042, 0x6047, 0xc046, 0x8044, 0x2045,
0xe053, 0x4052, 0x0050, 0xa051, 0x8054, 0x2055, 0x6057, 0xc056,
0x205d, 0x805c, 0xc05e, 0x605f, 0x405a, 0xe05b, 0xa059, 0x0058,
0xa0e9, 0x00e8, 0x40ea, 0xe0eb, 0xc0ee, 0x60ef, 0x20ed, 0x80ec,
0x60e7, 0xc0e6, 0x80e4, 0x20e5, 0x00e0, 0xa0e1, 0xe0e3, 0x40e2,
0x80f4, 0x20f5, 0x60f7, 0xc0f6, 0xe0f3, 0x40f2, 0x00f0, 0xa0f1,
0x40fa, 0xe0fb, 0xa0f9, 0x00f8, 0x20fd, 0x80fc, 0xc0fe, 0x60ff,
0xe0d3, 0x40d2, 0x00d0, 0xa0d1, 0x80d4, 0x20d5, 0x60d7, 0xc0d6,
0x20dd, 0x80dc, 0xc0de, 0x60df, 0x40da, 0xe0db, 0xa0d9, 0x00d8,
0xc0ce, 0x60cf, 0x20cd, 0x80cc, 0xa0c9, 0x00c8, 0x40ca, 0xe0cb,
0x00c0, 0xa0c1, 0xe0c3, 0x40c2, 0x60c7, 0xc0c6, 0x80c4, 0x20c5,
0x209d, 0x809c, 0xc09e, 0x609f, 0x409a, 0xe09b, 0xa099, 0x0098,
0xe093, 0x4092, 0x0090, 0xa091, 0x8094, 0x2095, 0x6097, 0xc096,
0x0080, 0xa081, 0xe083, 0x4082, 0x6087, 0xc086, 0x8084, 0x2085,
0xc08e, 0x608f, 0x208d, 0x808c, 0xa089, 0x0088, 0x408a, 0xe08b,
0x60a7, 0xc0a6, 0x80a4, 0x20a5, 0x00a0, 0xa0a1, 0xe0a3, 0x40a2,
0xa0a9, 0x00a8, 0x40aa, 0xe0ab, 0xc0ae, 0x60af, 0x20ad, 0x80ac,
0x40ba, 0xe0bb, 0xa0b9, 0x00b8, 0x20bd, 0x80bc, 0xc0be, 0x60bf,
0x80b4, 0x20b5, 0x60b7, 0xc0b6, 0xe0b3, 0x40b2, 0x00b0, 0xa0b1};
static unsigned char rev_table[] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
0x3f, 0xbf, 0x7f, 0xff};
unsigned crc16(unsigned crc, unsigned char *buf, int len)
{
while (len--) {
crc ^= *buf++ << 8;
crc = (crc << 8) ^ crc16_table[(crc >> 8) & 0xff];
}
return crc & 0xffff;
}
inline unsigned rev16(unsigned val)
{
return (rev_table[val & 0xff] << 8) | rev_table[(val >> 8) & 0xff];
}
Related
I am in need of a highly optimized CRC8 algorithm. My goal is to develop a Slice-by-4 solution as known from CRC16 / CRC32. I want to keep the code as close to the solution which I am using for CRC16 posted below.
Functions to generate the CRC LookUp-Table:
void crcspeed16_genTable(crcfn16 crcfn, uint16_t table[8][256]) {
uint16_t crc;
/* generate CRCs for all single byte sequences */
for (int n = 0; n < 256; n++) {
table[0][n] = crcfn(0, &n, 1);
}
/* generate nested CRC table for future slice-by-8 lookup */
for (int n = 0; n < 256; n++) {
crc = table[0][n];
for (int k = 1; k < 8; k++) {
crc = table[0][(crc >> 8) & 0xff] ^ (crc << 8);
table[k][n] = crc;
}
}
}
uint16_t crc16(uint16_t crc, const void *in_data, uint64_t len) {
const uint8_t *data = (const uint8_t*) in_data;
for (uint64_t i = 0; i < len; i++) {
crc = crc ^ (data[i] << 8);
for (int j = 0; j < 8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ CRC16_POLYNOMINAL;
} else {
crc = (crc << 1);
}
}
}
return crc;
}
Call to generate the table:
crcspeed16_genTable(crc16, crc16_LUT);
Function to generate the CRC16 based on the Slice-by-4 solution:
uint16_t crc16_slice4(const void *buf, size_t len, uint16_t initialValue, uint16_t XOR_OUT) {
uint16_t crc = initialValue;
unsigned char *next = (unsigned char *)buf;
// process individual bytes until we reach an 8-byte aligned pointer
while (len && ((uintptr_t)next & 7) != 0) {
crc = crc16_LUT[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
len--;
}
// fast middle processing, 4 bytes (aligned!) per loop */
while (len >= 4) {
uint32_t n = *(uint32_t *)next;
crc = crc16_LUT[3][(n & 0xff) ^ ((crc >> 8) & 0xff)] ^
crc16_LUT[2][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
crc16_LUT[1][(n >> 16) & 0xff] ^
crc16_LUT[0][n >> 24];
next += 4;
len -= 4;
}
// process remaining bytes (can't be larger than 8)
while (len) {
crc = crc16_LUT[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
len--;
}
return crc ^ XOR_OUT;
}
My aim is to adapt the algorithm to be working for CRC8 and CRC4. What I have managed so far is to change the LUT-Generator to be generating a valid first row of the LUT and process a valid CRC based on this LUT data. I am failing to adapt the middle part to calculate and utilize the full potential of the CRC table.
Adapted functions (not fully functional) for CRC8:
Table generation:
void crcspeed8_genTable(crcfn8 crcfn, uint8_t table[8][256]) {
uint16_t crc;
/* generate CRCs for all single byte sequences */
for (int n = 0; n < 256; n++) {
table[0][n] = crcfn(0, &n, 1);
}
/* generate nested CRC table for future slice-by-8 lookup */
for (int n = 0; n < 256; n++) {
crc = table[0][n];
for (int k = 1; k < 8; k++) {
//crc = table[0][crc] ^ crc;
crc = table[0][(crc >> 4) & 0x0f] ^ (crc << 4);
table[k][n] = crc;
}
}
}
uint8_t crc8(uint8_t crc, const void *in_data, uint64_t len) {
const uint8_t *data = (const uint8_t*) in_data;
for (uint64_t i = 0; i < len; i++) {
//crc = crc ^ (data[i] << 8);
crc = crc ^ data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x80) {
crc = (crc << 1) ^ CRC8_POLYNOMINAL;
} else {
crc = (crc << 1);
}
}
}
return crc;
}
CRC calculation:
uint8_t crc8_slice4(const void *buf, size_t len, uint8_t initialValue, uint8_t XOR_OUT) {
uint8_t crc = initialValue;
unsigned char *next = (unsigned char *)buf;
// process individual bytes until we reach an 8-byte aligned pointer
while (len && ((uintptr_t)next & 7) != 0) {
printf("\nAlign processing");
crc = crc8_LUT[0][crc ^ *next++];
len--;
}
//fast middle processing, 4 bytes (aligned!) per loop
while (len >= 4) {
printf("\nSlice processing");
uint32_t n = *(uint32_t *)next;
//This part should be adopted to work for CRC8
/*crc = crc8_LUT[3][(n & 0xff) ^ crc] ^
crc8_LUT[2][(n >> 8) & 0xff] ^
crc8_LUT[1][(n >> 16) & 0xff] ^
crc8_LUT[0][n >> 24]; */
uint32_t n0 = (n & 0xFF) ^ crc;
uint32_t n1 = (n >> 8) & 0xFF;
uint32_t n2 = (n >> 16) & 0xFF;
uint32_t n3 = (n >> 24);
//Working multi step for CRC 4 only using first row of LUT
uint8_t crc0 = crc8_LUT[0][crc ^ n0];
uint8_t crc1 = crc8_LUT[0][crc0 ^ n1];
uint8_t crc2 = crc8_LUT[0][crc1 ^ n2];
uint8_t crc3 = crc8_LUT[0][crc2 ^ n3];
crc = crc3;
next += 4;
len -= 4;
}
// process remaining bytes (can't be larger than 8)
while (len) {
printf("\nRemain processing");
crc = crc8_LUT[0][crc ^ *next++];
len--;
}
return crc ^ XOR_OUT;
}
I tried to change the functions to be working for CRC8 but I can't figure out the middle part. A solution explaining the general approach to generating Look-Up-Tables for various CRCs (4/8/16/24/32...) would also be highly appreciated.
Thanks for hopefully pointing me in the right direction.
You didn't provide your polynomial, initial value, or final exclusive or. With those (and that the CRC in your case is not reflected), you can use crcany to generate the code for you.
Here is an example for little-endian slice-by-4:
#include <stddef.h>
#include <stdint.h>
#define table_byte table_word[0]
static uint8_t const table_word[][256] = {
{0xbd, 0x92, 0xe3, 0xcc, 0x01, 0x2e, 0x5f, 0x70, 0xea, 0xc5, 0xb4, 0x9b, 0x56,
0x79, 0x08, 0x27, 0x13, 0x3c, 0x4d, 0x62, 0xaf, 0x80, 0xf1, 0xde, 0x44, 0x6b,
0x1a, 0x35, 0xf8, 0xd7, 0xa6, 0x89, 0xce, 0xe1, 0x90, 0xbf, 0x72, 0x5d, 0x2c,
0x03, 0x99, 0xb6, 0xc7, 0xe8, 0x25, 0x0a, 0x7b, 0x54, 0x60, 0x4f, 0x3e, 0x11,
0xdc, 0xf3, 0x82, 0xad, 0x37, 0x18, 0x69, 0x46, 0x8b, 0xa4, 0xd5, 0xfa, 0x5b,
0x74, 0x05, 0x2a, 0xe7, 0xc8, 0xb9, 0x96, 0x0c, 0x23, 0x52, 0x7d, 0xb0, 0x9f,
0xee, 0xc1, 0xf5, 0xda, 0xab, 0x84, 0x49, 0x66, 0x17, 0x38, 0xa2, 0x8d, 0xfc,
0xd3, 0x1e, 0x31, 0x40, 0x6f, 0x28, 0x07, 0x76, 0x59, 0x94, 0xbb, 0xca, 0xe5,
0x7f, 0x50, 0x21, 0x0e, 0xc3, 0xec, 0x9d, 0xb2, 0x86, 0xa9, 0xd8, 0xf7, 0x3a,
0x15, 0x64, 0x4b, 0xd1, 0xfe, 0x8f, 0xa0, 0x6d, 0x42, 0x33, 0x1c, 0x5e, 0x71,
0x00, 0x2f, 0xe2, 0xcd, 0xbc, 0x93, 0x09, 0x26, 0x57, 0x78, 0xb5, 0x9a, 0xeb,
0xc4, 0xf0, 0xdf, 0xae, 0x81, 0x4c, 0x63, 0x12, 0x3d, 0xa7, 0x88, 0xf9, 0xd6,
0x1b, 0x34, 0x45, 0x6a, 0x2d, 0x02, 0x73, 0x5c, 0x91, 0xbe, 0xcf, 0xe0, 0x7a,
0x55, 0x24, 0x0b, 0xc6, 0xe9, 0x98, 0xb7, 0x83, 0xac, 0xdd, 0xf2, 0x3f, 0x10,
0x61, 0x4e, 0xd4, 0xfb, 0x8a, 0xa5, 0x68, 0x47, 0x36, 0x19, 0xb8, 0x97, 0xe6,
0xc9, 0x04, 0x2b, 0x5a, 0x75, 0xef, 0xc0, 0xb1, 0x9e, 0x53, 0x7c, 0x0d, 0x22,
0x16, 0x39, 0x48, 0x67, 0xaa, 0x85, 0xf4, 0xdb, 0x41, 0x6e, 0x1f, 0x30, 0xfd,
0xd2, 0xa3, 0x8c, 0xcb, 0xe4, 0x95, 0xba, 0x77, 0x58, 0x29, 0x06, 0x9c, 0xb3,
0xc2, 0xed, 0x20, 0x0f, 0x7e, 0x51, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87,
0xa8, 0x32, 0x1d, 0x6c, 0x43, 0x8e, 0xa1, 0xd0, 0xff},
{0xfa, 0x13, 0x07, 0xee, 0x2f, 0xc6, 0xd2, 0x3b, 0x7f, 0x96, 0x82, 0x6b, 0xaa,
0x43, 0x57, 0xbe, 0xdf, 0x36, 0x22, 0xcb, 0x0a, 0xe3, 0xf7, 0x1e, 0x5a, 0xb3,
0xa7, 0x4e, 0x8f, 0x66, 0x72, 0x9b, 0xb0, 0x59, 0x4d, 0xa4, 0x65, 0x8c, 0x98,
0x71, 0x35, 0xdc, 0xc8, 0x21, 0xe0, 0x09, 0x1d, 0xf4, 0x95, 0x7c, 0x68, 0x81,
0x40, 0xa9, 0xbd, 0x54, 0x10, 0xf9, 0xed, 0x04, 0xc5, 0x2c, 0x38, 0xd1, 0x6e,
0x87, 0x93, 0x7a, 0xbb, 0x52, 0x46, 0xaf, 0xeb, 0x02, 0x16, 0xff, 0x3e, 0xd7,
0xc3, 0x2a, 0x4b, 0xa2, 0xb6, 0x5f, 0x9e, 0x77, 0x63, 0x8a, 0xce, 0x27, 0x33,
0xda, 0x1b, 0xf2, 0xe6, 0x0f, 0x24, 0xcd, 0xd9, 0x30, 0xf1, 0x18, 0x0c, 0xe5,
0xa1, 0x48, 0x5c, 0xb5, 0x74, 0x9d, 0x89, 0x60, 0x01, 0xe8, 0xfc, 0x15, 0xd4,
0x3d, 0x29, 0xc0, 0x84, 0x6d, 0x79, 0x90, 0x51, 0xb8, 0xac, 0x45, 0xfd, 0x14,
0x00, 0xe9, 0x28, 0xc1, 0xd5, 0x3c, 0x78, 0x91, 0x85, 0x6c, 0xad, 0x44, 0x50,
0xb9, 0xd8, 0x31, 0x25, 0xcc, 0x0d, 0xe4, 0xf0, 0x19, 0x5d, 0xb4, 0xa0, 0x49,
0x88, 0x61, 0x75, 0x9c, 0xb7, 0x5e, 0x4a, 0xa3, 0x62, 0x8b, 0x9f, 0x76, 0x32,
0xdb, 0xcf, 0x26, 0xe7, 0x0e, 0x1a, 0xf3, 0x92, 0x7b, 0x6f, 0x86, 0x47, 0xae,
0xba, 0x53, 0x17, 0xfe, 0xea, 0x03, 0xc2, 0x2b, 0x3f, 0xd6, 0x69, 0x80, 0x94,
0x7d, 0xbc, 0x55, 0x41, 0xa8, 0xec, 0x05, 0x11, 0xf8, 0x39, 0xd0, 0xc4, 0x2d,
0x4c, 0xa5, 0xb1, 0x58, 0x99, 0x70, 0x64, 0x8d, 0xc9, 0x20, 0x34, 0xdd, 0x1c,
0xf5, 0xe1, 0x08, 0x23, 0xca, 0xde, 0x37, 0xf6, 0x1f, 0x0b, 0xe2, 0xa6, 0x4f,
0x5b, 0xb2, 0x73, 0x9a, 0x8e, 0x67, 0x06, 0xef, 0xfb, 0x12, 0xd3, 0x3a, 0x2e,
0xc7, 0x83, 0x6a, 0x7e, 0x97, 0x56, 0xbf, 0xab, 0x42},
{0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0xa1, 0xaf, 0xbd, 0xb3, 0x99,
0x97, 0x85, 0x8b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0x41, 0x4f,
0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x3e, 0x30, 0x22, 0x2c, 0x06, 0x08, 0x1a,
0x14, 0x4e, 0x40, 0x52, 0x5c, 0x76, 0x78, 0x6a, 0x64, 0xde, 0xd0, 0xc2, 0xcc,
0xe6, 0xe8, 0xfa, 0xf4, 0xae, 0xa0, 0xb2, 0xbc, 0x96, 0x98, 0x8a, 0x84, 0x20,
0x2e, 0x3c, 0x32, 0x18, 0x16, 0x04, 0x0a, 0x50, 0x5e, 0x4c, 0x42, 0x68, 0x66,
0x74, 0x7a, 0xc0, 0xce, 0xdc, 0xd2, 0xf8, 0xf6, 0xe4, 0xea, 0xb0, 0xbe, 0xac,
0xa2, 0x88, 0x86, 0x94, 0x9a, 0xcf, 0xc1, 0xd3, 0xdd, 0xf7, 0xf9, 0xeb, 0xe5,
0xbf, 0xb1, 0xa3, 0xad, 0x87, 0x89, 0x9b, 0x95, 0x2f, 0x21, 0x33, 0x3d, 0x17,
0x19, 0x0b, 0x05, 0x5f, 0x51, 0x43, 0x4d, 0x67, 0x69, 0x7b, 0x75, 0x1c, 0x12,
0x00, 0x0e, 0x24, 0x2a, 0x38, 0x36, 0x6c, 0x62, 0x70, 0x7e, 0x54, 0x5a, 0x48,
0x46, 0xfc, 0xf2, 0xe0, 0xee, 0xc4, 0xca, 0xd8, 0xd6, 0x8c, 0x82, 0x90, 0x9e,
0xb4, 0xba, 0xa8, 0xa6, 0xf3, 0xfd, 0xef, 0xe1, 0xcb, 0xc5, 0xd7, 0xd9, 0x83,
0x8d, 0x9f, 0x91, 0xbb, 0xb5, 0xa7, 0xa9, 0x13, 0x1d, 0x0f, 0x01, 0x2b, 0x25,
0x37, 0x39, 0x63, 0x6d, 0x7f, 0x71, 0x5b, 0x55, 0x47, 0x49, 0xed, 0xe3, 0xf1,
0xff, 0xd5, 0xdb, 0xc9, 0xc7, 0x9d, 0x93, 0x81, 0x8f, 0xa5, 0xab, 0xb9, 0xb7,
0x0d, 0x03, 0x11, 0x1f, 0x35, 0x3b, 0x29, 0x27, 0x7d, 0x73, 0x61, 0x6f, 0x45,
0x4b, 0x59, 0x57, 0x02, 0x0c, 0x1e, 0x10, 0x3a, 0x34, 0x26, 0x28, 0x72, 0x7c,
0x6e, 0x60, 0x4a, 0x44, 0x56, 0x58, 0xe2, 0xec, 0xfe, 0xf0, 0xda, 0xd4, 0xc6,
0xc8, 0x92, 0x9c, 0x8e, 0x80, 0xaa, 0xa4, 0xb6, 0xb8},
{0x84, 0x31, 0xc1, 0x74, 0x0e, 0xbb, 0x4b, 0xfe, 0xbf, 0x0a, 0xfa, 0x4f, 0x35,
0x80, 0x70, 0xc5, 0xf2, 0x47, 0xb7, 0x02, 0x78, 0xcd, 0x3d, 0x88, 0xc9, 0x7c,
0x8c, 0x39, 0x43, 0xf6, 0x06, 0xb3, 0x68, 0xdd, 0x2d, 0x98, 0xe2, 0x57, 0xa7,
0x12, 0x53, 0xe6, 0x16, 0xa3, 0xd9, 0x6c, 0x9c, 0x29, 0x1e, 0xab, 0x5b, 0xee,
0x94, 0x21, 0xd1, 0x64, 0x25, 0x90, 0x60, 0xd5, 0xaf, 0x1a, 0xea, 0x5f, 0x73,
0xc6, 0x36, 0x83, 0xf9, 0x4c, 0xbc, 0x09, 0x48, 0xfd, 0x0d, 0xb8, 0xc2, 0x77,
0x87, 0x32, 0x05, 0xb0, 0x40, 0xf5, 0x8f, 0x3a, 0xca, 0x7f, 0x3e, 0x8b, 0x7b,
0xce, 0xb4, 0x01, 0xf1, 0x44, 0x9f, 0x2a, 0xda, 0x6f, 0x15, 0xa0, 0x50, 0xe5,
0xa4, 0x11, 0xe1, 0x54, 0x2e, 0x9b, 0x6b, 0xde, 0xe9, 0x5c, 0xac, 0x19, 0x63,
0xd6, 0x26, 0x93, 0xd2, 0x67, 0x97, 0x22, 0x58, 0xed, 0x1d, 0xa8, 0x45, 0xf0,
0x00, 0xb5, 0xcf, 0x7a, 0x8a, 0x3f, 0x7e, 0xcb, 0x3b, 0x8e, 0xf4, 0x41, 0xb1,
0x04, 0x33, 0x86, 0x76, 0xc3, 0xb9, 0x0c, 0xfc, 0x49, 0x08, 0xbd, 0x4d, 0xf8,
0x82, 0x37, 0xc7, 0x72, 0xa9, 0x1c, 0xec, 0x59, 0x23, 0x96, 0x66, 0xd3, 0x92,
0x27, 0xd7, 0x62, 0x18, 0xad, 0x5d, 0xe8, 0xdf, 0x6a, 0x9a, 0x2f, 0x55, 0xe0,
0x10, 0xa5, 0xe4, 0x51, 0xa1, 0x14, 0x6e, 0xdb, 0x2b, 0x9e, 0xb2, 0x07, 0xf7,
0x42, 0x38, 0x8d, 0x7d, 0xc8, 0x89, 0x3c, 0xcc, 0x79, 0x03, 0xb6, 0x46, 0xf3,
0xc4, 0x71, 0x81, 0x34, 0x4e, 0xfb, 0x0b, 0xbe, 0xff, 0x4a, 0xba, 0x0f, 0x75,
0xc0, 0x30, 0x85, 0x5e, 0xeb, 0x1b, 0xae, 0xd4, 0x61, 0x91, 0x24, 0x65, 0xd0,
0x20, 0x95, 0xef, 0x5a, 0xaa, 0x1f, 0x28, 0x9d, 0x6d, 0xd8, 0xa2, 0x17, 0xe7,
0x52, 0x13, 0xa6, 0x56, 0xe3, 0x99, 0x2c, 0xdc, 0x69}
};
// This code assumes that integers are stored little-endian.
uint8_t crc8autosar_word(uint8_t crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0;
while (len && ((ptrdiff_t)data & 0x3)) {
len--;
crc = table_byte[crc ^ *data++];
}
size_t n = len >> 2;
for (size_t i = 0; i < n; i++) {
uint32_t word = crc ^ ((uint32_t const *)data)[i];
crc = table_word[3][word & 0xff] ^
table_word[2][(word >> 8) & 0xff] ^
table_word[1][(word >> 16) & 0xff] ^
table_word[0][word >> 24];
}
data += n << 2;
len &= 3;
while (len) {
len--;
crc = table_byte[crc ^ *data++];
}
return crc;
}
The convention for this code is that when called with mem == NULL, crc is ignored and the initial CRC, i.e. the CRC of an empty message, is returned.
I have c++ code that read 16 byte from a file as char value
And I have a table of unsigned char from 0 to 255
I want to use byte values from file as a index in my unsigned char table to change the original file byte values but I get negative value from file and as you know you can't use negative value as a index in array
What should I do ?
Edit
const unsigned char TopSbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
void RunFunction(){
ifstream reader;
ofstream writer;
reader.open(myfile_address, ifstream::binary);
writer.open(storage_file,ofstream::out);
unsigned int BufferSize =16;
char *Transform_Buffer = new char[BufferSize];
reader.read(Transform_Buffer, BufferSize);
ExchangeData(Transform_Buffer, BufferSize);
writer.write(Transform_Buffer, BufferSize);
writer.flush();
}
void EData::ExchangeData(char data[], const unsigned int size){
for (unsigned int i = 0; i<size; i++){
data[i] = TopSbox[data[i]];
}
}
Don't use operator new unless absolutely necessary.
Rather than
char *Transform_Buffer = new char[BufferSize];
you can define the buffer as a local array:
const unsigned int BufferSize = 16;
unsigned char Transform_Buffer[BufferSize];
For this to work, you should declare BufferSize as const. Notice also that I declared the elements of the buffer as unsigned char.
Then, this line
reader.read(Transform_Buffer, BufferSize);
can be replaced with
reader.read(reinterpret_cast<char*>(Transform_Buffer), BufferSize);
and similarly for writer.
Please also replace all char* in function declarations with unsigned char*, eg:
void EData::ExchangeData(unsigned char data[], const unsigned int size){
I guess everything should work as expected now.
Just have buffer of unsigned chars. Then pass it as char* to ifstream::read. Let's say char* works kind of like a generic pointer.
You may want to prefer to use standard containers.
std::vector<unsigned char> transform_buffer(buffer_size);
reader.read(static_cast<char*>(transform_buffer.data()), transform_buffer.size());
exchange_data(transform_buffer);
}
void exchange_data(std::vector<unsigned char>& transform_buffer) {
for (auto&& i : transform_buffer) {
i = TopSbox[i];
}
}
I am looking for examples of calling the libtomcrypt ecc sign and verify code using inputs created using the OpenSSL command line. I have created private and public keys, using the prime256v1 curve, created a signature for a text file and verified it using the command line. I have pulled those keys and the signature in to my C++ test driver and used the libtomcrypt methods to import those. I created the hash of the text file using the openssl command line and put that into my test driver as well, but when I call the libtomcrypt ecc_verify_hash method, it fails to verify. At this point I have verified that the keys and the signature are importing correctly, so I'm not sure what I'm doing incorrectly.
Here is the code for my test driver. Any help with this would be greatly appreciated.
int main ()
{
ltc_mp = ltm_desc;
int idx = 0;
prng_state myPrng;
//unsigned char buf[4096];
//unsigned long b;
int stat, err;
ecc_key pubKey;
ecc_key privKey;
void* sig;
static unsigned char MSG_STR[] = "Test Message";
const int MSG_STR_LEN = 12;
static unsigned char DGST[] =
"C87D25A09584C040F3BFC53B5701199591DEB10BA";
const int DGST_LEN = 41;
// the DER forms of the keys
static unsigned char PRIV_KEY[] =
{
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x4f,
0xab, 0xef, 0xfb, 0x6a, 0xe4, 0xcd, 0xd5, 0x83,
0xb7, 0x39, 0x57, 0xf5, 0x63, 0xd4, 0x60, 0xa6,
0x83, 0x26, 0x56, 0xb8, 0x1e, 0x78, 0xee, 0x3d,
0xf0, 0xa9, 0xe8, 0x3b, 0x2c, 0x34, 0xc1, 0xa0,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00,
0x04, 0x24, 0x72, 0xcb, 0x56, 0xb5, 0xae, 0x0a,
0x8e, 0x14, 0xc9, 0x89, 0x3d, 0xc8, 0x61, 0xb6,
0xed, 0x74, 0xa2, 0x2f, 0x15, 0xb7, 0x31, 0x14,
0xc6, 0xd5, 0x38, 0x71, 0xaa, 0x3f, 0x52, 0x5c,
0x8e, 0x3e, 0x59, 0xaa, 0x68, 0xcd, 0xcd, 0x8c,
0x2c, 0x63, 0x9b, 0xbc, 0x46, 0x79, 0x87, 0xd4,
0xdd, 0x4f, 0xbd, 0x97, 0x2b, 0xc2, 0x6a, 0x5d,
0x5c, 0xb5, 0xc7, 0x91, 0xaa, 0x15, 0xf8, 0x7c,
0x27
};
const int PRIV_KEY_LEN = 121;
static unsigned char PUB_KEY[] =
{
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0x24, 0x72, 0xcb, 0x56, 0xb5,
0xae, 0x0a, 0x8e, 0x14, 0xc9, 0x89, 0x3d, 0xc8,
0x61, 0xb6, 0xed, 0x74, 0xa2, 0x2f, 0x15, 0xb7,
0x31, 0x14, 0xc6, 0xd5, 0x38, 0x71, 0xaa, 0x3f,
0x52, 0x5c, 0x8e, 0x3e, 0x59, 0xaa, 0x68, 0xcd,
0xcd, 0x8c, 0x2c, 0x63, 0x9b, 0xbc, 0x46, 0x79,
0x87, 0xd4, 0xdd, 0x4f, 0xbd, 0x97, 0x2b, 0xc2,
0x6a, 0x5d, 0x5c, 0xb5, 0xc7, 0x91, 0xaa, 0x15,
0xf8, 0x7c, 0x27
};
const int PUB_KEY_LEN = 91;
static unsigned char OPENSSL_SIG[] =
{
0x30, 0x46, 0x02, 0x21, 0x00, 0xf3, 0x69, 0xd9,
0xaf, 0xad, 0xc7, 0x16, 0xac, 0x03, 0x9a, 0x5c,
0xae, 0xf7, 0x05, 0x86, 0x56, 0x24, 0x18, 0x09,
0x44, 0x3b, 0x07, 0xc9, 0xec, 0x6b, 0x72, 0x69,
0x18, 0x13, 0x10, 0xd7, 0x32, 0x02, 0x21, 0x00,
0xd5, 0xa1, 0x21, 0xc0, 0xf8, 0x5d, 0xb6, 0x6f,
0x46, 0x04, 0x9b, 0x2e, 0x1f, 0x96, 0xdc, 0x55,
0xd6, 0x5e, 0xc5, 0x14, 0x3c, 0x68, 0x70, 0x2a,
0x0c, 0x17, 0xad, 0xa1, 0xb8, 0x90, 0x0b, 0x07
};
const int OPENSSL_SIG_LEN = 72;
static unsigned char RAND_DATA[] =
"8e2582c586c37099c3126170e48352c5416c41ef44972ec0708ef2caab08"
"583f10b277276c2507dee509a0c492bb806108590db675f6d908025999a6"
"7cc049290fe4ea0beb6b62004cbc82c580e5c00fa360d2f55b565535f6ec"
"41a2adfe83ffc3a2007ee1e1ba03b94fb777350e1c3a2caffcf6434534bd"
"8d29c2b62a9abf279c9a419a53ae54c3f22d0d0886ced81d7422bfb2493b"
"2231d8aad890d80f1dc42280e6803fa768d2a5ebaf954e91713d9e0d93d9"
"9749b7b29d8deac683fa930d39758212020e6ebc850993804ce6a6a969a3"
"261ad870040634bb2c506c911e06b20ab723d03df239c39ecf210fa67ab2"
"54573c5531a475c3e7158eb89074a77238182b9b72d0f4d1407cffb6d59c"
"53ec202a5b36bd649b2a6f31ad182072d549402df2e1ed8289ad08973444"
"1269bbccca6bc8899e8a750329c35a1c7a19281bf90c1575ebc5c197e19f"
"5cc4e3f3dd5f507df6457a6e39b4609a774c11e5b15210d2a49ee3dab9e3"
"fb89966b8fa83cc9c3045f67001f8447d9d035c512f3c1c6332c701b403c"
"52d424d116b78426e013e34b1c3b7dbf87669970799a719971e1583135db"
"727ea7297bf76d093fc4648fca0cf79dbd6144963061838178d8b32efe9d"
"ee5ff58e9c6e6fc922b9e94631c7d76e06a0d28fc1c40d634e65e332ed4d"
"ff85293e5a9f103410c5e974775be91a773508293b5fcd8672a1a30640a7"
"9e42755d2b5229292848b6e56b540ba2d1bd2e7e5d61895293c5e9ee83ce"
"bba4194a3191fc9f0e6924835761c512d0515bb63b334c5e98dc0d43e7ce"
"3ee11e46872e4d8d767104189429f5cbcf4fd8db7c3022dd5e5ae99f5a48"
"e595fdff8d9db23e3beebef219341c53aa7e6da2fad750d2a648b58a0151"
"d0b029cf5d1900b65c047b95dd3004a048be4611d49f6a96f3f054b3c476"
"4b2e1a521a57e46b3df537d8a442726ce0e318fc356538e888d8825edfa2"
"4c3c42716a628c331db6261455c9c5d4b98d466f4831d28a6f9eb2abe758"
"38f81ca42e06f362d3d263a9c0e7bffaff635fc640434b02dd2f740a4737"
"6180bbe217436b86d481f83825e28b92ab3444b7c3326e18d796ac9c2633"
"4d9cc9310f29f42dfe4d9b53bd40b7f1433708c87ad412bbf8b646ec1468"
"76a8083e08029de1b84f7ebb606bf84a59dc7f1b46df2cc5c0ba5008761d"
"9da2344434f524e7ad6e648964a761907c1a0ccb1fdee645ad7aaf4ea0c8"
"68fd39ae75b2bc41b8c86f5adaa2105f84e9b187c5a887c9e0d726383564"
"34fe79c7ae0460cc7eddffe3f3109f83cf7a80ba8432ff9dd9f0b664cb6d"
"fc215800e4253d0bfa1a74df5f7b52f0d0ac9e3ce1af856058d7c2b117ae"
"7a5a7cfac7ea592e88c8417d16fe10f4545af981e937fb194c26a2e44f3f"
"40ea26dd794ad8f2d16f36eb27c6eaa6780925e8d7e96dfdde483800a9b3"
"95c7a358";
const int RAND_DATA_LEN = 2049;
ltm_desc.init(&privKey.k);
ltm_desc.init(&pubKey.pubkey.x);
ltm_desc.init(&pubKey.pubkey.y);
ltm_desc.init(&pubKey.pubkey.z);
ltm_desc.init(&sig);
// set up the random number generator
if ((err = register_prng(&yarrow_desc)) != CRYPT_OK) {
cout << "Failed to register prng. Err = " << err << endl;
return err;
}
if ((err = yarrow_start(&myPrng)) != CRYPT_OK) {
cout << "Yarrow failed to start! Err = " << err << endl;
return err;
}
if ((err = yarrow_add_entropy(RAND_DATA, RAND_DATA_LEN, &myPrng))
!= CRYPT_OK) {
cout << "Failed adding entropy Err = " << err << endl;
return err;
}
if ((err = yarrow_ready(&myPrng)) != CRYPT_OK) {
cout << "Failed to set state to ready. Err = " << err << endl;
return err;
}
// read in the private key information
if ((err = ecc_import_openssl(PRIV_KEY, PRIV_KEY_LEN, &privKey))
!= CRYPT_OK)
{
cout << "Failed to import private key, err =" << err << endl;
return err;
}
// read in the public key information
if ((err = ecc_import_openssl(PUB_KEY, PUB_KEY_LEN, &pubKey))
!= CRYPT_OK)
{
cout << "Failed to import public key, err =" << err << endl;
return err;
}
// try to verify the signature created using OpenSSL
// with the libtom verify method
if (((err = ecc_verify_hash(OPENSSL_SIG,
OPENSSL_SIG_LEN,
DGST,
DGST_LEN,
&stat,
&pubKey)) != CRYPT_OK)) {
cout << "Failed to verify OpenSSL signature using libtom. Error ="
<< err << endl;
return err;
} else if (stat == 0) {
cout << "Failed to verify OpenSSL signature using libtom. Error ="
<< err << endl;
return err;
}
else {
cout << "Successfully verifed OpenSSL signature using libtom."
<< endl;
}
ecc_free (&pubKey);
ecc_free (&privKey);
}
I have a C++ compile-at-run-time script written for a VxWorks derived PowerPC platform, which calculates checksums for files on the embedded OS. It uses a pair of lookup tables to compute the checksum (see my code below).
I'm trying to port this script to use on Windows, because the platform dictates that I must hardcode a new script for every single file I wish to calculate the checksum for, and with what I'm trying to do that will take many hours. I need to change a bunch of files on the platform file system and provide their checksums to the system or it will refuse to load them.
I've got the code running, having changed all of the UI/output and file input stuff to work with Windows, but I'm getting the wrong checksum. On my test file, I should be getting 404f and I'm actually getting 5fb4.
Having done some research I believe I may need to convert or regenerate the lookup tables, but I have no idea how to go about this and would be grateful for any input.
Thanks!
// rt6_crc_checker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define TRUE 1
#define FALSE 0
#define SKIP 1
#include <windows.h>
#include <iostream>
#include <cstdlib>
#include <sys/stat.h>
using namespace std;
int PL_FileExists( char *p_pPath );
void PL_itoa10( int i , char* s );
void PL_itoa16( int i , char* s );
int change_endian(int num){
int byte0, byte1, byte2, byte3;
byte0 = (num & 0x000000FF) >> 0 ;
byte1 = (num & 0x0000FF00) >> 8 ;
byte2 = (num & 0x00FF0000) >> 16 ;
byte3 = (num & 0xFF000000) >> 24 ;
return((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | (byte3 << 0));
}
/*** MAIN ***/
int main ( int argc, char **argv )
{
char carlu;
char s_nb[16];
char s_i[16];
char CRC_FIC[16];
char CRC_INF[16];
char MessPL[256];
int nb;
int size_FIC;
int size_INF;
int answ;
int CRC;
int c1;
int c2;
int rg;
int i;
int j;
FILE *l_fileIN;
FILE *l_fileOUT;
char l_line[20];
int table_h[]=
{
0x00, 0xdf, 0xbe, 0x61, 0x7c, 0xa3, 0xc2, 0x1d, 0xd3, 0x0c, 0x6d, 0xb2, 0xaf, 0x70, 0x11, 0xce,
0x8d, 0x52, 0x33, 0xec, 0xf1, 0x2e, 0x4f, 0x90, 0x5e, 0x81, 0xe0, 0x3f, 0x22, 0xfd, 0x9c, 0x43,
0x1a, 0xc5, 0xa4, 0x7b, 0x66, 0xb9, 0xd8, 0x07, 0xc9, 0x16, 0x77, 0xa8, 0xb5, 0x6a, 0x0b, 0xd4,
0x97, 0x48, 0x29, 0xf6, 0xeb, 0x34, 0x55, 0x8a, 0x44, 0x9b, 0xfa, 0x25, 0x38, 0xe7, 0x86, 0x59,
0x1f, 0xc0, 0xa1, 0x7e, 0x63, 0xbc, 0xdd, 0x02, 0xcc, 0x13, 0x72, 0xad, 0xb0, 0x6f, 0x0e, 0xd1,
0x92, 0x4d, 0x2c, 0xf3, 0xee, 0x31, 0x50, 0x8f, 0x41, 0x9e, 0xff, 0x20, 0x3d, 0xe2, 0x83, 0x5c,
0x05, 0xda, 0xbb, 0x64, 0x79, 0xa6, 0xc7, 0x18, 0xd6, 0x09, 0x68, 0xb7, 0xaa, 0x75, 0x14, 0xcb,
0x88, 0x57, 0x36, 0xe9, 0xf4, 0x2b, 0x4a, 0x95, 0x5b, 0x84, 0xe5, 0x3a, 0x27, 0xf8, 0x99, 0x46,
0x15, 0xca, 0xab, 0x74, 0x69, 0xb6, 0xd7, 0x08, 0xc6, 0x19, 0x78, 0xa7, 0xba, 0x65, 0x04, 0xdb,
0x98, 0x47, 0x26, 0xf9, 0xe4, 0x3b, 0x5a, 0x85, 0x4b, 0x94, 0xf5, 0x2a, 0x37, 0xe8, 0x89, 0x56,
0x0f, 0xd0, 0xb1, 0x6e, 0x73, 0xac, 0xcd, 0x12, 0xdc, 0x03, 0x62, 0xbd, 0xa0, 0x7f, 0x1e, 0xc1,
0x82, 0x5d, 0x3c, 0xe3, 0xfe, 0x21, 0x40, 0x9f, 0x51, 0x8e, 0xef, 0x30, 0x2d, 0xf2, 0x93, 0x4c,
0x0a, 0xd5, 0xb4, 0x6b, 0x76, 0xa9, 0xc8, 0x17, 0xd9, 0x06, 0x67, 0xb8, 0xa5, 0x7a, 0x1b, 0xc4,
0x87, 0x58, 0x39, 0xe6, 0xfb, 0x24, 0x45, 0x9a, 0x54, 0x8b, 0xea, 0x35, 0x28, 0xf7, 0x96, 0x49,
0x10, 0xcf, 0xae, 0x71, 0x6c, 0xb3, 0xd2, 0x0d, 0xc3, 0x1c, 0x7d, 0xa2, 0xbf, 0x60, 0x01, 0xde,
0x9d, 0x42, 0x23, 0xfc, 0xe1, 0x3e, 0x5f, 0x80, 0x4e, 0x91, 0xf0, 0x2f, 0x32, 0xed, 0x8c, 0x53
};
int table_l[]=
{
0x00, 0x2b, 0x57, 0x7c, 0xaf, 0x84, 0xf8, 0xd3, 0xf6, 0xdd, 0xa1, 0x8a, 0x59, 0x72, 0x0e, 0x25,
0x45, 0x6e, 0x12, 0x39, 0xea, 0xc1, 0xbd, 0x96, 0xb3, 0x98, 0xe4, 0xcf, 0x1c, 0x37, 0x4b, 0x60,
0x8b, 0xa0, 0xdc, 0xf7, 0x24, 0x0f, 0x73, 0x58, 0x7d, 0x56, 0x2a, 0x01, 0xd2, 0xf9, 0x85, 0xae,
0xce, 0xe5, 0x99, 0xb2, 0x61, 0x4a, 0x36, 0x1d, 0x38, 0x13, 0x6f, 0x44, 0x97, 0xbc, 0xc0, 0xeb,
0xbe, 0x95, 0xe9, 0xc2, 0x11, 0x3a, 0x46, 0x6d, 0x48, 0x63, 0x1f, 0x34, 0xe7, 0xcc, 0xb0, 0x9b,
0xfb, 0xd0, 0xac, 0x87, 0x54, 0x7f, 0x03, 0x28, 0x0d, 0x26, 0x5a, 0x71, 0xa2, 0x89, 0xf5, 0xde,
0x35, 0x1e, 0x62, 0x49, 0x9a, 0xb1, 0xcd, 0xe6, 0xc3, 0xe8, 0x94, 0xbf, 0x6c, 0x47, 0x3b, 0x10,
0x70, 0x5b, 0x27, 0x0c, 0xdf, 0xf4, 0x88, 0xa3, 0x86, 0xad, 0xd1, 0xfa, 0x29, 0x02, 0x7e, 0x55,
0xd4, 0xff, 0x83, 0xa8, 0x7b, 0x50, 0x2c, 0x07, 0x22, 0x09, 0x75, 0x5e, 0x8d, 0xa6, 0xda, 0xf1,
0x91, 0xba, 0xc6, 0xed, 0x3e, 0x15, 0x69, 0x42, 0x67, 0x4c, 0x30, 0x1b, 0xc8, 0xe3, 0x9f, 0xb4,
0x5f, 0x74, 0x08, 0x23, 0xf0, 0xdb, 0xa7, 0x8c, 0xa9, 0x82, 0xfe, 0xd5, 0x06, 0x2d, 0x51, 0x7a,
0x1a, 0x31, 0x4d, 0x66, 0xb5, 0x9e, 0xe2, 0xc9, 0xec, 0xc7, 0xbb, 0x90, 0x43, 0x68, 0x14, 0x3f,
0x6a, 0x41, 0x3d, 0x16, 0xc5, 0xee, 0x92, 0xb9, 0x9c, 0xb7, 0xcb, 0xe0, 0x33, 0x18, 0x64, 0x4f,
0x2f, 0x04, 0x78, 0x53, 0x80, 0xab, 0xd7, 0xfc, 0xd9, 0xf2, 0x8e, 0xa5, 0x76, 0x5d, 0x21, 0x0a,
0xe1, 0xca, 0xb6, 0x9d, 0x4e, 0x65, 0x19, 0x32, 0x17, 0x3c, 0x40, 0x6b, 0xb8, 0x93, 0xef, 0xc4,
0xa4, 0x8f, 0xf3, 0xd8, 0x0b, 0x20, 0x5c, 0x77, 0x52, 0x79, 0x05, 0x2e, 0xfd, 0xd6, 0xaa, 0x81
};
i = 0;
j = 0;
size_FIC = 0;
size_INF = 0;
c1 = 0;
c2 = 0;
rg = 0;
CRC = 0;
if ( PL_FileExists( "crc_check.ext" ) != TRUE )
{
cout << "input MISSING !";
return 0;
}
struct stat stat_buf;
int rc = stat("crc_check.ext", &stat_buf);
size_FIC = rc == 0 ? stat_buf.st_size : -1;
cout << "input found " << size_FIC << endl;
PL_itoa10 ( size_FIC , s_nb );
strcpy ( MessPL , "Size : " );
strcat ( MessPL , s_nb );
strcat ( MessPL , " K..." );
cout << MessPL << endl;
// Calculate CRC...
l_fileIN = fopen ( "crc_check.ext", "r");
if ( NULL == l_fileIN )
{
cout << "Error opening" << endl;
}
else
{
cout << "Ok will calculate CRC bear with" << endl;
c1 = 0;
c2 = 0;
rg = 0;
for ( i = 0 ; i < size_FIC ; i++ )
{
fseek ( l_fileIN , i , 0 );
if ( i % 4000 == 0 )
{
j = ( 100 * i ) / size_FIC ;
}
if ( NULL == fgets ( l_line , 2 , l_fileIN ) )
{
PL_itoa10 ( i , s_i );
strcpy ( MessPL , "READ Error ! " );
strcat ( MessPL , s_i );
cout << MessPL << endl;
i = size_FIC;
}
else
{
nb = (int) l_line[0];
if ( nb < 0 )
nb += 256;
rg = c1 ^ nb;
c1 = c2 ^ table_h[rg];
c2 = table_l[rg];
}
}
fclose(l_fileIN);
}
PL_itoa16 ( c1 , s_nb );
if ( c1 < 16 )
{
strcpy ( CRC_FIC , "0" );
strcat ( CRC_FIC , s_nb );
}
else
strcpy ( CRC_FIC , s_nb );
PL_itoa16 ( c2 , s_nb );
if ( c2 < 16 )
{
strcat ( CRC_FIC , "0" );
strcat ( CRC_FIC , s_nb );
}
else
strcat ( CRC_FIC , s_nb );
cout << CRC_FIC << endl;
}
void PL_itoa10 (int i , char* s)
{
char l_s[16];
int n = 0 , m = 0;
if ( i < 0 )
{
s[m++] = '-';
i=-i;
}
do
{
l_s[n++] = (char)('0'+(i%10));
i /= 10;
}
while ( i );
for ( --n ; n>=0 ; n--,m++ )
s[m] = l_s[n];
s[m]=0;
}
void PL_itoa16 (int i , char* s)
{
char l_s[16];
int n = 0 , m = 0;
if ( i < 0 )
{
s[m++] = '-';
i=-i;
}
do
{
if ( i%16 < 10 )
l_s[n++] = (char)('0'+(i%16));
else
l_s[n++] = (char)('a'+(i%16)-10);
i /= 16;
}
while ( i );
for ( --n ; n>=0 ; n--,m++ )
s[m] = l_s[n];
s[m]=0;
}
int PL_FileExists ( char *p_pPath )
{
FILE* l_pFich = NULL;
if (NULL == (l_pFich = fopen (p_pPath, "r")))
{
return (FALSE);
}
else
{
fclose (l_pFich);
return (TRUE);
}
}
This code is labeled as CCITT Standard CRC16 non-reflected CRC using the polynomial 0x1021. Would produced that type of table.
Try this:
static unsigned short crctable[256];
void make_crc_table( void )
{
int i, j;
unsigned long poly, c;
static const byte p[] = {0,5,12};
poly = 0L;
for ( i = 0; i < sizeof( p ) / sizeof( byte ); i++ )
{
poly |= 1L << p[i];
}
for ( i = 0; i < 256; i++ )
{
c = i << 8;
for ( j = 0; j < 8; j++ )
{
c = ( c & 0x8000 ) ? poly ^ ( c << 1 ) : ( c << 1 );
}
crctable[i] = (unsigned short) c;
}
}
I need to do AES-128/CTR encryption/decryption using Intel TinyCrypt (written in C). I took a look at the test case provided by the library, but still have a few questions on how to use it. Here's the code of the test case (see the complete source code here):
/*
* NIST SP 800-38a CTR Test for encryption and decryption.
*/
uint32_t test_1_and_2(void)
{
const uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c
};
uint8_t ctr[16] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff
};
const uint8_t plaintext[64] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11,
0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46,
0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b,
0xe6, 0x6c, 0x37, 0x10
};
const uint8_t ciphertext[80] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff, 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, 0xf6, 0x6b,
0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02,
0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1,
0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
};
struct tc_aes_key_sched_struct sched;
uint8_t out[80];
uint8_t decrypted[64];
uint32_t result = TC_PASS;
TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n");
(void)tc_aes128_set_encrypt_key(&sched, key);
(void)memcpy(out, ctr, sizeof(ctr));
if (tc_ctr_mode(&out[TC_AES_BLOCK_SIZE], sizeof(plaintext),
plaintext, sizeof(plaintext), ctr, &sched) == 0) {
TC_ERROR("CTR test #1 (encryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(1, ciphertext, sizeof(out), out, sizeof(out));
TC_END_RESULT(result);
TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n");
(void) memcpy(ctr, out, sizeof(ctr));
if (tc_ctr_mode(decrypted, sizeof(decrypted), &out[TC_AES_BLOCK_SIZE],
sizeof(decrypted), ctr, &sched) == 0) {
TC_ERROR("CTR test #2 (decryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(2, plaintext, sizeof(plaintext),
decrypted, sizeof(plaintext));
exitTest1:
TC_END_RESULT(result);
return result;
}
My input data is a double pointer (2D array) and I'd like to keep it that way:
uint8_t ** mydata = gen_rand_data(const size_t height, const size_t length);
Here's my understanding (correct me if I'm wrong):
AES-128 is a block cipher, with 128-bit key.
CTR mode makes the AES-128 a stream cipher and lets encrypt/decrypt data with arbitrary size.
Having AES-128/CTR, the output (ciphertext) has the same length as plaintext.
To improve the security, it's better to use 128-bit IV (nonce) for encryption.
Now here's my questions:
Can I say ctr (initial counter, right?) is our IV?
Why the ciphertext (expected value) and out (calculated value) are 128-bit bigger than plaintext?
Why the code copies ctr value in the beginning of out?
To encrypt mydata (2D array), I just need to loop over it and simple feed bytes from mydata to tc_ctr_mode, regardless of the dimension of mydata. Is this correct?
Thanks in advance.
The counter is generally supplied as the iv parameter if there is no specific counter parameter.
The output is 16-bytes longer because the counter is prepended, the counter is block sized and AES has a 16-byte block size..
The counter value is not secret and is needed for decryption. Since the same key/counter combination can never be reused if the key is going to be reused (a common situation) the counter must be unique and thus not pre-shared. The general answer is to pre-pend the counter value to the encrypted data.
Yes providing the decryption end knows a priori the array dimensions. But is is probably better to use some form of marshaling to preserve the array shape.