Merge pull request #6692 from kivaisan/remove_singleton

Lora: Remove singleton pattern
pull/6735/head
Cruz Monrreal 2018-04-24 12:14:05 -05:00 committed by GitHub
commit 0e86fa2529
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 289 additions and 243 deletions

View File

@ -23,14 +23,9 @@
using namespace events; using namespace events;
inline LoRaWANStack& stk_obj()
{
return LoRaWANStack::get_lorawan_stack();
}
LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio) LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio)
{ {
stk_obj().bind_radio_driver(radio); _lw_stack.bind_radio_driver(radio);
} }
LoRaWANInterface::~LoRaWANInterface() LoRaWANInterface::~LoRaWANInterface()
@ -39,95 +34,95 @@ LoRaWANInterface::~LoRaWANInterface()
lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue) lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue)
{ {
return stk_obj().initialize_mac_layer(queue); return _lw_stack.initialize_mac_layer(queue);
} }
lorawan_status_t LoRaWANInterface::connect() lorawan_status_t LoRaWANInterface::connect()
{ {
return stk_obj().connect(); return _lw_stack.connect();
} }
lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect) lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect)
{ {
return stk_obj().connect(connect); return _lw_stack.connect(connect);
} }
lorawan_status_t LoRaWANInterface::disconnect() lorawan_status_t LoRaWANInterface::disconnect()
{ {
return stk_obj().shutdown(); return _lw_stack.shutdown();
} }
lorawan_status_t LoRaWANInterface::add_link_check_request() lorawan_status_t LoRaWANInterface::add_link_check_request()
{ {
return stk_obj().set_link_check_request(); return _lw_stack.set_link_check_request();
} }
void LoRaWANInterface::remove_link_check_request() void LoRaWANInterface::remove_link_check_request()
{ {
stk_obj().remove_link_check_request(); _lw_stack.remove_link_check_request();
} }
lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate) lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate)
{ {
return stk_obj().set_channel_data_rate(data_rate); return _lw_stack.set_channel_data_rate(data_rate);
} }
lorawan_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count) lorawan_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count)
{ {
return stk_obj().set_confirmed_msg_retry(count); return _lw_stack.set_confirmed_msg_retry(count);
} }
lorawan_status_t LoRaWANInterface::enable_adaptive_datarate() lorawan_status_t LoRaWANInterface::enable_adaptive_datarate()
{ {
return stk_obj().enable_adaptive_datarate(true); return _lw_stack.enable_adaptive_datarate(true);
} }
lorawan_status_t LoRaWANInterface::disable_adaptive_datarate() lorawan_status_t LoRaWANInterface::disable_adaptive_datarate()
{ {
return stk_obj().enable_adaptive_datarate(false); return _lw_stack.enable_adaptive_datarate(false);
} }
lorawan_status_t LoRaWANInterface::set_channel_plan(const lorawan_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::set_channel_plan(const lorawan_channelplan_t &channel_plan)
{ {
return stk_obj().add_channels(channel_plan); return _lw_stack.add_channels(channel_plan);
} }
lorawan_status_t LoRaWANInterface::get_channel_plan(lorawan_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::get_channel_plan(lorawan_channelplan_t &channel_plan)
{ {
return stk_obj().get_enabled_channels(channel_plan); return _lw_stack.get_enabled_channels(channel_plan);
} }
lorawan_status_t LoRaWANInterface::remove_channel(uint8_t id) lorawan_status_t LoRaWANInterface::remove_channel(uint8_t id)
{ {
return stk_obj().remove_a_channel(id); return _lw_stack.remove_a_channel(id);
} }
lorawan_status_t LoRaWANInterface::remove_channel_plan() lorawan_status_t LoRaWANInterface::remove_channel_plan()
{ {
return stk_obj().drop_channel_list(); return _lw_stack.drop_channel_list();
} }
int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data, uint16_t length, int flags) int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data, uint16_t length, int flags)
{ {
return stk_obj().handle_tx(port, data, length, flags); return _lw_stack.handle_tx(port, data, length, flags);
} }
int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length, int flags) int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length, int flags)
{ {
return stk_obj().handle_rx(data, length, port, flags, true); return _lw_stack.handle_rx(data, length, port, flags, true);
} }
int16_t LoRaWANInterface::receive(uint8_t* data, uint16_t length, uint8_t& port, int& flags) int16_t LoRaWANInterface::receive(uint8_t* data, uint16_t length, uint8_t& port, int& flags)
{ {
return stk_obj().handle_rx(data, length, port, flags, false); return _lw_stack.handle_rx(data, length, port, flags, false);
} }
lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks) lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks)
{ {
return stk_obj().set_lora_callbacks(callbacks); return _lw_stack.set_lora_callbacks(callbacks);
} }
lorawan_status_t LoRaWANInterface::set_device_class(const device_class_t device_class) lorawan_status_t LoRaWANInterface::set_device_class(const device_class_t device_class)
{ {
return stk_obj().set_device_class(device_class); return _lw_stack.set_device_class(device_class);
} }

