Fix overflow in SPI memory when writing default key dictionnaries.

Boundaries were defined in the memory layout but weren't enforced
by the client, causing an overflow when trying to load a
dictionnary that was too big.
It's too hard to enforce it on the ARM side as the command is a
generic write.
Now that limits are defined, also outputs them as part of the
`hw status` command.
This commit is contained in:
Jean-Michel Picod 2022-11-24 03:16:58 +01:00
commit 1adec4dfb2
3 changed files with 30 additions and 15 deletions

View file

@ -594,7 +594,7 @@ void Flashmem_print_info(void) {
if (isok == 2) { if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]); num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0) if (num != 0xFFFF && num != 0x0)
Dbprintf(" Mifare.................. "_YELLOW_("%d")" keys", num); Dbprintf(" Mifare.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_MF_KEYS_MAX);
} }
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
@ -602,7 +602,7 @@ void Flashmem_print_info(void) {
if (isok == 2) { if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]); num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0) if (num != 0xFFFF && num != 0x0)
Dbprintf(" T55x7................... "_YELLOW_("%d")" keys", num); Dbprintf(" T55x7................... "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_T55XX_KEYS_MAX);
} }
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
@ -610,7 +610,7 @@ void Flashmem_print_info(void) {
if (isok == 2) { if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]); num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0) if (num != 0xFFFF && num != 0x0)
Dbprintf(" iClass.................. "_YELLOW_("%d")" keys", num); Dbprintf(" iClass.................. "_YELLOW_("%d")" / "_GREEN_("%d")" keys", num, DEFAULT_ICLASS_KEYS_MAX);
} }
FlashStop(); FlashStop();

View file

@ -204,19 +204,23 @@ static int CmdFlashMemLoad(const char *Cmd) {
size_t datalen = 0; size_t datalen = 0;
uint32_t keycount = 0; uint32_t keycount = 0;
int res = 0; int res = 0;
uint8_t keylen = 0;
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
switch (d) { switch (d) {
case DICTIONARY_MIFARE: case DICTIONARY_MIFARE:
offset = DEFAULT_MF_KEYS_OFFSET; offset = DEFAULT_MF_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount); keylen = 6;
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
return PM3_EFILE; return PM3_EFILE;
} }
// limited space on flash mem // limited space on flash mem
if (keycount > 0xFFFF) if (keycount > DEFAULT_MF_KEYS_MAX) {
keycount &= 0xFFFF; keycount = DEFAULT_MF_KEYS_MAX;
datalen = keycount * keylen;
}
data[0] = (keycount >> 0) & 0xFF; data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF; data[1] = (keycount >> 8) & 0xFF;
@ -224,14 +228,17 @@ static int CmdFlashMemLoad(const char *Cmd) {
break; break;
case DICTIONARY_T55XX: case DICTIONARY_T55XX:
offset = DEFAULT_T55XX_KEYS_OFFSET; offset = DEFAULT_T55XX_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount); keylen = 4;
res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
return PM3_EFILE; return PM3_EFILE;
} }
// limited space on flash mem // limited space on flash mem
if (keycount > 0xFFFF) if (keycount > DEFAULT_T55XX_KEYS_MAX) {
keycount &= 0xFFFF; keycount = DEFAULT_T55XX_KEYS_MAX;
datalen = keycount * keylen;
}
data[0] = (keycount >> 0) & 0xFF; data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF; data[1] = (keycount >> 8) & 0xFF;
@ -239,14 +246,16 @@ static int CmdFlashMemLoad(const char *Cmd) {
break; break;
case DICTIONARY_ICLASS: case DICTIONARY_ICLASS:
offset = DEFAULT_ICLASS_KEYS_OFFSET; offset = DEFAULT_ICLASS_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount); res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
return PM3_EFILE; return PM3_EFILE;
} }
// limited space on flash mem // limited space on flash mem
if (keycount > 0xFFFF) if (keycount > DEFAULT_ICLASS_KEYS_MAX) {
keycount &= 0xFFFF; keycount = DEFAULT_ICLASS_KEYS_MAX;
datalen = keycount * keylen;
}
data[0] = (keycount >> 0) & 0xFF; data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF; data[1] = (keycount >> 8) & 0xFF;

View file

@ -65,17 +65,23 @@
// Reserved space for T55XX PWD = 4 kb // Reserved space for T55XX PWD = 4 kb
#ifndef DEFAULT_T55XX_KEYS_OFFSET #ifndef DEFAULT_T55XX_KEYS_OFFSET
# define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) # define DEFAULT_T55XX_KEYS_LEN (0x1000)
# define DEFAULT_T55XX_KEYS_OFFSET (T55XX_CONFIG_OFFSET - DEFAULT_T55XX_KEYS_LEN)
# define DEFAULT_T55XX_KEYS_MAX ((DEFAULT_T55XX_KEYS_LEN - 2) / 4)
#endif #endif
// Reserved space for iClass keys = 4 kb // Reserved space for iClass keys = 4 kb
#ifndef DEFAULT_ICLASS_KEYS_OFFSET #ifndef DEFAULT_ICLASS_KEYS_OFFSET
# define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) # define DEFAULT_ICLASS_KEYS_LEN (0x1000)
# define DEFAULT_ICLASS_KEYS_OFFSET (DEFAULT_T55XX_KEYS_OFFSET - DEFAULT_ICLASS_KEYS_LEN)
# define DEFAULT_ICLASS_KEYS_MAX ((DEFAULT_ICLASS_KEYS_LEN - 2) / 8)
#endif #endif
// Reserved space for MIFARE Keys = 8 kb // Reserved space for MIFARE Keys = 8 kb
#ifndef DEFAULT_MF_KEYS_OFFSET #ifndef DEFAULT_MF_KEYS_OFFSET
# define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x6000) # define DEFAULT_MF_KEYS_LEN (0x2000)
# define DEFAULT_MF_KEYS_OFFSET (DEFAULT_ICLASS_KEYS_OFFSET - DEFAULT_MF_KEYS_LEN)
# define DEFAULT_MF_KEYS_MAX ((DEFAULT_MF_KEYS_LEN - 2) / 6)
#endif #endif
// RDV40, validation structure to help identifying that client/firmware is talking with RDV40 // RDV40, validation structure to help identifying that client/firmware is talking with RDV40