How to decode MAP Invoke messages using asn1c generated code - c++

I am using the c code generated by asn1c from the MAP protocol specification (i.e., the corresponding ASN1 files). Please consider the following sample code:
// A real byte stream of a MAP message:
unsigned char packet_bytes[] = {
0xa2, 0x60, 0x02, 0x01, 0x00, 0x30, 0x5b, 0x02,
0x01, 0x38, 0xa3, 0x56, 0xa1, 0x54, 0x30, 0x52,
0x04, 0x10, 0x7a, 0x0e, 0x1f, 0xef, 0x73, 0x77,
0xbe, 0xb0, 0x9d, 0x6f, 0x23, 0x13, 0xfb, 0xc2,
0x32, 0xa6, 0x04, 0x08, 0x65, 0xda, 0x19, 0x1e,
0x18, 0x4b, 0x04, 0x99, 0x04, 0x10, 0x47, 0xe1,
0x36, 0x82, 0xe9, 0xb3, 0xf3, 0x54, 0x76, 0x67,
0x1d, 0xe4, 0xed, 0x25, 0xc8, 0x76, 0x04, 0x10,
0x37, 0x1d, 0x80, 0x82, 0xde, 0xec, 0x70, 0x51,
0xc6, 0xcd, 0x08, 0xc9, 0x30, 0x64, 0xc6, 0x54,
0x04, 0x10, 0x82, 0xbc, 0x2d, 0xdb, 0x1d, 0x92,
0x82, 0x34, 0x55, 0xbc, 0xeb, 0x87, 0x72, 0xf3,
0x90, 0xce
};
// Initializing ...
MAP_Component_t _pdu, *pdu = &_pdu;
memset(pdu, 0, sizeof(*pdu));
// Decoding:
asn_dec_rval_t dec_ret = ber_decode(NULL, &asn_DEF_MAP_Component, (void **) &pdu, MAP_packet_bytes, sizeof(MAP_packet_bytes));
The invokeId and opCode parameters are truely detected, and the parser gives us a buffer named as invokeParameters which is of type ANY.
GSM Mobile Application
Component: invoke (1)
invoke
invokeID: -70
opCode: localValue (0)
invokeParameters: ....
The question is how to decode (parse) invokeParameters?
GSM Mobile Application
Component: returnResultLast (2)
returnResultLast
invokeID: 0
resultretres
opCode: localValue (0)
localValue: sendAuthenticationInfo (56)
authenticationSetList: quintupletList (1)
quintupletList: 1 item
AuthenticationQuintuplet
rand: 7a0e1fef7377beb09d6f2313fbc232a6
xres: 65da191e184b0499
ck: 47e13682e9b3f35476671de4ed25c876
ik: 371d8082deec7051c6cd08c93064c654
autn: 82bc2ddb1d92823455bceb8772f390ce

The invokeId and opCode parameters are truely detected, and the parser gives us a buffer named as invokeParameters which is of type ANY.
The question is how to decode (parse) invokeParameters?
You need to call ber_decode with the appropriate type (depending on the operation code) and the content of the ANY buffer. From ANY.h
typedef struct ANY {
uint8_t *buf; /* BER-encoded ANY contents */
int size; /* Size of the above buffer */
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
} ANY_t;
In your case it should be something like
SendAuthenticationInfoArg_t _sai, *sai = &_sai;
memset(sai, 0, sizeof(*sai));
asn_dec_rval_t dec_ret = ber_decode(NULL,
&asn_DEF_SendAuthenticationInfoArg,
(void **) &sai,
_pdu.invoke.invokeparameter->buf,
_pdu.invoke.invokeparameter->size);

Related

Load ECDSA private key with Crypto++

