C++ AES Decrypt and Nodejs AES Decrypt producing different outputs - c++

I've reimplemented this AES c++ decryption in nodejs.
The "buffer" contains the encrypted content.
The "decryptKey" contains the key to decrypt the "buffer".
The "expectedOutput" contains the expected output.
In order to bypass the bad decrypt exception thrown by node I had to disable the autoPadding in my crypt object.
To simplify I added the c++ code and I added tests to three different algorithms (AES-128-ECB, AES-192-ECB, AES-256-ECB). None of the decrypt results match the C++ output.
What am I missing?
var crypto = require('crypto');
var buffer = new Buffer([
0x5e,0x51,0xa3,0x53,0x9d,0xe7,0xe5,0xd3,
0xee,0x30,0xbb,0xf8,0x0c,0x72,0x9f,0x80
]);
var decryptKey = new Buffer([
0x36, 0x46, 0xb4, 0xf6,
0x8e, 0x6d, 0xdc, 0xf4,
0xb0, 0x31, 0x7e, 0x81,
0x6b, 0x5d, 0x96, 0x55
])
/*
After looking to my C++ code I noticed that despite of providing a 32 length key the 128 argument ensures that only the first 16 bytes are used
var decryptKey = new Buffer([
0x36, 0x46, 0xb4, 0xf6,
0x8e, 0x6d, 0xdc, 0xf4,
0xb0, 0x31, 0x7e, 0x81,
0x6b, 0x5d, 0x96, 0x55, // 16
0x15, 0x9c, 0x78, 0x54,
0x8c, 0xca, 0x3e, 0x39,
0x2d, 0x49, 0x75, 0x5d,
0xa1, 0x1a, 0xc3, 0xe3 // 32
])*/
var expectedOutput = new Buffer([
0xc8,0x6c,0x8f,0x2b,0xe8,0x21,0xc4,0x2e,
0xfb,0x4a,0x8e,0x8b,0xc3,0x94,0x19,0xc2
]);
// aes_context aes_ctx;
function decrypt(data, password, algorithm, padding){
if (padding === void 0) padding = true;
algorithm = algorithm || 'aes-128-ecb';
//aes_setkey_dec( &aes_ctx, digest, 128 );
var crypt = crypto.createDecipher(algorithm,password);
crypt.setAutoPadding(padding);
// aes_crypt_ecb( &aes_ctx, AES_DECRYPT, buffer, buffer );
var res = crypt.update(data, null, 'hex')
res += crypt.final('hex');
return new Buffer(res,'hex');
}
// aes_setkey_dec( &aes_ctx, digest, 128 );
var algoList = [
'aes-128-ecb',
'aes-192-ecb',
'aes-256-ecb'
];
for (var i = 0; i<= 1; i++){
console.log('\n ******* AUTO PADDING: ' + (padding ? 'ON': 'OFF') + ' ********* ');
var padding = i === 0;
for (let algo of algoList){
try {
var output = decrypt(buffer, decryptKey, algo, padding);
console.log(algo + ' => ' + output.toString('hex') + ' < ' + (Buffer.compare(expectedOutput, output) === 0 ? 'ok' : 'ko'))
} catch (err){
console.log('Failed to perform ' + algo + ' with autopadding ' + (padding ? ' on ': ' off ') + ' due to ' + err.message);
}
}
}
/*
******* AUTO PADDING: OFF *********
Failed to perform aes-128-ecb with autopadding on due to error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Failed to perform aes-192-ecb with autopadding on due to error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Failed to perform aes-256-ecb with autopadding on due to error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
******* AUTO PADDING: ON *********
aes-128-ecb => d9817f142f9bca262b67f6a6be570345 < ko
aes-192-ecb => 9181784373bb6060c04c9ba75de26322 < ko
aes-256-ecb => c5945203368de477e5f0dbeedeb2189f < ko
*/
Heres the c++ code
#include "aes.h"
#include "sha2.h"
int main(int argc, char *argv[]) {
unsigned char data[16] = {
0x5e,0x51,0xa3,0x53,0x9d,0xe7,0xe5,0xd3,0xee,0x30,0xbb,0xf8,0x0c,0x72,0x9f,0x80
};
unsigned char key[32] = {
0x36, 0x46, 0xb4, 0xf6,
0x8e, 0x6d, 0xdc, 0xf4,
0xb0, 0x31, 0x7e, 0x81,
0x6b, 0x5d, 0x96, 0x55, // 16
0x15, 0x9c, 0x78, 0x54,
0x8c, 0xca, 0x3e, 0x39,
0x2d, 0x49, 0x75, 0x5d,
0xa1, 0x1a, 0xc3, 0xe3 // 32
};
aes_context aes_ctx;
aes_setkey_dec(&aes_ctx, key, 128);
aes_crypt_ecb(&aes_ctx, AES_DECRYPT, data, data);
for (int i = 0; i< sizeof(data); ++i)
std::cout << std::hex << (int)data[i];
/* Output => c86c8f2be821c42efb4a8e8bc39419c2*/
}
references:
https://tls.mbed.org/discussions/generic/question-about-using-aes
http://aes.online-domain-tools.com/link/133660agcLyPgFri4s/ - Example of decryption online
The solution based in answer below
var crypto = require('crypto')
var buffer = new Buffer([
0x5e,0x51,0xa3,0x53,0x9d,0xe7,0xe5,0xd3,
0xee,0x30,0xbb,0xf8,0x0c,0x72,0x9f,0x80
]);
var decryptKey = new Buffer([
0x36, 0x46, 0xb4, 0xf6,
0x8e, 0x6d, 0xdc, 0xf4,
0xb0, 0x31, 0x7e, 0x81,
0x6b, 0x5d, 0x96, 0x55
])
var expectedOutput = new Buffer([
0xc8,0x6c,0x8f,0x2b,0xe8,0x21,0xc4,0x2e,
0xfb,0x4a,0x8e,0x8b,0xc3,0x94,0x19,0xc2
]);
// aes_context aes_ctx;
function decrypt(data, password, algorithm, padding){
if (padding === void 0) padding = true;
algorithm = algorithm || 'aes-128-ecb';
//aes_setkey_dec( &aes_ctx, digest, 128 );
var crypt = crypto.createDecipheriv(algorithm,password, new Buffer([]));//new Buffer(32).fill(0).byteLength
crypt.setAutoPadding(padding);
// aes_crypt_ecb( &aes_ctx, AES_DECRYPT, buffer, buffer );
var res = crypt.update(data, null,'hex')
+ crypt.final('hex');
return new Buffer(res,'hex');
}
// aes_setkey_dec( &aes_ctx, digest, 128 );
var output = decrypt(buffer, decryptKey, 'aes-128-ecb', false);
console.log(Buffer.compare(expectedOutput, output) === 0 ? 'ok' : 'ko');

