some problems about AES CCM

1st problem:

There are some failed case when i run  \v2.9.1\modules\bsim_hw_models\nrf_hw_models\tests\zephyr_apps\54_aar_ccm_ecb\src\test_ccm.c

2nd problem:

If I reduce the amount of encrypted data in test_ccm_12b_encr_ble_255b_w_adata_nomac, the encryption process gets stuck.

Parents
  • ZTEST(nrf_ccm_tests, test_ccm_12c_encr_ble_0_255b_w_adata_nomac)
    {
    	printk("Encrypt 0-255 byte payload with adata and no MAC in BLE mode\n");
    
    	uint8_t K[16] = {0x99, 0xAD, 0x1B, 0x52, 0x26, 0xA3, 0x7E, 0x3E, 0x05, 0x8E, 0x3B, 0x8E, 0x27, 0xC2, 0xC6, 0x66};
    	uint8_t N[16] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x24, 0xAB, 0xDC, 0xBA, 0xBE, 0xBA, 0xAF, 0xDE};
    	uint8_t A[] = {0x0E};
    	uint8_t P[] = {0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,  0x8,  0x9, 0xa, 0xb,  0xc,  0xd,  0xe,  0xf,  0x10,
    			0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
    			0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    			0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
    			0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54,
    			0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
    			0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    			0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
    			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
    			0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
    			0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
    			0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
    			0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc,
    			0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
    			0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
    	uint8_t C[] = {
    			0x6D, 0x71, 0xB7, 0x03, 0x74, 0x41, 0x0C, 0x9D, 0x0A, 0x74, 0xE2, 0xFD, 0x67, 0x67, 0x64, 0x26, 0x0A, 0xF6, 0x76,
    			0x6F, 0x59, 0x4B, 0x7B, 0xBC, 0xC6, 0xDF, 0x18, 0x5B, 0x50, 0x2D, 0x3D, 0x5E, 0xD9, 0xAF, 0xF6, 0xB8, 0xFE, 0x86,
    			0xC5, 0x23, 0x3A, 0xA8, 0x35, 0xE4, 0xE6, 0xA0, 0xB6, 0xC9, 0x48, 0xFF, 0xFF, 0xF5, 0xA0, 0xC0, 0x19, 0x32, 0x71,
    			0x60, 0x61, 0x0C, 0x1B, 0xE5, 0x43, 0xCE, 0xB5, 0xBC, 0x9E, 0x3A, 0x3D, 0x85, 0xB7, 0xAA, 0x65, 0x64, 0x2E, 0x38,
    			0x82, 0x27, 0x3D, 0xA4, 0x13, 0xFE, 0xE5, 0x89, 0x1F, 0x2F, 0x0E, 0x9B, 0x02, 0x0B, 0x10, 0xCD, 0xA8, 0xCD, 0xBA,
    			0xA6, 0xD0, 0x40, 0x44, 0xD0, 0x75, 0x37, 0xBB, 0x06, 0x16, 0x54, 0x04, 0x7F, 0x8A, 0x0C, 0x2E, 0x7E, 0xB8, 0x06,
    			0x06, 0x63, 0x3F, 0x4A, 0x08, 0xFF, 0x21, 0x28, 0x6C, 0x8F, 0x65, 0xB6, 0x29, 0xE5, 0xFC, 0x58, 0x29, 0x7D, 0x55,
    			0xFE, 0xA8, 0x24, 0xDE, 0xE5, 0xB1, 0x8C, 0x9B, 0xAF, 0xD3, 0x78, 0xCE, 0x87, 0x92, 0x07, 0x4F, 0x40, 0x75, 0xE6,
    			0xA7, 0x61, 0x09, 0x73, 0xBE, 0x0A, 0x29, 0x05, 0x3F, 0xF7, 0xBD, 0xD8, 0x9C, 0xC7, 0xDA, 0x4B, 0xAC, 0xE9, 0xC2,
    			0xE4, 0xD7, 0x4C, 0x2C, 0x26, 0x8C, 0x00, 0xE4, 0xE6, 0xBE, 0x05, 0x0E, 0xC2, 0xDA, 0x1E, 0xA7, 0xAE, 0xD7, 0x35,
    			0xA8, 0x26, 0xCD, 0xF8, 0x93, 0x93, 0x26, 0x0C, 0xD5, 0x47, 0x9B, 0x7C, 0x35, 0x62, 0x7D, 0xFB, 0xCF, 0xAD, 0x78,
    			0x91, 0xA6, 0x0C, 0xC8, 0x5C, 0xBF, 0x05, 0xBF, 0x7E, 0xE4, 0x0C, 0x4A, 0x9E, 0xC9, 0xD2, 0x9F, 0x75, 0x7A, 0x58,
    			0x84, 0x9B, 0xD4, 0x9A, 0x2B, 0x51, 0xB2, 0x4A, 0x3A, 0x45, 0xEB, 0x58, 0x33, 0x86, 0x53, 0xC5, 0xBA, 0x63, 0x73,
    			0xB6, 0x89, 0x25, 0xD7,
    	};
    	unsigned mac_len = 0;
    	uint8_t adata_mask = 0xE3;
    
    	for (uint8_t len = 0; len <= 255; len++)
    	{
    		build_ccm_test_case_and_run(K, N, P, len, len, A, sizeof(A), C, len, mac_len, adata_mask, false,
    				false, ENCRYPT, BLE_MODE, NULL, false);
    	}
    }

    I wrote an example of encrypting data of different lengths according to test_ccm_12b, but it got stuck when len=36.

  • Could this be Errata [1] CCM: MAC error is returned if MDATA size is slightly larger than MLEN?

    Try to set MLEN (len) to a lot higher than sizeof(P), as suggested in the workaround

  • yes, It prompts CCM->EVENTS_ERROR not equal zero, and CCM->ERRORSTATUS = 1, which means End of INPTR job list before CCM data structure was read.

    If i have mlen set to len, it freezes when len = 36

  • Since CCM is usually with a MAC, I found it easier to make a CCM test script for the test_ccm_12b_encr_ble_255b_w_adata case. So I did.
    Here is an example of a shorter CCM with that case, and the python script (made with help from chatgpt)  that I used to generate test data:

    54_ccm_only_2.zip

    from Crypto.Cipher import AES
    from Crypto.Util import Counter
    
    # === Configuration ===
    # Key (16 bytes)
    K = bytes([
        0x99, 0xAD, 0x1B, 0x52, 0x26, 0xA3, 0x7E, 0x3E,
        0x05, 0x8E, 0x3B, 0x8E, 0x27, 0xC2, 0xC6, 0x66
    ])
    # Full Nonce Blob (16 bytes)
    N_full = bytes([
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80,
        0x24, 0xAB, 0xDC, 0xBA, 0xBE, 0xBA, 0xAF, 0xDE
    ])
    # CCM requires nonce length 7..13 bytes; take the last 13 bytes
    nonce = N_full[-13:]
    
    # Associated data (AAD)
    A = bytes([0x0E])
    # Hardware-specific AAD mask for BLE mode
    adata_mask = 0xE3
    # Apply mask to each AAD byte
    masked_A = bytes([b & adata_mask for b in A])
    
    # Define mac length; set to 0 for "no MAC"
    mac_len = 0
    # Tag length in bytes (4, 6, 8, 10, 12, 14, or 16) when mac_len > 0
    tag_len = 4
    
    # === Define Plaintext P below ===
    # Replace or extend this byte list as needed
    P = bytes([
        0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,  0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe,  0xf,  0x10,
    			0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
    			0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    			0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
    			0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54,
    			0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
    			0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    			0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
    			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
    			0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
    			0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
    			0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
    			0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc,
    			0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
    			0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
    ])
    
    # === Encryption ===
    if mac_len > 0:
        # AES-CCM authenticated encryption
        cipher = AES.new(
            K,
            AES.MODE_CCM,
            nonce=nonce,
            mac_len=tag_len,
            msg_len=len(P)
        )
        # Use masked AAD
        cipher.update(masked_A)
        C = cipher.encrypt(P)
        tag = cipher.digest()
        data = C + tag
    else:
        # AES-CTR for "no MAC" scenario
        # Construct counter using nonce as prefix
        bit_len = 128 - len(nonce)*8
        ctr = Counter.new(bit_len, prefix=nonce)
        cipher = AES.new(K, AES.MODE_CTR, counter=ctr)
        data = cipher.encrypt(P)
    
    # === Output in C-array format ===
    for i, b in enumerate(data):
        end = "\n" if (i + 1) % 8 == 0 else " "
        sep = "," if i < len(data) - 1 else ""
        print(f"    0x{b:02X}{sep}", end=end)
    print()
    print(f"// Output length = {len(data)} bytes")
    

    Are these helpful?

  • I need to encrypt packets on-the-fly in radio transmit mode later, so I need to know why it freezes when use CCM.

  • Did you test the sample I uploaded? Does it work for you?

    LeeRJ said:
    I need to encrypt packets on-the-fly in radio transmit mode later, so I need to know why it freezes when use CCM.

    It freezes in  here in the sample code.

    If the freeze is an issue for you, you can make this loop time out, and then handle it as an error.

  • The solution is not very reliable since it's unclear when issues may arise. Could it be a chip design problem similar to Errata [1] CCM: MAC error is returned if MDATA size is slightly larger than MLEN? I want to identify the root cause and resolve it.

Reply Children
No Data
Related