AtmelATAES132 Mac поколения

Я пытаюсь подтвердить подлинность против Atmel ATAES132 Crypto Chip из приложения C ++. Для вычисления MAC я хочу использовать библиотеку Crypto ++. Чип использует AES CCM для вычисления MAC, который сравнивается с MAC, который я должен вычислять в программном обеспечении.

Генерирование MAC описывается в таблице данных как шифрование 128-битного блока данных (B0) в режиме CBC, XOR его с использованием 128-битных данных только для аутентификации и XORing результата с помощью другого 128-битного блока данных (A0), зашифрованного в режиме AES CTR.

Что я делаю, так это:

string macB0string;

macB0string.append("\x79", 1);
macB0string.append(nonceString);
macB0string.append("\x01\x00\x00", 3);

// Authentication Only Data
byte aa[] = {
0x00, 0x0E, 0x00, 0xEE, 0x03, 0x01, 0x00, 0x01, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};

string input, output;

input.append(macB0string);

byte zeroIV[16];
memset(zeroIV, 0, sizeof(zeroIV));

CBC_Mode< AES >::Encryption cbc;
cbc.SetKeyWithIV(key, sizeof(key), zeroIV);StringSource(input, true,
new StreamTransformationFilter(cbc,
new StringSink(output),
StreamTransformationFilter::NO_PADDING
)
);

// Encrypt aa with same key and previous computed cipher as IV
// This is our cleartext MAC
CBC_Mode< AES >::Encryption cbc2;
cbc2.SetKeyWithIV(key, sizeof(key), (byte*)output.c_str());

string output2;
StringSource(string((const char*)aa, sizeof(aa)), true,
new StreamTransformationFilter(cbc2,
new StringSink(output2),
StreamTransformationFilter::NO_PADDING
)
);

string macA0;

macA0.append("\0x01", 1);
macA0.append(nonceString);
macA0.append("\0x01\0x00\x00", 3);// Encrypt cleartext MAC
CTR_Mode< AES >::Encryption ctr;
ctr.SetKeyWithIV(key, sizeof(key), (byte*)macA0.c_str());

string MAC;

StringSource(output2, true,
new StreamTransformationFilter(ctr,
new StringSink(MAC)
)
);

Это именно то, что объясняется в таблице данных на стр. 112. Но попытка аутентификации с помощью синхронизированного MAC не удалась.
Я использовал заполненный нулями IV в первом шифровании CBC, потому что я понял, что CCM похож на CBC-MAC с нулевым IV плюс шифрование CTR.

Если бы кто-то с опытом работы с ATAES132 мог указать мне правильное направление, что идет не так, я был бы очень благодарен.

РЕДАКТИРОВАТЬ

Так описывается процесс CCM в техническом описании.

В следующем примере показано, как рассчитывается MAC-адрес целостности для операции аутентификации, требующей до 14 байтов данных только для аутентификации. Эта операция включает три прохода через криптографический движок AES; все три используют один и тот же ключ. Если существует более 14 байтов данных только для аутентификации, то требуется еще один проход через криптографический механизм AES.

Существует два прохода через крипто-механизм AES в режиме CBC для создания открытого текста MAC. Входы в крипто-механизм для этих блоков обозначены как B0 и B1, а выходы — B’0 и B’1 соответственно.

  • B0 состоит из следующих 128 битов:
    • 1-байтовый флаг, фиксированное значение b0111 1001.
    • 12-байтовый Nonce, генерируемый командой Nonce.
    • 1 байт MacCount, 1 для первого поколения MAC.
    • Поле длиной 2 байта, всегда 0x00 00 только для аутентификации.
  • B1 — это XOR B’0 со следующими 128 битами:
    • 2-байтовое поле длины, размер данных только для аутентификации.
    • Только 14-байтовые данные для аутентификации.
  • B’1 — это текстовый MAC, который должен быть зашифрован перед отправкой в ​​систему.

Существует один дополнительный проход через крипто-механизм AES в режиме CTR для создания блока ключей, который используется для шифрования MAC.
Вход в крипто-движок для этого блока помечен как A0, а выход — как A’0. A’0 — это MAC, отправленный в систему в качестве выходного параметра команды Auth.

  • A0 состоит из следующих 128 битов:
    • 1 байт флаг — фиксированное значение b0000 0001.
    • 12-байтовый Nonce — генерируется ATAES132 во время команды Nonce.
    • 1 байт MacCount — один для первого поколения MAC.
    • Поле счетчика 2 байта — всегда 0x00 00 для A0.
  • «0» — это «XOR» с открытым текстом «MAC» («В1») и отправка в систему.

И это код, который я пытался

byte key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F
}; // Testkey Set in Chip as KeyID 1

byte nonce[] = {
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
};

byte crc[2];

string nonceCommand;

nonceCommand.append("\x01", 1); // Opcode
nonceCommand.append("\x00", 1); // Mode: 00 = Set Nonce
nonceCommand.append("\x00\x00\x00\x00", 4); // 4 Bytes Zero
nonceCommand.append( string((const char*)nonce, sizeof(nonce)) );

char count = nonceCommand.length() + 3; // length + 1byte count and 2bytes
//  crc