The deprecated crypto.createDecypher() derives the key from the password argument:
The implementation of crypto.createDecipher() derives keys using the OpenSSL function EVP_BytesToKey with the digest algorithm set to MD5, one iteration, and no salt.
What you want instead is to use a raw key. For that you should use crypto.createDecipheriv() instead:
var crypt = crypto.createDecipheriv(algorithm,password,new Buffer([]));
(In ECB mode the IV can be empty)
Of course, the key length must then match the requested algorithm (128, 192 or 256 bits). You key is 128 bits, so only aes-128-ecb will work.

The reason you need to pass false to setAutoPadding is that your ciphertext is not padded. You haven't included your encryption code that generates the ciphertext, but I can tell from the length of it that it is not padded, because a plaintext of one block size in length, when encrypted using PKCS#7 padding, will produce a ciphertext that is two block sizes in length, rather than the single block that you have.
The reason this decrypts with aes_crypt_ecb is that it looks like aes_crypt_ecb simply performs individual block encryption/decryption, so does not do any padding or unpadding. The Javscript code though, if passed true to the setAutoPadding function, will be expecting padding (probably PKCS#7). Which will of course fail because your encryption has not used padding.
Ideally you should modify your encryption code so that it uses proper padding when doing the encryption, as this is much more secure than not using padding. Otherwise you will need to make sure that your call to setAutoPadding is passing false when doing the decryption, so the Javascript knows there is no padding.

Related

How to decrypt using openssl EVP?

I'm trying to decrypt a file using C (but I can change to C++), but I don't know how to use the EVP library correctly.
The console command that I want to replicate is:
openssl enc -rc2-ecb -d -in myfile.bin -iter 1 -md sha1 -pbkdf2 -pass pass:'Yumi'
My actual C code using EVP is:
unsigned char salt[8] = "Salted__";
ctx=EVP_CIPHER_CTX_new();
PKCS5_PBKDF2_HMAC_SHA1("Yumi", -1,
salt, 8, 1,
EVP_MAX_KEY_LENGTH, key);
EVP_DecryptInit(ctx, EVP_rc2_ecb(), key, iv);
pt = (unsigned char *)malloc(sz + EVP_CIPHER_CTX_block_size(ctx) + 1);
EVP_DecryptUpdate(ctx, pt, &ptlen, ciphertext, sz);
if (!EVP_DecryptFinal(ctx,&pt[ptlen],&tmplen)) {
printf("Error decrypting on padding \n");
} else {
printf("Succesful decryption\n");
}
I suppose that's not working because I have to declare something to use SHA1 instead of SHA256 (default on rc2-ecb), but I'm not seeing how to do it.
Any help will be appreciated
The following hex encoded ciphertext could be decrypted with the posted OpenSSL statement, if this data would be contained hex decoded in myfile.bin:
53616C7465645F5F2DC4C4867D3B9268C82E23A672D6698FB51D41EA8601367A9112623EC27CDEB18FD1444BDB8D8DE16F1A35706EC7FED266CB909D28BF6BEC
The decryption would result in:
The quick brown fox jumps over the lazy dog
For simplicity, the ciphertext is assigned directly and the loading of the ciphertext from a file is skipped:
unsigned char data[] = {
0x53, 0x61, 0x6C, 0x74, 0x65, 0x64, 0x5F, 0x5F, // Salted__
0x2D, 0xC4, 0xC4, 0x86, 0x7D, 0x3B, 0x92, 0x68, // Salt
0xC8, 0x2E, 0x23, 0xA6, 0x72, 0xD6, 0x69, 0x8F, 0xB5, 0x1D, 0x41, 0xEA, 0x86, 0x01, 0x36, 0x7A, // Ciphertext...
0x91, 0x12, 0x62, 0x3E, 0xC2, 0x7C, 0xDE, 0xB1, 0x8F, 0xD1, 0x44, 0x4B, 0xDB, 0x8D, 0x8D, 0xE1,
0x6F, 0x1A, 0x35, 0x70, 0x6E, 0xC7, 0xFE, 0xD2, 0x66, 0xCB, 0x90, 0x9D, 0x28, 0xBF, 0x6B, 0xEC };
int dataLength = sizeof(data) / sizeof(unsigned char);
For decryption, salt and ciphertext must first be separated, e.g.:
int ciphertextLength = dataLength - 16;
unsigned char* salt = (unsigned char*)malloc(sizeof(unsigned char) * 8);
unsigned char* ciphertext = (unsigned char*)malloc(sizeof(unsigned char) * ciphertextLength);
memcpy(salt, data + 8, 8); // Get 8 bytes salt (starts at index 8)
memcpy(ciphertext, data + 16, ciphertextLength); // Get ciphertext (starts at index 16)
The next step is to derive the key, see PKCS5_PBKDF2_HMAC, e.g.:
#define KEYSIZE 16
unsigned char key[KEYSIZE];
const char* password = "'Yumi'"; // The quotation marks (') in the openssl-statement are part of the password.
int passwordLen = strlen(password);
PKCS5_PBKDF2_HMAC(password, passwordLen, salt, 8, 1, EVP_sha1(), KEYSIZE, key);
Finally the decryption can be performed, see here and here, e.g.:
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_rc2_ecb(), NULL, NULL, NULL);
EVP_CIPHER_CTX_set_key_length(ctx, KEYSIZE); // RC2 is an algorithm with variable key size. Therefore the key size must generally be set.
EVP_DecryptInit_ex(ctx, NULL, NULL, key, NULL);
unsigned char* plaintext = (unsigned char*)malloc(sizeof(unsigned char) * ciphertextLength);
int length;
EVP_DecryptUpdate(ctx, plaintext, &length, ciphertext, ciphertextLength);
int plaintextLength = length;
EVP_DecryptFinal_ex(ctx, plaintext + plaintextLength, &length);
plaintextLength += length;
printf("Plaintext: "); for (int i = 0; i < plaintextLength; i++) { printf("%c", plaintext[i]); } printf("\n");
For simplicity, the code doesn't include exception handling and memory release.
Note the following:
Some of the parameters used in the posted OpenSSL statement are insecure, e.g. the ECB mode and an iteration count of 1. Instead, a mode with an IV should be used and an iteration count of 10,000 or larger if performance allows.
OpenSSL generates a random 8 bytes salt during encryption, which is used to derive the key. The ciphertext consists of the ASCII encoding of Salted__, followed by the 8 bytes salt, followed by the actual ciphertext, here. Just this format is expected by the posted OpenSSL statement for decryption.
RC2 defines a variable key size. The posted OpenSSL statement uses a size of 16 bytes.
The -pass pass: option specifies the password without quotation marks, i.e. in the posted OpenSSL statement the quotation marks are part of the password.

