Обсуждаем цифровые устройства...
Ответить

Re: Ковыряем RFID Mifare и MFRC522

Пн ноя 27, 2017 14:51:10

Более подобно DES.
Дело в том что каждый 0 LSB бит является темпорари битом. То-есть выполняет определенную системную алгоритмическую роль для внутренних нужд алгоритма.
И полезная нагрузочная способность шифрования у DES на самом деле не 64 бита, а 56 бит на один ключ. Более подробно о des https://ru.wikipedia.org/wiki/Triple_DES

NXP рекомендует сбрасывать данный бит в 0, дабы усложнить задачу взломщику.
Функция на C:

void ArrForDes(byte *arr,int cnt){
for(int i=0;i<cnt;i++){
arr[i]&=~(1<<0);
}
}

Пример работы (до, после):
До
<- 01 02 03 04 45 5D 26 B7 05 06 07 08 5D 33 F5 68 01 02 03 04 45 5D 26 B7
После
<- 00 02 02 04 44 5C 26 B6 04 06 06 08 5C 32 F4 68 00 02 02 04 44 5C 26 B6

01 - [00000001]
00 - [00000000]

LSB бит на позиции 0 - всегда меняется на 0. Таким нехитрым образом шифр становится менее уязвимым к атакам.

Продолжаю с авторизацией. 45 - версия ключа.

С системной информацией
-> 03 45 61 21
<- 03 00 0B 01 EC 86

Без системной информации
-> 45
<- 0B 01
0x0B как я уже описывал это Premission ключа.
Изображение

0x01 разберем подробнее.
MSB - LSB (справа налево).
[00000001] первые 4 бита кодируют количество ключей (всего их 14) и в данном случае версия ключа 0001 - 1 ключ.
Два последних бита описывают алгоритм, который необходимо использовать при работе с данным ключом.
00 - DES/3DES/2K3DES
01 - 3K3DES
10 - AES

Раньше я считал, что оставшиеся 5-6 биты описывают режим коммуникации и это было бы логично, но оказалось что режим коммуникации настраивается на уровне файла.

Вообще конечно если я понял все правильно, и все так, как я описываю, то мне не нравится схема определения типа ключа по первым 2 бит. Можно было бы сделать 4 типа, и тогда ситуация с алгоритмом шифрования была бы более понятна.
00 - Des/3des
01 - 2k3DES
10 - 3k3DES
11 - AES

В сухом остатке вам не будет ясно, является ли ключ на карте des/3des или это 2k3des. При этом, в случае с des/3des можно закрыть глаза на производительность используя 3DES работая с DES, но вот авторизоваться на карте 2k3des по ключу des/3des не получится, и придется производить операцию повторно.
И конечно версию ключа можно закодировать на уровне названия приложения, но root key находится всегда в приложении 00 00 00.

С другой стороны операция кодирования ключа производится раз в некий период использования карты, и в последующем ваша программа должна знать, какой тип ключа использовать.

Re: Ковыряем RFID Mifare и MFRC522

Вт ноя 28, 2017 17:08:48

Механизм нативной авторизации

-> 02 5A AA BB CC 6D B1
<- 02 00 10 2D
-> 03 0A 00 00 B7
<- 03 AF 96 F1 76 F9 8A B5 9B 67 B0 A1
CurrentKey <- 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
RND_B_RECIVED <- 96 F1 76 F9 8A B5 9B 67
RND_A <- 01 02 03 04 05 06 07 08
RND_A_DEC <- C7 65 26 59 B5 BD D7 F3
RND_B_DEC <- 62 02 F4 6E 6F 75 76 63
RND_B_ROT <- 02 F4 6E 6F 75 76 63 62
RND_B_ROT_DEC <- 2B 38 19 1B 90 D8 55 1A
-> 02 AF C7 65 26 59 B5 BD D7 F3 2B 38 19 1B 90 D8 55 1A D3 F0
<- 02 00 53 F4 CF F3 A4 8B AF 0B 25 85
RND_A_RECIVED <- 53 F4 CF F3 A4 8B AF 0B
RND_A_RECIVED_DEC <- 02 03 04 05 06 07 08 01

Но почему мой SessionKey отличается от данных выше?
SessionKey <- 00 02 02 04 62 02 F4 6E 04 06 06 08 6E 74 76 62 00 02 02 04 62 02 F4 6E

В пред идущем посте я упомянул о нулевом бите каждого байта.
"NXP рекомендует сбрасывать данный бит в 0, дабы усложнить задачу взломщику." и даже привел простейшую функцию на C, которая реализует данный механизм.

