NRF_CRYPTO AESCCM and python AES CCM encryption not gives the same output

from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from Crypto.Util.strxor import strxor

# Key derivation parameters
# password = b"your_secret_password"
# salt = get_random_bytes(16)
# key = PBKDF2(password, salt, dkLen=32)
key=b"kwb3IfPnbMx8RvGYm3yl4O6E2ZNZ4Gwq"

# AES-CCM parameters
nonce = bytes.fromhex("00000000000000000000000000")
associated_data = bytes.fromhex("AABBCCDD")
plaintext = b"ABC"
print(plaintext.hex())
# Initialize AES-CCM cipher
cipher = AES.new(key, AES.MODE_CCM, nonce=nonce,mac_len=4,assoc_len=4,use_aesni=0)

# Encrypt the data
cipher.update(associated_data)
ciphertext = cipher.encrypt(plaintext)
mac=cipher.digest()
# Print the encrypted data and MAC
print("Ciphertext:", ciphertext.hex())
print("nonce",nonce.hex(),nonce.__len__())
print("key",key.__str__(),key.__len__())
print("MAC:", mac.hex())
cipher = AES.new(key, AES.MODE_CCM, nonce=nonce,mac_len=4,assoc_len=4,use_aesni=0)
cipher.update(associated_data)
ciphertext=cipher.decrypt(ciphertext)
print("Ciphertext:", ciphertext.hex())

Hi Nordic Team,

NRF crypto example  AES CCM main.c code follows NIST standards and  Pycryptodome library follows the same. I tried encryption on both platform but the results will be different, So How can I match the outputs. Suggest any methods to sync the same.  

The Outputs are given below

C Code Output

Plain text (hex) (len: 3) ----41 42 43

Encrypted text (hex) (len: 3) ----86 9E 06

MAC (hex) (len: 4) ---- 06 C6 68 5D

Python Code Output

Plain text -- 414243

Ciphertext: --e1 29 d1

MAC:-- bc 3a b0 c8

 I hereby attached the python code. The parameters of AES CCM are same for both python and C code 