Openssl C++ AES decryption adding unexpected symbols

I'm trying to decrypt in C++ a file that have been encrypted with the Linux command : openssl enc -aes-256-cbc -nosalt -K "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855" -iv "5DF6E0E2761359D30A8275058E299FCC" -p -in file.json -out file.enc
The decryption works well, but unexpected symbols appear at the end of the file when I print it in the terminal, as in the following image Image
Here is my C++ code, can someone help me ?
int main(int argc, char **argv)
{
EVP_CIPHER_CTX *en, *de;
en = EVP_CIPHER_CTX_new();
de = EVP_CIPHER_CTX_new();
unsigned char key_data[] = {0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B,0x78, 0x52, 0xB8, 0x55};
int key_data_len = 32;
std::ifstream in("file.enc");
std::string contents((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
unsigned char iv[] = {0x5D, 0xF6, 0xE0, 0xE2, 0x76, 0x13, 0x59, 0xD3, 0x0A, 0x82, 0x75, 0x05, 0x8E, 0x29, 0x9F, 0xCC};
EVP_CIPHER_CTX_init(en);
EVP_EncryptInit_ex(en, EVP_aes_256_cbc(), NULL, key_data, iv);
EVP_CIPHER_CTX_init(de);
EVP_DecryptInit_ex(de, EVP_aes_256_cbc(), NULL, key_data, iv);
char *plaintext;
int len = strlen(contents.c_str())+1;
plaintext = (char *)aes_decrypt(de, (unsigned char *)contents.c_str(), &len);
printf("%s", plaintext);
free(plaintext);
EVP_CIPHER_CTX_cleanup(en);
EVP_CIPHER_CTX_cleanup(de);
}
And the function to decrypt :
unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
{
int p_len = *len, f_len = 0;
unsigned char *plaintext = (unsigned char *)calloc(sizeof(char*), p_len);
EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len);
*len = p_len + f_len;
return plaintext;
}
SOLVED : I had to remove the PKCS#7 padding added by the encoder PKCS#7 Padding
The input length is incorrect - strlen(contents.c_str()) + 1 will either return length including additional null byte which should not be included as it is not part of encrypted data, or length of data to the first null byte in encrypted data if there is one. You should use contents.size() instead.
This causes EVP_DecryptUpdate to decrypt all data including last block with padding and expect more data and EVP_DecryptFinal_ex to fail after that. With correct length the padding from last block will be stripped as expected.
There's also issue with output buffer length - it's sizeof(char*) * p_len instead of sizeof(char) * (p_len + EVP_CIPHER_block_size(EVP_aes_256_cbc())). EVP_DecryptUpdate requires output buffer to be large enough to hold input length + cipher block size.
You should also make sure to use only len data in plaintext buffer - printf will output data until null byte, which might not be included in decrypted data.

Missing something when decompressing HTTP gzipped response

I have recently been setting up various testing environments and in this cas I nneed to read and decode a gzip response from a HTTP server. I know what I have so far works as I have tested it with wireshark and hardcoded data as outlined below, my question is what is wrong with how I am handling the gizzped data from a HTTP server?
Here is what Im using:
From this thread http://www.qtcentre.org/threads/30031-qUncompress-data-from-gzip I am using the gzipDecopress function with the data provided and seeing that it works.
QByteArray gzipDecompress( QByteArray compressData )
{
//Hardcode sample data
const char dat[40] = {
0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xAA, 0x2E, 0x2E, 0x49, 0x2C, 0x29,
0x2D, 0xB6, 0x4A, 0x4B, 0xCC, 0x29, 0x4E, 0xAD, 0x05, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00,
0x2A, 0x63, 0x18, 0xC5, 0x0E, 0x00, 0x00, 0x00};
compressData = QByteArray::fromRawData( dat, 40);
//decompress GZIP data
//strip header and trailer
compressData.remove(0, 10);
compressData.chop(12);
const int buffersize = 16384;
quint8 buffer[buffersize];
z_stream cmpr_stream;
cmpr_stream.next_in = (unsigned char *)compressData.data();
cmpr_stream.avail_in = compressData.size();
cmpr_stream.total_in = 0;
cmpr_stream.next_out = buffer;
cmpr_stream.avail_out = buffersize;
cmpr_stream.total_out = 0;
cmpr_stream.zalloc = Z_NULL;
cmpr_stream.zalloc = Z_NULL;
if( inflateInit2(&cmpr_stream, -8 ) != Z_OK) {
qDebug() << "cmpr_stream error!";
}
QByteArray uncompressed;
do {
int status = inflate( &cmpr_stream, Z_SYNC_FLUSH );
if(status == Z_OK || status == Z_STREAM_END) {
uncompressed.append(QByteArray::fromRawData((char *)buffer, buffersize - cmpr_stream.avail_out));
cmpr_stream.next_out = buffer;
cmpr_stream.avail_out = buffersize;
} else {
inflateEnd(&cmpr_stream);
}
if(status == Z_STREAM_END) {
inflateEnd(&cmpr_stream);
break;
}
}while(cmpr_stream.avail_out == 0);
return uncompressed;
}
When the data is hardcoded as in that example, the string is decompressed. However, when I read the response from a HTTP server and store it in a QByteArray, it cannot be uncompressed. I am reading the response as follows and I can see it works when comparing the results on wireshark
//Read that length of encoded data
char EncodedData[ LengthToRead ];
memset( EncodedData, 0, LengthToRead );
recv( socketDesc, EncodedData, LengthToRead, 0 );
EndOfData = true;
//EncodedDataBytes = QByteArray((char*)EncodedData);
EncodedDataBytes = QByteArray::fromRawData(EncodedData, LengthToRead );
I assume i am missing some header or byte order when reading the response, but at the moment have no idea what. Any help very welcome!!
EDIT: So I have been looking at this a little more over the weekend and at the moment im trying to test the encode and decode of the given hex string, which is "{status:false}" in plain text. I have tried to use online gzip encoders such as http://www.txtwizard.net/compression but it returns some ascii text that does not match the hex string in the above code. When I use PHPs gzcompress( "{status:false}", 1) function it gives me non-ascii values, that I cannot copy/paste to test since they are ascii. So I am wondering if there is any standard reference for gzip encode/decode? It is definitely not in some special encoding since both firefox and wireshark can decode the packets, but my software cannot.
So the issue was with my gzip function, the correct function I found on this link: uncompress error when using zlib
As mentioned above by Cornstalks the infalteInit2 function needs to take MAX_WBITS+16 as its max bit size, I think that was the issue. If anybody knows any libraries or plugins to handle this please post them here! I am surprised that this had to be coded manually when it is so commonly used by HTTP clients/servers.

Newbie C/C++ struct array pointing to other struct array elements

I stumbled upon a neat trick that I've started using to write binary files into (flash) memory on arduino/esp8266 using a library someone posted to one of the esp8266 forums. I've been trying a number of ways to expand upon it. Most recently I've been minifying and compressing my web content files and compiling them in with sketches on my ESP.
The script he posted first uses the output of the unix command xxd -i to write the binary file into an array of hex. The second part uses a struct to combine the file details with a pointer to the array that you can reference from the code whenever the server gets a uri request that matches an entry in the array.
What I would like to do is create a second array of these things with 'default' tools already pre-compressed so I don't have to go through it every time and/or modify my script that builds the header file any time I create a new server sketch. Basically compress and xxd stuff like jquery.js, bootstrap.css and bootstrap.js (or more often their smaller counterparts like backbone or barekit)
Currently once a file is dumped to hex, for example:
FLASH_ARRAY(uint8_t, __js__simple_js,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x2b,
0xcd, 0x4b, 0x2e, 0xc9, 0xcc, 0xcf, 0x53, 0xc8, 0xad, 0xf4, 0xcf, 0xf3,
0xc9, 0x4f, 0x4c, 0xd1, 0xd0, 0xac, 0x4e, 0xcc, 0x49, 0x2d, 0x2a, 0xd1,
0x50, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0xc4, 0x3c, 0x85, 0xfc,
0xbc, 0x1c, 0xa0, 0x94, 0x42, 0x6e, 0x6a, 0x71, 0x71, 0x62, 0x7a, 0xaa,
0x92, 0xa6, 0x75, 0x51, 0x6a, 0x49, 0x69, 0x51, 0x9e, 0x42, 0x49, 0x51,
0x69, 0x6a, 0x2d, 0x00, 0x16, 0xa6, 0x25, 0xe5, 0x43, 0x00, 0x00, 0x00);
The existing code added them all at once along with the struct definition:
struct t_websitefiles {
const char* path;
const char* mime;
const unsigned int len;
const char* enc;
const _FLASH_ARRAY<uint8_t>* content;
} files[] = {
{
.path = "/js/simple.js",
.mime = "application/javascript",
.len = 84,
.enc = "gzip",
.content = &__js__simple_js,
},
{
/* details for file2 ...*/
},
{
/* details for file3 ...*/
}
};
Building an array of the structs representing the various files.
My questions amount to noob questions regarding the language syntax. Can I assume that I can use an identical populated struct in the place of what is inside the curly brackets? For example, if I had a second header file with my regularly used libraries, and jquery was compressed in an array called 'default_files' at position 3, could I use something like &default_files[3] in the place of { /* definitions stuffs */ }. Such as:
struct t_websitefiles {
const char* path;
const char* mime;
const unsigned int len;
const char* enc;
const _FLASH_ARRAY<uint8_t>* content;
} files[] = {
{
.path = "/js/simple.js",
.mime = "application/javascript",
.len = 84,
.enc = "gzip",
.content = &__js__simple_js,
},
&default_files[1],
&default_files[3],
{
.path = "/text/readme.txt",
.mime = "text/text",
.len = 112,
.enc = "",
.content = &__text__readme_txt,
}
};
(I'm guessing based on what I've learned thus far it needs the & in front of it?)
I also assume rather than re-writing the struct definition twice,I could do it as a typedef and then just do:
t_websitefiles files[] = { {/*definitions*/},{ /*stuffs*/ } };
Is that correct? Any help is appreciated. It's hard sometimes to find details on the syntax for specific use cases in documentation covering basics. (I would just try it, but I'm not conveniently in front of a compiler at the moment nor do I have direct access to my codebase but want to work on it later when I might not have direct access to the net)
From what I understand, you want create an array of structs such contains both compound literals and items from another array, all defined in header information.
I don't think this is possible - or at least not in the exact way you suggest. I'll try and provide an alternative though.
Can I assume that I can use an identical populated struct in the place of what is inside the curly brackets?
No - you're mixing your types. 'files' is defined as an array of 'struct t_website'.
The code
struct t_websitefiles files[] = {
...
&default_files[1],
...
}
won't compile as you are mixing your types. files is defined as an array of struct t_websitefile, but &default_files[1] is a pointer. C makes a distinction between pointers and non-pointers. They are seperate types.
The obvious option that I can see to do what you want is to use pointers. This will allow you to define everything in header information.
struct t_websitefiles default_files[] = {
....
}
struct t_websitefiles files[] = {
....
}
// An array of pointers
struct t_websitefiles *files_combined[] = {
&files[0],
&files[1],
&default_files[0],
// Or whatever values you want here
...
}
// Example main, just iterates through the combined list
// of files
int main(int argc, char* argv[]) {
int i;
int files_combined_len = sizeof(files_combined)/sizeof(struct t_websitefiles);
for (i=0; i<files_combined_len; i++) {
printf("File %s\r\n", files_combined[i]->path);
}
return 0;
}
Hope this helps.

