<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AES CCM encryption by S132 timeslot API</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/28524/aes-ccm-encryption-by-s132-timeslot-api</link><description>Hi, 
 I have tested AES-CCM of nRF52832 with reference to the following answered questions. 
 devzone.nordicsemi.com/.../ 
 devzone.nordicsemi.com/.../ 
 devzone.nordicsemi.com/.../ 
 I have confirmed that the NIST example would produce correct results</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 21 Jun 2018 16:11:30 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/28524/aes-ccm-encryption-by-s132-timeslot-api" /><item><title>RE: AES CCM encryption by S132 timeslot API</title><link>https://devzone.nordicsemi.com/thread/137155?ContentTypeID=1</link><pubDate>Thu, 21 Jun 2018 16:11:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:947deb2a-d6dc-4a23-b8aa-12ee97290cad</guid><dc:creator>matthewbeckler</dc:creator><description>&lt;p&gt;Hello, I too am trying to use the nRF51 AES CCM hardware &amp;quot;manually&amp;quot; (that is, not using the BLE soft-device, not even in a BLE context at all, but for securing communications via a different communications medium). I have run into the same issue of matching-ciphertext but differing MIC. I have finally figured this out, specifically how to decrypt and authenticate data that is encrypted by the nRF AES CCM hardware, using software crypto libraries on my computer.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve determined that the nRF AES CCM hardware is not a generic AES CCM device, but instead is targeting the BLE way of using AES CCM. Specifically, the &amp;quot;formatting function&amp;quot; that is used to generate blocks b_0, b_1, ... for the MIC calculation is not part of the CCM specification, but instead specified by the BLE spec (Core v5.0: Vol 6: Part E: Section 2: &amp;quot;CCM&amp;quot;). To correctly compute the MIC using software crypto libraries, it is necessary to use one byte of &amp;quot;adata&amp;quot; or &amp;quot;additional data&amp;quot;. The BLE spec says that byte is used as the third byte of the block b_1 (Table 2.3 in the section mentioned before), and must be equal to the &amp;quot;data channel PDU header&amp;#39;s first octet with NESN, SN and MD bits masked to 0&amp;quot;. Since I&amp;#39;m not using bluetooth, I was puzzled about how this byte is determined by the nRF AES CCM hardware and used in the MIC calculation. I&amp;#39;ve now determined that it is simply the first byte of the unencrypted packet you point to with NRF_CCM-&amp;gt;INPTR, but masked with 0xE3 (to zero the NESN, SN, and MD bits).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Here&amp;#39;s my sample code for the above test values (nRF51 side):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;typedef struct aesCcmData_struct { 
  uint8_t key[16];
  uint8_t packetCounter[5]; // top bit ignored
  uint8_t reserved[3];
  uint8_t directionBit; // bit 0 = direction bit
  uuint8_t iv[8];
} aesCcmData_s;

aesCcmData_s ccmData = {
  key = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 
  packetCounter = {0,0,0,0,0}, 
  reserved = {0}, 
  directionBit = 0, 
  iv = {2,2,2,2,2,2,2,2}, 
};

uint8_t pktInput[] = {
  0, // header - THIS DETERMINES THE BYTE OF ADATA YOU MUST ADD TO YOUR SOFTWARE DECRYPTION/VERIFICTION CODE
  16, // length
  0, // RFU
  // here are the 16 payload bytes:
  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
};
uint8_t pktOutput[4 + sizeof(pktInput)] = {0};
uint8_t scratch[16 + sizeof(pktOutput)] = {0}; // apparently this should be 16 + maxpacketlength?

NRF_CCM-&amp;gt;ENABLE = 2; // Enable CCM 
NRF_CCM-&amp;gt;SHORTS = 1; // Enable shortcut between ENDKSGEN and CRYPT 
NRF_CCM-&amp;gt;MODE = 0; // ENcrypt 
NRF_CCM-&amp;gt;CNFPTR = (uintptr_t) ccmData; 
NRF_CCM-&amp;gt;INPTR = (uintptr_t) pktInput; 
NRF_CCM-&amp;gt;OUTPTR = (uintptr_t) pktOutput; 
NRF_CCM-&amp;gt;SCRATCHPTR = (uintptr_t) scratch;

NRF_CCM-&amp;gt;EVENTS_ENDKSGEN = 0;
NRF_CCM-&amp;gt;EVENTS_ENDCRYPT = 0;
NRF_CCM-&amp;gt;EVENTS_ERROR = 0;
NRF_CCM-&amp;gt;TASKS_KSGEN = 1;

