Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1518 lines
43 KiB

  1. /*!
  2. * \file LoRaMacCrypto.c
  3. *
  4. * \brief LoRa MAC layer cryptography 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. #include <stdbool.h>
  34. #include <stdlib.h>
  35. #include <stdint.h>
  36. #include "utilities.h"
  37. #include "secure-element.h"
  38. #include "LoRaMacParser.h"
  39. #include "LoRaMacSerializer.h"
  40. #include "LoRaMacCrypto.h"
  41. /*
  42. * Frame direction definition for uplink communications
  43. */
  44. #define UPLINK 0
  45. /*
  46. * Frame direction definition for downlink communications
  47. */
  48. #define DOWNLINK 1
  49. /*
  50. * CMAC/AES Message Integrity Code (MIC) Block B0 size
  51. */
  52. #define MIC_BLOCK_BX_SIZE 16
  53. /*
  54. * Number of security context entries
  55. */
  56. #define NUM_OF_SEC_CTX 5
  57. /*
  58. * Maximum size of the message that can be handled by the crypto operations
  59. */
  60. #define CRYPTO_MAXMESSAGE_SIZE 256
  61. /*
  62. * Maximum size of the buffer for crypto operations
  63. */
  64. #define CRYPTO_BUFFER_SIZE CRYPTO_MAXMESSAGE_SIZE + MIC_BLOCK_BX_SIZE
  65. /*
  66. * Key-Address item
  67. */
  68. typedef struct sKeyAddr
  69. {
  70. /*
  71. * Address identifier
  72. */
  73. AddressIdentifier_t AddrID;
  74. /*
  75. * Application session key
  76. */
  77. KeyIdentifier_t AppSkey;
  78. /*
  79. * Network session key
  80. */
  81. KeyIdentifier_t NwkSkey;
  82. /*
  83. * Rootkey (Multicast only)
  84. */
  85. KeyIdentifier_t RootKey;
  86. }KeyAddr_t;
  87. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  88. /*
  89. * RJcount0 is a counter incremented with every Type 0 or 2 Rejoin frame transmitted.
  90. */
  91. static uint16_t RJcount0;
  92. #endif
  93. /*
  94. * Non volatile module context.
  95. */
  96. static LoRaMacCryptoNvmData_t* CryptoNvm;
  97. /*
  98. * Key-Address list
  99. */
  100. static KeyAddr_t KeyAddrList[NUM_OF_SEC_CTX] =
  101. {
  102. { MULTICAST_0_ADDR, MC_APP_S_KEY_0, MC_NWK_S_KEY_0, MC_KEY_0 },
  103. { MULTICAST_1_ADDR, MC_APP_S_KEY_1, MC_NWK_S_KEY_1, MC_KEY_1 },
  104. { MULTICAST_2_ADDR, MC_APP_S_KEY_2, MC_NWK_S_KEY_2, MC_KEY_2 },
  105. { MULTICAST_3_ADDR, MC_APP_S_KEY_3, MC_NWK_S_KEY_3, MC_KEY_3 },
  106. { UNICAST_DEV_ADDR, APP_S_KEY, S_NWK_S_INT_KEY, NO_KEY }
  107. };
  108. /*
  109. * Encrypts the payload
  110. *
  111. * \param[IN] keyID - Key identifier
  112. * \param[IN] address - Address
  113. * \param[IN] dir - Frame direction ( Uplink or Downlink )
  114. * \param[IN] frameCounter - Frame counter
  115. * \param[IN] size - Size of data
  116. * \param[IN/OUT] buffer - Data buffer
  117. * \retval - Status of the operation
  118. */
  119. static LoRaMacCryptoStatus_t PayloadEncrypt( uint8_t* buffer, int16_t size, KeyIdentifier_t keyID, uint32_t address, uint8_t dir, uint32_t frameCounter )
  120. {
  121. if( buffer == 0 )
  122. {
  123. return LORAMAC_CRYPTO_ERROR_NPE;
  124. }
  125. uint8_t bufferIndex = 0;
  126. uint16_t ctr = 1;
  127. uint8_t sBlock[16] = { 0 };
  128. uint8_t aBlock[16] = { 0 };
  129. aBlock[0] = 0x01;
  130. aBlock[5] = dir;
  131. aBlock[6] = address & 0xFF;
  132. aBlock[7] = ( address >> 8 ) & 0xFF;
  133. aBlock[8] = ( address >> 16 ) & 0xFF;
  134. aBlock[9] = ( address >> 24 ) & 0xFF;
  135. aBlock[10] = frameCounter & 0xFF;
  136. aBlock[11] = ( frameCounter >> 8 ) & 0xFF;
  137. aBlock[12] = ( frameCounter >> 16 ) & 0xFF;
  138. aBlock[13] = ( frameCounter >> 24 ) & 0xFF;
  139. while( size > 0 )
  140. {
  141. aBlock[15] = ctr & 0xFF;
  142. ctr++;
  143. if( SecureElementAesEncrypt( aBlock, 16, keyID, sBlock ) != SECURE_ELEMENT_SUCCESS )
  144. {
  145. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  146. }
  147. for( uint8_t i = 0; i < ( ( size > 16 ) ? 16 : size ); i++ )
  148. {
  149. buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
  150. }
  151. size -= 16;
  152. bufferIndex += 16;
  153. }
  154. return LORAMAC_CRYPTO_SUCCESS;
  155. }
  156. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  157. /*
  158. * Encrypts the FOpts
  159. *
  160. * \param[IN] address - Address
  161. * \param[IN] dir - Frame direction ( Uplink or Downlink )
  162. * \param[IN] fCntID - Frame counter identifier
  163. * \param[IN] frameCounter - Frame counter
  164. * \param[IN] size - Size of data
  165. * \param[IN/OUT] buffer - Data buffer
  166. * \retval - Status of the operation
  167. */
  168. static LoRaMacCryptoStatus_t FOptsEncrypt( uint16_t size, uint32_t address, uint8_t dir, FCntIdentifier_t fCntID, uint32_t frameCounter, uint8_t* buffer )
  169. {
  170. if( buffer == 0 )
  171. {
  172. return LORAMAC_CRYPTO_ERROR_NPE;
  173. }
  174. uint8_t bufferIndex = 0;
  175. uint8_t sBlock[16] = { 0 };
  176. uint8_t aBlock[16] = { 0 };
  177. aBlock[0] = 0x01;
  178. if( CryptoNvm->LrWanVersion.Value > 0x01010000 )
  179. {
  180. // Introduced in LoRaWAN 1.1.1 specification
  181. switch( fCntID )
  182. {
  183. case FCNT_UP:
  184. {
  185. aBlock[4] = 0x01;
  186. break;
  187. }
  188. case N_FCNT_DOWN:
  189. {
  190. aBlock[4] = 0x01;
  191. break;
  192. }
  193. case A_FCNT_DOWN:
  194. {
  195. aBlock[4] = 0x02;
  196. break;
  197. }
  198. default:
  199. return LORAMAC_CRYPTO_FAIL_PARAM;
  200. }
  201. }
  202. aBlock[5] = dir;
  203. aBlock[6] = address & 0xFF;
  204. aBlock[7] = ( address >> 8 ) & 0xFF;
  205. aBlock[8] = ( address >> 16 ) & 0xFF;
  206. aBlock[9] = ( address >> 24 ) & 0xFF;
  207. aBlock[10] = frameCounter & 0xFF;
  208. aBlock[11] = ( frameCounter >> 8 ) & 0xFF;
  209. aBlock[12] = ( frameCounter >> 16 ) & 0xFF;
  210. aBlock[13] = ( frameCounter >> 24 ) & 0xFF;
  211. if( CryptoNvm->LrWanVersion.Value > 0x01010000 )
  212. {
  213. // Introduced in LoRaWAN 1.1.1 specification
  214. aBlock[15] = 0x01;
  215. }
  216. if( size > 0 )
  217. {
  218. if( SecureElementAesEncrypt( aBlock, 16, NWK_S_ENC_KEY, sBlock ) != SECURE_ELEMENT_SUCCESS )
  219. {
  220. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  221. }
  222. for( uint8_t i = 0; i < size; i++ )
  223. {
  224. buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
  225. }
  226. }
  227. return LORAMAC_CRYPTO_SUCCESS;
  228. }
  229. #endif
  230. /*
  231. * Prepares B0 block for cmac computation.
  232. *
  233. * \param[IN] msgLen - Length of message
  234. * \param[IN] keyID - Key identifier
  235. * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
  236. * \param[IN] devAddr - Device address
  237. * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
  238. * \param[IN] fCnt - Frame counter
  239. * \param[IN/OUT] b0 - B0 block
  240. * \retval - Status of the operation
  241. */
  242. static LoRaMacCryptoStatus_t PrepareB0( uint16_t msgLen, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint8_t* b0 )
  243. {
  244. if( b0 == 0 )
  245. {
  246. return LORAMAC_CRYPTO_ERROR_NPE;
  247. }
  248. b0[0] = 0x49;
  249. if( ( isAck == true ) && ( dir == DOWNLINK ) )
  250. {
  251. // confFCnt contains the frame counter value modulo 2^16 of the "confirmed" uplink or downlink frame that is being acknowledged
  252. uint16_t confFCnt = 0;
  253. confFCnt = ( uint16_t )( CryptoNvm->FCntList.FCntUp % 65536 );
  254. b0[1] = confFCnt & 0xFF;
  255. b0[2] = ( confFCnt >> 8 ) & 0xFF;
  256. }
  257. else
  258. {
  259. b0[1] = 0x00;
  260. b0[2] = 0x00;
  261. }
  262. b0[3] = 0x00;
  263. b0[4] = 0x00;
  264. b0[5] = dir;
  265. b0[6] = devAddr & 0xFF;
  266. b0[7] = ( devAddr >> 8 ) & 0xFF;
  267. b0[8] = ( devAddr >> 16 ) & 0xFF;
  268. b0[9] = ( devAddr >> 24 ) & 0xFF;
  269. b0[10] = fCnt & 0xFF;
  270. b0[11] = ( fCnt >> 8 ) & 0xFF;
  271. b0[12] = ( fCnt >> 16 ) & 0xFF;
  272. b0[13] = ( fCnt >> 24 ) & 0xFF;
  273. b0[14] = 0x00;
  274. b0[15] = msgLen & 0xFF;
  275. return LORAMAC_CRYPTO_SUCCESS;
  276. }
  277. /*
  278. * Computes cmac with adding B0 block in front.
  279. *
  280. * cmac = aes128_cmac(keyID, B0 | msg)
  281. *
  282. * \param[IN] msg - Message to compute the integrity code
  283. * \param[IN] len - Length of message
  284. * \param[IN] keyID - Key identifier
  285. * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
  286. * \param[IN] devAddr - Device address
  287. * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
  288. * \param[IN] fCnt - Frame counter
  289. * \param[OUT] cmac - Computed cmac
  290. * \retval - Status of the operation
  291. */
  292. static LoRaMacCryptoStatus_t ComputeCmacB0( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint32_t* cmac )
  293. {
  294. if( ( msg == 0 ) || ( cmac == 0 ) )
  295. {
  296. return LORAMAC_CRYPTO_ERROR_NPE;
  297. }
  298. if( len > CRYPTO_MAXMESSAGE_SIZE )
  299. {
  300. return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
  301. }
  302. uint8_t micBuff[MIC_BLOCK_BX_SIZE];
  303. // Initialize the first Block
  304. PrepareB0( len, keyID, isAck, dir, devAddr, fCnt, micBuff );
  305. if( SecureElementComputeAesCmac( micBuff, msg, len, keyID, cmac ) != SECURE_ELEMENT_SUCCESS )
  306. {
  307. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  308. }
  309. return LORAMAC_CRYPTO_SUCCESS;
  310. }
  311. /*!
  312. * Verifies cmac with adding B0 block in front.
  313. *
  314. * \param[IN] msg - Message to compute the integrity code
  315. * \param[IN] len - Length of message
  316. * \param[IN] keyID - Key identifier
  317. * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
  318. * \param[IN] devAddr - Device address
  319. * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
  320. * \param[IN] fCnt - Frame counter
  321. * \param[in] expectedCmac - Expected cmac
  322. * \retval - Status of the operation
  323. */
  324. static LoRaMacCryptoStatus_t VerifyCmacB0( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint32_t expectedCmac )
  325. {
  326. if( msg == 0 )
  327. {
  328. return LORAMAC_CRYPTO_ERROR_NPE;
  329. }
  330. if( len > CRYPTO_MAXMESSAGE_SIZE )
  331. {
  332. return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
  333. }
  334. uint8_t micBuff[CRYPTO_BUFFER_SIZE];
  335. memset1( micBuff, 0, CRYPTO_BUFFER_SIZE );
  336. // Initialize the first Block
  337. PrepareB0( len, keyID, isAck, dir, devAddr, fCnt, micBuff );
  338. // Copy the given data to the mic computation buffer
  339. memcpy1( ( micBuff + MIC_BLOCK_BX_SIZE ), msg, len );
  340. SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
  341. retval = SecureElementVerifyAesCmac( micBuff, ( len + MIC_BLOCK_BX_SIZE ), expectedCmac, keyID );
  342. if( retval == SECURE_ELEMENT_SUCCESS )
  343. {
  344. return LORAMAC_CRYPTO_SUCCESS;
  345. }
  346. else if( retval == SECURE_ELEMENT_FAIL_CMAC )
  347. {
  348. return LORAMAC_CRYPTO_FAIL_MIC;
  349. }
  350. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  351. }
  352. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  353. /*
  354. * Prpares B1 block for cmac computation.
  355. *
  356. * \param[IN] msgLen - Length of message
  357. * \param[IN] keyID - Key identifier
  358. * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
  359. * \param[IN] txDr - Data rate used for the transmission
  360. * \param[IN] txCh - Index of the channel used for the transmission
  361. * \param[IN] devAddr - Device address
  362. * \param[IN] fCntUp - Frame counter
  363. * \param[IN/OUT] b0 - B0 block
  364. * \retval - Status of the operation
  365. */
  366. static LoRaMacCryptoStatus_t PrepareB1( uint16_t msgLen, KeyIdentifier_t keyID, bool isAck, uint8_t txDr, uint8_t txCh, uint32_t devAddr, uint32_t fCntUp, uint8_t* b1 )
  367. {
  368. if( b1 == 0 )
  369. {
  370. return LORAMAC_CRYPTO_ERROR_NPE;
  371. }
  372. b1[0] = 0x49;
  373. if( isAck == true )
  374. {
  375. // confFCnt contains the frame counter value modulo 2^16 of the "confirmed" uplink frame that is being acknowledged
  376. uint16_t confFCnt = ( uint16_t )( *CryptoNvm->LastDownFCnt % 65536 );
  377. b1[1] = confFCnt & 0xFF;
  378. b1[2] = ( confFCnt >> 8 ) & 0xFF;
  379. }
  380. else
  381. {
  382. b1[1] = 0x00;
  383. b1[2] = 0x00;
  384. }
  385. b1[3] = txDr;
  386. b1[4] = txCh;
  387. b1[5] = UPLINK; // dir = Uplink
  388. b1[6] = devAddr & 0xFF;
  389. b1[7] = ( devAddr >> 8 ) & 0xFF;
  390. b1[8] = ( devAddr >> 16 ) & 0xFF;
  391. b1[9] = ( devAddr >> 24 ) & 0xFF;
  392. b1[10] = fCntUp & 0xFF;
  393. b1[11] = ( fCntUp >> 8 ) & 0xFF;
  394. b1[12] = ( fCntUp >> 16 ) & 0xFF;
  395. b1[13] = ( fCntUp >> 24 ) & 0xFF;
  396. b1[14] = 0x00;
  397. b1[15] = msgLen & 0xFF;
  398. return LORAMAC_CRYPTO_SUCCESS;
  399. }
  400. /*
  401. * Computes cmac with adding B1 block in front ( only for Uplink frames LoRaWAN 1.1 )
  402. *
  403. * cmac = aes128_cmac(keyID, B1 | msg)
  404. *
  405. * \param[IN] msg - Message to calculate the Integrity code
  406. * \param[IN] len - Length of message
  407. * \param[IN] keyID - Key identifier
  408. * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
  409. * \param[IN] txDr - Data rate used for the transmission
  410. * \param[IN] txCh - Index of the channel used for the transmission
  411. * \param[IN] devAddr - Device address
  412. * \param[IN] fCntUp - Uplink Frame counter
  413. * \param[OUT] cmac - Computed cmac
  414. * \retval - Status of the operation
  415. */
  416. static LoRaMacCryptoStatus_t ComputeCmacB1( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t txDr, uint8_t txCh, uint32_t devAddr, uint32_t fCntUp, uint32_t* cmac )
  417. {
  418. if( ( msg == 0 ) || ( cmac == 0 ) )
  419. {
  420. return LORAMAC_CRYPTO_ERROR_NPE;
  421. }
  422. if( len > CRYPTO_MAXMESSAGE_SIZE )
  423. {
  424. return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
  425. }
  426. uint8_t micBuff[MIC_BLOCK_BX_SIZE];
  427. // Initialize the first Block
  428. PrepareB1( len, keyID, isAck, txDr, txCh, devAddr, fCntUp, micBuff );
  429. if( SecureElementComputeAesCmac( micBuff, msg, len, keyID, cmac ) != SECURE_ELEMENT_SUCCESS )
  430. {
  431. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  432. }
  433. return LORAMAC_CRYPTO_SUCCESS;
  434. }
  435. #endif
  436. /*
  437. * Gets security item from list.
  438. *
  439. * \param[IN] addrID - Address identifier
  440. * \param[OUT] keyItem - Key item reference
  441. * \retval - Status of the operation
  442. */
  443. static LoRaMacCryptoStatus_t GetKeyAddrItem( AddressIdentifier_t addrID, KeyAddr_t** item )
  444. {
  445. for( uint8_t i = 0; i < NUM_OF_SEC_CTX; i++ )
  446. {
  447. if( KeyAddrList[i].AddrID == addrID )
  448. {
  449. *item = &( KeyAddrList[i] );
  450. return LORAMAC_CRYPTO_SUCCESS;
  451. }
  452. }
  453. return LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID;
  454. }
  455. /*
  456. * Derives a session key as of LoRaWAN versions prior to 1.1.0
  457. *
  458. * \param[IN] keyID - Key Identifier for the key to be calculated
  459. * \param[IN] joinNonce - Sever nonce
  460. * \param[IN] netID - Network Identifier
  461. * \param[IN] deviceNonce - Device nonce
  462. * \retval - Status of the operation
  463. */
  464. static LoRaMacCryptoStatus_t DeriveSessionKey10x( KeyIdentifier_t keyID, uint32_t joinNonce, uint32_t netID, uint16_t devNonce )
  465. {
  466. uint8_t compBase[16] = { 0 };
  467. switch( keyID )
  468. {
  469. case F_NWK_S_INT_KEY:
  470. case S_NWK_S_INT_KEY:
  471. case NWK_S_ENC_KEY:
  472. compBase[0] = 0x01;
  473. break;
  474. case APP_S_KEY:
  475. compBase[0] = 0x02;
  476. break;
  477. default:
  478. return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
  479. }
  480. compBase[1] = ( uint8_t )( ( joinNonce >> 0 ) & 0xFF );
  481. compBase[2] = ( uint8_t )( ( joinNonce >> 8 ) & 0xFF );
  482. compBase[3] = ( uint8_t )( ( joinNonce >> 16 ) & 0xFF );
  483. compBase[4] = ( uint8_t )( ( netID >> 0 ) & 0xFF );
  484. compBase[5] = ( uint8_t )( ( netID >> 8 ) & 0xFF );
  485. compBase[6] = ( uint8_t )( ( netID >> 16 ) & 0xFF );
  486. compBase[7] = ( uint8_t )( ( devNonce >> 0 ) & 0xFF );
  487. compBase[8] = ( uint8_t )( ( devNonce >> 8 ) & 0xFF );
  488. if( SecureElementDeriveAndStoreKey( compBase, NWK_KEY, keyID ) != SECURE_ELEMENT_SUCCESS )
  489. {
  490. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  491. }
  492. return LORAMAC_CRYPTO_SUCCESS;
  493. }
  494. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  495. /*
  496. * Derives a session key as of LoRaWAN 1.1.0
  497. *
  498. * \param[IN] keyID - Key Identifier for the key to be calculated
  499. * \param[IN] joinNonce - Sever nonce
  500. * \param[IN] joinEUI - Join Server EUI
  501. * \param[IN] deviceNonce - Device nonce
  502. * \retval - Status of the operation
  503. */
  504. static LoRaMacCryptoStatus_t DeriveSessionKey11x( KeyIdentifier_t keyID, uint32_t joinNonce, uint8_t* joinEUI, uint16_t devNonce )
  505. {
  506. if( joinEUI == 0 )
  507. {
  508. return LORAMAC_CRYPTO_ERROR_NPE;
  509. }
  510. uint8_t compBase[16] = { 0 };
  511. KeyIdentifier_t rootKeyId = NWK_KEY;
  512. switch( keyID )
  513. {
  514. case F_NWK_S_INT_KEY:
  515. compBase[0] = 0x01;
  516. break;
  517. case S_NWK_S_INT_KEY:
  518. compBase[0] = 0x03;
  519. break;
  520. case NWK_S_ENC_KEY:
  521. compBase[0] = 0x04;
  522. break;
  523. case APP_S_KEY:
  524. rootKeyId = APP_KEY;
  525. compBase[0] = 0x02;
  526. break;
  527. default:
  528. return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
  529. }
  530. compBase[1] = ( uint8_t )( ( joinNonce >> 0 ) & 0xFF );
  531. compBase[2] = ( uint8_t )( ( joinNonce >> 8 ) & 0xFF );
  532. compBase[3] = ( uint8_t )( ( joinNonce >> 16 ) & 0xFF );
  533. memcpyr( compBase + 4, joinEUI, 8 );
  534. compBase[12] = ( uint8_t )( ( devNonce >> 0 ) & 0xFF );
  535. compBase[13] = ( uint8_t )( ( devNonce >> 8 ) & 0xFF );
  536. if( SecureElementDeriveAndStoreKey( compBase, rootKeyId, keyID ) != SECURE_ELEMENT_SUCCESS )
  537. {
  538. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  539. }
  540. return LORAMAC_CRYPTO_SUCCESS;
  541. }
  542. /*
  543. * Derives a life time session key (JSIntKey or JSEncKey) as of LoRaWAN 1.1.0
  544. *
  545. * \param[IN] keyID - Key Identifier for the key to be calculated
  546. * \param[IN] devEUI - Device EUI
  547. * \retval - Status of the operation
  548. */
  549. static LoRaMacCryptoStatus_t DeriveLifeTimeSessionKey( KeyIdentifier_t keyID, uint8_t* devEUI )
  550. {
  551. if( devEUI == 0 )
  552. {
  553. return LORAMAC_CRYPTO_ERROR_NPE;
  554. }
  555. uint8_t compBase[16] = { 0 };
  556. switch( keyID )
  557. {
  558. case J_S_INT_KEY:
  559. compBase[0] = 0x06;
  560. break;
  561. case J_S_ENC_KEY:
  562. compBase[0] = 0x05;
  563. break;
  564. default:
  565. return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
  566. }
  567. memcpyr( compBase + 1, devEUI, 8 );
  568. if( SecureElementDeriveAndStoreKey( compBase, NWK_KEY, keyID ) != SECURE_ELEMENT_SUCCESS )
  569. {
  570. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  571. }
  572. return LORAMAC_CRYPTO_SUCCESS;
  573. }
  574. #endif
  575. /*
  576. * Gets the last received frame counter
  577. *
  578. * \param[IN] fCntID - Frame counter identifier
  579. * \param[IN] lastDown - Last downlink counter value
  580. *
  581. * \retval - Status of the operation
  582. */
  583. static LoRaMacCryptoStatus_t GetLastFcntDown( FCntIdentifier_t fCntID, uint32_t* lastDown )
  584. {
  585. if( lastDown == NULL )
  586. {
  587. return LORAMAC_CRYPTO_ERROR_NPE;
  588. }
  589. switch( fCntID )
  590. {
  591. case N_FCNT_DOWN:
  592. *lastDown = CryptoNvm->FCntList.NFCntDown;
  593. CryptoNvm->LastDownFCnt = CryptoNvm->FCntList.NFCntDown;
  594. break;
  595. case A_FCNT_DOWN:
  596. *lastDown = CryptoNvm->FCntList.AFCntDown;
  597. CryptoNvm->LastDownFCnt = CryptoNvm->FCntList.AFCntDown;
  598. break;
  599. case FCNT_DOWN:
  600. *lastDown = CryptoNvm->FCntList.FCntDown;
  601. CryptoNvm->LastDownFCnt = CryptoNvm->FCntList.FCntDown;
  602. break;
  603. #if ( LORAMAC_MAX_MC_CTX > 0 )
  604. case MC_FCNT_DOWN_0:
  605. *lastDown = CryptoNvm->FCntList.McFCntDown[0];
  606. break;
  607. #endif
  608. #if ( LORAMAC_MAX_MC_CTX > 1 )
  609. case MC_FCNT_DOWN_1:
  610. *lastDown = CryptoNvm->FCntList.McFCntDown[1];
  611. break;
  612. #endif
  613. #if ( LORAMAC_MAX_MC_CTX > 2 )
  614. case MC_FCNT_DOWN_2:
  615. *lastDown = CryptoNvm->FCntList.McFCntDown[2];
  616. break;
  617. #endif
  618. #if ( LORAMAC_MAX_MC_CTX > 3 )
  619. case MC_FCNT_DOWN_3:
  620. *lastDown = CryptoNvm->FCntList.McFCntDown[3];
  621. break;
  622. #endif
  623. default:
  624. return LORAMAC_CRYPTO_FAIL_FCNT_ID;
  625. }
  626. return LORAMAC_CRYPTO_SUCCESS;
  627. }
  628. /*
  629. * Checks the downlink counter value
  630. *
  631. * \param[IN] fCntID - Frame counter identifier
  632. * \param[IN] currentDown - Current downlink counter value
  633. *
  634. * \retval - Status of the operation
  635. */
  636. static bool CheckFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
  637. {
  638. uint32_t lastDown = 0;
  639. if( GetLastFcntDown( fCntID, &lastDown ) != LORAMAC_CRYPTO_SUCCESS )
  640. {
  641. return false;
  642. }
  643. if( ( currentDown > lastDown ) ||
  644. // For LoRaWAN 1.0.X only. Allow downlink frames of 0
  645. ( lastDown == FCNT_DOWN_INITAL_VALUE ) )
  646. {
  647. return true;
  648. }
  649. else
  650. {
  651. return false;
  652. }
  653. }
  654. /*!
  655. * Updates the reference downlink counter
  656. *
  657. * \param[IN] fCntID - Frame counter identifier
  658. * \param[IN] currentDown - Current downlink counter value
  659. *
  660. * \retval - Status of the operation
  661. */
  662. static void UpdateFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
  663. {
  664. switch( fCntID )
  665. {
  666. case N_FCNT_DOWN:
  667. CryptoNvm->FCntList.NFCntDown = currentDown;
  668. break;
  669. case A_FCNT_DOWN:
  670. CryptoNvm->FCntList.AFCntDown = currentDown;
  671. break;
  672. case FCNT_DOWN:
  673. CryptoNvm->FCntList.FCntDown = currentDown;
  674. break;
  675. #if ( LORAMAC_MAX_MC_CTX > 0 )
  676. case MC_FCNT_DOWN_0:
  677. CryptoNvm->FCntList.McFCntDown[0] = currentDown;
  678. break;
  679. #endif
  680. #if ( LORAMAC_MAX_MC_CTX > 1 )
  681. case MC_FCNT_DOWN_1:
  682. CryptoNvm->FCntList.McFCntDown[1] = currentDown;
  683. break;
  684. #endif
  685. #if ( LORAMAC_MAX_MC_CTX > 2 )
  686. case MC_FCNT_DOWN_2:
  687. CryptoNvm->FCntList.McFCntDown[2] = currentDown;
  688. break;
  689. #endif
  690. #if ( LORAMAC_MAX_MC_CTX > 3 )
  691. case MC_FCNT_DOWN_3:
  692. CryptoNvm->FCntList.McFCntDown[3] = currentDown;
  693. break;
  694. #endif
  695. default:
  696. break;
  697. }
  698. }
  699. /*!
  700. * Resets the frame counters
  701. */
  702. static void ResetFCnts( void )
  703. {
  704. CryptoNvm->FCntList.FCntUp = 0;
  705. CryptoNvm->FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
  706. CryptoNvm->FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
  707. CryptoNvm->FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
  708. CryptoNvm->LastDownFCnt = CryptoNvm->FCntList.FCntDown;
  709. for( int32_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
  710. {
  711. CryptoNvm->FCntList.McFCntDown[i] = FCNT_DOWN_INITAL_VALUE;
  712. }
  713. }
  714. /*
  715. * API functions
  716. */
  717. LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmData_t* nvm )
  718. {
  719. if( nvm == NULL )
  720. {
  721. return LORAMAC_CRYPTO_FAIL_PARAM;
  722. }
  723. // Assign non volatile context
  724. CryptoNvm = nvm;
  725. // Initialize with default
  726. memset1( ( uint8_t* )CryptoNvm, 0, sizeof( LoRaMacCryptoNvmData_t ) );
  727. // Set default LoRaWAN version
  728. CryptoNvm->LrWanVersion.Fields.Major = 1;
  729. CryptoNvm->LrWanVersion.Fields.Minor = 1;
  730. CryptoNvm->LrWanVersion.Fields.Patch = 1;
  731. CryptoNvm->LrWanVersion.Fields.Revision = 0;
  732. // Reset frame counters
  733. ResetFCnts( );
  734. return LORAMAC_CRYPTO_SUCCESS;
  735. }
  736. LoRaMacCryptoStatus_t LoRaMacCryptoSetLrWanVersion( Version_t version )
  737. {
  738. CryptoNvm->LrWanVersion = version;
  739. return LORAMAC_CRYPTO_SUCCESS;
  740. }
  741. LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp )
  742. {
  743. if( currentUp == NULL )
  744. {
  745. return LORAMAC_CRYPTO_ERROR_NPE;
  746. }
  747. *currentUp = CryptoNvm->FCntList.FCntUp + 1;
  748. return LORAMAC_CRYPTO_SUCCESS;
  749. }
  750. LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint32_t frameFcnt, uint32_t* currentDown )
  751. {
  752. uint32_t lastDown = 0;
  753. int32_t fCntDiff = 0;
  754. LoRaMacCryptoStatus_t cryptoStatus = LORAMAC_CRYPTO_ERROR;
  755. if( currentDown == NULL )
  756. {
  757. return LORAMAC_CRYPTO_ERROR_NPE;
  758. }
  759. cryptoStatus = GetLastFcntDown( fCntID, &lastDown );
  760. if( cryptoStatus != LORAMAC_CRYPTO_SUCCESS )
  761. {
  762. return cryptoStatus;
  763. }
  764. // For LoRaWAN 1.0.X only, allow downlink frames of 0
  765. if( lastDown == FCNT_DOWN_INITAL_VALUE )
  766. {
  767. *currentDown = frameFcnt;
  768. }
  769. else
  770. {
  771. // Add difference, consider roll-over
  772. fCntDiff = ( int32_t )( ( int64_t )frameFcnt - ( int64_t )( lastDown & 0x0000FFFF ) );
  773. if( fCntDiff > 0 )
  774. { // Positive difference
  775. *currentDown = lastDown + fCntDiff;
  776. }
  777. else if( fCntDiff == 0 )
  778. { // Duplicate FCnt value, keep the current value.
  779. *currentDown = lastDown;
  780. return LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED;
  781. }
  782. else
  783. { // Negative difference, assume a roll-over of one uint16_t
  784. *currentDown = ( lastDown & 0xFFFF0000 ) + 0x10000 + frameFcnt;
  785. }
  786. }
  787. return LORAMAC_CRYPTO_SUCCESS;
  788. }
  789. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  790. LoRaMacCryptoStatus_t LoRaMacCryptoGetRJcount( FCntIdentifier_t fCntID, uint16_t* rJcount )
  791. {
  792. if( rJcount == 0 )
  793. {
  794. return LORAMAC_CRYPTO_ERROR_NPE;
  795. }
  796. switch( fCntID )
  797. {
  798. case RJ_COUNT_0:
  799. *rJcount = RJcount0 + 1;
  800. break;
  801. case RJ_COUNT_1:
  802. *rJcount = CryptoNvm->FCntList.RJcount1 + 1;
  803. break;
  804. default:
  805. return LORAMAC_CRYPTO_FAIL_FCNT_ID;
  806. }
  807. return LORAMAC_CRYPTO_SUCCESS;
  808. }
  809. #endif
  810. LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList )
  811. {
  812. if( multicastList == NULL )
  813. {
  814. return LORAMAC_CRYPTO_ERROR_NPE;
  815. }
  816. for( int32_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
  817. {
  818. multicastList[i].DownLinkCounter = &CryptoNvm->FCntList.McFCntDown[i];
  819. }
  820. return LORAMAC_CRYPTO_SUCCESS;
  821. }
  822. LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( KeyIdentifier_t keyID, uint8_t* key )
  823. {
  824. if( SecureElementSetKey( keyID, key ) != SECURE_ELEMENT_SUCCESS )
  825. {
  826. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  827. }
  828. if( keyID == APP_KEY )
  829. {
  830. // Derive lifetime keys
  831. if( LoRaMacCryptoDeriveMcRootKey( CryptoNvm->LrWanVersion.Fields.Minor, keyID ) != LORAMAC_CRYPTO_SUCCESS )
  832. {
  833. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  834. }
  835. if( LoRaMacCryptoDeriveMcKEKey( MC_ROOT_KEY ) != LORAMAC_CRYPTO_SUCCESS )
  836. {
  837. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  838. }
  839. }
  840. return LORAMAC_CRYPTO_SUCCESS;
  841. }
  842. LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg )
  843. {
  844. if( macMsg == 0 )
  845. {
  846. return LORAMAC_CRYPTO_ERROR_NPE;
  847. }
  848. KeyIdentifier_t micComputationKeyID = NWK_KEY;
  849. // Add device nonce
  850. #if ( USE_RANDOM_DEV_NONCE == 1 )
  851. uint32_t devNonce = 0;
  852. SecureElementRandomNumber( &devNonce );
  853. CryptoNvm->DevNonce = devNonce;
  854. #else
  855. CryptoNvm->DevNonce++;
  856. #endif
  857. macMsg->DevNonce = CryptoNvm->DevNonce;
  858. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  859. // Derive lifetime session keys
  860. if( DeriveLifeTimeSessionKey( J_S_INT_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
  861. {
  862. return LORAMAC_CRYPTO_ERROR;
  863. }
  864. if( DeriveLifeTimeSessionKey( J_S_ENC_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
  865. {
  866. return LORAMAC_CRYPTO_ERROR;
  867. }
  868. #endif
  869. // Serialize message
  870. if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  871. {
  872. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  873. }
  874. // Compute mic
  875. if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_JOIN_REQ_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), micComputationKeyID, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
  876. {
  877. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  878. }
  879. // Reserialize message to add the MIC
  880. if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  881. {
  882. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  883. }
  884. return LORAMAC_CRYPTO_SUCCESS;
  885. }
  886. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  887. LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaMacMessageReJoinType1_t* macMsg )
  888. {
  889. if( macMsg == 0 )
  890. {
  891. return LORAMAC_CRYPTO_ERROR_NPE;
  892. }
  893. // Check for RJcount1 overflow
  894. if( CryptoNvm->FCntList.RJcount1 == 65535 )
  895. {
  896. return LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW;
  897. }
  898. // Serialize message
  899. if( LoRaMacSerializerReJoinType1( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  900. {
  901. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  902. }
  903. // Compute mic
  904. // cmac = aes128_cmac(JSIntKey, MHDR | RejoinType | JoinEUI| DevEUI | RJcount1)
  905. if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_RE_JOIN_1_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), J_S_INT_KEY, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
  906. {
  907. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  908. }
  909. // Reserialize message to add the MIC
  910. if( LoRaMacSerializerReJoinType1( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  911. {
  912. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  913. }
  914. // Increment RJcount1
  915. CryptoNvm->FCntList.RJcount1++;
  916. return LORAMAC_CRYPTO_SUCCESS;
  917. }
  918. LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg )
  919. {
  920. if( macMsg == 0 )
  921. {
  922. return LORAMAC_CRYPTO_ERROR_NPE;
  923. }
  924. // Check for RJcount0 overflow
  925. if( RJcount0 == 65535 )
  926. {
  927. return LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW;
  928. }
  929. // Serialize message
  930. if( LoRaMacSerializerReJoinType0or2( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  931. {
  932. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  933. }
  934. // Compute mic
  935. // cmac = aes128_cmac(SNwkSIntKey, MHDR | Rejoin Type | NetID | DevEUI | RJcount0)
  936. if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_RE_JOIN_0_2_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), S_NWK_S_INT_KEY, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
  937. {
  938. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  939. }
  940. // Re-serialize message to add the MIC
  941. if( LoRaMacSerializerReJoinType0or2( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  942. {
  943. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  944. }
  945. // Increment RJcount0
  946. RJcount0++;
  947. return LORAMAC_CRYPTO_SUCCESS;
  948. }
  949. #endif
  950. LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEUI, LoRaMacMessageJoinAccept_t* macMsg )
  951. {
  952. if( ( macMsg == 0 ) || ( joinEUI == 0 ) )
  953. {
  954. return LORAMAC_CRYPTO_ERROR_NPE;
  955. }
  956. LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
  957. uint8_t decJoinAccept[LORAMAC_JOIN_ACCEPT_FRAME_MAX_SIZE] = { 0 };
  958. uint8_t versionMinor = 0;
  959. uint16_t nonce = CryptoNvm->DevNonce;
  960. // Nonce selection depending on JoinReqType
  961. // JOIN_REQ : CryptoNvm->DevNonce
  962. // REJOIN_REQ_0 : RJcount0
  963. // REJOIN_REQ_1 : CryptoCtx.RJcount1
  964. // REJOIN_REQ_2 : RJcount0
  965. if( joinReqType == JOIN_REQ )
  966. {
  967. // Nothing to be done
  968. }
  969. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  970. else
  971. {
  972. // If Join-accept is a reply to a rejoin, the RJcount(0 or 1) replaces DevNonce in the key derivation process.
  973. if( ( joinReqType == REJOIN_REQ_0 ) || ( joinReqType == REJOIN_REQ_2 ) )
  974. {
  975. nonce = RJcount0;
  976. }
  977. else
  978. {
  979. nonce = CryptoNvm->FCntList.RJcount1;
  980. }
  981. }
  982. #endif
  983. if( SecureElementProcessJoinAccept( joinReqType, joinEUI, nonce, macMsg->Buffer,
  984. macMsg->BufSize, decJoinAccept,
  985. &versionMinor ) != SECURE_ELEMENT_SUCCESS )
  986. {
  987. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  988. }
  989. memcpy1( macMsg->Buffer, decJoinAccept, macMsg->BufSize );
  990. // Parse the message
  991. if( LoRaMacParserJoinAccept( macMsg ) != LORAMAC_PARSER_SUCCESS )
  992. {
  993. return LORAMAC_CRYPTO_ERROR_PARSER;
  994. }
  995. uint32_t currentJoinNonce;
  996. currentJoinNonce = ( uint32_t )macMsg->JoinNonce[0];
  997. currentJoinNonce |= ( ( uint32_t )macMsg->JoinNonce[1] << 8 );
  998. currentJoinNonce |= ( ( uint32_t )macMsg->JoinNonce[2] << 16 );
  999. #if( USE_JOIN_NONCE_COUNTER_CHECK == 1 )
  1000. // Check if the JoinNonce is greater as the previous one
  1001. if( currentJoinNonce > CryptoNvm->JoinNonce )
  1002. #else
  1003. // Check if the JoinNonce is different from the previous one
  1004. if( currentJoinNonce != CryptoNvm->JoinNonce )
  1005. #endif
  1006. {
  1007. CryptoNvm->JoinNonce = currentJoinNonce;
  1008. }
  1009. else
  1010. {
  1011. return LORAMAC_CRYPTO_FAIL_JOIN_NONCE;
  1012. }
  1013. // Derive lifetime keys
  1014. retval = LoRaMacCryptoDeriveMcRootKey( versionMinor, APP_KEY );
  1015. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1016. {
  1017. return retval;
  1018. }
  1019. retval = LoRaMacCryptoDeriveMcKEKey( MC_ROOT_KEY );
  1020. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1021. {
  1022. return retval;
  1023. }
  1024. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  1025. if( versionMinor == 1 )
  1026. {
  1027. // Operating in LoRaWAN 1.1.x mode
  1028. retval = DeriveSessionKey11x( F_NWK_S_INT_KEY, currentJoinNonce, joinEUI, nonce );
  1029. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1030. {
  1031. return retval;
  1032. }
  1033. retval = DeriveSessionKey11x( S_NWK_S_INT_KEY, currentJoinNonce, joinEUI, nonce );
  1034. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1035. {
  1036. return retval;
  1037. }
  1038. retval = DeriveSessionKey11x( NWK_S_ENC_KEY, currentJoinNonce, joinEUI, nonce );
  1039. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1040. {
  1041. return retval;
  1042. }
  1043. retval = DeriveSessionKey11x( APP_S_KEY, currentJoinNonce, joinEUI, nonce );
  1044. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1045. {
  1046. return retval;
  1047. }
  1048. }
  1049. else
  1050. #endif
  1051. {
  1052. // Operating in LoRaWAN 1.0.x mode
  1053. uint32_t netID;
  1054. netID = ( uint32_t )macMsg->NetID[0];
  1055. netID |= ( ( uint32_t )macMsg->NetID[1] << 8 );
  1056. netID |= ( ( uint32_t )macMsg->NetID[2] << 16 );
  1057. retval = DeriveSessionKey10x( APP_S_KEY, currentJoinNonce, netID, nonce );
  1058. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1059. {
  1060. return retval;
  1061. }
  1062. retval = DeriveSessionKey10x( NWK_S_ENC_KEY, currentJoinNonce, netID, nonce );
  1063. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1064. {
  1065. return retval;
  1066. }
  1067. retval = DeriveSessionKey10x( F_NWK_S_INT_KEY, currentJoinNonce, netID, nonce );
  1068. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1069. {
  1070. return retval;
  1071. }
  1072. retval = DeriveSessionKey10x( S_NWK_S_INT_KEY, currentJoinNonce, netID, nonce );
  1073. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1074. {
  1075. return retval;
  1076. }
  1077. }
  1078. // Join-Accept is successfully processed
  1079. // Save LoRaWAN specification version
  1080. CryptoNvm->LrWanVersion.Fields.Minor = versionMinor;
  1081. // Reset frame counters
  1082. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  1083. RJcount0 = 0;
  1084. #endif
  1085. CryptoNvm->FCntList.FCntUp = 0;
  1086. CryptoNvm->FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
  1087. CryptoNvm->FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
  1088. CryptoNvm->FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
  1089. return LORAMAC_CRYPTO_SUCCESS;
  1090. }
  1091. LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t* macMsg )
  1092. {
  1093. LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
  1094. KeyIdentifier_t payloadDecryptionKeyID = APP_S_KEY;
  1095. if( macMsg == NULL )
  1096. {
  1097. return LORAMAC_CRYPTO_ERROR_NPE;
  1098. }
  1099. if( fCntUp < CryptoNvm->FCntList.FCntUp )
  1100. {
  1101. return LORAMAC_CRYPTO_FAIL_FCNT_SMALLER;
  1102. }
  1103. // Encrypt payload
  1104. if( macMsg->FPort == 0 )
  1105. {
  1106. // Use network session key
  1107. payloadDecryptionKeyID = NWK_S_ENC_KEY;
  1108. }
  1109. if( fCntUp > CryptoNvm->FCntList.FCntUp )
  1110. {
  1111. retval = PayloadEncrypt( macMsg->FRMPayload, macMsg->FRMPayloadSize, payloadDecryptionKeyID, macMsg->FHDR.DevAddr, UPLINK, fCntUp );
  1112. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1113. {
  1114. return retval;
  1115. }
  1116. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  1117. if( CryptoNvm->LrWanVersion.Fields.Minor == 1 )
  1118. {
  1119. // Encrypt FOpts
  1120. retval = FOptsEncrypt( macMsg->FHDR.FCtrl.Bits.FOptsLen, macMsg->FHDR.DevAddr, UPLINK, FCNT_UP, fCntUp, macMsg->FHDR.FOpts );
  1121. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1122. {
  1123. return retval;
  1124. }
  1125. }
  1126. #endif
  1127. }
  1128. // Serialize message
  1129. if( LoRaMacSerializerData( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  1130. {
  1131. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  1132. }
  1133. // Compute mic
  1134. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  1135. if( CryptoNvm->LrWanVersion.Fields.Minor == 1 )
  1136. {
  1137. uint32_t cmacS = 0;
  1138. uint32_t cmacF = 0;
  1139. // cmacS = aes128_cmac(SNwkSIntKey, B1 | msg)
  1140. retval = ComputeCmacB1( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), S_NWK_S_INT_KEY, macMsg->FHDR.FCtrl.Bits.Ack, txDr, txCh, macMsg->FHDR.DevAddr, fCntUp, &cmacS );
  1141. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1142. {
  1143. return retval;
  1144. }
  1145. //cmacF = aes128_cmac(FNwkSIntKey, B0 | msg)
  1146. retval = ComputeCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), F_NWK_S_INT_KEY, macMsg->FHDR.FCtrl.Bits.Ack, UPLINK, macMsg->FHDR.DevAddr, fCntUp, &cmacF );
  1147. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1148. {
  1149. return retval;
  1150. }
  1151. // MIC = cmacS[0..1] | cmacF[0..1]
  1152. macMsg->MIC = ( ( cmacF << 16 ) & 0xFFFF0000 ) | ( cmacS & 0x0000FFFF );
  1153. }
  1154. else
  1155. #endif
  1156. {
  1157. // MIC = cmacF[0..3]
  1158. // The IsAck parameter is every time false since the ConfFCnt field is not used in legacy mode.
  1159. retval = ComputeCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), NWK_S_ENC_KEY, false, UPLINK, macMsg->FHDR.DevAddr, fCntUp, &macMsg->MIC );
  1160. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1161. {
  1162. return retval;
  1163. }
  1164. }
  1165. // Re-serialize message to add the MIC
  1166. if( LoRaMacSerializerData( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
  1167. {
  1168. return LORAMAC_CRYPTO_ERROR_SERIALIZER;
  1169. }
  1170. CryptoNvm->FCntList.FCntUp = fCntUp;
  1171. return LORAMAC_CRYPTO_SUCCESS;
  1172. }
  1173. LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg )
  1174. {
  1175. if( macMsg == 0 )
  1176. {
  1177. return LORAMAC_CRYPTO_ERROR_NPE;
  1178. }
  1179. if( CheckFCntDown( fCntID, fCntDown ) == false )
  1180. {
  1181. return LORAMAC_CRYPTO_FAIL_FCNT_SMALLER;
  1182. }
  1183. LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
  1184. KeyIdentifier_t payloadDecryptionKeyID = APP_S_KEY;
  1185. KeyIdentifier_t micComputationKeyID = S_NWK_S_INT_KEY;
  1186. KeyAddr_t* curItem;
  1187. // Parse the message
  1188. if( LoRaMacParserData( macMsg ) != LORAMAC_PARSER_SUCCESS )
  1189. {
  1190. return LORAMAC_CRYPTO_ERROR_PARSER;
  1191. }
  1192. // Determine current security context
  1193. retval = GetKeyAddrItem( addrID, &curItem );
  1194. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1195. {
  1196. return retval;
  1197. }
  1198. payloadDecryptionKeyID = curItem->AppSkey;
  1199. micComputationKeyID = curItem->NwkSkey;
  1200. // Check if it is our address
  1201. if( address != macMsg->FHDR.DevAddr )
  1202. {
  1203. return LORAMAC_CRYPTO_FAIL_ADDRESS;
  1204. }
  1205. // Compute mic
  1206. bool isAck = macMsg->FHDR.FCtrl.Bits.Ack;
  1207. if( CryptoNvm->LrWanVersion.Fields.Minor == 0 )
  1208. {
  1209. // In legacy mode the IsAck parameter is forced to be false since the ConfFCnt field is not used.
  1210. isAck = false;
  1211. }
  1212. // Verify mic
  1213. retval = VerifyCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), micComputationKeyID, isAck, DOWNLINK, address, fCntDown, macMsg->MIC );
  1214. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1215. {
  1216. return retval;
  1217. }
  1218. // Decrypt payload
  1219. if( macMsg->FPort == 0 )
  1220. {
  1221. // Use network session encryption key
  1222. payloadDecryptionKeyID = NWK_S_ENC_KEY;
  1223. }
  1224. retval = PayloadEncrypt( macMsg->FRMPayload, macMsg->FRMPayloadSize, payloadDecryptionKeyID, address, DOWNLINK, fCntDown );
  1225. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1226. {
  1227. return retval;
  1228. }
  1229. #if( USE_LRWAN_1_1_X_CRYPTO == 1 )
  1230. if( CryptoNvm->LrWanVersion.Fields.Minor == 1 )
  1231. {
  1232. if( addrID == UNICAST_DEV_ADDR )
  1233. {
  1234. // Decrypt FOpts
  1235. retval = FOptsEncrypt( macMsg->FHDR.FCtrl.Bits.FOptsLen, address, DOWNLINK, fCntID, fCntDown, macMsg->FHDR.FOpts );
  1236. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1237. {
  1238. return retval;
  1239. }
  1240. }
  1241. }
  1242. #endif
  1243. UpdateFCntDown( fCntID, fCntDown );
  1244. return LORAMAC_CRYPTO_SUCCESS;
  1245. }
  1246. LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( uint8_t versionMinor, KeyIdentifier_t keyID )
  1247. {
  1248. // Prevent other keys than AppKey
  1249. if( keyID != APP_KEY )
  1250. {
  1251. return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
  1252. }
  1253. uint8_t compBase[16] = { 0 };
  1254. if( versionMinor == 1 )
  1255. {
  1256. compBase[0] = 0x20;
  1257. }
  1258. if( SecureElementDeriveAndStoreKey( compBase, keyID, MC_ROOT_KEY ) != SECURE_ELEMENT_SUCCESS )
  1259. {
  1260. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  1261. }
  1262. return LORAMAC_CRYPTO_SUCCESS;
  1263. }
  1264. LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID )
  1265. {
  1266. // Prevent other keys than McRootKey
  1267. if( keyID != MC_ROOT_KEY )
  1268. {
  1269. return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
  1270. }
  1271. uint8_t compBase[16] = { 0 };
  1272. if( SecureElementDeriveAndStoreKey( compBase, keyID, MC_KE_KEY ) != SECURE_ELEMENT_SUCCESS )
  1273. {
  1274. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  1275. }
  1276. return LORAMAC_CRYPTO_SUCCESS;
  1277. }
  1278. LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t addrID, uint32_t mcAddr )
  1279. {
  1280. if( mcAddr == 0 )
  1281. {
  1282. return LORAMAC_CRYPTO_ERROR_NPE;
  1283. }
  1284. LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
  1285. // Determine current security context
  1286. KeyAddr_t* curItem;
  1287. retval = GetKeyAddrItem( addrID, &curItem );
  1288. if( retval != LORAMAC_CRYPTO_SUCCESS )
  1289. {
  1290. return retval;
  1291. }
  1292. // McAppSKey = aes128_encrypt(McKey, 0x01 | McAddr | pad16)
  1293. // McNwkSKey = aes128_encrypt(McKey, 0x02 | McAddr | pad16)
  1294. uint8_t compBaseAppS[16] = { 0 };
  1295. uint8_t compBaseNwkS[16] = { 0 };
  1296. compBaseAppS[0] = 0x01;
  1297. compBaseAppS[1] = mcAddr & 0xFF;
  1298. compBaseAppS[2] = ( mcAddr >> 8 ) & 0xFF;
  1299. compBaseAppS[3] = ( mcAddr >> 16 ) & 0xFF;
  1300. compBaseAppS[4] = ( mcAddr >> 24 ) & 0xFF;
  1301. compBaseNwkS[0] = 0x02;
  1302. compBaseNwkS[1] = mcAddr & 0xFF;
  1303. compBaseNwkS[2] = ( mcAddr >> 8 ) & 0xFF;
  1304. compBaseNwkS[3] = ( mcAddr >> 16 ) & 0xFF;
  1305. compBaseNwkS[4] = ( mcAddr >> 24 ) & 0xFF;
  1306. if( SecureElementDeriveAndStoreKey( compBaseAppS, curItem->RootKey, curItem->AppSkey ) != SECURE_ELEMENT_SUCCESS )
  1307. {
  1308. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  1309. }
  1310. if( SecureElementDeriveAndStoreKey( compBaseNwkS, curItem->RootKey, curItem->NwkSkey ) != SECURE_ELEMENT_SUCCESS )
  1311. {
  1312. return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
  1313. }
  1314. return LORAMAC_CRYPTO_SUCCESS;
  1315. }