Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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