Заранее создано приложение 0xAA 0xBB 0xCC с версией ключа 0x00.
0x0A - нативная авторизация. На что карта возвращает нам RND_B 96 F1 76 F9 8A B5 9B 67
Генерируем свой (любой) RND_A или используем заранее подготовленный (не имеет значения)
RND_A <- 01 02 03 04 05 06 07 08
Теперь используя 3des (или DES, все зависит от того, какой тип ключа использует ваша карта) производим ВНИМАНИЕ DEcrypt
вашего RND_A. Да, именно ДЕ-шифровку, так как карта умеет только шифровать, но не ДЕ-шифровать.
И по логике, если вы де-шифруете данные, то карта шифруя их аналогичным ключом - получит правильные данные.
RND_A_DEC <- C7 65 26 59 B5 BD D7 F3 это де-шифрованный RND_A <- 01 02 03 04 05 06 07 08
Теперь де-шифруем RND_B полученный ранее.
Производим сдвиг влево << на 8 бит.
И производим ДЕ-шифровку в режиме CBC, где в качестве вектора используем ранее дешифрованный RND_A_DEC.
В результате на выходе у вас
RND_A_DEC <- C7 65 26 59 B5 BD D7 F3
RND_B_ROT_ENC <- 2B 38 19 1B 90 D8 55 1A
Которые необходимо отправить карте
-> 02 AF C7 65 26 59 B5 BD D7 F3 2B 38 19 1B 90 D8 55 1A D3 F0

Далее очень важно понять. Карта произведет шифрование полученных данных, и если RND_B высланный вами ранее совпадет, то карта, не зависимо от того, правильно ли вы сформировали RND_A, или не правильно, ответит вам:
<- 02 00 53 F4 CF F3 A4 8B AF 0B 25 85
00 - авторизация верна.
Но не факт, что верен RND_A, а его правильность повлияет на SessionKey, который необходимо для дешифровки дальнейших данных отправляемых карте.
Далее для проверки правильности RND_A мы его просто расшифровываем без IV-вектора.
RND_A_RECIVED <- 53 F4 CF F3 A4 8B AF 0B
RND_A_RECIVED_DEC <- 02 03 04 05 06 07 08 01
Как видите, присланный картой RND_A совпадает с нашим, за исключением того, что он сдвинут на 8 бит влево, и необходимо подвинуть на 8 бит в обратную сторону.
Мой SessionKey <- 01 02 03 04 93 68 22 50 05 06 07 08 A5 9F 78 CC 01 02 03 04 93 68 22 50
В данном случае использовался ключ 2k3des, а значит SessionKey состоит из:
Первой половины RND_A, первой половины RND_B, второй половины RND_A, второй половины RND_B
В случае с DES:
Первой половины RND_A, первой половины RND_B, опять первой половины RND_A, и опять первой половины RND_B

SessionKey всегда равен 16 байтам.

Это был правильный нативный алгоритм работы который проверен на моей карте Desfire EV1.
Где то я находил информацию о том, что данный механизм для EV1 уже устарел, и необходимо авторизовать карту иначе. Но дело в том что пока эти данные я не подтвердил но и не опроверг.

Теперь о смене ключа.
NewKey
<- 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00

DataBlocks
<- 05 00 00 00 00 00 00 00
<- 00 00 00 00 00 00 00 00
<- 45 EF 00 00 00 00 00 00

DecryptedKeyData
<- 06 26 8B 06 4A BA 55 09
<- E6 13 2C 3A 2B 89 50 C3
<- EE AB 5C 19 D4 AF D6 98
-> 02 C4 00 06 26 8B 06 4A BA 55 09 E6 13 2C 3A 2B 89 50 C3 EE AB 5C 19 D4 AF D6 98 D0 5A
<- 02 00 10 2D

Механизм простой.
Участники - SessionKey, NewKey, Три блока по 8 байт:
1 - Первая часть нового ключа
2 - Вторая часть нового ключа
3 - Два байта crc16 (нового ключа - 16 байт) + так называемый padding из 00 00 00 00 00 00, так как блоки должны быть кратными 8-ми байтам.

Далее при помощи SessionKey и первого начального вектора из 8-ми нулей, производим ДЕ-шифровку первого блока
<- 06 26 8B 06 4A BA 55 09
Затем производим ту же операцию над вторым блоком, но в качестве вектора используем первый дешифрованный блок.
<- E6 13 2C 3A 2B 89 50 C3
Аналогично, но в качестве вектора используем второй дешифрованный блок.
<- EE AB 5C 19 D4 AF D6 98

Теперь данные отправляются карте:
-> 02 C4 00 06 26 8B 06 4A BA 55 09 E6 13 2C 3A 2B 89 50 C3 EE AB 5C 19 D4 AF D6 98 D0 5A

C4 00 - изменить ключ 00.
Дешифрованная строка.
D0 5A - crc16 дешифрованной строки.
В моем случае ответ:
<- 02 00 10 2D
Ключ успешно изменен.

Еще немного о шифре.
Карта с завода шифрована восемью нулями при помощи DES (0x00).
Авторизовать ее можно просто используя SingleDES.
3DES используем только для двух или трех уникальных ключей (2k3des,3k3des).
DES, 2k3DES, 3k3DES! Три алгоритма.

Других DES алгоритмов картой не предусмотрено, хотя возможность есть.
Очевидно, не имеет смысла использовать 3des в связке с одним уникальным ключом (8 байт) понапрасну расходуя ограниченные ресурсы процессора.
Единственный резон всегда использовать 3des, только в том случае, если вы не знаете какой ключ установлен на карте, но вы то об этом знаете. 8)

Пробираюсь дальше. В следующих сериях AES, Read/Write, CMAC, тесты производительности и финал. :)