while (!(NRF_CCM-&amp;gt;EVENTS_ENDCRYPT || NRF_CCM-&amp;gt;EVENTS_ERROR)) {
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After the CCM hardware runs, our buffers have these contents:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;ccmData:   01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 02 02 02 02 02 02 02 02
pktInput:  00 10 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 00 00 00 00 00 00 00
pktOutput: 00 14 00 0D AF 4B 8E 52 50 3A 6E 91 F4 D8 34 26 9B 4E 74 6D DA 11 AD 00 00 00 00 00 00 00 00&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We can see that the output packet has chipertext bytes [0D AF ...&amp;nbsp;&lt;span&gt;4E 74] and&amp;nbsp;MAC bytes [6D DA 11 AD] (which match the nRF test data above).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Now we go to do the same operation on the computer in software. I&amp;#39;m using Python and the Cryptodome library. Here&amp;#39;s the code to correctly compute the MAC:&lt;br /&gt;&lt;pre class="ui-code" data-mode="python"&gt;#!/usr/bin/env python

from Cryptodome.Cipher import AES
import binascii

hdr_byte = 0x00 # THIS BYTE MUST MATCH THE FIRST BYTE OF THE nRF INPUT PACKET (&amp;amp; with 0xE3 of course)
hdr = binascii.a2b_hex(&amp;#39;%02X&amp;#39; % (hdr_byte &amp;amp; 0xE3))
plaintext = &amp;#39;\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f&amp;#39;
key = &amp;#39;\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01&amp;#39;
nonce = &amp;#39;\x00\x00\x00\x00\x00\x02\x02\x02\x02\x02\x02\x02\x02&amp;#39;
print &amp;quot;key:   &amp;quot;, repr(binascii.b2a_hex(key))
print &amp;quot;nonce: &amp;quot;, repr(binascii.b2a_hex(nonce))
print &amp;quot;plain: &amp;quot;, repr(binascii.b2a_hex(plaintext))

cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=4, assoc_len=len(hdr))
cipher.update(hdr)
ciphertext = cipher.encrypt(plaintext)
mac = cipher.digest()
print &amp;quot;cipher:&amp;quot;, repr(binascii.b2a_hex(ciphertext))
print &amp;quot;&amp;quot;
print &amp;quot;mac:   &amp;quot;, repr(binascii.b2a_hex(mac)), &amp;quot;(computed in python)&amp;quot;
#print &amp;quot;mac:    &amp;#39;6dda11ad&amp;#39; (computed by nRF HW)&amp;quot;
print &amp;quot;&amp;quot;

msg = nonce, hdr, ciphertext, mac

# We assume that the tuple ``msg`` is transmitted to the receiver:

nonce, hdr, ciphertext, mac = msg
key = &amp;#39;\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01&amp;#39;
cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=4, assoc_len=len(hdr))
cipher.update(hdr)
plaintext = cipher.decrypt(ciphertext)
print &amp;quot;plain: &amp;quot;, repr(binascii.b2a_hex(plaintext))
try:
    cipher.verify(mac)
    print &amp;quot;The message is authentic: hdr=%s, pt=%s&amp;quot; % (repr(binascii.b2a_hex(hdr)), repr(binascii.b2a_hex(plaintext)))
except ValueError:
    print &amp;quot;Key incorrect or message corrupted&amp;quot;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you don&amp;#39;t do the `cipher.update(hdr)` to add the header byte, then the decryption is correct but the MAC doesn&amp;#39;t match what the nRF CCM hardware calculated.&lt;/p&gt;
&lt;p&gt;Here is the output of the python script. We can see that the plaintext is correctly computed, and the MAC is computed correctly (at least it matches how the nRF hw computed the MAC).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;$ python ccm_test.py 
key:    &amp;#39;01010101010101010101010101010101&amp;#39;
nonce:  &amp;#39;00000000000202020202020202&amp;#39;
plain:  &amp;#39;000102030405060708090a0b0c0d0e0f&amp;#39;
cipher: &amp;#39;0daf4b8e52503a6e91f4d834269b4e74&amp;#39;

mac:    &amp;#39;6dda11ad&amp;#39; (computed in python)

plain:  &amp;#39;000102030405060708090a0b0c0d0e0f&amp;#39;
The message is authentic: hdr=&amp;#39;00&amp;#39;, pt=&amp;#39;000102030405060708090a0b0c0d0e0f&amp;#39;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I hope this helps other folks to figure out how to use the nRF AES CCM hardware outside of a BLE context!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AES CCM encryption by S132 timeslot API</title><link>https://devzone.nordicsemi.com/thread/112934?ContentTypeID=1</link><pubDate>Wed, 20 Dec 2017 14:01:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e533a6dc-822f-4479-909d-bd7ecdad6202</guid><dc:creator>run_ar</dc:creator><description>&lt;p&gt;Duplicated &lt;a href="https://devzone.nordicsemi.com/question/183142/aes-ccm-encryption-by-s132-timeslot-api/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: AES CCM encryption by S132 timeslot API</title><link>https://devzone.nordicsemi.com/thread/112933?ContentTypeID=1</link><pubDate>Wed, 06 Dec 2017 15:43:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:37879c20-efe2-440f-993f-e2ee92d26933</guid><dc:creator>Petter Myhre</dc:creator><description>&lt;p&gt;How are you using the CCM module? Could you include some code that shows how you are using it? Or even better, upload your complete project so we can test it here.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>