View File

@ -434,6 +434,9 @@ public:
* or other negative error code if request failed. * or other negative error code if request failed.
*/ */
virtual lorawan_status_t set_device_class(const device_class_t device_class); virtual lorawan_status_t set_device_class(const device_class_t device_class);
private:
LoRaWANStack _lw_stack;
}; };
#endif /* LORAWANINTERFACE_H_ */ #endif /* LORAWANINTERFACE_H_ */

View File

@ -103,19 +103,9 @@ LoRaWANStack::LoRaWANStack()
LoRaMacPrimitives.mlme_indication = callback(this, &LoRaWANStack::mlme_indication_handler); LoRaMacPrimitives.mlme_indication = callback(this, &LoRaWANStack::mlme_indication_handler);
} }
LoRaWANStack::~LoRaWANStack()
{
}
/***************************************************************************** /*****************************************************************************
* Public member functions * * Public member functions *
****************************************************************************/ ****************************************************************************/
LoRaWANStack& LoRaWANStack::get_lorawan_stack()
{
static LoRaWANStack _lw_stack;
return _lw_stack;
}
void LoRaWANStack::bind_radio_driver(LoRaRadio& radio) void LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
{ {
_loramac.bind_radio_driver(radio); _loramac.bind_radio_driver(radio);

View File

@ -70,7 +70,7 @@ private:
} device_states_t; } device_states_t;
public: public:
static LoRaWANStack& get_lorawan_stack(); LoRaWANStack();
/** Binds radio driver to PHY layer. /** Binds radio driver to PHY layer.
* *
@ -396,9 +396,6 @@ public:
lorawan_status_t set_device_class(const device_class_t& device_class); lorawan_status_t set_device_class(const device_class_t& device_class);
private: private:
LoRaWANStack();
~LoRaWANStack();
/** /**
* Checks if the user provided port is valid or not * Checks if the user provided port is valid or not
*/ */
@ -465,7 +462,6 @@ private:
void send_automatic_uplink_message(const uint8_t port); void send_automatic_uplink_message(const uint8_t port);
private: private:
LoRaMac _loramac; LoRaMac _loramac;
loramac_primitives_t LoRaMacPrimitives; loramac_primitives_t LoRaMacPrimitives;

View File