Re: Ковыряем RFID Mifare и MFRC522

Пн дек 04, 2017 20:38:29

Приветствую.
Сегодня меняем DES мастер ключ на AES.
Вообще вариантов как водится у NXP несколько, и я даже выявил один баг, не такой большой, но все же.
По всей видимости на данный момент (во всяком случае моей версии карты) данная ошибка все еще присутствует и не исправлена.

Первый вариант, это когда вы авторизовались через DES мастер ключ нативной командой 0a.
В этом случае смена ключа на AES ничем не отличается от смены DES ключа, за исключением второго байта, который указывает номер ключа.
Алгоритм следующий:

CRC16(KEY 16bytes);
Enc3des/des(KEY+CRC16+PADDING);
PADDING = до 24 байт нулями.

Пример:
KEY 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CRC 16 - 37 49
PADDING 00 00 00 00 00 00

Криптограмма:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
37 49 00 00 00 00 00 00

Шифрограмма:
74 ED 0C D7 BA 18 63 23
FF 66 1D 3F F9 6D B7 17
09 61 A9 BF D4 44 1A E3

Карте:
C4 80 74 ED 0C D7 BA 18 63 23 FF 66 1D 3F F9 6D B7 17 09 61 A9 BF D4 44 1A E3

С этого момент карта перестанет отвечать на команду 0a/1a. Теперь команда авторизации aa.

Баг первый:
Ключевая версия должна быть 80. Запрашиваем ее командой 64.
-> 64 00
<- 00 00
Видим 00. Ок, версию ключа, которую выдает команда 64 на самом деле можно сменить в мануальном режиме позже.
Запросим через 45 - ключевые параметры.

-> 5A 00 00 00
<- 00
-> 45
<- 00 0F 01
01 - DES/1 ключ.

Возможно, что новые карты не любят ни нативную авторизацию, ни нативную смену ключа. Возможно именно этим и вызван данный баг.

Сменим AES ключ на другой AES ключ.
CRC32(C4 + 80 + Ключ + 80); - 19 байт на все.
AES_CBC_128(Ключ + 80 + CRC32 + PADDING до 32 байт);
Карте C4 + 80 + AES_CBC_128 полученный ранее.
Таким образом мы поменяли AES на AES.

Криптограмма
<- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 AB 6A 55 58 00 00 00 00 00 00 00 00 00 00 00
Шифровагрмма
<- 50 D6 7D 42 AB 4B E6 A7 36 61 00 78 FB 0C 96 F0 2A B3 37 39 F3 D4 CF EB AD 10 BF D6 8B 48 BD 3F
Отправляю
-> C4 80 50 D6 7D 42 AB 4B E6 A7 36 61 00 78 FB 0C 96 F0 2A B3 37 39 F3 D4 CF EB AD 10 BF D6 8B 48 BD 3F
Отвт
<- 00

Теперь ключевая версия:
-> 64 00
<- 00 80
Но опять же
-> 45
<- 00 0F 01
Ок.

Вернуть DES/3des:
CRC32(C4 + 00 + Ключ); - 18 байт на все.
AES_CBC_128(Ключ + 00 + CRC32 + PADDING до 32 байт);
Карте C4 + 00 + AES_CBC_128 полученный ранее.

Почему в расчетах не участвует ключевая версия - не понятно. Но это еще не все.
Если подобным образом рассчитать AES ключ, (с4 80 вместо c4 00), то ключ тоже сменится, но ключевой версией будет первый байт CRC32.
Это ошибка на уровне проектирования.

Все что описано выше работает только в отношении Мастер Ключа расположенного в приложении 00 00 00. В других случаях необходимо действовать несколько иначе.
Например вы создаете новое приложение 01 00 00 с ключевой версией 81 (aes/1 ключ).
В этом случае команда смены мастер ключа приложения будет выглядеть так:

CRC32(C4 + 00 + Ключ + 80); - 19 байт на все.
AES_CBC_128(Ключ + 80 + CRC32 + PADDING до 32 байт);
Карте C4 + 00 + AES_CBC_128 полученный ранее.

Возможно это относится только лишь к нативному методу, но как видите NXP намудрил на сколько фантазия позволила :)

Re: Ковыряем RFID Mifare и MFRC522

Чт дек 07, 2017 23:34:14

Добрый вечер.
Начал разбираться с циклом антиколлизии и застрял на на первом каскаде, на отправлении SEL + NVB + CLn + CRC_A
В качестве примера взял эту программу
Код для arduino,- авторизация пока не работает, к ней я в настоящий момент подхожу.
Код:
  //Каскадный уровень 1
  Write(0x09,0x93);
  Write(0x09,0x20);
  Write(0x01,0x0c);
  Write(0x0d,0x80);
 
  //Читаем CT UID0 UID1 UID2 BCC (Первый SAK = 24)
  byte uid[] = {Read(0x89),Read(0x89),Read(0x89),Read(0x89),Read(0x89)};
 
  //Расчитываем CRC сопроцессором mfrc522 - на выходе crc[0] и crc[1]
  byte crc_1[]={0x93,0x70,uid[0],uid[1],uid[2],uid[3],uid[4]};
  GetCrc(crc_1,7);
 
  //Очищаем буффер
  Write(0x0a,0x80);
 
  //Отправляем селект 1
  Write(0x09,0x93);
  Write(0x09,0x70);
  //Добавляем к строке первую часть UID
  Write(0x09,uid[0]); // CT
  Write(0x09,uid[1]); // UID 0
  Write(0x09,uid[2]); // UID 1
  Write(0x09,uid[3]); // UID 2
  Write(0x09,uid[4]); // BCC
  //Добавляем к строке CRC
  Write(0x09,crc[0]);
  Write(0x09,crc[1]);
 
  //Отправляем карте
  Write(0x01,0x0c);
  Write(0x0d,0x80);


