Esp aes memory allocation fail

nonagon
Posts: 19
Joined: Thu May 06, 2021 12:56 pm

Esp aes memory allocation fail

Postby nonagon » Fri Aug 18, 2023 4:23 pm

Aes implementation work fine unilt after an intense usage of aes module the aes encryption fail forever with this message:

Code: Select all

esp-aes: Failed to allocate memory
Our products have external memory and it is mostly free, in the internal memory at least 30kb of ram are free.
Some data to locate chip and idf ver:

Code: Select all

I (1063) cpu_start: ESP-IDF:          4.4.5
I (1068) cpu_start: Min chip rev:     v0.0
I (1073) cpu_start: Max chip rev:     v1.99 
I (1078) cpu_start: Chip rev:         v0.0
I (1082) heap_init: Initializing. RAM available for dynamic allocation:
I (1090) heap_init: At 3FFD5EE0 len 00026120 (152 KiB): DRAM
I (1096) heap_init: At 3FFFC000 len 00003A10 (14 KiB): DRAM
I (1102) heap_init: At 3FF9E000 len 00002000 (8 KiB): RTCRAM
I (1109) spiram: Adding pool of 2048K of external SPI memory to heap allocator
our code implementation:

Code: Select all


int aes256_hw_accel_crypt(
	unsigned char* plaintext, int plaintext_len, unsigned char* key,
	unsigned char* iv, unsigned char* ciphertext)
{
	int res;
	esp_aes_context ctx;
	esp_aes_init(&ctx);
	esp_aes_setkey(&ctx, key, 256);

	res = esp_aes_crypt_cbc(
		&ctx,
		ESP_AES_ENCRYPT,
		plaintext_len,
		iv,
		(uint8_t*)plaintext,
		(uint8_t*)ciphertext);

	esp_aes_free(&ctx);

	if (res == 0)
	{
		return plaintext_len;
	}

	return 0;
}

int aes256_hw_accel_decrypt(
	unsigned char* ciphertext, int ciphertext_len, unsigned char* key,
	unsigned char* iv, unsigned char* plaintext)
{
	int res;
	esp_aes_context ctx;
	esp_aes_init(&ctx);
	esp_aes_setkey(&ctx, key, 256);

	res = esp_aes_crypt_cbc(
		&ctx,
		ESP_AES_DECRYPT,
		ciphertext_len,
		iv,
		(uint8_t*)ciphertext,
		(uint8_t*)plaintext);

	esp_aes_free(&ctx);

	if (res == 0)
	{
		return ciphertext_len;
	}

	return 0;
}
Someone can't point us to discover the problem?
Thanks in advice

nonagon
Posts: 19
Joined: Thu May 06, 2021 12:56 pm

Re: Esp aes memory allocation fail

Postby nonagon » Fri Aug 18, 2023 4:58 pm

UPDATE:
We have been able to systematically reproduce the problem:
1) we set a product to normally connect to hotspot
2) we set another product to cyclically connected and disconnect to the hotspot

after several connections and reconnections the problem appeared:

Code: Select all

[34.580 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[34.590 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[34.925 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[34.925 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[35.295 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[35.405 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[35.775 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[35.805 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[36.140 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[36.145 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[36.545 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[36.550 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[36.945 NoTime] Station connected to this hotspot --> Unknow S/N 0000000000000000
[0;94m[37.105 NoTime] Hotspot Assigned IP to a client 192.18.1.3
[0;31mE (56612) esp-aes: Failed to allocate memory
[37.710 NoTime] Decryptation Failed, unknow error, data len is 4144. key/iv hash: a687 7913
Using this workaround we made it working:

Code: Select all


int aes256_hw_accel_crypt(
	unsigned char* plaintext, int plaintext_len, unsigned char* key,
	unsigned char* iv, unsigned char* ciphertext)
{
	int res = 0;
	esp_aes_context ctx;
	esp_aes_init(&ctx);
	esp_aes_setkey(&ctx, key, 256);

	u32 blockdim, seek = 0;

	while (seek < plaintext_len && res == 0)
	{
		blockdim =
			(plaintext_len - seek) >= 256 ? 256 : plaintext_len - seek;

		res = esp_aes_crypt_cbc(
			&ctx,
			ESP_AES_ENCRYPT,
			blockdim,
			iv,
			(uint8_t*)&plaintext[seek],
			(uint8_t*)&ciphertext[seek]);

		seek += blockdim;
	}

	esp_aes_free(&ctx);

	if (res == 0)
	{
		return plaintext_len;
	}

	return 0;
}

int aes256_hw_accel_decrypt(
	unsigned char* ciphertext, int ciphertext_len, unsigned char* key,
	unsigned char* iv, unsigned char* plaintext)
{
	int res = 0;
	esp_aes_context ctx;
	esp_aes_init(&ctx);
	esp_aes_setkey(&ctx, key, 256);

	u32 blockdim, seek = 0;

	while (seek < ciphertext_len && res == 0)
	{
		blockdim =
			(ciphertext_len - seek) >= 256 ? 256 : ciphertext_len - seek;

		res = esp_aes_crypt_cbc(
			&ctx,
			ESP_AES_DECRYPT,
			blockdim,
			iv,
			(uint8_t*)&ciphertext[seek],
			(uint8_t*)&plaintext[seek]);

		seek += blockdim;
	}

	esp_aes_free(&ctx);

	if (res == 0)
	{
		return ciphertext_len;
	}

	return 0;
}
anyway, of course if there is a memory leakage problem we need to fix it, we are writing here to check if it's not an IDF framework problem.

MicroController
Posts: 1733
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Esp aes memory allocation fail

Postby MicroController » Fri Aug 18, 2023 7:22 pm

Of course, there may be a memory leak somewhere else in your code. However,
in the internal memory at least 30kb of ram are free
does not imply that any allocation of up to 30kb will be possible/successful: Fragmentation of the heap can make memory unusable for allocations above a certain size.

Mitigation can be two-fold:
1. reduce/prevent fragmentation of the heap
2. reduce the requirement of allocating "big" blocks of consecutive memory from the heap.

The latter seems to be what's working in your case, splitting input into smaller blocks.

rsimpsonbusa
Posts: 131
Joined: Tue May 17, 2016 8:12 pm

Re: Esp aes memory allocation fail

Postby rsimpsonbusa » Fri Aug 25, 2023 8:41 pm

Hi.

Ive used the aes function extensively w/o problems (thousands of messages in hours).

My strategy, which you might consider, is that the aes ctx variable is a GLOBAL and initialized just once along with the iv variable (also global and which I believe is only used when segmenting a decrypt/encrypt block). The key could change every message, still strange to do so, should not cause problems.

The out of memory might be FRAGMENTATION as Microcontroller suggests due to calling aes_init every time. Also I’ve had ram problems (not able to allocate) when using psram which you are also using. Never did know why the psram failed but I did try all psram configurations posible to no avail.

Again, IV should be zero, if possible not null (8 bytes I think) and just create the aes context once.

Deinitializing aes will free ram but eventually fragment it. Good luck.

Regards.

Who is online

Users browsing this forum: Matthias199 and 134 guests