@ -24,7 +24,6 @@ SPDX-License-Identifier: BSD-3-Clause
#include <stdlib.h> #include <stdlib.h>
#include "LoRaMac.h" #include "LoRaMac.h"
#include "LoRaMacCrypto.h"
#if defined(FEATURE_COMMON_PAL) #if defined(FEATURE_COMMON_PAL)
#include "mbed_trace.h" #include "mbed_trace.h"
@ -37,6 +36,13 @@ SPDX-License-Identifier: BSD-3-Clause
using namespace events; using namespace events;
/*
* LoRaWAN spec 6.2: AppKey is AES-128 key
*/
#define APPKEY_KEY_LENGTH 128
/*! /*!
* Maximum length of the fOpts field * Maximum length of the fOpts field
*/ */
@ -311,17 +317,22 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
return; return;
} }
if (0 != decrypt_join_frame(payload + 1, size - 1, if (0 != _lora_crypto.decrypt_join_frame(payload + 1,
_params.keys.app_key, size - 1,
_params.payload + 1)) { _params.keys.app_key,
APPKEY_KEY_LENGTH,
_params.payload + 1)) {
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
return; return;
} }
_params.payload[0] = mac_hdr.value; _params.payload[0] = mac_hdr.value;
if (0 != compute_join_frame_mic(_params.payload, size - LORAMAC_MFR_LEN, if (0 != _lora_crypto.compute_join_frame_mic(_params.payload,
_params.keys.app_key, &mic)) { size - LORAMAC_MFR_LEN,
_params.keys.app_key,
APPKEY_KEY_LENGTH,
&mic)) {
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
return; return;
} }
@ -333,11 +344,12 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
if (mic_rx == mic) { if (mic_rx == mic) {
if (0 != compute_skeys_for_join_frame(_params.keys.app_key, if (0 != _lora_crypto.compute_skeys_for_join_frame(_params.keys.app_key,
_params.payload + 1, APPKEY_KEY_LENGTH,
_params.dev_nonce, _params.payload + 1,
_params.keys.nwk_skey, _params.dev_nonce,
_params.keys.app_skey)) { _params.keys.nwk_skey,
_params.keys.app_skey)) {
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
return; return;
} }
@ -436,15 +448,17 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
if (sequence_counter_diff < (1 << 15)) { if (sequence_counter_diff < (1 << 15)) {
downlink_counter += sequence_counter_diff; downlink_counter += sequence_counter_diff;
compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey, _lora_crypto.compute_mic(payload, size - LORAMAC_MFR_LEN,
address, DOWN_LINK, downlink_counter, &mic); nwk_skey, sizeof(_params.keys.nwk_skey)*8, // sizeof nws_skey must be the same as _params.keys.nwk_skey
address, DOWN_LINK, downlink_counter, &mic);
if (mic_rx == mic) { if (mic_rx == mic) {
is_mic_ok = true; is_mic_ok = true;
} }
} else { } else {
uint32_t downlink_counter_tmp = downlink_counter + 0x10000 + (int16_t)sequence_counter_diff; uint32_t downlink_counter_tmp = downlink_counter + 0x10000 + (int16_t)sequence_counter_diff;
compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey, _lora_crypto.compute_mic(payload, size - LORAMAC_MFR_LEN,
address, DOWN_LINK, downlink_counter_tmp, &mic); nwk_skey, sizeof(_params.keys.nwk_skey)*8, // sizeof nws_skey must be the same as _params.keys.nwk_skey
address, DOWN_LINK, downlink_counter_tmp, &mic);
if (mic_rx == mic ) { if (mic_rx == mic ) {
is_mic_ok = true; is_mic_ok = true;
@ -539,13 +553,14 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
if (port == 0) { if (port == 0) {
if (fctrl.bits.fopts_len == 0) { if (fctrl.bits.fopts_len == 0) {
if (0 != decrypt_payload(payload + app_payload_start_index, if (0 != _lora_crypto.decrypt_payload(payload + app_payload_start_index,
frame_len, frame_len,
nwk_skey, nwk_skey,
address, sizeof(_params.keys.nwk_skey)*8, // sizeof nws_skey must be the same as _params.keys.nwk_skey
DOWN_LINK, address,
downlink_counter, DOWN_LINK,
_params.payload)) { downlink_counter,
_params.payload)) {
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
} }
@ -575,13 +590,14 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
} }
} }
if (0 != decrypt_payload(payload + app_payload_start_index, if (0 != _lora_crypto.decrypt_payload(payload + app_payload_start_index,
frame_len, frame_len,
app_skey, app_skey,
address, sizeof(_params.keys.app_skey)*8, // sizeof app_skey must be the same as _params.keys.app_skey
DOWN_LINK, address,
downlink_counter, DOWN_LINK,
_params.payload)) { downlink_counter,
_params.payload)) {
_mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
} }
@ -1563,9 +1579,11 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
_params.buffer[_params.buffer_pkt_len++] = _params.dev_nonce & 0xFF; _params.buffer[_params.buffer_pkt_len++] = _params.dev_nonce & 0xFF;
_params.buffer[_params.buffer_pkt_len++] = (_params.dev_nonce >> 8) & 0xFF; _params.buffer[_params.buffer_pkt_len++] = (_params.dev_nonce >> 8) & 0xFF;
if (0 != compute_join_frame_mic(_params.buffer, if (0 != _lora_crypto.compute_join_frame_mic(_params.buffer,
_params.buffer_pkt_len & 0xFF, _params.buffer_pkt_len & 0xFF,
_params.keys.app_key, &mic)) { _params.keys.app_key,
APPKEY_KEY_LENGTH,
&mic)) {
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
@ -1646,23 +1664,27 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
_params.buffer[pkt_header_len++] = frame_port; _params.buffer[pkt_header_len++] = frame_port;
uint8_t *key = _params.keys.app_skey; uint8_t *key = _params.keys.app_skey;
uint32_t key_length = sizeof(_params.keys.app_skey)*8;
if (frame_port == 0) { if (frame_port == 0) {
mac_commands.clear_command_buffer(); mac_commands.clear_command_buffer();
key = _params.keys.nwk_skey; key = _params.keys.nwk_skey;
key_length = sizeof(_params.keys.nwk_skey)*8;
} }
if (0 != encrypt_payload((uint8_t*) payload, _params.payload_length, if (0 != _lora_crypto.encrypt_payload((uint8_t*) payload, _params.payload_length,
key, _params.dev_addr, UP_LINK, key, key_length,
_params.ul_frame_counter, _params.dev_addr, UP_LINK,
&_params.buffer[pkt_header_len])) { _params.ul_frame_counter,
&_params.buffer[pkt_header_len])) {
status = LORAWAN_STATUS_CRYPTO_FAIL; status = LORAWAN_STATUS_CRYPTO_FAIL;
} }
} }
_params.buffer_pkt_len = pkt_header_len + _params.payload_length; _params.buffer_pkt_len = pkt_header_len + _params.payload_length;
if (0 != compute_mic(_params.buffer, _params.buffer_pkt_len, if (0 != _lora_crypto.compute_mic(_params.buffer, _params.buffer_pkt_len,
_params.keys.nwk_skey, _params.dev_addr, _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey)*8,
UP_LINK, _params.ul_frame_counter, &mic)) { _params.dev_addr,
UP_LINK, _params.ul_frame_counter, &mic)) {
status = LORAWAN_STATUS_CRYPTO_FAIL; status = LORAWAN_STATUS_CRYPTO_FAIL;
} }

View File

@ -50,6 +50,8 @@
#include "LoRaMacChannelPlan.h" #include "LoRaMacChannelPlan.h"
#include "LoRaMacCommand.h" #include "LoRaMacCommand.h"
#include "LoRaMacCrypto.h"
class LoRaMac { class LoRaMac {
@ -542,6 +544,11 @@ private:
*/ */
LoRaMacChannelPlan channel_plan; LoRaMacChannelPlan channel_plan;
/**
* Crypto handling subsystem
*/
LoRaMacCrypto _lora_crypto;
/** /**
* Central MAC layer data storage * Central MAC layer data storage
*/ */

View File

@ -26,59 +26,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "mbedtls/aes.h"
#include "mbedtls/cmac.h"
#include "LoRaMacCrypto.h" #include "LoRaMacCrypto.h"
#include "system/lorawan_data_structures.h" #include "system/lorawan_data_structures.h"
#if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_CIPHER_C) #if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_CIPHER_C)
/** LoRaMacCrypto::LoRaMacCrypto()
* CMAC/AES Message Integrity Code (MIC) Block B0 size : mic_block_b0(),
*/ computed_mic(),
#define LORAMAC_MIC_BLOCK_B0_SIZE 16 a_block(),
s_block()
/**
* MIC field computation initial data
*/
static uint8_t mic_block_b0[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/**
* Contains the computed MIC field.
*
* \remark Only the 4 first bytes are used
*/
static uint8_t computed_mic[16];
/**
* Encryption aBlock and sBlock
*/
static uint8_t a_block[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t s_block[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/**
* AES computation context variable
*/
static mbedtls_aes_context aes_ctx;
/**
* CMAC computation context variable
*/
static mbedtls_cipher_context_t aes_cmac_ctx[1];
#define AES_CMAC_KEY_LENGTH 16
int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint32_t *mic)
{ {
mic_block_b0[0] = 0x49;
a_block[0] = 0x01;
}
int LoRaMacCrypto::compute_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, const uint32_t key_length,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint32_t *mic)
{
int ret = 0; int ret = 0;
mic_block_b0[5] = dir; mic_block_b0[5] = dir;
@ -104,13 +72,11 @@ int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, key_length);
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0, ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0, sizeof(mic_block_b0));
LORAMAC_MIC_BLOCK_B0_SIZE);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
@ -133,9 +99,10 @@ exit: mbedtls_cipher_free(aes_cmac_ctx);
return ret; return ret;
} }
int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key, int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size,
uint32_t address, uint8_t dir, uint32_t seq_counter, const uint8_t *key, const uint32_t key_length,
uint8_t *enc_buffer) uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer)
{ {
uint16_t i; uint16_t i;
uint8_t bufferIndex = 0; uint8_t bufferIndex = 0;
@ -143,7 +110,7 @@ int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
int ret = 0; int ret = 0;
mbedtls_aes_init(&aes_ctx); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
@ -190,16 +157,18 @@ exit: mbedtls_aes_free(&aes_ctx);
return ret; return ret;
} }
int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key, int LoRaMacCrypto::decrypt_payload(const uint8_t *buffer, uint16_t size,
uint32_t address, uint8_t dir, uint32_t seq_counter, const uint8_t *key, uint32_t key_length,
uint8_t *dec_buffer) uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer)
{ {
return encrypt_payload(buffer, size, key, address, dir, seq_counter, return encrypt_payload(buffer, size, key, key_length, address, dir, seq_counter,
dec_buffer); dec_buffer);
} }
int compute_join_frame_mic(const uint8_t *buffer, uint16_t size, int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t *mic) const uint8_t *key, uint32_t key_length,
uint32_t *mic)
{ {
int ret = 0; int ret = 0;
@ -211,8 +180,7 @@ int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key, key_length);
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
@ -235,14 +203,15 @@ exit: mbedtls_cipher_free(aes_cmac_ctx);
return ret; return ret;
} }
int decrypt_join_frame(const uint8_t *buffer, uint16_t size, const uint8_t *key, int LoRaMacCrypto::decrypt_join_frame(const uint8_t *buffer, uint16_t size,
uint8_t *dec_buffer) const uint8_t *key, uint32_t key_length,
uint8_t *dec_buffer)
{ {
int ret = 0; int ret = 0;
mbedtls_aes_init(&aes_ctx); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
@ -261,9 +230,9 @@ exit: mbedtls_aes_free(&aes_ctx);
return ret; return ret;
} }
int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce, int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *key, uint32_t key_length,
uint16_t dev_nonce, uint8_t *nwk_skey, const uint8_t *app_nonce, uint16_t dev_nonce,
uint8_t *app_skey) uint8_t *nwk_skey, uint8_t *app_skey)
{ {
uint8_t nonce[16]; uint8_t nonce[16];
uint8_t *p_dev_nonce = (uint8_t *) &dev_nonce; uint8_t *p_dev_nonce = (uint8_t *) &dev_nonce;
@ -271,7 +240,7 @@ int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
mbedtls_aes_init(&aes_ctx); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, key_length);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
@ -294,12 +263,17 @@ int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
} }
#else #else
LoRaMacCrypto::LoRaMacCrypto()
{
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
}
// If mbedTLS is not configured properly, these dummies will ensure that // If mbedTLS is not configured properly, these dummies will ensure that
// user knows what is wrong and in addition to that these ensure that // user knows what is wrong and in addition to that these ensure that
// Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction // Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction
// with mbedTLS is not being used. // with mbedTLS is not being used.
int compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t, int LoRaMacCrypto::compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t,
uint8_t dir, uint32_t, uint32_t *) uint8_t dir, uint32_t, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -307,8 +281,8 @@ int compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, int LoRaMacCrypto::encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t,
uint8_t , uint32_t , uint8_t *) uint8_t , uint32_t , uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -316,8 +290,8 @@ int encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, int LoRaMacCrypto::decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t,
uint8_t , uint32_t , uint8_t *) uint8_t , uint32_t , uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -325,7 +299,7 @@ int decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t *) int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -333,7 +307,7 @@ int compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint8_t *) int LoRaMacCrypto::decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint32_t, uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -341,8 +315,8 @@ int decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint8_t *)
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int compute_skeys_for_join_frame(const uint8_t *, const uint8_t *, uint16_t , int LoRaMacCrypto::compute_skeys_for_join_frame(const uint8_t *, uint32_t, const uint8_t *, uint16_t ,
uint8_t *, uint8_t *) uint8_t *, uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");

View File

@ -1,4 +1,6 @@
/** /**
\code
/ _____) _ | | / _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__ ( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \ \____ \| ___ | (_ _) ___ |/ ___) _ \
@ -11,6 +13,8 @@
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions=============== embedded.connectivity.solutions===============
\endcode
Description: LoRa MAC Crypto implementation Description: LoRa MAC Crypto implementation
License: Revised BSD License, see LICENSE.TXT file include in the project License: Revised BSD License, see LICENSE.TXT file include in the project
@ -26,97 +30,150 @@ SPDX-License-Identifier: BSD-3-Clause
#ifndef MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__ #ifndef MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__
#define MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__ #define MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__
/** #include "mbedtls/aes.h"
* Computes the LoRaMAC frame MIC field #include "mbedtls/cmac.h"
*
* @param [in] buffer - Data buffer
* @param [in] size - Data buffer size
* @param [in] key - AES key to be used
* @param [in] address - Frame address
* @param [in] dir - Frame direction [0: uplink, 1: downlink]
* @param [in] seq_counter - Frame sequence counter
* @param [out] mic - Computed MIC field
*
* @return 0 if successful, or a cipher specific error code
*/
int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint32_t *mic);
/**
* Performs payload encryption class LoRaMacCrypto
* {
* @param [in] buffer - Data buffer public:
* @param [in] size - Data buffer size /**
* @param [in] key - AES key to be used * Constructor
* @param [in] address - Frame address */
* @param [in] dir - Frame direction [0: uplink, 1: downlink] LoRaMacCrypto();
* @param [in] seq_counter - Frame sequence counter
* @param [out] enc_buffer - Encrypted buffer /**
* * Computes the LoRaMAC frame MIC field
* @return 0 if successful, or a cipher specific error code *
*/ * @param [in] buffer - Data buffer
int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key, * @param [in] size - Data buffer size
* @param [in] key - AES key to be used
* @param [in] key_length - Length of the key (bits)
* @param [in] address - Frame address
* @param [in] dir - Frame direction [0: uplink, 1: downlink]
* @param [in] seq_counter - Frame sequence counter
* @param [out] mic - Computed MIC field
*
* @return 0 if successful, or a cipher specific error code
*/
int compute_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t key_length,
uint32_t address, uint8_t dir, uint32_t seq_counter, uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer); uint32_t *mic);
/** /**
* Performs payload decryption * Performs payload encryption
* *
* @param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* @param [in] size - Data buffer size * @param [in] size - Data buffer size
* @param [in] key - AES key to be used * @param [in] key - AES key to be used
* @param [in] address - Frame address * @param [in] key_length - Length of the key (bits)
* @param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] address - Frame address
* @param [in] seq_counter - Frame sequence counter * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* @param [out] dec_buffer - Decrypted buffer * @param [in] seq_counter - Frame sequence counter
* * @param [out] enc_buffer - Encrypted buffer
* @return 0 if successful, or a cipher specific error code *
*/ * @return 0 if successful, or a cipher specific error code
int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key, */
uint32_t address, uint8_t dir, uint32_t seq_counter, int encrypt_payload(const uint8_t *buffer, uint16_t size,
uint8_t *dec_buffer); const uint8_t *key, uint32_t key_length,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer);
/** /**
* Computes the LoRaMAC Join Request frame MIC field * Performs payload decryption
* *
* @param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* @param [in] size - Data buffer size * @param [in] size - Data buffer size
* @param [in] key - AES key to be used * @param [in] key - AES key to be used
* @param [out] mic - Computed MIC field * @param [in] key_length - Length of the key (bits)
* * @param [in] address - Frame address
* @return 0 if successful, or a cipher specific error code * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* * @param [in] seq_counter - Frame sequence counter
*/ * @param [out] dec_buffer - Decrypted buffer
int compute_join_frame_mic(const uint8_t *buffer, uint16_t size, *
const uint8_t *key, uint32_t *mic); * @return 0 if successful, or a cipher specific error code
*/
int decrypt_payload(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t key_length,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC Join Request frame MIC field
* *
* @param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* @param [in] size - Data buffer size * @param [in] size - Data buffer size
* @param [in] key - AES key to be used * @param [in] key - AES key to be used
* @param [out] dec_buffer - Decrypted buffer * @param [in] key_length - Length of the key (bits)
* * @param [out] mic - Computed MIC field
* @return 0 if successful, or a cipher specific error code *
*/ * @return 0 if successful, or a cipher specific error code
int decrypt_join_frame(const uint8_t *buffer, uint16_t size, *
const uint8_t *key, uint8_t *dec_buffer); */
int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t key_length,
uint32_t *mic);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC join frame decryption
* *
* @param [in] key - AES key to be used * @param [in] buffer - Data buffer
* @param [in] app_nonce - Application nonce * @param [in] size - Data buffer size
* @param [in] dev_nonce - Device nonce * @param [in] key - AES key to be used
* @param [out] nwk_skey - Network session key * @param [in] key_length - Length of the key (bits)
* @param [out] app_skey - Application session key * @param [out] dec_buffer - Decrypted buffer
* *
* @return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce, int decrypt_join_frame(const uint8_t *buffer, uint16_t size,
uint16_t dev_nonce, uint8_t *nwk_skey, const uint8_t *key, uint32_t key_length,
uint8_t *app_skey ); uint8_t *dec_buffer);
/**
* Computes the LoRaMAC join frame decryption
*
* @param [in] key - AES key to be used
* @param [in] key_length - Length of the key (bits)
* @param [in] app_nonce - Application nonce
* @param [in] dev_nonce - Device nonce
* @param [out] nwk_skey - Network session key
* @param [out] app_skey - Application session key
*
* @return 0 if successful, or a cipher specific error code
*/
int compute_skeys_for_join_frame(const uint8_t *key, uint32_t key_length,
const uint8_t *app_nonce, uint16_t dev_nonce,
uint8_t *nwk_skey, uint8_t *app_skey);
private:
/**
* MIC field computation initial data
*/
uint8_t mic_block_b0[16];
/**
* Contains the computed MIC field.
*
* \remark Only the 4 first bytes are used
*/
uint8_t computed_mic[16];
/**
* Encryption aBlock and sBlock
*/
uint8_t a_block[16];
uint8_t s_block[16];
/**
* AES computation context variable
*/
mbedtls_aes_context aes_ctx;
/**
* CMAC computation context variable
*/
mbedtls_cipher_context_t aes_cmac_ctx[1];
};
#endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__ #endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__

View File

@ -1244,11 +1244,13 @@ typedef struct {
/*! /*!
* AES encryption/decryption cipher network session key * AES encryption/decryption cipher network session key
* NOTE! LoRaMac determines the length of the key based on sizeof this variable
*/ */
uint8_t nwk_skey[16]; uint8_t nwk_skey[16];
/*! /*!
* AES encryption/decryption cipher application session key * AES encryption/decryption cipher application session key
* NOTE! LoRaMac determines the length of the key based on sizeof this variable
*/ */
uint8_t app_skey[16]; uint8_t app_skey[16];