У меня карточка MIFARE Plus EV1 (ATQA 0x00 0x04) 4 байтный адрес, спецификации вычитал SAK можно получить за 1 каскадный уровень.
UID я получил, сделал проверку на парность, дальше я делаю:
Код:
MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, 0x93);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, 0x70);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[0]);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[1]);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[2]);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[3]);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, crcOutput[0]);
   MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, crcOutput[1]);

   MFRC522_Write(&MFRC522_Transport, MFRC522_CommandReg, 0x0c);
   MFRC522_Write(&MFRC522_Transport, MFRC522_BitFramingReg, 0x80);

// знаю что гавнокод, но таким образом я сделал задержку - ибо обработчик у меня крутится в RX прерывании
for (uint16_t i = 0; i < 0x00FF; i++) {
      for (uint8_t j = 0; j < 0x0F; j++);
   }

   USART_MySendData(USART1, MFRC522_Read(&MFRC522_Transport, MFRC522_FIFOLevelReg));


В итоге у меня FIFO буфер пустой
И немного не понял почему в вашем коде отправляется 4 байта в 1ом каскаде, если в спецификации написано что для 7-ми байтного адреса в первом каскаде приходят: каскадный тэг + 3 байта адреса + Байт парности (ISO-IEC 14443-3), а для селекта нужно отправить: SEL + NVB + UID CLn + CRC_A

Re: Ковыряем RFID Mifare и MFRC522

Пт дек 08, 2017 00:01:40

И немного не понял почему в вашем коде отправляется 4 байта в 1ом каскаде, если в спецификации написано что для 7-ми байтного адреса в первом каскаде приходят: каскадный тэг + 3 байта адреса + Байт парности (ISO-IEC 14443-3), а для селекта нужно отправить: SEL + NVB + UID CLn + CRC_A

Изображение

А, вижу, че-то не прочитал сразу. В общем REQA есть.
Что до селекта, в общем то процедура для mifare plus должна быть аналогичной для любых 4 byte UID.
-> 52 - 7 битный фрейм.
<- 04 00
-> 93 20
<- B0 42 85 7A 0D
-> 93 70 B0 42 85 7A 0D D9 4B
<- 08 B6 DD

BCC упустили?
Код:
MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[2]);
MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, uid[3]);
----------(&MFRC522_Transport, MFRC522_FIFODataReg, bcc[xxx]);
MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, crcOutput[0]);
MFRC522_Write(&MFRC522_Transport, MFRC522_FIFODataReg, crcOutput[1]);


Расчет CRC осуществляйте средствами микроконтроллера, код есть на предыдущей страничке. Там же есть хороший код под crc32 (понадобится для шифрования).
Код:
uint16_t CalcCrc16(const byte* u8_Data, int s32_Length){
    uint16_t u16_Crc = 0x6363;
    for (int i=0; i<s32_Length; i++){
        byte ch = u8_Data[i];
        ch = ch ^ (byte)u16_Crc;
        ch = ch ^ (ch << 4);
        u16_Crc = (u16_Crc >> 8) ^ ((uint16_t)ch << 8) ^ ((uint16_t)ch << 3) ^ ((uint16_t)ch >> 4);
    }
    crc16[0] = u16_Crc & 0xff;
    crc16[1] = (u16_Crc >> 8) & 0xff;
    //return u16_Crc;
}

Delay - в микросекундах и все. Значение отрегулируйте. Карта отвечает на разные запросы с регламентированной скоростью которая разнится на максимум 5 - 7 микросекунд.
Код:
for (uint16_t i = 0; i < 0x00FF; i++) {
      for (uint8_t j = 0; j < 0x0F; j++);
   }

Циклы антиколлизии карта должна проходить очень быстро (50 микросекунд вероятнее всего).
Желательно какие то логи показать. Что там куда уходит.

Карты Mifare Plus мне только идут из Китая, поэтому мне было бы интересно следить за вашим прогрессом в ее отношении.
Но надо понимать, что по плюсу информации в сети практически нет, вам вероятнее всего потребуется запросить NDA. Хотя.

Re: Ковыряем RFID Mifare и MFRC522

Пт дек 08, 2017 12:16:16

BCC упустили?
Код:
----------(&MFRC522_Transport, MFRC522_FIFODataReg, bcc[xxx]);

Я пытался и его передавать, и включая в подсчет CRC и без, очередной раз покурив ISO решил без него отправить, результат был 0.

