Skopane adresy pamięci w memcpy

0

Cześć,
piszę aplikację w której korzystam z tej biblioteki https://github.com/kokke/tiny-AES-c
W kodzie mam sobie taką strukturę danych:

typedef struct
{
	long long timestamp;
	int value;

} entry;

I jeszcze takiego defina

#define CAPTURED_DATA_SIZE 4
#define ENTRY_UINT8 sizeof(entry)*CAPTURED_DATA_SIZE

I właściwa funkcja szyfrująca:

void encrypt()
{
	#if defined(AES256)
		uint8_t key[] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
						  0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 };
	#elif defined(AES192)
		uint8_t key[] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b };
	#elif defined(AES128)
		uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
	#endif

	uint8_t iv[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
	uint8_t in[ENTRY_UINT8];

	memcpy(in, captured_data, sizeof(captured_data));
	struct AES_ctx ctx;
	AES_init_ctx_iv(&ctx, key, iv);
	AES_CBC_encrypt_buffer(&ctx, in, sizeof(in));
	AES_CBC_decrypt_buffer(&ctx, in, sizeof(in));

	entry recover[CAPTURED_DATA_SIZE];
	memcpy(recover, in, sizeof(in));

	int x = 0;
	for(x = 0; x < CAPTURED_DATA_SIZE; x = x + 1)
	{
		dlog_print(DLOG_ERROR, "A_MY_TAG", "I: %d TIMESTAMP: %llu VALUE: %d", x, recover[x].timestamp, recover[x].value);
	}
}

Tablica captured data jest globalna, definicja:

entry captured_data[CAPTURED_DATA_SIZE];

Ogólnie chciałem przetestowac jak działa i czy na pewno poprawnie wszystko szyfruję. I problem jest taki że w tym kodzie po odczytaniu recover[0] to są śmieci, reszta danych jest prawidłowa. Tak patrzę w ten kod już jakiś czas i nie widzę co jest nie tak. Licze na pomoc.

No i zapomniałem o najważniejszym. Jak zakomentowałem tę cześć:

	struct AES_ctx ctx;
	AES_init_ctx_iv(&ctx, key, iv);
	AES_CBC_encrypt_buffer(&ctx, in, sizeof(in));
	AES_CBC_decrypt_buffer(&ctx, in, sizeof(in));

To było poprawnie

0

Spróbuj zbudować z -fsanitize=address.
Ale na oko: coś Ci nadpisuje zmienną na stosie, imho gdzieś jest jakiś off-by-one.
Odkomentowuj problematyczną część sukcesywnie i jechane, potem zostaje Ci debugger ;)
Jaka to architektura? Jaki sizeof(entry)?

0

@alagner: wychodzi 12, architektura hmm prawdę mówiąc nie wiem. Aplikacja pisana jest na smartwatch, środowisko tizen od samsunga. Na "wczoraj" już dałem sobie spokój. Dziś jak się wyśpię spojrzę na to.

1

Nie podoba mi się w ogóle ta libka, bo nadpisuje dane w buforze in. Jest to o tyle słabe, że pewnie padduje dane do pełnego bloku, albo co gorsza zakłada ze są już paddowane, a ty tego nie robisz! Jeśli sizeof(in) nie jest wielokrotnością 16 bajtów to coś tu nie będzie działać. Albo szyfrowanie wyjdzie ci poza tablicę bo z paddingiem danych będzie więcej, albo ten kod już zakłada że twoje dane maja padding i są wyrównane do bloku i wtedy szyfrowanie zaszyfruje jakieś śmieci za tablicą.

edit:

No padding is provided so for CBC and ECB all buffers should be multiples of 16 bytes. For padding PKCS7 is recommendable.

Można też dla testu zrobic kolejny raz AES_init_ctx_iv(&ctx, key, iv); przed deszyfrowaniem, bo może ta libka robi coś głupiego z kontekstem po pierwszym szyfrowaniu.

0

@Shalom: Nie padduje, dokładnie zakłada ze ja to robię. Ale to robię - w redame podane jest wielokrotność 16 bajtów, ustawione mam na 48 jak mnie pamięć nie myli czy założenie spełnione. No ale dobra, skoro nie ta to jaką polecasz? To którą wykorzystam nie ma większego znaczenia.

1

Psują kontekst bo zmieniają IV po szyfrowaniu :) Bo w przypadku CBC każdy blok xorujesz z innym IV (pierwszy z oryginalnym, a każdy następny z poprzednim ciphertextem).

0

@Shalom: O no i fajnie dodanie AES_init_ctx_iv(&ctx, key, iv); przed decrypt pomogło :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1