This is part of a program that I use to decrypt AES in C. The program is supposed to take in an IV from an external file, read it then set as the IV. Unfortunately the IV is declared as a char array in the code (which I cannot change) so what I tried to do is to read the external file as byte[], then convert it to char[].
One of the issues I am currently facing is regarding the AES_IV variable as seen below:
#define AES_BLOCK_SIZE 0x10
char AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
When I try to print out the AES_IV using the code
printf("\nAES_IV: ");
for (i3 = 0; i3 < AES_BLOCK_SIZE; i3++) {
printf("%02x", AES_IV[i3]);
}
printf("\n");
The output is:
AES_IV: 0c0a513398f1eda13ed2fc7213b50b10
Which is different from the AES_IV I declared.
I changed the for loop to
for (i3 = 0; i3 < 50; i3++) {
and the resultant output is much longer
AES_IV: 0c0a513398f1eda13ed2fc7213b50b105369a...(100 chars in total)
I checked the length of AES_IV and it is still 16, but why does my for loop returns such a long result? Also why did the value of AES_IV change? I have checked and there are no reference to AES_IV anywhere before this part.
Your help is much appreciated.
Source code for reference:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <dlfcn.h>
#include "SmartSDLib.h"
#define SDCARD_PATH "/boot"
#define P1_INDEX 2
#define P2_INDEX 3
#define P3_INDEX 4
#define AES_BLOCK_SIZE 0x10
#define APDU_HEADER_SIZE 5
#define FILELEN 32 // For reading IV from file
void To_Hex(char s8Data[],char hexBuffer[], int offset, int nlen)
{
int j;
int nSize = (nlen - offset);
char finalhash[8192];
char hexval [] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for(j=0 ; j < nSize; j++)
{
finalhash[j*2] = hexval[(s8Data[j] >> 4) & 0xF];
finalhash[(j*2) + 1] = hexval[s8Data[j] & 0x0F];
}
memset(hexBuffer,0x00,8192);
memcpy(hexBuffer, finalhash, nSize*2);
}
char * AccessAPDU(char command[], int size)
{
unsigned char u8Ret;
int s32Len[1];
char s8Buffer[512], hexBuffer[8192];
To_Hex(command, hexBuffer, 0, size);
//printf ("%s\n%s%s\n", "AccessAPDUCommand:","CMD:" , hexBuffer);
u8Ret = OT_SmartSDCard_AccessAPDUCommand(size, command, s32Len, s8Buffer, 0);
if(u8Ret == 0x00)
{
printResult(s32Len, s8Buffer);
}
else
{
printf ("%s%x\n\n", "Error 0x", u8Ret);
}
return s8Buffer;
}
void printResult (int s32Len[], char s8Buffer[])
{
char hexBuffer[8192];
if(s32Len[0] >= 2)
{
To_Hex(s8Buffer, hexBuffer, 0, s32Len[0]);
// printf ("%s%s\n", "Ret:", hexBuffer);
// printf ("%s%d\n\n", "Len: ", s32Len[0]);
}
else
{
printf ("%s%d\n", "Len: ", s32Len[0]);
}
}
void CopyBuffer(char Dest[], char Source[], unsigned int length){
while(length){
Dest[length - 1] = Source[length - 1];
length--;
}
}
int ascii_to_hex(char c) // For reading IV from file
{
int num = (int) c;
if(num < 58 && num > 47) // Handle numbers (0-9)
{
return num - 48;
}
if(num < 103 && num > 96) // Handle lowercase alphabets (a-f)
{
return num - 87;
}
if(num < 71 && num > 64) // Handle uppercase alphabets (A-F)
{
return num - 55;
}
return num;
}
int main()
{
unsigned char u8Ret;
char SDCard_Path[64];
char line[64];
int s32Len[1];
char s8Buffer[512], hexBuffer[8192];
int exit = 1;
int iChoice;
char * response;
int test;
char testchar[32];
bool flag = true;
char fileName[100];
char encrypted[100];
char decrypted[100];
int i;
int j;
int blockCounter = 0;
int commandCounter = 0;
char imageBuffer[1];
/* APDU commands */
char AES_encrypt_cmd[APDU_HEADER_SIZE + AES_BLOCK_SIZE] = {0x80, 0x2A, 0x01,0x00, AES_BLOCK_SIZE}; //encryption APDU
char AES_decrypt_cmd[APDU_HEADER_SIZE + AES_BLOCK_SIZE] = {0x80, 0x2A, 0x02,0x00, AES_BLOCK_SIZE}; //decryption APDU
char GetResponse_cmd[] = {0x00, 0xC0, 0x00,0x00, 0x00}; //Le to be changed before use
char SelectAESapplet_cmd[] = {0x00, 0xA4, 0x04,0x00, 0x10, 0xA0, 0x00, 0x00, 0x00, 0x77, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x04};
//char PutKeyAES_cmd[] = {0x80, 0xD8, 0x00,0xF8, 0x20, 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00};
char PutKeyAES_cmd[] = {0x80, 0xD8, 0x00,0xF8, 0x20, 0xCF,0x10,0xF9,0xBD,0xF6,0xAA,0x15,0xC5,0x0E,0xCD,0x79,0xE6,0x28,0x3D,0xA8,0x0A,0x79,0x7A,0x2D,0x27,0x03,0xAE,0x07,0xD5,0x2F,0x5D,0x8F,0x60,0x1F,0x1E,0xF2,0x6F};
/* AES variables */
int AES_keyIndex = 0;
char AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
//char AES_IV[AES_BLOCK_SIZE] = {0x12,0xFB,0x87,0x11,0x62,0x7E,0xBB,0x55,0x71,0x7B,0x2F,0x70,0xA4,0x97,0x55,0x7B};
//char AES_IV[AES_BLOCK_SIZE];
char AES_CBC_vector[AES_BLOCK_SIZE];
char AES_cmdBuffer[APDU_HEADER_SIZE + AES_BLOCK_SIZE];
FILE * rFile;
FILE * wFile;
FILE *fileptr;char *buffer;long filelen;int i2,i3,i4;char IV_temp[AES_BLOCK_SIZE]; // This line for the file --> byte --> Hex
printf ("%s\n", "This program will run 1, 2 followed by 6");
// case 1 :
printf ("%s\n", "Initializing: ");
u8Ret = OT_SmartSDCard_Initialization(SDCARD_PATH);
if(u8Ret == 0x00)
printf ("%s\n\n", "Initialization OK");
else
printf ("%s%x\n\n", "Initialization: Error 0x",u8Ret);
// printf ("%s\n\n", "-------------------------------------");
/* ATR */
u8Ret = OT_SmartSDCard_Reset(s32Len, s8Buffer);
if(u8Ret == 0x00)
{
To_Hex(s8Buffer,hexBuffer, 0, s32Len[0]);
// printf ("%s%s\n", "ATR : ", hexBuffer);
// printf ("%s%d\n\n", "Len : ", s32Len[0]);
}
else
printf ("%s%x\n\n", "Reset: Error 0x",u8Ret);
// printf ("%s\n\n", "-------------------------------------");
/* Select AES applet */
printf("%s\n", "Selecting AES applet...");
response = AccessAPDU(SelectAESapplet_cmd, sizeof(SelectAESapplet_cmd));
if(response[0] == 0x61){
GetResponse_cmd[P3_INDEX] = response[1];
AccessAPDU(GetResponse_cmd, sizeof(GetResponse_cmd));
}
// printf ("%s\n\n", "-------------------------------------");
// case 2 :
printf("Putting key...");
AES_keyIndex = 0;
memset(line, 0x00, sizeof(line));
PutKeyAES_cmd[2] = AES_keyIndex;
printf("putting key on index %d\n", AES_keyIndex);
response = AccessAPDU(PutKeyAES_cmd, sizeof(PutKeyAES_cmd));
AES_encrypt_cmd[P2_INDEX] = AES_keyIndex;
AES_decrypt_cmd[P2_INDEX] = AES_keyIndex;
// printf ("%s\n\n", "-------------------------------------");
// case 6 :
printf ("Decrypting in CBC...");
// printf ("File Name: /home/pi/test_encrypted\n");
// printf ("Encrypted File Name: /home/pi/test_decrypted\n");
rFile = fopen("/home/pi/test_encrypted","rb");
wFile = fopen("/home/pi/test_decrypted","wb");
////////////////////////////////////////////////////////////////
// This part to read rFile and store as a byte [WORKING!]
fseek(rFile, 0, SEEK_END); // Jump to the end of the file
filelen = ftell(rFile); // Get the current byte offset in the file
rewind(rFile); // Jump back to the beginning of the file
buffer = (char *)malloc((filelen+1)*sizeof(char)); // Enough memory for file + \0
fread(buffer, filelen, 1, rFile); // Read in the entire file
// This part to convert buffer to hex value [WORKING!]
for (i2 = 0; i2 < 100; i2++)
{
if (i2 > 0) printf(" ");
printf("%02X", buffer[i2]);
IV_temp[i2] = buffer[i2];
}
// This part to print stuff [AES_IV not printing out correctly]
printf("\nAES_IV: ");
//fwrite(AES_IV, 1, sizeof(AES_IV), stdout);
for (i3 = 0; i3 < 50; i3++) {
printf("%02x", AES_IV[i3]);
}
printf("\n");
/*
printf("IV_temp: ");
for (i4 = 0; i4 < AES_BLOCK_SIZE; i4++) {
printf("%02x", IV_temp[i4]);
}
printf("\n");
*/
for (i3 = 0; i3 < AES_BLOCK_SIZE; i3++) {
AES_IV[i3] = IV_temp[i3];
}
printf("\nLength of AES_IV = %d\n", sizeof(AES_IV));
printf("\nAES_IV: ");
for (i3 = 0; i3 < 50; i3++) {
printf("%02x", AES_IV[i3]);
}
printf("\n");
// Return the file pointer to start of file
rewind(rFile);
////////////////////////////////////////////////////////////////
if (rFile == NULL || wFile == NULL)
perror("Error opening File");
else{
int IsEOF = false;
// Initialize the CBC block with IV
CopyBuffer(AES_CBC_vector, AES_IV, AES_BLOCK_SIZE);
while (IsEOF == false) {
i = 0;
while(i < AES_BLOCK_SIZE){ // i run from 0 to (AES_BLOCK_SIZE - 1)
AES_cmdBuffer[APDU_HEADER_SIZE + i] = fgetc(rFile);
if(feof(rFile)) {
IsEOF = true;
if(i == 0) { // break out of while loop if a new block is not yet in progress
break;
} else { // continue to finish the block and pad with zeros
AES_cmdBuffer[APDU_HEADER_SIZE + i] = 0x00; //padding
}
}
i++;
}
if(i == 0) break; //break out of while loop, nothing to send to card
// Fill in the APDU header
CopyBuffer(AES_cmdBuffer, AES_decrypt_cmd, APDU_HEADER_SIZE);
response = AccessAPDU(AES_cmdBuffer, sizeof(AES_cmdBuffer));
if(response[0] == 0x61){
if(response[1] != AES_BLOCK_SIZE) {
perror("Card returning wrong block size");
}
GetResponse_cmd[P3_INDEX] = AES_BLOCK_SIZE;
response = AccessAPDU(GetResponse_cmd, sizeof(GetResponse_cmd));
/* CBC mode */
for(i = 0; i < AES_BLOCK_SIZE; i++){
response[i] ^= AES_CBC_vector[i];
}
fwrite(response, sizeof(char), AES_BLOCK_SIZE, wFile);
// Take the ciphertext to perform XOR next time
CopyBuffer(AES_CBC_vector, &AES_cmdBuffer[APDU_HEADER_SIZE], AES_BLOCK_SIZE);
} else {
perror("Error decrypting file using the smart card");
}
}
}
fclose (rFile);
fclose (wFile);
// printf ("%s\n\n", "-------------------------------------");
return 0;
}
As one comment already stated you should use unsigned char otherwise each element is treated as a signed char by default. Better yet you might want to use fixed-width uint8_t from #include <stdint.h> instead.
Here is a minimal example that works as expected:
#include <stdint.h>
#include <stdio.h>
#define AES_BLOCK_SIZE 0x10
uint8_t AES_IV[AES_BLOCK_SIZE] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
int
main( void )
{
int i;
for ( i = 0; i < sizeof(AES_IV); i++ ) {
printf( "%02x", AES_IV[i] );
}
return 0;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have str:
char *str = "lala";
Now, I would like convert any chars in str to hexadecimal, example:
str = convert(str);
print str: 0x6C 0x61 0x6C 0x61
^ l ^ a ^ l ^ a
How I can do that ?
char *convert(char const *str) {
int len = strlen(str);
char *retVal = (char *)malloc(5 * len);
char *pos = retVal;
int i;
for(i = 0; i < len; ++i, pos += 5) sprintf(pos, i? " 0x%x" : "0x%x", str[i]);
retVal[5 * len - 1] = '\0';
return retVal;
}
Might have missed something, haven't used C for eight years.
Simply by asking printf to do it :
void convert(char* str, size_t length) {
size_t i;
for(i = 0; i < length; i++)
printf("0x%02x ", str[i]);
}
You can achieve it by using this implementation....
#define MAX 100
char *convert(char *str)
{
char *hexStr = (char *)malloc(strnlen(str, MAX) * 5);
if (hexStr == NULL)
return NULL;
int i,j;
for (i=0, j=0; str[i]; j+=5, i++)
sprintf(hexStr + j, "0x%02x ", str[i]);
hexStr[--j] = '\0';
return hexStr;
}
char* x = str - 1;
while(*++x) printf("%02x ", (int) *x); // Print one character in hex
printf("\n") // Finish with a carriage return
I have this string
c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
How does one swap it so it becomes
000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1
Those two are basically examples, but that is what i need to do, but not know how as i have very little knowledge of C.
The above two strings are actually unsigned char[] in the C program
P.S
Don't think i didn't go through google. I did, but i found very little of what i needed so every attempt to do that failed.
for (int i = 0; i < size; i += 2) {
myNewStr[size - i - 2] = myStr[i];
myNewStr[size - i - 1] = myStr[i + 1];
}
Something like this; probably not perfect but gives you the idea. You'll want appropriate error checking, initialization of your buffer, etc.
Edit: I made an assumption I shouldn't have, possibly. I interpreted your string as hex representations of bytes, so I took c1 as an unsigned char and switched it with 00, for example. If your string is actually lowercase c, the number 1, etc., then Micah's answer is what you want, not mine.
void reverse_string(unsigned char *buf, int length)
{
int i;
unsigned char temp;
for (i = 0; i < length / 2; i++)
{
temp = buf[i];
buf[i] = buf[length - i - 1];
buf[length - i - 1] = temp;
}
}
This seems to do what you want, include at least string.h and stdlib.h.
unsigned char *stringrev(const unsigned char *s) {
size_t n = strlen((const char *)s);
unsigned char *r = malloc(n + 1);
if (r != NULL && !(n & 1)) {
const unsigned char *fp = s;
unsigned char *rp = r + n;
for(*rp = '\0'; n > 1; n -= 2) {
*--rp = fp[1];
*--rp = fp[0];
fp += 2;
}
}
return r;
}
Slight alternative to Micah's answer. I assume that the size is precalculated and even, and check that it's greater than 0 because s-2 is potentially UB. I modify the string in-place just for variety.
static inline void swap_uchar(unsigned char *l, unsigned char *r) {
unsigned char tmp = *l;
*l = *r;
*r = tmp;
}
void reverse_pairs(unsigned char *s, size_t size) {
if (size > 0) {
for (unsigned char *l=s, *r=s+size-2; l < r; l += 2, r -= 2) {
swap_uchar(l, r);
swap_uchar(l+1, r+1);
}
}
}
If you have a string: "12ab\0" then the reverse endian of this string would be "\0ba21" .
If you have a numeric: 0x12ab then the reverse endian of this numeric would be 0xab12 .
Which one do you want.
Here is a function for converting between endian, which will handle the passed argument as a block of memory and change the endian.
Code
#include <stdio.h>
typedef struct _test {
unsigned int a, b;
} test;
/* x: base address of the memory
* n: length of the memory
*/
void reverse_endian (void *x, int n)
{
char *arr_conv, *arr, t;
arr = arr_conv = (char *) x;
arr += (n-1);
n/=2;
while (n)
{
t = *arr_conv;
*arr_conv = *arr;
*arr = t;
n--;
arr_conv++;
arr--;
}
}
int main (void)
{
char str1[] = "c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000";
char str2[] = "hellio";
/* Assigns the str1 as hex values */
unsigned char str3[] = {0xc1, 0xeb, 0x04, 0x4f, 0x07, 0x08, 0x01, 0x5b, 0x26, 0x79, 0x13, 0xfc, 0x4d, 0xff, 0x5a, 0xab, 0xe3, 0xdd, 0x4a, 0x97, 0xf1, 0x0f, 0x7b, 0xa9, 0x35, 0xcd, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00};
test x;
char q = 0x12;
int v = 0x1234abcd;
int i, n;
x.a = 0x12ab34cd;
x.b = 0x98ef76af;
printf ("\nNormal : x.a = %x x.b = %x", x.a, x.b);
reverse_endian (&x, sizeof (x));
printf ("\nReverse: x.a = %x x.b = %x", x.a, x.b);
printf ("\nNormal : q = %x", q);
reverse_endian (&q, sizeof (q));
printf ("\nReverse: q = %x", q);
printf ("\nNormal : q = %x", v);
reverse_endian (&v, sizeof (v));
printf ("\nReverse: q = %x", v);
printf ("\nNormal : str1 = %s", str1);
/* minus 1 to avoid the trailing nul character */
reverse_endian (str1, sizeof (str1) - 1);
printf ("\nReverse: str1 = %s", str1);
printf ("\nNormal : str2 = %s", str2);
/* minus 1 to avoid the trailing nul character */
reverse_endian (str2, sizeof (str2) - 1);
printf ("\nReverse: str2 = %s", str2);
printf ("\nNormal : str3 = ");
n = sizeof (str3);
for (i=0; i < n; i++)
{
printf ("%x", (str3[i]>>4)&0x0f);
printf ("%x", str3[i]&0x0f);
}
reverse_endian (str3, sizeof (str3));
printf ("\nReversed: str3 = ");
for (i=0; i < n; i++)
{
printf ("%x", (str3[i]>>4)&0x0f);
printf ("%x", str3[i]&0x0f);
}
printf ("\n");
return 0;
}
Output
Normal : x.a = 12ab34cd x.b = 98ef76af
Reverse: x.a = af76ef98 x.b = cd34ab12
Normal : q = 12
Reverse: q = 12
Normal : q = 1234abcd
Reverse: q = cdab3412
Normal : str1 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reverse: str1 = 000000000063dc539ab7f01f79a4dd3ebaa5ffd4cf319762b5108070f440be1c
Normal : str2 = hellio
Reverse: str2 = oilleh
Normal : str3 = c1eb044f0708015b267913fc4dff5aabe3dd4a97f10f7ba935cd360000000000
Reversed: str3 = 000000000036cd35a97b0ff1974adde3ab5aff4dfc1379265b0108074f04ebc1
Note that the strings str1, str2 are simply reversed, because each character of the string is one byte. The same character string you have provided is represented as byte string in str3. Its hex values are shown as output. The operations for all the data are identical, as it is only concerned to memory byte ordering.