Расчет CRC осуществляйте средствами микроконтроллера, код есть на предыдущей страничке. Там же есть хороший код под crc32 (понадобится для шифрования).

Попробую сегодня вечером, может неправильно считал аппаратно на MFRC522

Delay - в микросекундах и все. Значение отрегулируйте. Карта отвечает на разные запросы с регламентированной скоростью которая разнится на максимум 5 - 7 микросекунд.

Пытался сделать задержку средствами системного таймера, но прерывание в обработчике не выполняется, а большие циклы - виснут МК, надо будет архитектуру пересмотреть.

Спасибо за ответ, я вечером еще поковыряюсь и дам знать.

Re: Ковыряем RFID Mifare и MFRC522

Пт дек 08, 2017 13:51:18

Ваши данные антиколлизии должны иметь вид:

93 70 UID0 UID1 UID2 UID3 BCC CRC0 CRC1 (9 байт).

Если мне не изменяет память, то mfrc522 возвращает crc в обратной последовательности: попробуйте поменять местами crc0 и 1 перед отправкой.
Что до времени на передачу и таймаутов.

Есть несколько добротных вариантов выдерживать паузу между получением/отправкой данных.
1 - Делая запрос с определенным интервалом (я рекомендую 250 микросекунд) к регистрам status2reg. Но этот вариант я пока не проработал основательно, и на данный момент он мне не очень нравится. Кроме того, вряд ли он вообще правильный. Хотя.

2 - Делать запрос, с тем же интервалом но к регистру 0x8a - возвращает количество байт в буффере. Создаете функцию, вводите количество ожидаемых данных, если превышено количество n-чтений "таймаут" - false. Одна итерация длится примерно 17 микросекунд (данные не мои, так что желательно проверять).

3 - Метод основанный на двух регистрах FIFOLevelHI/LOW Reg в сочетании с выводом прерывания на IRQ PIN. Самый производительный и правильный.

Сделайте небольшой вывод в консоль - куда/что/когда.
Delay тут. http://blablacode.ru/mikrokontrollery/457 Там кстати в комментах подсказывают, что можно через HAL если что.

Re: Ковыряем RFID Mifare и MFRC522

Пт дек 08, 2017 16:10:43

Заработало, использовал вашу функцию для подсчета CRC, у меня, видимо как-то неправильно настроен MFRC, потому что после подсчета он включает таймер и у меня начинаются прерывания.
Сделал функцию задержки:
Код:
void Delay_Mks(uint16_t delayMks)
{
   uint32_t counter = (SystemCoreClock / 1000000) * delayMks;

   while (counter > 0) {
      counter--;
   }
}


и все заработало, вот лог:
-> 02 52 REQA
<- 00 04 ATQA
-> 93 20 SEL + NVB
<- 93 03 45 E5 30 UID0 + UID1 + UID2 + UID3 + BCC
-> 93 70 93 03 45 E5 30 E1 46 SEL + NVB + UID0 + UID1 + UID2 + UID3 + UID4 + BCC + CRC_A0 + CRC_A1
<- 08 B6 DD SAK CRC_A0 CRC_A1

Вот только тут мне не понятно что за CRC пришел вместе с SAK кодом, мою подсчитанный CRC не совпадает с ним

Re: Ковыряем RFID Mifare и MFRC522

Пт дек 08, 2017 16:29:25

Заработало, использовал вашу функцию для подсчета CRC, у меня, видимо как-то неправильно настроен MFRC

После расчета CRC процессором MFRC,- необходимо отправлять команду IDLE перед дальнейшей отправкой чего либо в буффер. Вероятнее всего проблема в этом. Но смысла в расчете crc сопроцессором нет, особенно в случае с STM32.

Re: Ковыряем RFID Mifare и MFRC522

Сб дек 09, 2017 20:52:16

CMAC.
https://www.nxp.com/docs/en/application ... N10922.pdf
http://nvlpubs.nist.gov/nistpubs/Legacy ... 00-38b.pdf
http://www.ietf.org/rfc/rfc4493.txt

AES128
Данные
<- BD 04 00 00 00 08 00 00
Данные с паддингом
<- BD 04 00 00 00 08 00 00 80 00 00 00 00 00 00 00
Ключ сессии
<- 00 01 02 03 16 96 E3 11 0C 0D 0E 0F 4D FE 0D EF
Исходник ключа_0
<- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Ключ_0
<- DB D8 E1 FA BB FC C9 7E 52 9D 72 96 2A 11 2B 97
Ключ_1
<- B7 B1 C3 F5 77 F9 92 FC A5 3A E5 2C 54 22 57 A9
Ключ_2
<- 6F 63 87 EA EF F3 25 F9 4A 75 CA 58 A8 44 AF D5
Дата
<- BD 04 00 00 00 08 00 00 80 00 00 00 00 00 00 00
CMAC
<- 72 53 95 61 06 83 92 11 DA E2 2A FD C2 09 64 5F
Шифрограмма - Новый IV
<- 60 AE 97 FA A2 BD D3 6D F9 91 AD B0 E4 77 8E 5B
Криптограмма
<- 11 11 11 11 00 00 00 00 92 CA 7F 1B 00 00 00 00
Вторая часть шифрограммы
<- 1A B0 CF BB 47 70 55 F3 E6 5D 92 6D 62 2D 73 46
XOR - Вторая часть шифрограммы @ Новый IV
<- DD AA 97 FA A2 B5 D3 6D 79 91 AD B0 E4 77 8E 5B
CMAC
<- 27 18 23 21 AA 53 98 23 5B 6A B0 54 E2 83 3D 08
Криптограмма
<- 11 11 11 11 00 00 00 00 92 CA 7F 1B 00 00 00 00

