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