BA / Mbed OS BaBoRo_test2
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMacCrypto.cpp Source File

LoRaMacCrypto.cpp

00001 /**
00002  *  / _____)             _              | |
00003  * ( (____  _____ ____ _| |_ _____  ____| |__
00004  *  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  *  _____) ) ____| | | || |_| ____( (___| | | |
00006  * (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007  *    (C)2013 Semtech
00008  *  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009  * / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010  * \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011  * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012  * embedded.connectivity.solutions===============
00013  *
00014  * Description: LoRa MAC crypto implementation
00015  *
00016  * License: Revised BSD License, see LICENSE.TXT file include in the project
00017  *
00018  * Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
00019  *
00020  *
00021  * Copyright (c) 2017, Arm Limited and affiliates.
00022  *
00023  * SPDX-License-Identifier: BSD-3-Clause
00024 */
00025 
00026 #include <stdlib.h>
00027 #include <stdint.h>
00028 
00029 #include "mbedtls/aes.h"
00030 #include "mbedtls/cmac.h"
00031 
00032 #include "LoRaMacCrypto.h"
00033 #include "system/lorawan_data_structures.h"
00034 
00035 
00036 #if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_CIPHER_C)
00037 
00038 /**
00039  * CMAC/AES Message Integrity Code (MIC) Block B0 size
00040  */
00041 #define LORAMAC_MIC_BLOCK_B0_SIZE                   16
00042 
00043 /**
00044  * MIC field computation initial data
00045  */
00046 static uint8_t mic_block_b0[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00047                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00048 
00049 /**
00050  * Contains the computed MIC field.
00051  *
00052  * \remark Only the 4 first bytes are used
00053  */
00054 static uint8_t computed_mic[16];
00055 
00056 /**
00057  * Encryption aBlock and sBlock
00058  */
00059 static uint8_t a_block[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00060                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00061 
00062 static uint8_t s_block[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00063                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00064 
00065 /**
00066  * AES computation context variable
00067  */
00068 static mbedtls_aes_context aes_ctx;
00069 
00070 /**
00071  * CMAC computation context variable
00072  */
00073 static mbedtls_cipher_context_t aes_cmac_ctx[1];
00074 
00075 #define AES_CMAC_KEY_LENGTH     16
00076 
00077 int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
00078                 uint32_t address, uint8_t dir, uint32_t seq_counter,
00079                 uint32_t *mic)
00080 {
00081 
00082     int ret = 0;
00083 
00084     mic_block_b0[5] = dir;
00085 
00086     mic_block_b0[6] = (address) & 0xFF;
00087     mic_block_b0[7] = (address >> 8) & 0xFF;
00088     mic_block_b0[8] = (address >> 16) & 0xFF;
00089     mic_block_b0[9] = (address >> 24) & 0xFF;
00090 
00091     mic_block_b0[10] = (seq_counter) & 0xFF;
00092     mic_block_b0[11] = (seq_counter >> 8) & 0xFF;
00093     mic_block_b0[12] = (seq_counter >> 16) & 0xFF;
00094     mic_block_b0[13] = (seq_counter >> 24) & 0xFF;
00095 
00096     mic_block_b0[15] = size & 0xFF;
00097 
00098     mbedtls_cipher_init(aes_cmac_ctx);
00099 
00100     const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
00101 
00102     if (NULL != cipher_info) {
00103         ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
00104         if (0 != ret)
00105             goto exit;
00106 
00107         ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
00108                                          AES_CMAC_KEY_LENGTH * 8);
00109         if (0 != ret)
00110             goto exit;
00111 
00112         ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0,
00113                                          LORAMAC_MIC_BLOCK_B0_SIZE);
00114         if (0 != ret)
00115             goto exit;
00116 
00117         ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
00118         if (0 != ret)
00119             goto exit;
00120 
00121         ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
00122         if (0 != ret)
00123             goto exit;
00124 
00125         *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
00126                 | (uint32_t) computed_mic[2] << 16
00127                 | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
00128     } else {
00129         ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
00130     }
00131 
00132 exit: mbedtls_cipher_free(aes_cmac_ctx);
00133     return ret;
00134 }
00135 
00136 int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
00137                     uint32_t address, uint8_t dir, uint32_t seq_counter,
00138                     uint8_t *enc_buffer)
00139 {
00140     uint16_t i;
00141     uint8_t bufferIndex = 0;
00142     uint16_t ctr = 1;
00143     int ret = 0;
00144 
00145     mbedtls_aes_init(&aes_ctx);
00146     ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
00147     if (0 != ret)
00148         goto exit;
00149 
00150     a_block[5] = dir;
00151 
00152     a_block[6] = (address) & 0xFF;
00153     a_block[7] = (address >> 8) & 0xFF;
00154     a_block[8] = (address >> 16) & 0xFF;
00155     a_block[9] = (address >> 24) & 0xFF;
00156 
00157     a_block[10] = (seq_counter) & 0xFF;
00158     a_block[11] = (seq_counter >> 8) & 0xFF;
00159     a_block[12] = (seq_counter >> 16) & 0xFF;
00160     a_block[13] = (seq_counter >> 24) & 0xFF;
00161 
00162     while (size >= 16) {
00163         a_block[15] = ((ctr) & 0xFF);
00164         ctr++;
00165         ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
00166                                     s_block);
00167         if (0 != ret)
00168             goto exit;
00169 
00170         for (i = 0; i < 16; i++) {
00171             enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
00172         }
00173         size -= 16;
00174         bufferIndex += 16;
00175     }
00176 
00177     if (size > 0) {
00178         a_block[15] = ((ctr) & 0xFF);
00179         ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
00180                                     s_block);
00181         if (0 != ret)
00182             goto exit;
00183 
00184         for (i = 0; i < size; i++) {
00185             enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
00186         }
00187     }
00188 
00189 exit: mbedtls_aes_free(&aes_ctx);
00190     return ret;
00191 }
00192 
00193 int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
00194                     uint32_t address, uint8_t dir, uint32_t seq_counter,
00195                     uint8_t *dec_buffer)
00196 {
00197     return encrypt_payload(buffer, size, key, address, dir, seq_counter,
00198                            dec_buffer);
00199 }
00200 
00201 int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
00202                            const uint8_t *key, uint32_t *mic)
00203 {
00204     int ret = 0;
00205 
00206     mbedtls_cipher_init(aes_cmac_ctx);
00207     const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
00208 
00209     if (NULL != cipher_info) {
00210         ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
00211         if (0 != ret)
00212             goto exit;
00213 
00214         ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
00215                                          AES_CMAC_KEY_LENGTH * 8);
00216         if (0 != ret)
00217             goto exit;
00218 
00219         ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
00220         if (0 != ret)
00221             goto exit;
00222 
00223         ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
00224         if (0 != ret)
00225             goto exit;
00226 
00227         *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
00228                 | (uint32_t) computed_mic[2] << 16
00229                 | (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
00230     } else {
00231         ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
00232     }
00233 
00234 exit: mbedtls_cipher_free(aes_cmac_ctx);
00235     return ret;
00236 }
00237 
00238 int decrypt_join_frame(const uint8_t *buffer, uint16_t size, const uint8_t *key,
00239                        uint8_t *dec_buffer)
00240 {
00241     int ret = 0;
00242 
00243     mbedtls_aes_init(&aes_ctx);
00244 
00245     ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
00246     if (0 != ret)
00247         goto exit;
00248 
00249     ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer,
00250                                 dec_buffer);
00251     if (0 != ret)
00252         goto exit;
00253 
00254     // Check if optional CFList is included
00255     if (size >= 16) {
00256         ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer + 16,
00257                                     dec_buffer + 16);
00258     }
00259 
00260 exit: mbedtls_aes_free(&aes_ctx);
00261     return ret;
00262 }
00263 
00264 int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
00265                                  uint16_t dev_nonce, uint8_t *nwk_skey,
00266                                  uint8_t *app_skey)
00267 {
00268     uint8_t nonce[16];
00269     uint8_t *p_dev_nonce = (uint8_t *) &dev_nonce;
00270     int ret = 0;
00271 
00272     mbedtls_aes_init(&aes_ctx);
00273 
00274     ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
00275     if (0 != ret)
00276         goto exit;
00277 
00278     memset(nonce, 0, sizeof(nonce));
00279     nonce[0] = 0x01;
00280     memcpy(nonce + 1, app_nonce, 6);
00281     memcpy(nonce + 7, p_dev_nonce, 2);
00282     ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, nwk_skey);
00283     if (0 != ret)
00284         goto exit;
00285 
00286     memset(nonce, 0, sizeof(nonce));
00287     nonce[0] = 0x02;
00288     memcpy(nonce + 1, app_nonce, 6);
00289     memcpy(nonce + 7, p_dev_nonce, 2);
00290     ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, app_skey);
00291 
00292     exit: mbedtls_aes_free(&aes_ctx);
00293     return ret;
00294 }
00295 #else
00296 
00297 // If mbedTLS is not configured properly, these dummies will ensure that
00298 // user knows what is wrong and in addition to that these ensure that
00299 // Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction
00300 // with mbedTLS is not being used.
00301 int compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
00302                 uint8_t dir, uint32_t, uint32_t *)
00303 {
00304     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00305 
00306     // Never actually reaches here
00307     return LORAWAN_STATUS_CRYPTO_FAIL;
00308 }
00309 
00310 int encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
00311                     uint8_t , uint32_t , uint8_t *)
00312 {
00313     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00314 
00315     // Never actually reaches here
00316     return LORAWAN_STATUS_CRYPTO_FAIL;
00317 }
00318 
00319 int decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
00320                     uint8_t , uint32_t , uint8_t *)
00321 {
00322     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00323 
00324     // Never actually reaches here
00325     return LORAWAN_STATUS_CRYPTO_FAIL;
00326 }
00327 
00328 int compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t *)
00329 {
00330     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00331 
00332     // Never actually reaches here
00333     return LORAWAN_STATUS_CRYPTO_FAIL;
00334 }
00335 
00336 int decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint8_t *)
00337 {
00338     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00339 
00340     // Never actually reaches here
00341     return LORAWAN_STATUS_CRYPTO_FAIL;
00342 }
00343 
00344 int compute_skeys_for_join_frame(const uint8_t *, const uint8_t *, uint16_t ,
00345                                  uint8_t *, uint8_t *)
00346 {
00347     MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
00348 
00349     // Never actually reaches here
00350     return LORAWAN_STATUS_CRYPTO_FAIL;
00351 }
00352 
00353 #endif