Как калькулировать CMAC я выкладывал на stack, можете глянуть последний ответ тут https://stackoverflow.com/questions/205 ... 2#47697182
Все алгоритмы работы со CMAC открыты NXP.
Но здесь приведу полную версию, так как выложенные данные на стаке всего лишь часть сути вопроса.

1 - Шифруем AES_128_ECB(ключом сессии(Исходник ключа_0));
2 - Проверяем ключ_0[0] бит MSB == 1. (7 бит [1/0 0 0 0 0 0 0 0])
3 - Смещаем весь ключ_0 << 1 на один бит.
4 - Если MSB бит ключа_0[0] был == 1, то ключ_0[15] ^ 0x87
5 - Результатом является ключ_1.
6 - Проверяем ключ_1[0] бит MSB == 1.
7 - Смещаем весь ключ_1 << 1 на один бит.
8 - Если MSB бит ключа_1[0] был == 1, то ключ_1[15] ^ 0x87
9 - Результатом является ключ_2.
10 - AES_128_CBC(Данные с паддингом, IV=ключ_2);
11 - Результат = CMAC
12 - После отправки данных карте, и получении ответа.
13 - Ответом является Шифрограмма, он же, новый IV для последующих итераций.
14 - Дешифровка ответа, в качестве вектора - CMAC: AES_128_CBC_DECRYPT(Шифрограмма, IV = CMAC);

Как вычислить следующий CMAC.
15 - CMAC = AES_128_CBC_ENCRYPT(Вторая часть шифрограммы ^ Новый IV, IV=ключ_2);
Результатом является новый CMAC прменив который в качестве IV можно дешифровать следующее сообщение карты.
16 - Дешифровка ответа, в качестве вектора - CMAC: AES_128_CBC_DECRYPT(Шифрограмма, IV = CMAC);

И так до последней итерации. В общем все просто.
Если ваши данные отправляемые карте равны 16 байтам, то в качестве IV требуется использовать ключ_1 на 10-ом шаге.

Вообще в доке NXP есть вот такая сноска:
"If the length of M is more than 15 bytes, standard CMAC algorithm can be used, without taking care of padding, XOR-ing and encryption. The message for standard CMAC is then the data of step 9."
Пункт 9 вышеназванного раздел содержит:
"Div constant is fixed, must be 0x01 for AES 128 keys."
Однако, так как я новичок в этом деле, то пока не работал над данной темой. Надо проверить на практике.

ФИНАЛ! :)
Делитесь информацией, это важно для улучшения мира!

Шиффтинг << на C:
void ShiftLeft(byte * data, byte cnt){
bool i = false;
if ((data[0] & 0x80)){
i = true;
}
for (int i=0;i<cnt-1;i++){
data[i]=((data[i]<<1) | ((data[i+1]>>7)&0x01));
}
data[cnt-1] <<= 1;
if (i){
data[cnt-1] ^= 0x87;
}
}

Re: Ковыряем RFID Mifare и MFRC522

Пн дек 11, 2017 18:28:46

Как оказалось Mifare classic 1k оказалась не совместима со стандартом ISO/IEC 14443-4
Поэтому руководствовался вот этой докой: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf

Авторизацию я прошел
Код:
uint8_t authData[] = {
         0x60, // команда авторизации с помощью ключа А
         0x01, // адрес Блока
         0xFF, // 1 байт ключа А
         0xFF, // 2 байт ключа А
         0xFF, // 3 байт ключа А
         0xFF, // 4 байт ключа А
         0xFF, // 5 байт ключа А
         0xFF, // 6 байт ключа А
         uid[0], // UID карты
         uid[1],
         uid[2],
         uid[3]
   };
MFRC522_SendToCard(&MFRC522_Transport, PCD_AUTHENT, authData, 12, 0, 0)


после успешной авторизации устанавливается бит MFCrypto1On в Status2Reg регистре
и дальше можно выполнять операции с блоками (читать, писать, инкремент, декремент...)

Но у меня почему-то не получилось считать блок, вместо 16 байт возвращается всего 12:
Код:
crcSourceData[0] = 0x30;
   crcSourceData[1] = 0x01;
   CalcCrc16(crcSourceData, crcResultSoft, 2);
   uint8_t readAddress[] = {
         0x30,
         0x01,
         crcResultSoft[0],
         crcResultSoft[1]
   };
   uint8_t readedData[64] = {0x00};
   uint8_t readedLength = 0x00;
   MFRC522_SendToCard(&MFRC522_Transport, PCD_TRANSCEIVE, readAddress, 4, readedData, &readedLength);
// readedLength = 12


UPD:
Пардонте, 12h = 18dec, все сходится! )))