I'm trying to load an EC key given as a byte array using Crypto++. Here is the key:
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPQLO9zyl40X3lh1wbSR6S88aCsUvJr9R5n2pA3DbD9+oAoGCCqGSM49
AwEHoUQDQgAEs+nDydkW5F07yZPb/c05TSjzRJXCvD8Ni76ppfWJFOEOdM/WuHU6
zBMcdIzoY+LuqdZ8LgVlMBsnx8NwNvvFAA==
-----END EC PRIVATE KEY-----
And here is the same key as a byte array (assuming I didn't mess up the conversion):
uint8_t server_priv_key_[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf4, 0x0b, 0x3b, 0xdc, 0xf2,
0x97, 0x8d, 0x17, 0xde, 0x58, 0x75, 0xc1, 0xb4, 0x91, 0xe9, 0x2f, 0x3c,
0x68, 0x2b, 0x14, 0xbc, 0x9a, 0xfd, 0x47, 0x99, 0xf6, 0xa4, 0x0d, 0xc3,
0x6c, 0x3f, 0x7e, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xb3, 0xe9, 0xc3,
0xc9, 0xd9, 0x16, 0xe4, 0x5d, 0x3b, 0xc9, 0x93, 0xdb, 0xfd, 0xcd, 0x39,
0x4d, 0x28, 0xf3, 0x44, 0x95, 0xc2, 0xbc, 0x3f, 0x0d, 0x8b, 0xbe, 0xa9,
0xa5, 0xf5, 0x89, 0x14, 0xe1, 0x0e, 0x74, 0xcf, 0xd6, 0xb8, 0x75, 0x3a,
0xcc, 0x13, 0x1c, 0x74, 0x8c, 0xe8, 0x63, 0xe2, 0xee, 0xa9, 0xd6, 0x7c,
0x2e, 0x05, 0x65, 0x30, 0x1b, 0x27, 0xc7, 0xc3, 0x70, 0x36, 0xfb, 0xc5,
0x00,
};
Finally, I'm loading the key like this:
ArraySource server_priv_key_source { server_priv_key_, sizeof(server_priv_key_), true };
ECDSA<ECP, SHA256>::PrivateKey server_priv_key;
server_priv_key.Load(server_priv_key_source);
However, the call to Load causes a "BER decode error" exception. What am I doing wrong?
Your private key has the SEC1 format, but only the PKCS#8 format is supported (see here and here), so the key has to be converted, e.g. with OpenSSL:
openssl pkcs8 -topk8 -nocrypt -in <path to input-sec1-pem> -out <path to output-pkcs8-pem>
This results in (PEM encoded):
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9As73PKXjRfeWHXB
tJHpLzxoKxS8mv1HmfakDcNsP36hRANCAASz6cPJ2RbkXTvJk9v9zTlNKPNElcK8
Pw2Lvqml9YkU4Q50z9a4dTrMExx0jOhj4u6p1nwuBWUwGyfHw3A2+8UA
-----END PRIVATE KEY-----
or as byte array (DER encoded):
uint8_t server_priv_key_[] = {
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
0xf4, 0x0b, 0x3b, 0xdc, 0xf2, 0x97, 0x8d, 0x17, 0xde, 0x58, 0x75, 0xc1,
0xb4, 0x91, 0xe9, 0x2f, 0x3c, 0x68, 0x2b, 0x14, 0xbc, 0x9a, 0xfd, 0x47,
0x99, 0xf6, 0xa4, 0x0d, 0xc3, 0x6c, 0x3f, 0x7e, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0xb3, 0xe9, 0xc3, 0xc9, 0xd9, 0x16, 0xe4, 0x5d, 0x3b, 0xc9,
0x93, 0xdb, 0xfd, 0xcd, 0x39, 0x4d, 0x28, 0xf3, 0x44, 0x95, 0xc2, 0xbc,
0x3f, 0x0d, 0x8b, 0xbe, 0xa9, 0xa5, 0xf5, 0x89, 0x14, 0xe1, 0x0e, 0x74,
0xcf, 0xd6, 0xb8, 0x75, 0x3a, 0xcc, 0x13, 0x1c, 0x74, 0x8c, 0xe8, 0x63,
0xe2, 0xee, 0xa9, 0xd6, 0x7c, 0x2e, 0x05, 0x65, 0x30, 0x1b, 0x27, 0xc7,
0xc3, 0x70, 0x36, 0xfb, 0xc5, 0x00
};
In this format the key can be imported with the posted code.
Test:
In the following code, the private key is imported, a message is signed, the public key is derived from the imported private key, and the message is then successfully verified:
#include <osrng.h>
#include <eccrypto.h>
using namespace CryptoPP;
using namespace std;
...
uint8_t server_priv_key_[] = ... // the DER encoded PKCS#8 key above
// Import private key
ArraySource server_priv_key_source{ server_priv_key_, sizeof(server_priv_key_), true };
ECDSA<ECP, SHA256>::PrivateKey server_priv_key;
server_priv_key.Load(server_priv_key_source);
// Derive public key
ECDSA<ECP, SHA256>::PublicKey publicKey;
server_priv_key.MakePublicKey(publicKey);
// Sign
AutoSeededRandomPool prng;
ECDSA<ECP, SHA256>::Signer signer(server_priv_key);
size_t signatureLen = signer.MaxSignatureLength();
string signature(signatureLen, 0x00);
string msg = "The quick brown fox jumps over the lazy dog";
signatureLen = signer.SignMessage(prng, (const byte*)&msg[0], msg.size(), (byte*)&signature[0]);
signature.resize(signatureLen);
// Verify
ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
bool result = verifier.VerifyMessage((const byte*)&msg[0], msg.size(), (const byte*)&signature[0], signature.size());
printf("%s", result ? "verified" : "failed"); // verified

C++ negative byte value

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];
}
}

ESP8266 WebServer how to stream unsigned char

