Skip to content

Secure element

Daniel Jäckle edited this page Dec 13, 2017 · 6 revisions

STACKFORCE Logo

LoRaMac Secure Element Integration

  1. Introduction
  2. Structure Overview
    1. Considered Scenarios
      1. Hard or Software basic Secure Element
      2. Advanced Secure Element
    2. Repository Structure
  3. API header files
    1. LoRaMacCrypto header
    2. secure-element header

Introduction

The idea is to introduce a new LoRaMac Crypto module which is doing everything to secure/unsecure messages. This enables to use a Secure Element (SE) which provides specific LoRaWAN cryptographic functionalities, a secure memory or only basic aes/cmac functionalities. Through this security tasks can be completely or partly performed in soft- or hardware.

Structure Overview

The new structure defines two layers of abstraction. The lower layer (secure-element) defines the minimum range of functionality to full fill requirements of the LoRaWAN-Secure element specification. That means it defines the basic secure element. In most application scenarios this part is performed on a secure element device which is connected via SPI , UART or any other inter processor communication. Anyway the LoRaMac Stack includes a software implementation of it. The second layer is called LoRaMacCrypto Module and defines a API to perform all security tasks required by the LoRaMac. It separates the security task from the core stack tasks. Since the task of securing a message is closely linked with the tasks of serializing and parsing messages, the LoRaMacCrypto is calling also the Serializer and Paser API. Those functionalities are still part of the LoRaMac stack.

Considered Scenarios

Hard or Software basic Secure Element

The following figure shows how the layers work with each other. The architecture on the left side shows the case of a pure software implementation. On the right side it shows a combination with a secure element device.

common architecture

Advanced Secure Element

The new architecture also allows to integrate a more advanced Secure Element which undertake other tasks such as the preparation of messages. The following figure shows greatest considered scope of functionality.

advanced architecture

Repository Structure

The file-directory tree of the stack repository shows where you can find the related files.

├── apps
├── boards
├── mac
│   ├── LoRaMacCrypto.c
│   ├── LoRaMacCrypto.h               ←  LoRaMac Crypto Module API
│   ├── LoRaMacHeaderTypes.h
│   ├── LoRaMacMessageTypes.h
│   ├── LoRaMacParser.c
│   ├── LoRaMacParser.h               ←  LoRaMac Parser API
│   ├── LoRaMacSerializer.c
│   ├── LoRaMacSerializer.h           ←  LoRaMac Serializer API
│   ├── secure-element.h              ←  Secure Element API
│   ├── ...
│   └── region
├── peripherals
│   ├── soft-se                       ←  Software Secure Element Implementation 
│   │   ├── aes.c
│   │   ├── aes.h
│   │   ├── cmac.c
│   │   ├── cmac.h
│   │   └── soft-se.c
│   └── ...
├── radio
└── system

API header files

LoRaMacCrypto header

/*!
 * \file      LoRaMacCrypto.h
 *
 * \brief     LoRa MAC layer cryptographic functionality implementation
 *
 * \copyright Revised BSD License, see section \ref LICENSE.
 *
 * \code
 *                ______                              _
 *               / _____)             _              | |
 *              ( (____  _____ ____ _| |_ _____  ____| |__
 *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 *               _____) ) ____| | | || |_| ____( (___| | | |
 *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
 *              (C)2013-2017 Semtech
 *
 *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
 *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
 *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
 *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
 *              embedded.connectivity.solutions===============
 *
 * \endcode
 *
 * \author    Miguel Luis ( Semtech )
 *
 * \author    Gregory Cristian ( Semtech )
 *
 * \author    Daniel Jaeckle ( STACKFORCE )
 *
 * \author    Johannes Bruder ( STACKFORCE )
 *
 * addtogroup LORAMAC
 * \{
 *
 */
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__

#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "LoRaMacMessageTypes.h"


/*!
 * Start value for unicast keys enumeration
 */
#define LORAMAC_CRYPTO_UNICAST_KEYS     0

/*!
 * Start value for multicast keys enumeration
 */
#define LORAMAC_CRYPTO_MULITCAST_KEYS   127

/*!
 * LoRaMac Crypto key identifier
 */
