1.2.11.2 Using The Library

The SE Security library is called perform cryptographic operations.

The following example, which is an extract from G3 LBP eap_psk.c file, illustrates how the Security service can be used.

Example of SE Security library usage

// *****************************************************************************
// *****************************************************************************
// Section: File includes
// *****************************************************************************
// *****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "adp_api_types.h"
#include "eap_psk.h"
#include "service/security/aes_wrapper.h"
#include "service/security/cipher_wrapper.h"

// *****************************************************************************
// *****************************************************************************
// Section: Macro Definitions
// *****************************************************************************
// *****************************************************************************

#define member_size(type, member) sizeof(((type *)0)->member)

/* IANA allocated value */
#define EAP_PSK_IANA_TYPE           0x2F

// *****************************************************************************
// *****************************************************************************
// Section: Interface Function Definitions
// *****************************************************************************
// *****************************************************************************

void EAP_PSK_Initialize(EAP_PSK_KEY *pKey, EAP_PSK_CONTEXT *pPskContext)
{
    uint8_t block[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t res[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    (void) memset(pPskContext, 0, sizeof(EAP_PSK_CONTEXT));

    /* Set key and trigger the AES ECB */
    AES_Wrapper_SetEncryptEcbKey(pKey->value);
    AES_Wrapper_EncryptEcb(block, res);

    /* Xor with c1 = "1" */
    res[15] ^= 0x01U;

    /* Generate AK */
    AES_Wrapper_EncryptEcb(res, pPskContext->ak.value);

    /* Generate AK */
    /* Xor with c1 = "2" */
    res[15] ^= 0x03U; /* 3 instead of 2 because it has been already xor'ed with 1 and we want to get back the initial value */

    /* Generate KDK */
    AES_Wrapper_EncryptEcb(res, pPskContext->kdk.value);
}

uint16_t EAP_PSK_EncodeMessage3(
    EAP_PSK_CONTEXT *pPskContext,
    uint8_t identifier,
    EAP_PSK_RAND *pRandS,
    EAP_PSK_RAND *pRandP,
    EAP_PSK_NETWORK_ACCESS_ID_S *pIdS,
    uint32_t nonce,
    uint8_t PChannelResult,
    uint16_t PChannelDataLength,
    uint8_t *pPChannelData,
    uint16_t memoryBufferLength,
    uint8_t *pMemoryBuffer
    )
{
    uint16_t encodeSize = 0U;
    uint8_t macS[16];
    uint8_t *pProtectedData = NULL;
    uint16_t protectedDataLength = 0U;
    uint8_t *pTag = NULL;
    uint8_t auxNonce[16];
    int32_t ret;
    uint8_t seed[LBP_NETWORK_ACCESS_ID_MAX_SIZE_S + member_size(EAP_PSK_RAND, value)];
    uint8_t seedSize = pIdS->size + (uint8_t)member_size(EAP_PSK_RAND, value);

    /* check the size of the buffer */
    if (memoryBufferLength >= FIXED_LEN + PChannelDataLength)
    {
        (void) memcpy(seed, pIdS->value, pIdS->size);
        (void) memcpy(&seed[pIdS->size], pRandP->value, sizeof(pRandP->value));

        ret = CIPHER_Wrapper_AesCmacDirect(seed, seedSize, macS, pPskContext->ak.value);

        /* Encode the EAP header; length field will be set at the end of the block */
        pMemoryBuffer[0] = EAP_REQUEST;
        pMemoryBuffer[1] = identifier;
        pMemoryBuffer[4] = EAP_PSK_IANA_TYPE;
        pMemoryBuffer[5] = EAP_PSK_T2;
        encodeSize = 6U;

        /* EAP message: add PSK fields */
        (void) memcpy(&pMemoryBuffer[encodeSize], pRandS->value, sizeof(pRandS->value));
        encodeSize += (uint16_t)sizeof(pRandS->value);
        (void) memcpy(&pMemoryBuffer[encodeSize], macS, sizeof(macS));
        encodeSize += (uint16_t)sizeof(macS);

        /* Prepare P-Channel content */
        (void) memset(auxNonce, 0, sizeof(auxNonce));
        auxNonce[12] = pMemoryBuffer[encodeSize++] = (uint8_t)(nonce >> 24);
        auxNonce[13] = pMemoryBuffer[encodeSize++] = (uint8_t)(nonce >> 16);
        auxNonce[14] = pMemoryBuffer[encodeSize++] = (uint8_t)(nonce >> 8);
        auxNonce[15] = pMemoryBuffer[encodeSize++] = (uint8_t)nonce;

        /* tag will be added later */
        pTag = &pMemoryBuffer[encodeSize];
        encodeSize += 16U;

        /* protected data */
        pProtectedData = &pMemoryBuffer[encodeSize];
        if (PChannelDataLength > 0U)
        {
            /* result / extension = 1 */
            pProtectedData[protectedDataLength] = (PChannelResult << 6) | 0x20U;
            protectedDataLength++;

            (void) memcpy(&pProtectedData[protectedDataLength], pPChannelData, PChannelDataLength);
            protectedDataLength += PChannelDataLength;
        }
        else
        {
            /* result / extension = 0 */
            pProtectedData[protectedDataLength] = (PChannelResult << 6);
            protectedDataLength++;
        }

        encodeSize += protectedDataLength;

        /* Update the EAP header length field */
        pMemoryBuffer[2] = (uint8_t)(encodeSize >> 8);
        pMemoryBuffer[3] = (uint8_t)encodeSize;

        /* right shift Code field with 2 bits as indicated in the EAP specification */
        pMemoryBuffer[0] >>= 2;

        /* Encrypt P-Channel using TEK key */
        if (CIPHER_WRAPPER_RETURN_GOOD != CIPHER_Wrapper_AesEaxEncrypt(
                                              pProtectedData,          /* the message buffer        */
                                              protectedDataLength,     /* and its length in bytes   */
                                              auxNonce,                /* the initialization vector */
                                              16U,                     /* and its length in bytes   */
                                              pMemoryBuffer,           /* the header buffer         */
                                              22U,                     /* and its length in bytes   */
                                              pTag,                    /* the buffer for the tag    */
                                              16U,                     /* and its length in bytes   */
                                              pPskContext->tek.value)) /* the key                   */
        {
            encodeSize = 0U;
        }

        /* Fix EAP header: left shift Code field with 2 bits as indicated in the G3 specification */
        pMemoryBuffer[0] <<= 2;
    }

    return encodeSize;
}