Re: Ковыряем RFID Mifare и MFRC522

Вт дек 12, 2017 23:07:09

Как оказалось Mifare classic 1k оказалась не совместима со стандартом ISO/IEC 14443-4

UPD:
Пардонте, 12h = 18dec, все сходится! )))


Вы не планируете использование Plus в sl3 режиме?

Re: Ковыряем RFID Mifare и MFRC522

Ср дек 13, 2017 10:59:36

Вы не планируете использование Plus в sl3 режиме?


А где за него почитать?

Re: Ковыряем RFID Mifare и MFRC522

Ср дек 13, 2017 13:30:24

Вы не планируете использование Plus в sl3 режиме?


А где за него почитать?


По Mifare Plus информации нет в сети в принципе. Даже libfreefare не содержит ни строчки кода Mifare Plus. Вам необходимо обратиться за NDA к NXP, после чего вы сможете получить доступ в закрытый раздел DocStore, но подписав этот пакет документов, вы более не сможете обсуждать техническую сторону вопроса на форумах и других ресурсах - даже форумах NXP.

SL3 - это Security Level 3 режим, ради которого Mifare Plus и затевалась.
Как вы знаете, карты с Crypto1 копируются за 10 секунд, через карман на пример, а если в рюкзаке большая антенна с хорошим источником питания то на расстоянии 2 метров не проблема. Crypto1 в общем не актуален.

Если перевести структуру памяти в SL3 режим, то она будет работать поверх AES128, которую невозможно взломать даже при помощи суперкомпьютеров.

Еще есть Desfire в режимах работы des/3des/2k3des/3k3des/AES128, и опять же - AES128 более эффективен и по скорости (до 10 раз по моим замерам), и по стойкости.

Вы с RFID в качестве хобби работаете, или решили реализовать какую то задумку коммерческую? Если последнее, или скажем решили себе замок сделать на входную дверь, то только SL3.

Еще если вы хотите вне хобби работать, то можете закупить Desfire ev1.
Но мне лично интересней поработать с Mifare Plus - карта стоит дешевле.
AES128 - очень быстрая работа на AVR.
Простая структура памяти.

Re: Ковыряем RFID Mifare и MFRC522

Ср дек 13, 2017 14:04:33

Вы с RFID в качестве хобби работаете...

Да, я web программист, а программирование на MCU это пока что мое хобби, изначально хотел построить систему типа
RFID + STM32 + (ESP | SIM900) + NodeJs
Дальше в планах было разбираться с ESP

Но теперь мне интересно и за SL3

Re: Ковыряем RFID Mifare и MFRC522

Чт дек 14, 2017 01:54:52

Вы с RFID в качестве хобби работаете...

Да, я web программист, а программирование на MCU это пока что мое хобби, изначально хотел построить систему типа
RFID + STM32 + (ESP | SIM900) + NodeJs
Дальше в планах было разбираться с ESP

Но теперь мне интересно и за SL3

SL3 только через закрытую документацию. Регистрируйтесь в доксторе, затем выбирайте любого локального дистрибьютора https://www.nxp.com/support/sample-buy/ ... FEDERATION
Просите как индивидуальный разработчик NDA.

Re: Ковыряем RFID Mifare и MFRC522

Чт дек 14, 2017 06:12:23

Потом поделитесь?

Re: Ковыряем RFID Mifare и MFRC522

Чт дек 14, 2017 13:49:48

Потом поделитесь?

Нарушать данное обещание не лучший способ существования.
Да и зачем, когда вы сами можете подписать данное соглашение и получить доступ к огромным архивам NXP. Там есть абсолютно все. Правда, я вот до сих пор не получил NDA, не смотря на то что мне его подтвердили.
NDA разрешается получать абсолютно всем, включая индивидуальных разработчиков.

Re: Ковыряем RFID Mifare и MFRC522

Ср дек 20, 2017 16:19:04

Все же требуется вернуться к вопросу о CMAC так как информации недостаточно.

Вот несколько примеров того, почему CMAC требует большего внимания.

Если мы читаем зашифрованные данные, то последние 16 байт вероятнее всего являются актуализированными IV который в дальнейшем используется для актуализации CMAC.

Грубо говоря: я читаю 16 байт данных с карты, которые ранее были закодированы.
Теперь для генерации следующего CMAC прочитанные данные являются IV вектором.

То-есть. Я беру прочитанные кодированные данный (16 байт), произвожу XOR со следующей отправляемой карте командой, и уже затем калькулирую CMAC получаемой строки при помощи KEY_2.

А для декодирования этих данных требуется использовать ранее полученный CMAC. Нехило так заморочились.

Однако, если мы получаем обычные данные (на пример результат работы команды 5f (список файлов)) то ответ не будет являться IV для расчета CMAC!
Более того, над обычными ответами требуется производить смещение на 8 бит влево, и уже затем калькулировать актуальный CMAC.

Позже выложу актуальные логи, так как данная задача все еще в работе.