typedef enum eKeyIdentifier
{
    /*!
     * Application root key
     */
    APP_KEY = 0,
    /*!
     * Network root key
     */
    NWK_KEY,
    /*!
     * Join session integrity key
     */
    J_S_INT_KEY,
    /*!
     * Join session encryption key
     */
    J_S_ENC_KEY,
    /*!
     * Forwarding Network session integrity key
     */
    F_NWK_S_INT_KEY,
    /*!
     * Serving Network session integrity key
     */
    S_NWK_S_INT_KEY,
    /*!
     * Network session encryption key
     */
    NWK_S_ENC_KEY,
    /*!
     * Application session key
     */
    APP_S_KEY,
    /*!
     * Multicast key encryption Key
     */
    MC_KE_KEY = LORAMAC_CRYPTO_MULITCAST_KEYS,
    /*!
     * Multicast root key
     */
    MC_KEY,
    /*!
     * Multicast Application session key index 0
     */
    MC_APP_S_KEY_0,
    /*!
     * Multicast Network session key index 0
     */
    MC_NWK_S_KEY_0,
    /*!
     * Multicast Application session key index 1
     */
    MC_APP_S_KEY_1,
    /*!
     * Multicast Network session key index 1
     */
    MC_NWK_S_KEY_1,
    /*!
     * Multicast Application session key index 2
     */
    MC_APP_S_KEY_2,
    /*!
     * Multicast Network session key index 2
     */
    MC_NWK_S_KEY_2,
    /*!
     * Multicast Application session key index 3
     */
    MC_APP_S_KEY_3,
    /*!
     * Multicast Network session key index 3
     */
    MC_NWK_S_KEY_3,
}KeyIdentifier_t;

/*!
 * LoRaMac Crypto address identifier
 */
typedef enum eAddressIdentifier
{
    /*!
     * Unicast End-device address
     */
    UNICAST_DEV_ADDR  = 0,
    /*!
     * Multicast Address for index 0
     */
    MULTICAST_0_ADDR,
    /*!
     * Multicast Address for index 1
     */
    MULTICAST_1_ADDR,
    /*!
     * Multicast Address for index 2
     */
    MULTICAST_2_ADDR,
    /*!
     * Multicast Address for index 3
     */
    MULTICAST_3_ADDR,

}AddressIdentifier_t;

/*!
 * LoRaMac Crypto join-request / rejoin type identifier
 */
typedef enum eJoinReqIdentifier
{
    /*!
     * Rejoin type 0
     */
    RE_JOIN_REQ_0 = 0x00,
    /*!
     * Rejoin type 1
     */
    RE_JOIN_REQ_1 = 0x01,
    /*!
     * Rejoin type 2
     */
    RE_JOIN_REQ_2 = 0x02,
    /*!
     * Join-request
     */
    JOIN_REQ = 0xFF,
}JoinReqIdentifier_t;

/*!
 * LoRaWAN specification version
 */
typedef enum eLoRaWANSpecVersion
{
    /*!
     * Version 1.1.0
     */
    V1_1_0 = 0,
}LoRaWANSpecVersion_t;

/*!
 * LoRaMac Cryto Status
 */
typedef enum eLoRaMacCryptoStatus
{
    /*!
     * No error occurred
     */
    LORAMAC_CRYPTO_SUCCESS = 0,
    /*!
     * MIC does not match
     */
    LORAMAC_CRYPTO_FAIL_MIC,
    /*!
     * Address does not match
     */
    LORAMAC_CRYPTO_FAIL_ADDRESS,
    /*!
     * JoinNonce was not greater than previous one.
     */
    LORAMAC_CRYPTO_FAIL_JOIN_NONCE,
    /*!
     * RJcount0 reached 2^16-1
     */
    LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
    /*!
     * FCntUp/Down check failed
     */
    LORAMAC_CRYPTO_FAIL_FCNT,
    /*!
     * Null pointer exception
     */
    LORAMAC_CRYPTO_ERROR_NPE,
    /*!
     * Invalid key identifier exception
     */
    LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID,
    /*!
     * Invalid address identifier exception
     */
    LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID,
    /*!
     * Invalid LoRaWAN specification version
     */
    LORAMAC_CRYPTO_ERROR_INVALID_VERSION,
    /*!
     * Incompatible buffer size
     */
    LORAMAC_CRYPTO_ERROR_BUF_SIZE,
    /*!
     * The secure element reports an error
     */
    LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC,
    /*!
     * Error from parser reported
     */
    LORAMAC_CRYPTO_ERROR_PARSER,
    /*!
     * Error from serializer reported
     */
    LORAMAC_CRYPTO_ERROR_SERIALIZER,
    /*!
     * RJcount1 reached 2^16-1 which should never happen
     */
    LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW,
    /*!
     * Undefined Error occurred
     */
    LORAMAC_CRYPTO_ERROR,
}LoRaMacCryptoStatus_t;