Parents
  • Hello,

    Did you modify main.c and sdk_config.h to use an AES 256-bit cipher? Note: cc310 does not support 256-bit keys.

    Best regards,

    Vidar

  • Hi Vedar 

    In nrf5 sdk 17.0.2->examples->crypto->nrf_crypto->aes->aes_ccm this location had on main.c file 

    /**
     * Copyright (c) 2018 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include <stdio.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <ctype.h>
    
    
    #include "nrf.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    
    #include "nrf_drv_power.h"
    
    #include "app_error.h"
    #include "app_util.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "boards.h"
    
    #include "nrf_crypto.h"
    #include "nrf_crypto_error.h"
    #include "mem_manager.h"
    
    #if NRF_MODULE_ENABLED(NRF_CRYPTO)
    /**@file
     * @defgroup AES_CCM_example main.c
     *
     * @{
     *
     */
    
    #define AES_MAC_SIZE                            (16)
    
    #define NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE    (100)
    
    #define AES_ERROR_CHECK(error)  \
        do {            \
            if (error)  \
            {           \
                NRF_LOG_RAW_INFO("\r\nError = 0x%x\r\n%s\r\n",           \
                                 (error),                                \
                                 nrf_crypto_error_string_get(error));    \
                return; \
            }           \
        } while (0);
    
    
    
    /* Maximum allowed key = 256 bit */
    static uint8_t m_key[32] = {'N', 'O', 'R', 'D', 'I', 'C', ' ',
                                'S', 'E', 'M', 'I', 'C', 'O', 'N', 'D', 'U', 'C', 'T', 'O', 'R',
                                'A', 'E', 'S', '&', 'M', 'A', 'C', ' ', 'T', 'E', 'S', 'T'};
    
    /* Below text is used as plain text for encryption, decryption and MAC calculation. */
    static char m_plain_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE] =
    {
        "Example string used to demonstrate basic usage of AES CCM mode."
    };
    
    static char m_encrypted_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE];
    static char m_decrypted_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE];
    
    static void text_print(char const* p_label, char const * p_text, size_t len)
    {
        NRF_LOG_RAW_INFO("----%s (len: %u) ----\r\n", p_label, len);
        NRF_LOG_FLUSH();
        for(size_t i = 0; i < len; i++)
        {
            NRF_LOG_RAW_INFO("%c", p_text[i]);
            NRF_LOG_FLUSH();
        }
        NRF_LOG_RAW_INFO("\r\n");
        NRF_LOG_RAW_INFO("---- %s end ----\r\n\r\n", p_label);
        NRF_LOG_FLUSH();
    }
    
    static void hex_text_print(char const* p_label, char const * p_text, size_t len)
    {
        NRF_LOG_RAW_INFO("---- %s (len: %u) ----\r\n", p_label, len);
        NRF_LOG_FLUSH();
    
        // Handle partial line (left)
        for (size_t i = 0; i < len; i++)
        {
            if (((i & 0xF) == 0) && (i > 0))
            {
                NRF_LOG_RAW_INFO("\r\n");
                NRF_LOG_FLUSH();
            }
    
            NRF_LOG_RAW_INFO("%02x ", p_text[i]);
            NRF_LOG_FLUSH();
        }
        NRF_LOG_RAW_INFO("\r\n");
        NRF_LOG_RAW_INFO("---- %s end ----\r\n\r\n", p_label);
        NRF_LOG_FLUSH();
    }
    
    
    
    static void plain_text_print(void)
    {
        text_print("Plain text", m_plain_text, strlen(m_plain_text));
        hex_text_print("Plain text (hex)", m_plain_text, strlen(m_plain_text));
    }
    
    static void encrypted_text_print(char const * p_text, size_t encrypted_len)
    {
        hex_text_print("Encrypted text (hex)", p_text, encrypted_len);
    }
    
    static void decrypted_text_print(char const * p_text, size_t decrypted_len)
    {
        text_print("Decrypted text", p_text, decrypted_len);
        hex_text_print("Decrypted text (hex)", p_text, decrypted_len);
    }
    
    static void mac_print(uint8_t const * p_buff, uint8_t mac_size)
    {
        hex_text_print("MAC (hex)", (char const*)p_buff, mac_size);
    }
    
    static void crypt_ccm(void)
    {
        uint32_t    len;
        ret_code_t  ret_val;
    
        static uint8_t     mac[AES_MAC_SIZE];
        static uint8_t     nonce[13];
        static uint8_t     adata[] = {0xAA, 0xBB, 0xCC, 0xDD};
    
        static nrf_crypto_aead_context_t ccm_ctx;
    
        memset(mac,   0, sizeof(mac));
        memset(nonce, 0, sizeof(nonce));
    
        plain_text_print();
    
        len = strlen((char const *)m_plain_text);
    
        /* Init encrypt and decrypt context */
        ret_val = nrf_crypto_aead_init(&ccm_ctx,
                                       &g_nrf_crypto_aes_ccm_128_info,
                                       m_key);
        AES_ERROR_CHECK(ret_val);
    
        /* encrypt and tag text */
        ret_val = nrf_crypto_aead_crypt(&ccm_ctx,
                                        NRF_CRYPTO_ENCRYPT,
                                        nonce,
                                        sizeof(nonce),
                                        adata,
                                        sizeof(adata),
                                        (uint8_t *)m_plain_text,
                                        len,
                                        (uint8_t *)m_encrypted_text,
                                        mac,
                                        sizeof(mac));
        AES_ERROR_CHECK(ret_val);
    
        encrypted_text_print(m_encrypted_text, len);
        mac_print(mac, sizeof(mac));
    
        /* decrypt text */
        ret_val = nrf_crypto_aead_crypt(&ccm_ctx,
                                        NRF_CRYPTO_DECRYPT,
                                        nonce,
                                        sizeof(nonce),
                                        adata,
                                        sizeof(adata),
                                        (uint8_t *)m_encrypted_text,
                                        len,
                                        (uint8_t *)m_decrypted_text,
                                        mac,
                                        sizeof(mac));
        AES_ERROR_CHECK(ret_val);
    
        ret_val = nrf_crypto_aead_uninit(&ccm_ctx);
        AES_ERROR_CHECK(ret_val);
    
        decrypted_text_print(m_decrypted_text, len);
    
        if (memcmp(m_plain_text, m_decrypted_text, strlen(m_plain_text)) == 0)
        {
            NRF_LOG_RAW_INFO("AES CCM example executed successfully.\r\n");
        }
        else
        {
            NRF_LOG_RAW_INFO("AES CCM example failed!!!.\r\n");
        }
    }
    
    int main(void)
    {
        ret_code_t ret;
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_RAW_INFO("AES CCM example started.\r\n\r\n");
        NRF_LOG_FLUSH();
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        nrf_drv_clock_lfclk_request(NULL);
    
        ret = nrf_crypto_init();
        APP_ERROR_CHECK(ret);
    
        ret = nrf_mem_init();
        APP_ERROR_CHECK(ret);
    
        crypt_ccm();
        while (true)
        {
            NRF_LOG_FLUSH();
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        }
    }
    
    /** @} */
    #endif // NRF_MODULE_ENABLED(NRF_CRYPTO)
    
    

    I worked on this file for aes ccm encryption and decryption. In this file key size is 256bit only. So how can I sync the output of device and python/android app. Is there is any other file to encrypt the data via aes ccm?  

  • I'm able to match the output from the c code and the python script when using the original input you posted.

    /**
     * Copyright (c) 2018 - 2021, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include <stdio.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <ctype.h>
    
    
    #include "nrf.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    
    #include "nrf_drv_power.h"
    
    #include "app_error.h"
    #include "app_util.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "boards.h"
    
    #include "nrf_crypto.h"
    #include "nrf_crypto_error.h"
    #include "mem_manager.h"
    
    #if NRF_MODULE_ENABLED(NRF_CRYPTO)
    /**@file
     * @defgroup AES_CCM_example main.c
     *
     * @{
     *
     */
    
    #define AES_MAC_SIZE                            (4)
    
    #define NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE    (3)
    
    #define AES_ERROR_CHECK(error)  \
        do {            \
            if (error)  \
            {           \
                NRF_LOG_RAW_INFO("\r\nError = 0x%x\r\n%s\r\n",           \
                                 (error),                                \
                                 nrf_crypto_error_string_get(error));    \
                return; \
            }           \
        } while (0);
    
    
    
    /* Maximum allowed key = 256 bit */
    static uint8_t m_key[32] = "kwb3IfPnbMx8RvGYm3yl4O6E2ZNZ4Gwq";
    
    /* Below text is used as plain text for encryption, decryption and MAC calculation. */
    static char m_plain_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE] =
    {
        "ABC"
    };
    
    static char m_encrypted_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE];
    static char m_decrypted_text[NRF_CRYPTO_EXAMPLE_AES_MAX_TEXT_SIZE];
    
    static void text_print(char const* p_label, char const * p_text, size_t len)
    {
        NRF_LOG_RAW_INFO("----%s (len: %u) ----\r\n", p_label, len);
        NRF_LOG_FLUSH();
        for(size_t i = 0; i < len; i++)
        {
            NRF_LOG_RAW_INFO("%c", p_text[i]);
            NRF_LOG_FLUSH();
        }
        NRF_LOG_RAW_INFO("\r\n");
        NRF_LOG_RAW_INFO("---- %s end ----\r\n\r\n", p_label);
        NRF_LOG_FLUSH();
    }
    
    static void hex_text_print(char const* p_label, char const * p_text, size_t len)
    {
        NRF_LOG_RAW_INFO("---- %s (len: %u) ----\r\n", p_label, len);
        NRF_LOG_FLUSH();
    
        // Handle partial line (left)
        for (size_t i = 0; i < len; i++)
        {
            if (((i & 0xF) == 0) && (i > 0))
            {
                NRF_LOG_RAW_INFO("\r\n");
                NRF_LOG_FLUSH();
            }
    
            NRF_LOG_RAW_INFO("%02x ", p_text[i]);
            NRF_LOG_FLUSH();
        }
        NRF_LOG_RAW_INFO("\r\n");
        NRF_LOG_RAW_INFO("---- %s end ----\r\n\r\n", p_label);
        NRF_LOG_FLUSH();
    }
    
    
    
    static void plain_text_print(void)
    {
        text_print("Plain text", m_plain_text, strlen(m_plain_text));
        hex_text_print("Plain text (hex)", m_plain_text, strlen(m_plain_text));
    }
    
    static void encrypted_text_print(char const * p_text, size_t encrypted_len)
    {
        hex_text_print("Encrypted text (hex)", p_text, encrypted_len);
    }
    
    static void decrypted_text_print(char const * p_text, size_t decrypted_len)
    {
        text_print("Decrypted text", p_text, decrypted_len);
        hex_text_print("Decrypted text (hex)", p_text, decrypted_len);
    }
    
    static void mac_print(uint8_t const * p_buff, uint8_t mac_size)
    {
        hex_text_print("MAC (hex)", (char const*)p_buff, mac_size);
    }
    
    static void crypt_ccm(void)
    {
        uint32_t    len;
        ret_code_t  ret_val;
    
        static uint8_t     mac[AES_MAC_SIZE];
        static uint8_t     nonce[13];
        static uint8_t     adata[] = {0xAA, 0xBB, 0xCC, 0xDD};
    
        static nrf_crypto_aead_context_t ccm_ctx;
    
        memset(mac,   0, sizeof(mac));
        memset(nonce, 0, sizeof(nonce));
    
        plain_text_print();
    
        len = strlen((char const *)m_plain_text);
    
        /* Init encrypt and decrypt context */
        ret_val = nrf_crypto_aead_init(&ccm_ctx,
                                       &g_nrf_crypto_aes_ccm_256_info,
                                       m_key);
        AES_ERROR_CHECK(ret_val);
    
        /* encrypt and tag text */
        ret_val = nrf_crypto_aead_crypt(&ccm_ctx,
                                        NRF_CRYPTO_ENCRYPT,
                                        nonce,
                                        sizeof(nonce),
                                        adata,
                                        sizeof(adata),
                                        (uint8_t *)m_plain_text,
                                        len,
                                        (uint8_t *)m_encrypted_text,
                                        mac,
                                        sizeof(mac));
        AES_ERROR_CHECK(ret_val);
    
        encrypted_text_print(m_encrypted_text, len);
        mac_print(mac, sizeof(mac));
    
        /* decrypt text */
        ret_val = nrf_crypto_aead_crypt(&ccm_ctx,
                                        NRF_CRYPTO_DECRYPT,
                                        nonce,
                                        sizeof(nonce),
                                        adata,
                                        sizeof(adata),
                                        (uint8_t *)m_encrypted_text,
                                        len,
                                        (uint8_t *)m_decrypted_text,
                                        mac,
                                        sizeof(mac));
        AES_ERROR_CHECK(ret_val);
    
        ret_val = nrf_crypto_aead_uninit(&ccm_ctx);
        AES_ERROR_CHECK(ret_val);
    
        decrypted_text_print(m_decrypted_text, len);
    
        if (memcmp(m_plain_text, m_decrypted_text, strlen(m_plain_text)) == 0)
        {
            NRF_LOG_RAW_INFO("AES CCM example executed successfully.\r\n");
        }
        else
        {
            NRF_LOG_RAW_INFO("AES CCM example failed!!!.\r\n");
        }
    }
    
    int main(void)
    {
        ret_code_t ret;
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_RAW_INFO("AES CCM example started.\r\n\r\n");
        NRF_LOG_FLUSH();
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        nrf_drv_clock_lfclk_request(NULL);
    
        ret = nrf_crypto_init();
        APP_ERROR_CHECK(ret);
    
        ret = nrf_mem_init();
        APP_ERROR_CHECK(ret);
    
        crypt_ccm();
        while (true)
        {
            NRF_LOG_FLUSH();
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        }
    }
    
    /** @} */
    #endif // NRF_MODULE_ENABLED(NRF_CRYPTO)
    

    AES CCM example started.
    
    ----Plain text (len: 3) ----
    ABC
    ---- Plain text end ----
    
    ---- Plain text (hex) (len: 3) ----
    41 42 43 
    ---- Plain text (hex) end ----
    
    ---- Encrypted text (hex) (len: 3) ----
    E1 29 D1 
    ---- Encrypted text (hex) end ----
    
    ---- MAC (hex) (len: 4) ----
    BC 3A B0 C8 
    ---- MAC (hex) end ----
    
    ----Decrypted text (len: 3) ----
    ABC
    ---- Decrypted text end ----
    
    ---- Decrypted text (hex) (len: 3) ----
    41 42 43 
    ---- Decrypted text (hex) end ----
    
    AES CCM example executed successfully.

  • Thanks Vidar, Now its works good, the outputs are perfectly matched.

    Best Regards 

    Sriyogesh Gopal 

  • I'm glad to hear that. Thank you for the update, Sriyogesh.

  • Hi vidar 

    One more doubt when I enable the softdevice, code is crashed in newly updated 256_info and the error code is  app: ERROR 34069.

    Whether aesccm mbedtls work along with softdevice?

  • Hi,

    The error code corresponds to NRF_ERROR_CRYPTO_ALLOC_FAILED (0x8515), which indicates that the function failed to allocate memory for this crypto operation. I suggest you compare the memory allocator configuration between with your working project (NRF_CRYPTO_ALLOCATOR). 

Reply Children
No Data
Related