Генерация происходит по схемы описанной выше на три или сколько то там постов.
Key_0
<- 93 F2 9E C5 BD F3 69 4D 2E 01 AD 6D 82 FC 5B 99
Key_1
<- 27 E5 3D 8B 7B E6 D2 9A 5C 03 5A DB 05 F8 B7 B5
Key_2
<- 4F CA 7B 16 F7 CD A5 34 B8 06 B5 B6 0B F1 6F 6A
IV
<- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
XOR Data @ new iv
<- BD 01 00 00 00 0C 00 00 80 00 00 00 00 00 00 00
CMAC
<- 1E 23 29 2A 72 FF F1 2A C6 A7 13 F5 27 97 FA 38
-> 03 BD 01 00 00 00 0C 00 00 4A EE
<- 03 00 31 C0 29 EB D5 20 C0 E0 F7 D0 F1 20 D1 A2 0F 47 A3 2E
IV
<- 31 C0 29 EB D5 20 C0 E0 F7 D0 F1 20 D1 A2 0F 47
Decrypted Answer
<- 01 02 03 04 05 06 07 08 09 10 11 12 4D 44 3A CC
IV
<- 31 C0 29 EB D5 20 C0 E0 F7 D0 F1 20 D1 A2 0F 47
XOR Data @ new iv
<- 8C C1 29 EB D5 2C C0 E0 77 D0 F1 20 D1 A2 0F 47
CMAC
<- 06 5A 46 36 AF 95 E1 0C FA A0 7A 61 23 1B BB A2
-> 02 BD 01 00 00 00 0C 00 00 B7 A3
<- 02 00 DA 3D 93 1A 86 81 2F 5F DC 4B B8 B6 9E B7 DB 96 BF EE
IV
<- DA 3D 93 1A 86 81 2F 5F DC 4B B8 B6 9E B7 DB 96
Decrypted Answer
<- 01 02 03 04 05 06 07 08 09 10 11 12 4D 44 3A CC
Command
<- 3D 01 00 00 00 10 00 00
Data + CRC32 + PADDING
<- 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 5E FB 61 CC 00 00 00 00 00 00 00 00 00 00 00 00
Encripted_data(Data + CRC32 + PADDING
<- 41 C0 B1 7D 96 8F 56 66 CD 5B F9 73 BF D4 E8 58 16 77 0E 10 88 DF 67 DC 8B 3B 2B C4 46 B1 B7 B0
Command + encrypted_data
<- 3D 01 00 00 00 10 00 00 41 C0 B1 7D 96 8F 56 66 CD 5B F9 73 BF D4 E8 58 16 77 0E 10 88 DF 67 DC 8B 3B 2B C4 46 B1 B7 B0
Sending
-> 03 3D 01 00 00 00 10 00 00 41 C0 B1 7D 96 8F 56 66 CD 5B F9 73 BF D4 E8 58 16 77 0E 10 88 DF 67 DC 8B 3B 2B C4 46 B1 B7 B0 C5 94
<- 03 00 89 3F C7 44 10 DA CA 25 FD 1B

Как видно, над первыми двумя командами калькуляция CMAC осуществляется верно, об этом свидетельствует вторая итерация.
Однако, он не отрабатывает над командой записи. И тому есть несколько причин.
Над этими причинами я в настоящий момент и работа.

Так же, это странно, однако https://www.nxp.com/docs/en/application ... N10922.pdf говорит о неком DIV ввиду 0x01 перед каждым блоком.
Я до текущего момент высчитывал и высчитываю CMAC без него. Высчитывается. Что я делаю не так? Вероятно, без div высчитываются блоки по 16 байт, тогда почему об этом нет ни слова в этой доке?
Ну и все в таком духе. Или актуальность данного документа утрачена, или я чего то еще не знаю.

Без зарытой документации приходится работать по сути на ощупь. Просто догадываясь о том или ином алгоритме.

Re: Ковыряем RFID Mifare и MFRC522

Вс дек 24, 2017 15:57:02

Вы с RFID в качестве хобби работаете...

Да, я web программист, а программирование на MCU это пока что мое хобби, изначально хотел построить систему типа
RFID + STM32 + (ESP | SIM900) + NodeJs
Дальше в планах было разбираться с ESP

Но теперь мне интересно и за SL3

Кстати, можете использовать Desfire EV1. Карта стоит где то 120 рублей в среднем. https://github.com/barkow/stm32-rfid/bl ... esfire.cpp для stm32.
Там не реализованы функции записи в криптографическом режиме (как впрочем и чтения), но библиотека может быть вам полезна для использования совместно с STM32.
Так же не реализованы данные функции в https://www.codeproject.com/Articles/10 ... ery-Backup этом проекте, что странно, так как в их основе используются такие библиотеки как libfreefare где данные функции реализованы (хотя не факт).
Во всяком случае как добавить криптографию можете понять прочитав мои посты.

Я сейчас прохожу процесс получения NDA, могу сразу сказать - к московским компаниям можете не обращаться - сплошной пафос у москвичей. Советую обращаться к маленьким компаниям, не имеющих ничего общего с корпоративным сегментом. Я лично обратился к белорусской компании, вернее двум, и сразу же получил во первых человеческое отношение к себе (от обоих компаний), а во вторых, по сути, требования с их стороны ограничивались ровно таким же требованиями, которыми руководствовался сам NXP.
Ответить