I was playing around with xxd -i this weekend to convert binary files into unsigned char arrays, thinking I could use it to embed small binary files into arduino code for transmission on mini web and other services. Problem is, it seems the functions in the existing libraries either expect const char *, string or File data types. (and of course, unsigned char arrays aren't really char arrays so they don't convert well to strings)
Not being someone familiar with c++ in depth (still learning) I'm wondering if there is any easy way to stream the unsigned char array created from xxd over the ESP webserver code or something similar? And/or is there a better way to encode a binary file for sending from same?
I'm basically looking at building primarily 'rest' based esp devices, but wanted to have some kind of very rudimentary html/js interface to directly connect and configure basic functionality or get basic telemetry back from the devices. My thought was that with very streamline html/js coding combined with a minify followed by a gzip, I could put such basic primitive interfaces directly into the code in a binary array to be served up when needed. For more complex devices, I've gotten the sd card webserver to work fine, but would prefer not to have to use sd cards for all applications. Before I go back to relying upon html content in huge strings or function calls full of concatenations/prints, I'd like to try to get this to work as another option.
Any help is appreciated.
--- EDITED ---
Example from xxd -i
unsigned char index_htm_gz[] = {
0x1f, 0x8b, 0x08, 0x08, 0x25, 0x38, 0xcf, 0x58, 0x02, 0x03, 0x69, 0x6e,
0x64, 0x65, 0x78, 0x2e, 0x6d, 0x69, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x00,
0x5d, 0x8d, 0xb1, 0x6a, 0xc4, 0x30, 0x10, 0x44, 0x7b, 0x7d, 0xc5, 0xe6,
0x03, 0xce, 0x4a, 0xc0, 0x98, 0x14, 0x2b, 0x35, 0x97, 0x40, 0xba, 0x4b,
0x61, 0x08, 0x29, 0x65, 0x7b, 0x2d, 0x2d, 0xb7, 0xb2, 0x8d, 0xb4, 0xc9,
0x91, 0xbf, 0x8f, 0x42, 0xba, 0x83, 0x61, 0x18, 0x1e, 0x33, 0x0c, 0x3e,
0xbc, 0x5c, 0xce, 0xe3, 0xe7, 0xfb, 0x2b, 0x24, 0xcd, 0xe2, 0xf1, 0xcf,
0x41, 0xc2, 0x16, 0x1d, 0x6d, 0x1e, 0x33, 0x69, 0x80, 0x39, 0x85, 0x52,
0x49, 0xdd, 0x97, 0xae, 0xa7, 0x67, 0x8f, 0xca, 0x2a, 0xe4, 0xdf, 0x48,
0x64, 0x07, 0xf3, 0xb1, 0x17, 0x59, 0xd0, 0xfe, 0x33, 0x14, 0xde, 0xae,
0x90, 0x0a, 0xad, 0x6e, 0xae, 0xd5, 0xe6, 0xc0, 0x5b, 0xd7, 0x02, 0x14,
0x12, 0x57, 0xf5, 0x47, 0xa8, 0x26, 0x22, 0x6d, 0x1f, 0x4f, 0x77, 0xf3,
0x06, 0xf0, 0xf0, 0x63, 0xe2, 0x0a, 0x4d, 0x01, 0x6e, 0x34, 0xc1, 0x11,
0x22, 0x75, 0x68, 0x0f, 0x8f, 0x9c, 0x23, 0x4c, 0x7b, 0x59, 0xa8, 0xb8,
0x47, 0x48, 0xc4, 0x31, 0xa9, 0x1b, 0x7a, 0x30, 0xb5, 0xcc, 0x8e, 0x73,
0xab, 0x55, 0xfb, 0x3d, 0x45, 0xda, 0x87, 0xbe, 0x8b, 0xbc, 0xc2, 0x8d,
0x17, 0x4d, 0xad, 0xe0, 0x8d, 0xf9, 0x05, 0x3d, 0x2a, 0xb3, 0xe0, 0xdd,
0x00, 0x00, 0x00
};
unsigned int index_htm_gz_len = 207;
As mentioned in comments, one thing I tried was switching the type from unsigned char to const char then running through the following:
void sendCompressed(String content_type, const char * content, unsigned int len) {
webServer.setContentLength(len);
webServer.sendHeader("Content-Encoding", "gzip");
webServer.send(200, content_type, String(content));
}
In such a case, my handleRoot function would call the sendCompressed with the data from the header:
void function handleRoot() {
sendCompressed("text/html", index_htm_gz, index_htm_gz_len);
}
It compiled without errors, but outputs nothing. I would also expect this not to be ideal as String data is generally 7-bit and obviously, binary compressed data is not.
This binary serve worked for me:
const char favicon[1344] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
... // ( way shortened )
0x44, 0xae, 0x42, 0x60, 0x82
};
void handleFavicon() {
server.send_P(200, "image/x-icon", favicon, sizeof(favicon));
}
server.on("/favicon.ico", handleFavicon); // in setup() or something like it
you might need to adjust your gzip header, but this method of embeding binary content works enough to show the right icon, i'd imaging a gzip stream works the same way...

IntelĀ® TinyCrypt: how to use AES-128/CTR

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.

Could not find space (120 bytes) for variable

I have an array defined with 60 hex values.
int ary[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59
};
When i compile this i get the error
could not find space (120 bytes) for variable _ary
Why is this happening, This is for a PIC program and i need the array to be type of int. What can i do?