# Testbed for LoRaWAN Security: Design and Validation through Man-in-the-Middle Attacks Study
## 4 Experimental Results
### LoRaWAN MAC Interception and Decryption  
After confirming that the GNU Radio can decode LoRa-modulated radio transmissions, we focused on making it understand and decode the MAC-layer formatting and encoding. For this, we re-enabled the LoRaWAN support and payload encryption on the victim device. Recall that the part of the PHY payload (FRMPayload) is encrypted either with the AppSKey key (if the message carries application data) or with the NwkSKey key (if the message carries a MAC command); therefore, an attacker needs to possess these keys for decrypting the traffic of a specific ED. There are different ways to obtain these keys. For example, an insider might extract them from the database at AS or intercept the transmission and reconstruct them from the DevNonce, AppNonce and NetID. These can be extracted from the OTAA activation procedure (see Figure 3) by capturing the JoinReq (DevNonce) and the JoinAcc (AppNonce, NetID) as discussed in Section 2.1.2. The JoinReq is not encrypted and the DevNonce value (the last 2 bytes) might be extracted and used straight for the key reconstruction; however, the JoinAcc is already encrypted by using the AES 128 [38] in ECB mode with AppKey [6]. Often, the AppKey is stored in the memory of an ED in raw format and can be extracted by obtaining physical access to the serial interface. Once the AppKey is obtained, the JoinAcc can be decrypted to obtain the AppNonce and NetID, and start the reconstruction process. The sequences showing how this can be accomplished are depicted in Figure 11. The first byte indicates whether the sequence will be used for NwkSKey \(|0x01|\) or AppSKey \(|0x02|\) and it is followed by the AppNonce (3B), NetID (3B), DevNonce (2B) and Padding (7B, i.e., zeros are appended until data length becomes a multiple of sixteen). Using these sequences, it is possible to obtain the NwkSKey and/or AppSKey:  
\[NwkSKey=AES_{128}(AppKey,|0x01|AppNonce|NetID|DevNonce|pad_{16}|), \tag{1}\]  
\[AppSKey=AES_{128}(AppKey,|0x02|AppNonce|NetID|DevNonce|pad_{16}|). \tag{2}\]  
Based on the theoretical background above, we carried out a practical trial, summarized in Figure 12 and successfully demonstrated the possibility of decrypting the messages within the LoRaWAN session. First, we obtained the AppKey by physically accessing the victim's serial interface. Then, we captured the PHY layer radio packet by eavesdropping the target device (RHF PS01509 described in Section 3.1.1) by SDR (HW, RTL-SDR Stick described in Section 3.1.3) and GNURadio (SW, described in Section 4.1). Recall that only a part of the message is encrypted (FRMPayload), and the rest of the message is not encrypted (Synchronization message, CRC, MHDR, MIC, DevAddr, FCtrl, FCnt, FOpts and FPort). Gradually, we parsed the message into parts until we were left with only the part of the FRMPayload. When decrypting the FRMPayload, it is essential to determine which key was used for encryption (AppSKey or NwkSKey). This can be found using the FPort value; therefore, if the FPort field contains 0, it is reserved only for MAC commands (e.g., ADR, link check \(\ldots\)), and it is encrypted with NwkSKey. If application data are transmitted  
Figure 11: String for deriving session keys. Figure 10: Decoding of the captured LoRa packet. (FPort value 1-223), LoRaWAN MAC protocol testing (FPORT 224) or ports reserved for future standardized application extensions (FPORT 225-255), FRMPayload is encrypted by the AppSKey application key. Subsequently, we generated \(k\) of 16-bytes \(A_{i}\) blocks. The number of blocks (\(k\)) depends on the size of the FRMPayload. The first byte is always 0x01. The next four bytes are equal to 0x00, followed by a byte to determine the direction of communication (\(|0x00|\) for uplink or \(|0x01|\) for downlink), 4 bytes for the device address, 4 bytes are reserved for the frame counter (2 bytes of FCnt followed by 2 bytes of zero octets), and one byte is set to 0x00. The last byte is \(i\), which signalizes the order number of \(A_{i}\) blocks.