I'm using this library: https://tls.mbed.org/download with an Espressif ESP32. The goal is to encrypt some data using AES-CTR then decrypt the cypher-text back to the original plain-text. I am getting incorrect result after I've decrypted.
Since we're using CTR mode, we don't need to have a separate "decrypt" function; We can just call the encrypt function once to encrypt then call the same function one more time and it should decrypt. At least, that's what most sources say and that was the case with this other implementation: https://github.com/kokke/tiny-AES-c
I tried using the same nonce, same stream-block, different nonces, different stream-blocks, set the key before each of the function calls, etc.
mbedtls_aes_context aes;
unsigned char key[16];
size_t plainText_len = 64;
unsigned int nc_off = 0;
unsigned char nonce_counter[16] = {0};
unsigned char stream_block[16] = {0};
unsigned char plainText[64] = {0x48, 0x45, 0x4c, 0x4c, 0x4f};
unsigned char encryptText[64];
unsigned char decryptText[64];
memcpy(key, key_128, 16); //key_128 comes from a different file
//Print Key
printf("aes Key: \n");
for(int i = 0; i < 16; i++){
printf("%x",key[i]);
}
printf("\n");
//Print plain-text
printf("aes plainText: \n");
for(int i = 0; i < 5; i++){
printf("%x",plainText[i]);
}
printf("\n");
esp_aes_init(&aes); //context is initialized
esp_aes_setkey(&aes, key, 128); //key is associated to context
esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, plainText, encryptText); //encrypt
//Print encrypt-text
printf("aes encryptText: \n");
for(int i = 0; i < 5; i++){
printf("%x",encryptText[i]);
}
printf("\n");
esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, encryptText, decryptText); //decrypt
//Print decrypt-text
printf("aes decrypt: \n");
for(int i = 0; i < 5; i++){
printf("%x",decryptText[i]);
}
printf("\n");
After the encrypt function is called a second time the resulting decryptText should be the same as the original plain-text, however, at the moment plainText =/= decryptText.
This is what my monitor is printing:
aes key: 7d3043fb95355e6ccd850ad8debc279
aes plainText: 48454c4c4f
aes encryptText: 852b97da59
aes decryptText: 814268329f
As you can see, I'm missing something that'll properly decrypt the encryptText!
Since we're using CTR mode, we don't need to have a separate "decrypt" function; We can just call the encrypt function...
I think you are conflating topics. CTR mode does operate the cipher in the forward direction for both encryption and decryption. However, the same sort of symmetry may not exist in the higher level mbedTLS objects.
esp_aes_init(&aes); //context is initialized
esp_aes_setkey(&aes, key, 128); //key is associated to context
esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, plainText, encryptText); //encrypt
// ...
esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, encryptText, decryptText); //decrypt
// ...
esp_aes_crypt_ctr is a define for mbedtls_aes_crypt_ctr. mbedtls_aes_crypt_ctr docs say the function updates both nonce_counter and stream_block. I believe you need to restart both when you want to perform decryption.
Here is one of the mentions of stream_block in the docs. You are not contiuing encryption. You need to restart the parameter.
stream_block - The saved stream block for resuming. This is overwritten by the function. It must be a readable-writeable buffer of
16 Bytes.
But in the bigger picture as was commented by #James... You should probably use mbedTLS the way it was designed to be used rather than trying to take shortcuts.
This question already has an answer here:
Summing the rows of a matrix (stored in either row-major or column-major order) in CUDA
(1 answer)
Closed 5 years ago.
I declared two GPU memory pointers, and allocated the GPU memory, transfer data and launch the kernel in the main:
// declare GPU memory pointers
char * gpuIn;
char * gpuOut;
// allocate GPU memory
cudaMalloc(&gpuIn, ARRAY_BYTES);
cudaMalloc(&gpuOut, ARRAY_BYTES);
// transfer the array to the GPU
cudaMemcpy(gpuIn, currIn, ARRAY_BYTES, cudaMemcpyHostToDevice);
// launch the kernel
role<<<dim3(1),dim3(40,20)>>>(gpuOut, gpuIn);
// copy back the result array to the CPU
cudaMemcpy(currOut, gpuOut, ARRAY_BYTES, cudaMemcpyDeviceToHost);
cudaFree(gpuIn);
cudaFree(gpuOut);
And this is my code inside the kernel:
__global__ void role(char * gpuOut, char * gpuIn){
int idx = threadIdx.x;
int idy = threadIdx.y;
char live = '0';
char dead = '.';
char f = gpuIn[idx][idy];
if(f==live){
gpuOut[idx][idy]=dead;
}
else{
gpuOut[idx][idy]=live;
}
}
But here are some errors, I think here are some errors on the pointers. Any body can give a help?
The key concept is the storage order of multidimensional arrays in memory -- this is well described here. A useful abstraction is to define a simple class which encapsulates a pointer to a multidimensional array stored in linear memory and provides an operator which gives something like the usual a[i][j] style access. Your code could be modified something like this:
template<typename T>
struct array2d
{
T* p;
size_t lda;
__device__ __host__
array2d(T* _p, size_t _lda) : p(_p), lda(_lda) {};
__device__ __host__
T& operator()(size_t i, size_t j) {
return p[j + i * lda];
}
__device__ __host__
const T& operator()(size_t i, size_t j) const {
return p[j + i * lda];
}
};
__global__ void role(array2d<char> gpuOut, array2d<char> gpuIn){
int idx = threadIdx.x;
int idy = threadIdx.y;
char live = '0';
char dead = '.';
char f = gpuIn(idx,idy);
if(f==live){
gpuOut(idx,idy)=dead;
}
else{
gpuOut(idx,idy)=live;
}
}
int main()
{
const int rows = 5, cols = 6;
const size_t ARRAY_BYTES = sizeof(char) * size_t(rows * cols);
// declare GPU memory pointers
char * gpuIn;
char * gpuOut;
char currIn[rows][cols], currOut[rows][cols];
// allocate GPU memory
cudaMalloc(&gpuIn, ARRAY_BYTES);
cudaMalloc(&gpuOut, ARRAY_BYTES);
// transfer the array to the GPU
cudaMemcpy(gpuIn, currIn, ARRAY_BYTES, cudaMemcpyHostToDevice);
// launch the kernel
role<<<dim3(1),dim3(rows,cols)>>>(array2d<char>(gpuOut, cols), array2d<char>(gpuIn, cols));
// copy back the result array to the CPU
cudaMemcpy(currOut, gpuOut, ARRAY_BYTES, cudaMemcpyDeviceToHost);
cudaFree(gpuIn);
cudaFree(gpuOut);
return 0;
}
The important point here is that a two dimensional C or C++ array stored in linear memory can be addressed as col + row * number of cols. The class in the code above is just a convenient way of expressing this.
I'm new to Arduino and currently learn to use PROGMEM to store variables so that I can save dynamic memory. I have 13 variables including these three below that I store using PROGMEM.
Here are some of example of variables that I store and use it in my functions :-
const unsigned int raw_0[62] PROGMEM = {2600,850,400,500,400,500,450,850,450,850,1350,850,450,450,400,500,400,450,450,400,450,450,450,450,400,450,900,850,900,850,900,450,450,850,900,850,900,850,450,450,900,450,400,450,400,900,450,450,450,400,450,450,450,450,400,450,450,450,450,400,450,};
const unsigned int raw_1[60] PROGMEM = {2600,850,450,450,450,450,450,850,450,850,1350,850,500,400,450,400,450,450,450,450,400,450,450,450,400,450,900,850,900,900,850,450,450,850,850,900,900,900,400,450,900,450,450,400,450,850,450,450,450,450,400,450,450,450,450,400,450,450,850,};
const unsigned int raw_a[100] PROGMEM = {3500,1700,400,450,450,1250,450,400,450,400,450,400,500,400,450,400,450,400,450,400,450,450,400,400,500,400,450,400,450,1300,400,450,450,400,450,400,450,400,450,400,450,400,500,350,500,400,450,400,450,1300,400,400,500,400,450,400,450,400,450,450,400,450,450,400,450,400,450,400,450,400,450,450,400,450,450,400,450,1250,450,400,450,400,500,400,450,400,450,400,450,400,450,400,450,1300,450,400,450,1250,450,};
Here is the table that store the variables. I learn this approach from Arduino website; https://www.arduino.cc/en/Reference/PROGMEM .
const unsigned int* const myTable[13] PROGMEM = {
raw_0,
raw_1,
raw_2,
raw_3,
raw_4,
raw_5,
raw_6,
raw_7,
raw_8,
raw_9,
raw_a,
raw_b,
raw_c};
My problem is, how do I retrieve these variables using PROGMEM such as raw_1 and raw_a ?
This is what I did but it did not work :-
unsigned int * ptr = (unsigned int *) pgm_read_word (&myTable [1]);
irsend.sendRaw(ptr,62,38);
Most of examples that I found, they use String or char datatype but in my case, I use array integer.
The ptr is also pointer to PROGMEM, so you have to read the value (or values in this case) by pgm_read_word. The IR library doesn't support that at all (I hope it's the correct one).
Anyway sendRaw implementation is this:
void IRsend::sendRaw (const unsigned int buf[], unsigned int len, unsigned int hz)
{
// Set IR carrier frequency
enableIROut(hz);
for (unsigned int i = 0; i < len; i++) {
if (i & 1) space(buf[i]) ;
else mark (buf[i]) ;
}
space(0); // Always end with the LED off
}
And all used methods are public, so you can implement your own function to do the same:
void mySendRaw (IRsend & dev, const unsigned int buf[], unsigned int len, unsigned int khz)
{
// Set IR carrier frequency
dev.devenableIROut(khz);
for (unsigned int i = 0; i < len; i++) {
if (i & 1) dev.space(pgm_read_word(buf+i));
else dev.mark (pgm_read_word(buf+i));
}
dev.space(0); // Always end with the LED off
}
// And usage:
mySendRaw(irsend, (const uint16_t*)pgm_read_word(myTable+1), 62, 38);
However the size of arrays should be stored somewhere too, so you can use something like:
byte cmd = 1;
mySendRaw(irsend, (const uint16_t*)pgm_read_word(myTable+cmd), pgm_read_word(myTableLenghts+cmd), 38);
I am trying to implement a AEAD sample code for encryption Using GCM encryption. But I always get invalid argument error while setting the key
static int init_aead(void)
{
printk("Starting encryption\n");
struct crypto_aead *tfm = NULL;
struct aead_request *req;
struct tcrypt_result tresult;
struct scatterlist plaintext[1] ;
struct scatterlist ciphertext[1];
struct scatterlist gmactext[1];
unsigned char *plaindata = NULL;
unsigned char *cipherdata = NULL;
unsigned char *gmacdata = NULL;
const u8 *key = kmalloc(16, GFP_KERNEL);
char *algo = "rfc4106(gcm(aes))";
unsigned char *ivp = NULL;
int ret, i, d;
unsigned int iv_len;
unsigned int keylen = 16;
/* Allocating a cipher handle for AEAD */
tfm = crypto_alloc_aead(algo, 0, 0);
init_completion(&tresult.completion);
if(IS_ERR(tfm)) {
pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
/* Allocating request data structure to be used with AEAD data structure */
req = aead_request_alloc(tfm, GFP_KERNEL);
if(IS_ERR(req)) {
pr_err("Couldn't allocate request handle for %s:\n", algo);
return PTR_ERR(req);
}
/* Allocting a callback function to be used , when the request completes */
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, aead_work_done,&tresult);
crypto_aead_clear_flags(tfm, ~0);
/* Set key */
get_random_bytes((void*)key, keylen);
if((ret = crypto_aead_setkey(tfm, key, 16) != 0)) {
pr_err("Return value for setkey is %d\n", ret);
pr_info("key could not be set\n");
ret = -EAGAIN;
return ret;
}
/* Set authentication tag length */
if(crypto_aead_setauthsize(tfm, 16)) {
pr_info("Tag size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
/* Set IV size */
iv_len = crypto_aead_ivsize(tfm);
if (!(iv_len)){
pr_info("IV size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
plaindata = kmalloc(16, GFP_KERNEL);
cipherdata = kmalloc(16, GFP_KERNEL);
gmacdata = kmalloc(16, GFP_KERNEL);
ivp = kmalloc(iv_len, GFP_KERNEL);
if(!plaindata || !cipherdata || !gmacdata || !ivp) {
printk("Memory not availaible\n");
ret = -ENOMEM;
return ret;
}
for (i = 0, d = 0; i < 16; i++, d++)
plaindata[i] = d;
memset(cipherdata, 0, 16);
memset(gmacdata, 0, 16);
for (i = 0,d=0xa8; i < 16; i++, d++)
ivp[i] = d;
sg_init_one(&plaintext[0], plaindata, 16);
sg_init_one(&ciphertext[0], cipherdata, 16);
sg_init_one(&gmactext[0], gmacdata, 128);
aead_request_set_crypt(req, plaintext, ciphertext, 16, ivp);
aead_request_set_assoc(req, gmactext, 16);
ret = crypto_aead_encrypt(req);
if (ret)
printk("cipher call returns %d \n", ret);
else
printk("Failure \n");
return 0;
}
module_init(init_aead);
module_exit(exit_aead);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My code for aead encryption test");
}
On inserting the module I get following output
Starting encryption
Return value for setkey is -22
key could not be set
According to AEAD specification aead uses aes-128 for encryption hence the block size should be 128 bit .
But my system shows only 1 Byte block size support for AEAD
name : rfc4106(gcm(aes))
driver : rfc4106-gcm-aesni
module : aesni_intel
priority : 400
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
Does the invalid argument error is thrown becuase of the block size. If so , what shall I do to make it work ?
The block size of AES is indeed always 128 bit. The block size of GCM is a different matter though. GCM (Galois-Counter Mode) is - as the name suggests - build on top of the CTR (Counter) mode of operation, sometimes also called the SIC (Segmented Integer Counter) mode of operation. This turns AES into a stream cipher. Stream ciphers - by definition - have a block size of one byte (or, more precisely, one bit, but bit level operations are usually not supported by API's).
Block size however has little to do with the key size displayed in the call, and the argument does seem to require bytes instead of bits (in which key lengths are usually defined).
The size of the IV should be 12 bytes (the default). Otherwise additional calculations may be needed by the GCM implementation (if those exist at all).
For Aes GCM RFC 4106 the key must be 20 bytes. I don't known yet why. I've looked into ipsec source code to see how the encryption is made there.