This is code to encrypt a struct
using DES
and then read it back after writing to File
:
#include "openssl/des.h"
#include "openssl/conf.h"
#include "openssl/evp.h"
#include "openssl/err.h"
#include <stdio.h>
typedef struct MyStruct_t
{
char m_Name[32];
char m_ID[16];
} MyStruct;
uint8_t* __stdcall myStructToBytes(const MyStruct * const iMyStruct)
{
const size_t len = sizeof(MyStruct;
uint8_t *buffer = (uint8_t*) malloc(len);
memcpy(buffer, iMyStruct, len);
return buffer;
}
const int __stdcall encodeMyStructToFile(const char *sOutputFilename,
const char *sKey, const MyStruct *iStruct)
{
DES_cblock key, iv;
DES_key_schedule schedule;
unsigned char *data = myStructToBytes((const MyStruct * const)iStruct);
long len = sizeof(MyStruct);
int ret = 0;
memcpy(key, &sKey[0], 8);
memcpy(iv, &sKey[0], 8);
DES_set_odd_parity(&key);
ret = DES_set_key_checked(&key, &schedule);
if(ret == 0) {
FILE *write_ptr;
unsigned char *encrypted = (unsigned char *)malloc(len);
DES_cbc_encrypt(data, encrypted, len, &schedule, &iv, DES_ENCRYPT);
// Write encrypted data to file...
fopen_s(&write_ptr, sOutputFilename, "wb");
fwrite(encrypted, len, 1, write_ptr);
fclose(write_ptr);
free(encrypted);
}
free(data);
return ret;
}
const int __stdcall decodeMyStructFromFile(const char *sInputFilename,
const char *sKey, MyStruct *oStruct)
{
int ret = 0;
DES_cblock key, iv;
DES_key_schedule schedule;
FILE *read_ptr;
long len = 0;
unsigned char *encrypted = NULL;
// Read encrypted data from file...
fopen_s(&read_ptr, sInputFilename, "rb");
ret = fseek(read_ptr, 0L, SEEK_END);
len = ftell(read_ptr);
rewind(read_ptr);
encrypted = (unsigned char *)malloc(len);
fread(encrypted, len, 1, read_ptr);
fclose(read_ptr);
// Perform decryption...
memcpy(key, &sKey[0], 8);
memcpy(iv, &sKey[0], 8);
DES_set_odd_parity(&key);
ret = DES_set_key_checked(&key, &schedule);
if(ret == 0) {
DES_cbc_encrypt(encrypted, (unsigned char *)oStruct, len, &schedule, &iv, DES_DECRYPT);
}
free(encrypted);
return ret;
}
int main() {
MyStruct tMyStruct;
MyStruct tMyStruct1;
char outputFilename[] = "abcd.bin";
char key[] = "key_to_file";
memset(&tMyStruct, 0, sizeof(MyStruct));
memcpy_s(tMyStruct.m_Name, 256, "Hello", 5);
memcpy_s(tMyStruct.m_ID, 32, "1234567890", 10);
encodeMyStructToFile((const char *)outputFilename, (const char *)key, (const MyStruct * const)&tMyStruct);
decodeLicenseStructFromFile(outputFilename, key, &tMyStruct1);
return 0;
}
Somehow, I get stack corruption error in debugger for both encrypt and decrypt functions. I traced down the problem around DES_cbc_encrypt()
. What am I doing wrong? I'm using compiled binaries for OpenSSL: openssl-1.1.0e-vs2012
on 64-bit
.
The reason, why I came back here, is because I noticed (although not producible from the sample code), that both DES_cbc_encrypt()
and DES_cbc_decrypt()
functions expect 8-byte aligned
inputs. Thus in the unfortunate case, if the struct here would have been not a multiple of 8 in size, DES_cbc_encrypt()
would write past the end of buffer, thus the obvious stack-corruption. Although, when padding is not explicitly disabled, sizeof()
still returns the sum of the sizes of the members, so this case I understand is the task of the application programmer. Maybe someone could light up more on this.