Function returning wrong value in lpc824

I am working on porting an application running on Arduino Mega to LPC824. The following piece of code is working differently for both the platforms.
/**
* Calculation of CMAC
*/
void cmac(const uint8_t* data, uint8_t dataLength) {
uint8_t trailer[1] = {0x80};
uint8_t bytes[_lenRnd];
uint8_t temp[_lenRnd];
memcpy(temp, data, dataLength);
concatArray(temp, dataLength, trailer, 1);
dataLength ++;
addPadding(temp, dataLength);
memcpy(bytes, _sk2, _lenRnd);
xorBytes(bytes,temp,_lenRnd);
aes128_ctx_t ctx;
aes128_init(_sessionkey, &ctx);
uint8_t* chain = aes128_enc_sendMode(bytes, _lenRnd, &ctx, _ivect);
Board_UARTPutSTR("chain\n\r");
printBytes(chain, 16, true);
memcpy(_ivect, chain, _lenRnd);
//memcpy(_ivect, aes128_enc_sendMode(bytes,_lenRnd,&ctx,_ivect), _lenRnd);
memcpy(_cmac,_ivect, _lenRnd);
Board_UARTPutSTR("Initialization vector\n\r");
printBytes(_ivect, 16, true);
}
I am expecting a value like {0x5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2} for the chain variable. But the follow function is working differently. The print inside the function has the correct value which I want ({5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2}).
But when the function returns chain is having a different value, compared to what I am expecting, I get the following value for chain {0x00, 0x20, 0x00, 0x10, 0x03, 0x01, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00}
Inside the function, the result is correct. But it returns a wrong value to the function which called it. Why is it happening so ?
uint8_t* aes128_enc_sendMode(unsigned char* data, unsigned short len, aes128_ctx_t* key,
const unsigned char* iv) {
unsigned char tmp[16];
uint8_t chain[16];
unsigned char c;
unsigned char i;
memcpy(chain, iv, 16);
while (len >= 16) {
memcpy(tmp, data, 16);
//xorBytes(tmp,chain,16);
for (i = 0; i < 16; i++) {
tmp[i] = tmp[i] ^ chain[i];
}
aes128_enc(tmp, key);
for (i = 0; i < 16; i++) {
//c = data[i];
data[i] = tmp[i];
chain[i] = tmp[i];
}
len -= 16;
data += 16;
}
Board_UARTPutSTR("Chain!!!:");
printBytes(chain, 16, true);
return chain;
}
A good start with an issue like this is to delete as much as you can while reproducing the error, with a minimal code example the answer is typically clear. I have done that for you here.
uint8_t* aes128_enc_sendMode(void) {
uint8_t chain[16];
return chain;
}
The chain variable is a local to the function, it ceases to be defined once the function exists. Accessing a pointer to that variable causes undefined behaviour, don't do it.
In practice the pointer to the array still exists and points to an arbitrary block of memory. This block of memory is no longer reserved and can be overwritten at any time.
I suspect it works for the AVR because it is a simple 8 bit chip and that piece of memory was sitting unmolested by the time you used it. The ARM would have used greater optimisations, possibly running the full array on registers, so the data doesn't survive the transition.
tldr; You need to malloc() any arrays that you want to live past the function's exit. Be careful, malloc and embedded systems go together like diesel and styrofoam, it gets messy real quick.