diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index 09f4cce306..4b4c631f39 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -643,12 +643,6 @@ void LoRaWANStack::process_transmission(void) { tr_debug("Transmission completed"); - if (_loramac.get_server_type() == LW1_1 && _device_mode_ind_ongoing) { - _device_mode_ind_ongoing = false; - _loramac.set_device_class(device_class_t(_new_class_type), mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception)); - send_event_to_application(CLASS_CHANGED); - } - make_tx_metadata_available(); if (_device_current_state == DEVICE_STATE_JOINING) { @@ -663,6 +657,12 @@ void LoRaWANStack::process_transmission(void) } _loramac.on_radio_tx_done(_tx_timestamp); + + if (_loramac.get_server_type() == LW1_1 && _device_mode_ind_ongoing == true) { + _device_mode_ind_ongoing = false; + _loramac.set_device_class(device_class_t(_new_class_type), mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception)); + send_event_to_application(CLASS_CHANGED); + } } void LoRaWANStack::post_process_tx_with_reception() @@ -779,7 +779,7 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size bool joined = _loramac.nwk_joined(); - _loramac.on_radio_rx_done(payload, size, rssi, snr, callback(this, &LoRaWANStack::mlme_confirm_handler)); + _loramac.on_radio_rx_done(payload, size, rssi, snr, mbed::callback(this, &LoRaWANStack::mlme_confirm_handler)); if (_loramac.get_mlme_confirmation()->pending) { _loramac.post_process_mlme_request(); @@ -865,6 +865,10 @@ void LoRaWANStack::process_reception_timeout(bool is_timeout) * never occurs. */ if (slot == RX_SLOT_WIN_2) { +<<<<<<< HEAD +======= + +>>>>>>> c998cc4... Implementing CR-FcntDwn-usage-in-FOpts-encryption post_process_tx_no_reception(); _loramac.post_process_mcps_req(); diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index d603212ffd..9f52c12652 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -67,6 +67,7 @@ using namespace mbed; */ #define DOWN_LINK 1 +#define MHDR_LEN 1 #define PORT_FIELD_LEN 1 #define FHDR_LEN_WITHOUT_FOPTS 7 @@ -244,6 +245,7 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay _params.rx_buffer[9] = _params.dev_nonce & 0xFF; // DevNonce _params.rx_buffer[10] = (_params.dev_nonce >> 8) & 0xFF; + // MIC is encrypted as part of payload mic_start = size + 11 - LORAMAC_MFR_LEN; payload_start += 11; @@ -283,13 +285,6 @@ loramac_event_info_status_t LoRaMac::handle_join_accept_frame(const uint8_t *pay return LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; } - tr_debug("%s", trace_array(_params.keys.nwk_skey, 16)); - tr_debug("%s", trace_array(_params.keys.app_skey, 16)); - tr_debug("%s", trace_array(_params.keys.snwk_sintkey, 16)); - tr_debug("%s", trace_array(_params.keys.nwk_senckey, 16)); - tr_debug("%s", trace_array(decrypt_key, 16)); - - _params.net_id = (uint32_t) _params.rx_buffer[payload_start + 3]; _params.net_id |= ((uint32_t) _params.rx_buffer[payload_start + 4] << 8); _params.net_id |= ((uint32_t) _params.rx_buffer[payload_start + 5] << 16); @@ -393,6 +388,7 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, uint8_t *app_skey, uint32_t address, uint32_t downlink_counter, + seq_counter_type_t cnt_type, int16_t rssi, int8_t snr, Callback confirm_handler) @@ -414,8 +410,9 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, address, DOWN_LINK, downlink_counter, - 1, // FMRPayload - _params.rx_buffer) != 0) { + cnt_type, + FRMPAYLOAD, + _params.rx_buffer, _params.server_type) != 0) { _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; } @@ -442,7 +439,7 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, return; } - if(!extract_mac_commands_only(payload, snr, fopts_len, confirm_handler)) { + if(!extract_mac_commands_only(payload, size, snr, fopts_len, confirm_handler)) { return; } @@ -454,8 +451,10 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, address, DOWN_LINK, downlink_counter, - 1, // FMRPayload - _params.rx_buffer) != 0) { + cnt_type, + FRMPAYLOAD, + _params.rx_buffer, + _params.server_type) != 0) { _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; } else { _mcps_indication.buffer = _params.rx_buffer; @@ -465,30 +464,29 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, } bool LoRaMac::extract_mac_commands_only(const uint8_t *payload, + uint16_t size, int8_t snr, uint8_t fopts_len, Callback confirm_handler) { if (fopts_len > 0) { - uint8_t buffer[15]; + uint8_t buffer[15] = {0}; - unsigned pld_idx = _dl_fport_available ? - FHDR_LEN_WITHOUT_FOPTS + PORT_FIELD_LEN + fopts_len : - FHDR_LEN_WITHOUT_FOPTS + fopts_len; + unsigned pld_idx = MHDR_LEN + FHDR_LEN_WITHOUT_FOPTS; if (_params.server_type == LW1_1) { if (0 != _lora_crypto.decrypt_payload(payload + pld_idx, fopts_len, _params.keys.nwk_senckey, sizeof(_params.keys.nwk_senckey) * 8, _params.dev_addr, DOWN_LINK, _params.dl_frame_counter, - 0, // FOpts field - buffer)) { + NFCNT_DOWN, + FOPTS, + buffer, + _params.server_type)) { _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL; return false; } - tr_debug("%s", trace_array(buffer, 15)); - tr_debug("%s", buffer); } else { memcpy(buffer, payload + pld_idx, fopts_len); } @@ -524,7 +522,7 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, multicast_params_t *cur_multicast_params; uint32_t address = 0; uint32_t downlink_counter = 0; - uint8_t app_payload_start_index = 0; + seq_counter_type_t cnt_type; uint8_t *nwk_skey = _params.keys.nwk_skey; uint8_t *mic_key = _params.keys.nwk_skey; uint8_t *app_skey = _params.keys.app_skey; @@ -541,11 +539,9 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, fctrl.value = payload[ptr_pos++]; - int check_frm_len = size - (fctrl.bits.fopts_len + LORA_MAC_FRMPAYLOAD_OVERHEAD); if (check_frm_len < 0) { - tr_debug("Port field was excluded in DOWNLINK"); _dl_fport_available = false; } @@ -584,10 +580,6 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, downlink_counter = _params.dl_frame_counter; } - app_payload_start_index = _dl_fport_available ? - FHDR_LEN_WITHOUT_FOPTS + PORT_FIELD_LEN + fctrl.bits.fopts_len : - FHDR_LEN_WITHOUT_FOPTS + fctrl.bits.fopts_len; - if (_params.server_type == LW1_1) { if (_params.is_node_ack_requested && fctrl.bits.ack) { confFCnt = _mcps_confirmation.ul_frame_counter; @@ -595,8 +587,10 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, if (!is_multicast) { if (_dl_fport_available && fport != 0) { downlink_counter = _params.app_dl_frame_counter; + cnt_type = AFCNT_DOWN; } else { nwk_skey = _params.keys.nwk_senckey; + cnt_type = NFCNT_DOWN; } } } @@ -700,10 +694,10 @@ void LoRaMac::handle_data_frame(const uint8_t *const payload, if (check_frm_len > 0) { extract_data_and_mac_commands(payload, size, fctrl.bits.fopts_len, nwk_skey, app_skey, address, - downlink_counter, rssi, snr, + downlink_counter, cnt_type, rssi, snr, confirm_handler); } else { - extract_mac_commands_only(payload, snr, fctrl.bits.fopts_len, confirm_handler); + extract_mac_commands_only(payload, size, snr, fctrl.bits.fopts_len, confirm_handler); } // Handle proprietary messages. @@ -1909,8 +1903,10 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, sizeof(_params.keys.nwk_senckey) * 8, _params.dev_addr, UP_LINK, _params.ul_frame_counter, - 0, //FOpts - &_params.tx_buffer[pkt_header_len])) { + FCNT_UP, + FOPTS, + &_params.tx_buffer[pkt_header_len], + _params.server_type)) { status = LORAWAN_STATUS_CRYPTO_FAIL; } pkt_header_len += mac_commands_len; @@ -1949,8 +1945,10 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, key, key_length, _params.dev_addr, UP_LINK, _params.ul_frame_counter, - 1, // FMRPayload - &_params.tx_buffer[pkt_header_len])) { + FCNT_UP, + FRMPAYLOAD, + &_params.tx_buffer[pkt_header_len], + _params.server_type)) { status = LORAWAN_STATUS_CRYPTO_FAIL; } } diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index f09f7c0e79..1f398e8221 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -554,6 +554,7 @@ private: uint8_t fopts_len, uint8_t *nwk_skey, uint8_t *app_skey, uint32_t address, uint32_t downlink_frame_counter, + seq_counter_type_t cnt_type, int16_t rssi, int8_t snr, mbed::Callback confirm_handler); /** @@ -561,7 +562,7 @@ private: * payload if there is no data * @return True if successful, false otherwise */ - bool extract_mac_commands_only(const uint8_t *payload, int8_t snr, uint8_t fopts_len, + bool extract_mac_commands_only(const uint8_t *payload, uint16_t size, int8_t snr, uint8_t fopts_len, mbed::Callback confirm_handler); /** diff --git a/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp b/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp index b5cb99e63a..0c29ddd908 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacCrypto.cpp @@ -128,13 +128,15 @@ exit: int LoRaMacCrypto::encrypt_payload(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, - uint16_t a1_block_start, - uint8_t *enc_buffer) + seq_counter_type_t seq_cnt_type, + payload_type_t pld_type, + uint8_t *enc_buffer, + server_type_t serv_type) { uint16_t i; uint8_t bufferIndex = 0; int ret = 0; - uint8_t a_block[16] = {}; + uint8_t a_block[16] = {0}; uint8_t s_block[16] = {}; mbedtls_aes_init(&aes_ctx); @@ -144,6 +146,17 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, } a_block[0] = 0x01; + + if (serv_type == LW1_1 && pld_type == FOPTS) { + if ((seq_cnt_type == FCNT_UP || seq_cnt_type == NFCNT_DOWN)) { + a_block[4] = 0x01; + } else if (seq_cnt_type == AFCNT_DOWN) { + a_block[4] = 0x02; + } + } + + + a_block[5] = dir; a_block[6] = (address) & 0xFF; @@ -156,9 +169,11 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, a_block[12] = (seq_counter >> 16) & 0xFF; a_block[13] = (seq_counter >> 24) & 0xFF; + a_block[15] = 0x01; + while (size >= 16) { - a_block[15] = ((a1_block_start) & 0xFF); - a1_block_start++; + a_block[15]++; + ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block, s_block); if (0 != ret) { @@ -173,7 +188,6 @@ int LoRaMacCrypto::encrypt_payload(const uint8_t *buffer, uint16_t size, } if (size > 0) { - a_block[15] = ((a1_block_start) & 0xFF); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block, s_block); if (0 != ret) { @@ -193,11 +207,13 @@ exit: int LoRaMacCrypto::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, - uint16_t a1_block_start, - uint8_t *dec_buffer) + seq_counter_type_t seq_cnt_type, + payload_type_t pld_type, + uint8_t *dec_buffer, + server_type_t serv_type) { return encrypt_payload(buffer, size, key, key_length, address, dir, seq_counter, - a1_block_start, dec_buffer); + seq_cnt_type, pld_type, dec_buffer, serv_type); } int LoRaMacCrypto::compute_join_frame_mic(const uint8_t *buffer, uint16_t size, diff --git a/features/lorawan/lorastack/mac/LoRaMacCrypto.h b/features/lorawan/lorastack/mac/LoRaMacCrypto.h index 38dfc5b0bf..1e468d0075 100644 --- a/features/lorawan/lorastack/mac/LoRaMacCrypto.h +++ b/features/lorawan/lorastack/mac/LoRaMacCrypto.h @@ -87,8 +87,10 @@ public: int encrypt_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, - uint16_t a1_block_start, - uint8_t *enc_buffer); + seq_counter_type_t seq_cnt_type, + payload_type_t pld_type, + uint8_t *enc_buffer, + server_type_t serv_type); /** * Performs payload decryption @@ -108,8 +110,10 @@ public: 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, - uint16_t a1_block_start, - uint8_t *dec_buffer); + seq_counter_type_t seq_cnt_type, + payload_type_t pld_type, + uint8_t *dec_buffer, + server_type_t serv_type); /** * Computes the LoRaMAC Join Request frame MIC field diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index b982aaeed9..3c7469157b 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -161,10 +161,21 @@ typedef enum { } join_req_type_t; typedef enum { - LW1_0_2, + LW1_0_2 = 0, LW1_1 } server_type_t; +typedef enum { + FCNT_UP = 0, + NFCNT_DOWN, + AFCNT_DOWN +} seq_counter_type_t; + +typedef enum { + FRMPAYLOAD = 0, + FOPTS +} payload_type_t; + /*! * The global MAC layer parameters. */