AtmelATAES132 Поколение Mac

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

Генерация MAC описана в таблице данных как шифрование 128-битного блока данных (B0) в режиме CBC, операция XOR с 128-битными данными только для аутентификации и операция XOR результата с другим 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 is composed of the following 128 bits:
    • 1 byte flag, a fixed value of b0111 1001.
    • 12-байтовый одноразовый номер, сгенерированный командой Nonce.
    • 1 байт MacCount, 1 для первого поколения MAC.
    • Поле длиной 2 байта, всегда 0x00 00 только для аутентификации.
  • B1 is the XOR of B’0 with the following 128 bits:
    • 2 byte length field, size of authenticate-only data.
    • Только 14-байтовые данные для аутентификации.
  • B’1 — это открытый MAC-адрес, который необходимо зашифровать перед отправкой в ​​систему.

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

  • A0 is composed of the following 128 bits:
    • 1 byte flag – fixed value of b0000 0001.
    • 12-байтовый одноразовый номер — сгенерированный ATAES132 во время команды Nonce.
    • 1 байт MacCount – один для первого поколения MAC.
    • 2-байтовое поле счетчика — всегда 0x00 00 для A0.
  • A’0 подвергается операции XOR с открытым текстом MAC (B’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 даются в описании из даташита


person Lamp    schedule 17.07.2014    source источник
comment
В описании спецификации четко указано, что есть два прохода с AES/CBC и один проход с AES/CTR. В спецификации не упоминается режим CCM. Почему вы используете режим CCM?   -  person jww    schedule 24.07.2014
comment
В описании упоминается, что используется шифрование/дешифрование AES-CCM. AES-CCM — это использование двух проходов в режиме CBC и одного прохода в режиме CTR. Однако я обнаружил ошибку при использовании режима CCM, и теперь он работает. В ближайшее время напишу ответ.   -  person Lamp    schedule 25.07.2014
comment
У вас получилось? можешь поделиться кодом?   -  person Muhammad    schedule 25.09.2020


Ответы (2)


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

Если вы хотите использовать режим Crypto++ CCM для вычисления 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.

person Lamp    schedule 25.07.2014

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

person Maarten Bodewes    schedule 17.07.2014
comment
Я знаю, что в Crypto++ есть режим CCM. Но из описания в даташите микросхемы мне непонятно какое значение должно быть у ИВ. Все блоки данных, указанные в таблице данных, имеют длину 128 бит, а CCM принимает только IV размером не более 12 байт. - person Lamp; 17.07.2014
comment
IV да, но он создает блок из того, что содержит длину и т. д. Возможно, этот блок указан/используется? - person Maarten Bodewes; 17.07.2014
comment
Входной блок для режима CTR содержит 12-байтовый одноразовый номер. Я попробовал это одноразовое значение в качестве IV для режима CCM, но аутентификация все еще не прошла. Возможно, Atmel строит CCM нестандартным способом... Придется продолжать играть с входными параметрами. - person Lamp; 17.07.2014
comment
Параметры CCM сложны, но поскольку у меня нет доступа к единой системе обмена сообщениями Atmel, я даже не знаю, с чего начать. Может быть, покажите, что вы пробовали в CCM, с описанием ожидаемого результата... И убедитесь, что вы, конечно, используете правильные ключи и тестируете ключи на SO :) - person Maarten Bodewes; 17.07.2014
comment
Да, я попробую это завтра. Спасибо за ваш вклад :) - person Lamp; 17.07.2014