/*!
 * Signature of callback function to be called by the LoRaMac Crypto module when the
 * non volatile context have to be stored. It is also possible to save the entire
 * crypto module context.
 *
 * \param[IN]     nvCryptoCtx     - Points to structure where the module store its non volatile context
 * \param[IN]     nvCryptoCtxSize - Size of the module non volatile context
 * \param[IN]     cryptoCtx       - Points to structure where the module store its context
 * \param[IN]     cryptoCtxSize   - Size of the module context
 */
typedef void ( *LoRaMacCryptoStoreCtx ) (  void *nvCryptoCtx, size_t nvCryptoCtxSize, void *cryptoCtx, size_t cryptoCtxSize );

/*!
 * Signature of callback function to be called by the LoRaMac Crypto module when the
 * non volatile context have to be restored. It is also possible to restore the entire
 * crypto module context.
 *
 * \param[IN]     nvCryptoCtx     - Points to structure where the module store its non volatile context
 * \param[IN]     nvCryptoCtxSize - Size of the module non volatile context
 * \param[IN]     cryptoCtx       - Points to structure where the module store its context
 * \param[IN]     cryptoCtxSize   - Size of the module context
 */
typedef void ( *LoRaMacCryptoRestoreCtx ) ( void *nvCryptoCtx, size_t nvCryptoCtxSize, void *cryptoCtx, size_t cryptoCtxSize );

/*!
 * Initialization of LoRaMac Crypto module
 * It sets initial values of volatile variables and assigns the non volatile context.
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN]     cryptoCtx      - Points to structure where the module store its context
 * \param[IN]     nvCryptoCtx    - Points to structure where the module store its non volatile context
 * \retval                       - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaWANSpecVersion_t version, LoRaMacCryptoStoreCtx storeCryptoCtx, LoRaMacCryptoRestoreCtx restoreCryptoCtx );

/*!
 * Sets a key
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN]     keyID          - Key identifier
 * \param[IN]     key            - Key value (16 byte)
 * \retval                    - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( LoRaWANSpecVersion_t version, KeyIdentifier_t keyID, uint8_t *key );

/*!
 * Prepares the join-request message.
 * It computes the mic and add it to the message.
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN/OUT] macMsg         - Join-request message object
 * \retval                       - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaWANSpecVersion_t version, LoRaMacMessageJoinRequest_t *macMsg );

/*!
 * Prepares a rejoin-request type 1 message.
 * It computes the mic and add it to the message.
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN/OUT] macMsg         - Rejoin message object
 * \retval                       - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaWANSpecVersion_t version, LoRaMacMessageReJoinType1_t *macMsg );

/*!
 * Prepares a rejoin-request type 0 or 2 message.
 * It computes the mic and add it to the message.
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN/OUT] macMsg         - Rejoin message object
 * \retval                       - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaWANSpecVersion_t version, LoRaMacMessageReJoinType0or2_t *macMsg );

/*!
 * Handles the join-accept message.
 * It decrypts the message, verifies the MIC and if successful derives the session keys.
 *
 * \param[IN]     version        - LoRaWAN specification Version
 * \param[IN]     joinReqType    - Type of last join-request or rejoin which triggered the join-accept response
 * \param[IN]     joinEUI        - Join server EUI (8 byte)
 * \param[IN/OUT] macMsg         - Join-accept message object
 * \retval                       - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( LoRaWANSpecVersion_t version, JoinReqIdentifier_t joinReqType, uint8_t *joinEUI, LoRaMacMessageJoinAccept_t *macMsg );

/*!
 * Secures a message (encryption + integrity).
 *
 * \param[IN]     version         - LoRaWAN specification Version
 * \param[IN]     fCntUp          - Uplink sequence counter
 * \param[IN]     txDr            - Data rate used for the transmission
 * \param[IN]     txCh            - Index of the channel used for the transmission
 * \param[IN/OUT] macMsg          - Data message object
 * \retval                        - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( LoRaWANSpecVersion_t version, uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t *macMsg );

/*!
 * Unsecures a message (decryption + integrity verification).
 *
 * \param[IN]     version         - LoRaWAN specification Version
 * \param[IN]     addrID          - Address identifier
 * \param[IN]     address         - Address
 * \param[IN]     fCntDown        - Downlink sequence counter
 * \param[IN/OUT] macMsg          - Data message object
 * \retval                        - Status of the operation
 */
LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( LoRaWANSpecVersion_t version, AddressIdentifier_t addrID, uint32_t address, uint32_t fCntDown, LoRaMacMessageData_t *macMsg );