nonceCommand.insert(0, &count, 1);
CalcCRC(nonceCommand.length(), (byte*)nonceCommand.c_str(), crc);
nonceCommand.append( string((const char*)crc, sizeof(crc)) );// SNIP
// Send SetNonceCommand and read response
// SNIP

string B0;
B0.append("\x79", 1); // FixedValue
B0.append( string((const char*)nonce, sizeof(nonce)) );
B0.append("\x01", 1); // MAC Count, 1 for first generation
B0.append("\x00\x00", 2); // 2 byte length field

string AA;
AA.append("\x00\xEE", 2); // Manufacturing ID
AA.append("\x03", 1); // Opcode
AA.append("\x02", 1); // Outbound authentication (we receive a MAC)
AA.append("\x00\x01", 2); // Key ID
AA.append("\x00\x07", 2); // Usage
AA.append("\x01", 1); // Mac Flag (1 for first generation)
AA.append("\x00\x00\x00\x00", 4); // 4 Bytes Zero
AA.append("\x00", 1); // 1 Byte padding

count = AA.length();
AA.insert(0, &count, 1);
AA.insert(0, "\x00", 1);

// CCM
const int TAG_SIZE = 16;
CCM< AES, TAG_SIZE >::Encryption ccm;
ccm.SetKeyWithIV(key, sizeof(key), nonce, sizeof(nonce));
ccm.SpecifyDataLengths(AA.length(), B0.length(), 0);

string cipher;
AuthenticatedEncryptionFilter ef(ccm,
new StringSink(cipher)
);

ef.ChannelPut(AAD_CHANNEL, (byte*)AA.c_str(), AA.length());
ef.ChannelMessageEnd(AAD_CHANNEL);

ef.ChannelPut(DEFAULT_CHANNEL, (byte*)B0.c_str(), B0.length());
ef.ChannelMessageEnd(DEFAULT_CHANNEL);

string enc = cipher.substr(0, cipher.length() - TAG_SIZE);
string tag = cipher.substr(cipher.length() - TAG_SIZE);

// Get Outbound MAC from IC
string authCommand;
authCommand.append("\x03", 1); // Opcode
authCommand.append("\x02", 1); // Mode Outbound only
authCommand.append("\x00\x01", 2); // KeyID
authCommand.append("\x00\x07", 2); // Usage

count = authCommand.length() + 3;
authCommand.insert(0, &count, 1);
CalcCRC(authCommand.length(), (byte*)authCommand.c_str(), crc);
authCommand.append( string((const char*)crc, sizeof(crc)) );

// SNIP
// Send Outbound Authentication Command to IC and receive response
// SNIP

Это приводит к

enc:    96 01 a1 0d ef 1e 5f f6 5f 9d 91 7e 80 25 71 a4
tag:    71 2b a3 6a 7c 35 49 63 46 4c 58 0e a9 4a 2c 5e

Но IC отправляет аутентификационный MAC

ea c1 fd 60 9f 93 89 87 63 8f 9a df ee 17 85 bb

Я не совсем понимаю, какие правильные входные параметры для режима CCM приведены в описании из таблицы

3

Решение

Я узнал, как использовать Crypto ++ AES CCM для вычисления MAC для ATAES132.
В техническом описании описывается AES CCM, но он уже рассчитан для алгоритма CCM. Вы не можете просто вставить это в функцию CCM.

Если вы хотите использовать Crypto ++ CCM Mode для вычисления MAC, сделайте следующее:

// Compute a 12 Byte Nonce as described in the datasheet
// Get the ManufacturingID from the IC

string iv = string((const char*)nonce, sizeof(nonce));
iv.append( MACCount ); // MAC Count is part of the IV giving it a size of 13

string authOnly, empty, cipher;

authOnly.append("\x00\xEE", 2); // Manufacturing ID
authOnly.append("\x03", 1); // Opcode
authOnly.append("\x02", 1); // Outbound authentication (we receive a MAC)
authOnly.append("\x00\x01", 2); // Key ID
authOnly.append("\x00\x07", 2); // Usage
authOnly.append("\x01", 1); // Mac Flag !!!NOT MACCOUNT!!!
authOnly.append("\x00\x00\x00\x00", 4); // 4 Bytes Zero
authOnly.append("\x00", 1); // 1 Byte padding

CCM< AES, 16 >::Enryption ccm;
ccm.SetKeyWithIV(key, sizeof(key), (byte*)iv.c_str(), iv.length());

ccm.SpecifyDataLengths(authOnly.length(), empty.length(), 0); // empty is an empty string
AuthenticatedEncryptionFilter ef(ccm,
new StringSink(cipher)
);

ef.ChannelPut(AAD_CHANNEL, (byte*)authOnly.c_str(), authOnly.length());
ef.ChannelMessageEnd(AAD_CHANNEL);

ef.ChannelPut(DEFAULT_CHANNEL, (byte*)empty.c_str(), empty.length());
ef.ChannelMessageEnd(DEFAULT_CHANNEL);

string tag = cipher.substr( cipher.length() - TAG_SIZE);

Теперь у вас должен быть тот же 16-байтовый MAC, который вычислял IC.

3

Другие решения

Я не знаю, какой именно чип Atmel, но я знаю, что Crypto ++ содержит режим шифрования CCM. Ты конечно вам нужно реализовать это самостоятельно?

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector