1 /*!
2  * \file      LoRaMacCrypto.h
3  *
4  * \brief     LoRa MAC layer cryptographic functionality implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
18  *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19  *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
20  *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21  *              embedded.connectivity.solutions===============
22  *
23  * \endcode
24  *
25  * \author    Miguel Luis ( Semtech )
26  *
27  * \author    Gregory Cristian ( Semtech )
28  *
29  * \author    Daniel Jaeckle ( STACKFORCE )
30  *
31  * \author    Johannes Bruder ( STACKFORCE )
32  *
33  * addtogroup LORAMAC
34  * \{
35  *
36  */
37 #ifndef __LORAMAC_CRYPTO_H__
38 #define __LORAMAC_CRYPTO_H__
39 
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif
44 
45 #include <stdlib.h>
46 #include <stdint.h>
47 #include <stdbool.h>
48 #include "utilities.h"
49 #include "LoRaMacTypes.h"
50 #include "LoRaMacMessageTypes.h"
51 #include "LoRaMacCryptoNvm.h"
52 
53 /*!
54  * Indicates if LoRaWAN 1.1.x crypto scheme is enabled
55  */
56 #ifndef USE_LRWAN_1_1_X_CRYPTO
57 #define USE_LRWAN_1_1_X_CRYPTO                      1
58 #endif
59 
60 /*!
61  * Indicates if a random devnonce must be used or not
62  */
63 #define USE_RANDOM_DEV_NONCE                        0
64 
65 /*!
66  * Indicates if JoinNonce is counter based and requires to be checked on 1.0.x devices
67  * \remark Only applies to LoRaWAN 1.0.x when following recomendations provided
68  *         by "Technical Recommendations for Preventing State Synchronization
69  *         Issues around LoRaWAN� 1.0.x Join Procedure"
70  *         https://lora-alliance.org/wp-content/uploads/2020/11/lorawan-1.0.x-join-synch-issues-remedies-v1.0.0.pdf
71  */
72 #define USE_10X_JOIN_NONCE_COUNTER_CHECK            0
73 
74 /*!
75  * Initial value of the frame counters
76  */
77 #define FCNT_DOWN_INITIAL_VALUE          0xFFFFFFFF
78 
79 /*!
80  * LoRaMac Crypto Status
81  */
82 typedef enum eLoRaMacCryptoStatus
83 {
84     /*!
85      * No error occurred
86      */
87     LORAMAC_CRYPTO_SUCCESS = 0,
88     /*!
89      * MIC does not match
90      */
91     LORAMAC_CRYPTO_FAIL_MIC,
92     /*!
93      * Address does not match
94      */
95     LORAMAC_CRYPTO_FAIL_ADDRESS,
96     /*!
97      * JoinNonce was not greater than previous one.
98      */
99     LORAMAC_CRYPTO_FAIL_JOIN_NONCE,
100     /*!
101      * RJcount0 reached 2^16-1
102      */
103     LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
104     /*!
105      * FCNT_ID is not supported
106      */
107     LORAMAC_CRYPTO_FAIL_FCNT_ID,
108     /*!
109      * FCntUp/Down check failed (new FCnt is smaller than previous one)
110      */
111     LORAMAC_CRYPTO_FAIL_FCNT_SMALLER,
112     /*!
113      * FCntUp/Down check failed (duplicated)
114      */
115     LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED,
116     /*!
117      * Not allowed parameter value
118      */
119     LORAMAC_CRYPTO_FAIL_PARAM,
120     /*!
121      * Null pointer exception
122      */
123     LORAMAC_CRYPTO_ERROR_NPE,
124     /*!
125      * Invalid key identifier exception
126      */
127     LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID,
128     /*!
129      * Invalid address identifier exception
130      */
131     LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID,
132     /*!
133      * Invalid LoRaWAN specification version
134      */
135     LORAMAC_CRYPTO_ERROR_INVALID_VERSION,
136     /*!
137      * Incompatible buffer size
138      */
139     LORAMAC_CRYPTO_ERROR_BUF_SIZE,
140     /*!
141      * The secure element reports an error
142      */
143     LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC,
144     /*!
145      * Error from parser reported
146      */
147     LORAMAC_CRYPTO_ERROR_PARSER,
148     /*!
149      * Error from serializer reported
150      */
151     LORAMAC_CRYPTO_ERROR_SERIALIZER,
152     /*!
153      * RJcount1 reached 2^16-1 which should never happen
154      */
155     LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW,
156     /*!
157      * Undefined Error occurred
158      */
159     LORAMAC_CRYPTO_ERROR,
160 }LoRaMacCryptoStatus_t;
161 
162 /*!
163  * Signature of callback function to be called by the LoRaMac Crypto module when the
164  * non-volatile context have to be stored. It is also possible to save the entire
165  * crypto module context.
166  *
167  */
168 typedef void ( *LoRaMacCryptoNvmEvent )( void );
169 
170 /*!
171  * Initialization of LoRaMac Crypto module
172  * It sets initial values of volatile variables and assigns the non-volatile context.
173  *
174  * \param[IN]     nvm                 - Pointer to the non-volatile memory data
175  *                                      structure.
176  * \retval                            - Status of the operation
177  */
178 LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmData_t* nvm );
179 
180 /*!
181  * Sets the LoRaWAN specification version to be used.
182  *
183  * \warning This function should be used for ABP only. In case of OTA the version will be set automatically.
184  *
185  * \param[IN]     version             - LoRaWAN specification version to be used.
186  *
187  * \retval                            - Status of the operation
188  */
189 LoRaMacCryptoStatus_t LoRaMacCryptoSetLrWanVersion( Version_t version );
190 
191 /*!
192  * Returns updated fCntID downlink counter value.
193  *
194  * \param[IN]     fCntID         - Frame counter identifier
195  * \param[IN]     frameFcnt      - Received frame counter (used to update current counter value)
196  * \param[OUT]    currentDown    - Current downlink counter value
197  * \retval                       - Status of the operation
198  */
199 LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint32_t frameFcnt, uint32_t* currentDown );
200 
201 /*!
202  * Returns updated fCntUp uplink counter value.
203  *
204  * \param[IN]     currentUp      - Uplink counter value
205  * \retval                       - Status of the operation
206  */
207 LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp );
208 
209 /*!
210  * Computes next RJcount0 or RJcount1 counter value.
211  *
212  * \param[IN]     fCntID          - Frame counter identifier
213  * \param[OUT]    rJcount         - RJcount value
214  *
215  * \retval                        - Status of the operation
216  */
217 LoRaMacCryptoStatus_t LoRaMacCryptoGetRJcount( FCntIdentifier_t fCntID, uint16_t* rJcount );
218 
219 /*!
220  * Provides multicast context.
221  *
222  * \param[IN]     multicastList - Pointer to the multicast context list
223  *
224  * \retval                      - Status of the operation
225  */
226 LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList );
227 
228 /*!
229  * Sets a key
230  *
231  * \param[IN]     keyID          - Key identifier
232  * \param[IN]     key            - Key value (16 byte), if its a multicast key it must be encrypted with McKEKey
233  * \retval                       - Status of the operation
234  */
235 LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( KeyIdentifier_t keyID, uint8_t* key );
236 
237 /*!
238  * Prepares the join-request message.
239  * It computes the mic and add it to the message.
240  *
241  * \param[IN/OUT] macMsg         - Join-request message object
242  * \retval                       - Status of the operation
243  */
244 LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg );
245 
246 /*!
247  * Prepares a rejoin-request type 1 message.
248  * It computes the mic and add it to the message.
249  *
250  * \param[IN/OUT] macMsg         - Rejoin message object
251  * \retval                       - Status of the operation
252  */
253 LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaMacMessageReJoinType1_t* macMsg );
254 
255 /*!
256  * Prepares a rejoin-request type 0 or 2 message.
257  * It computes the mic and add it to the message.
258  *
259  * \param[IN/OUT] macMsg         - Rejoin message object
260  * \retval                       - Status of the operation
261  */
262 LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg );
263 
264 /*!
265  * Handles the join-accept message.
266  * It decrypts the message, verifies the MIC and if successful derives the session keys.
267  *
268  * \param[IN]     joinReqType    - Type of last join-request or rejoin which triggered the join-accept response
269  * \param[IN]     joinEUI        - Join server EUI (8 byte)
270  * \param[IN/OUT] macMsg         - Join-accept message object
271  * \retval                       - Status of the operation
272  */
273 LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEUI, LoRaMacMessageJoinAccept_t* macMsg );
274 
275 /*!
276  * Secures a message (encryption + integrity).
277  *
278  * \param[IN]     fCntUp          - Uplink sequence counter
279  * \param[IN]     txDr            - Data rate used for the transmission
280  * \param[IN]     txCh            - Index of the channel used for the transmission
281  * \param[IN/OUT] macMsg          - Data message object
282  * \retval                        - Status of the operation
283  */
284 LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t* macMsg );
285 
286 /*!
287  * Unsecures a message (decryption + integrity verification).
288  *
289  * \param[IN]     addrID          - Address identifier
290  * \param[IN]     address         - Address
291  * \param[IN]     fCntID          - Frame counter identifier
292  * \param[IN]     fCntDown        - Downlink sequence counter
293  * \param[IN/OUT] macMsg          - Data message object
294  * \retval                        - Status of the operation
295  */
296 LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg );
297 
298 /*!
299  * Derives the McRootKey from the AppKey.
300  *
301  * 1.0.x
302  * McRootKey = aes128_encrypt(AppKey, 0x00 | pad16)
303  *
304  * 1.1.x
305  * McRootKey = aes128_encrypt(AppKey, 0x20 | pad16)
306  *
307  * \param[IN]     versionMinor    - LoRaWAN specification minor version to be used.
308  * \param[IN]     keyID           - Key identifier of the root key to use to perform the derivation ( AppKey )
309  * \retval                        - Status of the operation
310  */
311 LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( uint8_t versionMinor, KeyIdentifier_t keyID );
312 
313 /*!
314  * Derives the McKEKey from the McRootKey.
315  *
316  * McKEKey = aes128_encrypt(McRootKey , 0x00  | pad16)
317  *
318  * \param[IN]     keyID           - Key identifier of the root key to use to perform the derivation ( McRootKey )
319  * \retval                        - Status of the operation
320  */
321 LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID );
322 
323 /*!
324  * Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
325  *
326  * McAppSKey = aes128_encrypt(McKey, 0x01 | McAddr | pad16)
327  * McNwkSKey = aes128_encrypt(McKey, 0x02 | McAddr | pad16)
328  *
329  * \param[IN]     addrID          - Address identifier to select the multicast group
330  * \param[IN]     mcAddr          - Multicast group address (4 bytes)
331  * \retval                        - Status of the operation
332  */
333 LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t addrID, uint32_t mcAddr );
334 
335 /*! \} addtogroup LORAMAC */
336 
337 #ifdef __cplusplus
338 }
339 #endif
340 
341 #endif // __LORAMAC_CRYPTO_H__
342