/*! \} addtogroup LORAMAC */

#endif // __LORAMAC_CRYPTO_H__

secure-element header

/*!
 * \file      secure-element.h
 *
 * \brief     Secure Element driver API
 *
 * \copyright Revised BSD License, see section \ref LICENSE.
 *
 * \code
 *                ______                              _
 *               / _____)             _              | |
 *              ( (____  _____ ____ _| |_ _____  ____| |__
 *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 *               _____) ) ____| | | || |_| ____( (___| | | |
 *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
 *              (C)2013-2017 Semtech
 *
 *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
 *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
 *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
 *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
 *              embedded.connectivity.solutions===============
 *
 * \endcode
 *
 * \author    Miguel Luis ( Semtech )
 *
 * \author    Gregory Cristian ( Semtech )
 *
 * \author    Daniel Jaeckle ( STACKFORCE )
 *
 * \author    Johannes Bruder ( STACKFORCE )
 *
 */
#ifndef __SECURE_ELEMENT_H__
#define __SECURE_ELEMENT_H__

#include <stdint.h>
#include "LoRaMacCrypto.h"

/*!
 * Return values.
 */
typedef enum eSecureElementStatus
{
    /*!
     * No error occurred
     */
    SECURE_ELEMENT_SUCCESS = 0,
    /*!
     * CMAC does not match
     */
    SECURE_ELEMENT_FAIL_CMAC,
    /*!
     * Null pointer exception
     */
    SECURE_ELEMENT_ERROR_NPE,
    /*!
     * Invalid key identifier exception
     */
    SECURE_ELEMENT_ERROR_INVALID_KEY_ID,
    /*!
     * Invalid LoRaWAN specification version
     */
    SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION,
    /*!
     * Incompatible buffer size
     */
    SECURE_ELEMENT_ERROR_BUF_SIZE,
    /*!
     * Undefined Error occurred
     */
    SECURE_ELEMENT_ERROR,
}SecureElementStatus_t;

/*!
 * Sets a key
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[IN]  keyID          - Key identifier
 * \param[IN]  key            - Key value
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementSetKey( LoRaWANSpecVersion_t version, KeyIdentifier_t keyID, uint8_t *key );

/*!
 * Computes a CMAC
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[IN]  buffer         - Data buffer
 * \param[IN]  size           - Data buffer size
 * \param[IN]  keyID          - Key identifier to determine the AES key to be used
 * \param[OUT] cmac           - Computed cmac
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementComputeAesCmac( LoRaWANSpecVersion_t version, uint8_t *buffer, uint16_t size,  KeyIdentifier_t keyID, uint32_t *cmac );

/*!
 * Verifies a CMAC (computes and compare with expected cmac)
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[IN]  buffer         - Data buffer
 * \param[IN]  size           - Data buffer size
 * \param[in]  expectedCmac   - Expected cmac
 * \param[IN]  keyID          - Key identifier to determine the AES key to be used
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementVerifyAesCmac( LoRaWANSpecVersion_t version, uint8_t *buffer, uint16_t size, uint32_t expectedCmac, KeyIdentifier_t keyID);

/*!
 * Encrypt a buffer
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[IN]  buffer         - Data buffer
 * \param[IN]  size           - Data buffer size
 * \param[IN]  keyID          - Key identifier to determine the AES key to be used
 * \param[OUT] encBuffer      - Encrypted buffer
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementAesEncrypt( LoRaWANSpecVersion_t version, uint8_t *buffer, uint16_t size,  KeyIdentifier_t keyID, uint8_t *encBuffer );

/*!
 * Derives and store a session key
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[IN]  nonce          - Nonce data ( 16 byte )
 * \param[IN]  rootKeyID      - Key identifier of the root key to use to perform the derivation
 * \param[IN]  sessionKeyID   - Key identifier of the new session key which will be derived
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementDeriveAndStoreKey( LoRaWANSpecVersion_t version, uint8_t *nonce, KeyIdentifier_t rootKeyID, KeyIdentifier_t sessionKeyID );

/*!
 * Generates a random number
 *
 * \param[IN]  version        - LoRaWAN specification Version
 * \param[OUT] randomNum      - 32 bit random number
 * \retval                    - Status of the operation
 */
SecureElementStatus_t SecureElementRandomNumber( LoRaWANSpecVersion_t version, uint32_t *randomNum );

#endif //  __SECURE_ELEMENT_H__
Clone this wiki locally