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