249 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 | 
						|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | 
						|
 | 
						|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | 
						|
be copied by any method or incorporated into another program without
 | 
						|
the express written consent of Aerospace C.Power. This Information or any portion
 | 
						|
thereof remains the property of Aerospace C.Power. The Information contained herein
 | 
						|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | 
						|
liability for its use in any way and conveys no license or title under
 | 
						|
any patent or copyright and makes no representation or warranty that this
 | 
						|
Information is free from patent or copyright infringement.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
#include "mac_msdu.h"
 | 
						|
#include "iot_io.h"
 | 
						|
 | 
						|
#include "iot_crypto.h"
 | 
						|
#include "iot_pkt_api.h"
 | 
						|
#include "mac_crc.h"
 | 
						|
 | 
						|
#define MAC_CRYPTO_SG_ALIGN_LEN                           16
 | 
						|
#define MAC_CRYPTO_SG_CBC_IV_LEN                          16
 | 
						|
#define MAC_CRYPTO_SG_HMAC_GCM_IV_LEN                     12
 | 
						|
#define MAC_CRYPTO_SG_IV_DATA_LEN                         12
 | 
						|
 | 
						|
#if HW_PLATFORM == HW_PLATFORM_SILICON
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief mac_crypto_handle     encrypt or decrypt data
 | 
						|
 *
 | 
						|
 * @param is_encrypt:           1 - encrypt, 0 - decrypt
 | 
						|
 * @param key:                  key buffer
 | 
						|
 * @param keybits:              key bit number
 | 
						|
 * @param data_in:              for encrypt, this is plaintext
 | 
						|
 *                              for decrypt, this is chipertext
 | 
						|
 * @param data_in_len:          input text byte length
 | 
						|
 * @param output:               for encrypt, this is chipertext
 | 
						|
 *                              for decrypt, this is plaintext
 | 
						|
 * @param p_data_out_len:       point to output text byte length
 | 
						|
 * @param iv:                   input iv buffer
 | 
						|
 * @param iv_len:               length of iv
 | 
						|
 * @param type                  crypto type see MAC_ENCRYPT_SG_MSDU_XXX_XXX
 | 
						|
 * @param tag:                  output tag buffer
 | 
						|
 *
 | 
						|
 * @retval:                     error code. see CRYPTO_RET_XXX
 | 
						|
 */
 | 
						|
static uint32_t mac_crypto_handle(uint8_t is_encrypt, uint8_t *key,
 | 
						|
    uint16_t keybits, uint8_t *data_in, uint32_t data_in_len, uint8_t *data_out,
 | 
						|
    uint32_t *p_data_out_len, uint8_t *iv, uint8_t iv_len, uint8_t type,
 | 
						|
    uint8_t *hmac)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    switch(type) {
 | 
						|
    case MAC_ENCRYPT_SG_MSDU_AES_CBC:
 | 
						|
    {
 | 
						|
        if (iot_crypto_aes_cbc_with_key(key, keybits, is_encrypt, data_in_len,
 | 
						|
            iv, data_in, data_out, NULL, 1) != CRYPTO_RET_OK) {
 | 
						|
            ret = ERR_FAIL;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case MAC_ENCRYPT_SG_MSDU_AES_GCM:
 | 
						|
    {
 | 
						|
        if (iot_crypto_aes_gcm(is_encrypt, key, keybits, data_in, data_in_len,
 | 
						|
            iv, iv_len, NULL, 0, data_out, hmac) != CRYPTO_RET_OK) {
 | 
						|
            ret = ERR_FAIL;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case MAC_ENCRYPT_SG_MSDU_SM4_CBC:
 | 
						|
    {
 | 
						|
        if (iot_crypto_sm4(is_encrypt, SM4_CBC, data_in, data_in_len,
 | 
						|
            data_out, p_data_out_len, key, iv, 1) != CRYPTO_RET_OK) {
 | 
						|
            ret = ERR_FAIL;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        ret = ERR_INVAL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief mac_crypto_para_is_valid     check the parameter is valid or not
 | 
						|
 *
 | 
						|
 * @param vdev:                        vdev pointer
 | 
						|
 * @param data_buf :                   input msdu pkt
 | 
						|
 *
 | 
						|
 * @retval:                            true - valid
 | 
						|
 *                                     false - invalid
 | 
						|
 */
 | 
						|
static bool_t mac_crypto_para_is_valid(mac_vdev_t *vdev,
 | 
						|
    iot_pkt_t *data_buf)
 | 
						|
{
 | 
						|
    bool_t ret = true;
 | 
						|
    (void)data_buf;
 | 
						|
 | 
						|
    do {
 | 
						|
        if ((vdev->sec_key == NULL) ||
 | 
						|
            ((vdev->sec_key->encrypt_type != MAC_ENCRYPT_SG_MSDU_AES_CBC) &&
 | 
						|
            (vdev->sec_key->encrypt_type != MAC_ENCRYPT_SG_MSDU_AES_GCM) &&
 | 
						|
            (vdev->sec_key->encrypt_type != MAC_ENCRYPT_SG_MSDU_SM4_CBC))) {
 | 
						|
            ret = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (vdev->sec_key->key_type != ENCRYPT_KEY_TYPE_CEK) {
 | 
						|
            ret = false;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    } while(0);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_crypto_check_msdu_buf(mac_vdev_t *vdev,
 | 
						|
    iot_pkt_t **p_data_buf, uint32_t proto)
 | 
						|
{
 | 
						|
    uint32_t msdu_len;
 | 
						|
    uint32_t pkt_len;
 | 
						|
    uint32_t tail_len;
 | 
						|
    iot_pkt_t *out_pkt = *p_data_buf;
 | 
						|
    uint8_t fill_len;
 | 
						|
    uint8_t *fill_data;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    mac_short_header_t *mac_hdr = (mac_short_header_t *)iot_pkt_data(*p_data_buf);
 | 
						|
 | 
						|
    if ((proto != PLC_PROTO_TYPE_SG) ||
 | 
						|
        (mac_hdr->version != MAC_HEADER_SHORT_VER)) {
 | 
						|
        ret = ERR_INVAL;
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mac_crypto_para_is_valid(vdev, *p_data_buf)) {
 | 
						|
        msdu_len = mac_hdr->msdu_len;
 | 
						|
        fill_len = (msdu_len & 0x0F) ? MAC_CRYPTO_SG_ALIGN_LEN -
 | 
						|
            (msdu_len & 0x0F) : 0;
 | 
						|
        mac_hdr->zero_pad_len = fill_len;
 | 
						|
        if (vdev->sec_key->encrypt_type == MAC_ENCRYPT_SG_MSDU_AES_GCM) {
 | 
						|
            fill_len += MAC_CRYPTO_SG_ALIGN_LEN;
 | 
						|
        }
 | 
						|
 | 
						|
        tail_len = iot_pkt_block_len(*p_data_buf, IOT_PKT_BLOCK_TAIL);
 | 
						|
        if (fill_len > tail_len) {
 | 
						|
            pkt_len = iot_pkt_block_len(*p_data_buf, IOT_PKT_BLOCK_ALL);
 | 
						|
            out_pkt = iot_pkt_alloc(pkt_len + fill_len - tail_len,
 | 
						|
                PLC_MAC_RF_MID);
 | 
						|
            if (out_pkt == NULL) {
 | 
						|
                iot_printf("%s fail to alloc a bigger pkt\n", __FUNCTION__);
 | 
						|
                mac_hdr->key_type = ENCRYPT_KEY_TYPE_NONE;
 | 
						|
                mac_hdr->zero_pad_len = 0;
 | 
						|
                mac_hdr->cek_seq = 0;
 | 
						|
                ret = ERR_NOMEM;
 | 
						|
                return ret;
 | 
						|
            }
 | 
						|
 | 
						|
            iot_pkt_cpy_with_head(out_pkt, *p_data_buf);
 | 
						|
            iot_pkt_free(*p_data_buf);
 | 
						|
            *p_data_buf = out_pkt;
 | 
						|
        }
 | 
						|
 | 
						|
        if (fill_len) {
 | 
						|
            mac_hdr->msdu_len = (uint16_t)(msdu_len + fill_len);
 | 
						|
            fill_data = iot_pkt_block_ptr(out_pkt, IOT_PKT_BLOCK_TAIL) -
 | 
						|
                SG_MAC_MSDU_CRC_LEN;
 | 
						|
            iot_pkt_put(out_pkt, fill_len);
 | 
						|
            os_mem_set(fill_data, 0, fill_len);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        mac_hdr->key_type = ENCRYPT_KEY_TYPE_NONE;
 | 
						|
        mac_hdr->zero_pad_len = 0;
 | 
						|
        mac_hdr->cek_seq = 0;
 | 
						|
        ret = ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_encrypt_msdu_handle(iot_pkt_t *data_buf,
 | 
						|
    uint8_t *fc, uint32_t proto, uint16_t key_idx)
 | 
						|
{
 | 
						|
    mac_short_header_t *mac_hdr = (mac_short_header_t *)iot_pkt_data(data_buf);
 | 
						|
    uint32_t msdu_len;
 | 
						|
    mac_vdev_t *vdev;
 | 
						|
    uint8_t *msdu_data;
 | 
						|
    uint8_t iv_buf[max(MAC_CRYPTO_SG_CBC_IV_LEN,
 | 
						|
        MAC_CRYPTO_SG_HMAC_GCM_IV_LEN)];
 | 
						|
    uint8_t iv_len;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
 | 
						|
    if ((vdev->sec_key->encrypt_type == MAC_ENCRYPT_SG_MSDU_AES_CBC) ||
 | 
						|
        (vdev->sec_key->encrypt_type == MAC_ENCRYPT_SG_MSDU_SM4_CBC)) {
 | 
						|
        iv_len = MAC_CRYPTO_SG_CBC_IV_LEN;
 | 
						|
        os_mem_set(&iv_buf[MAC_CRYPTO_SG_IV_DATA_LEN], 0,
 | 
						|
            MAC_CRYPTO_SG_CBC_IV_LEN - MAC_CRYPTO_SG_IV_DATA_LEN);
 | 
						|
    } else {
 | 
						|
        iv_len = MAC_CRYPTO_SG_HMAC_GCM_IV_LEN;
 | 
						|
    }
 | 
						|
 | 
						|
    os_mem_cpy(iv_buf, fc, MAC_CRYPTO_SG_IV_DATA_LEN);
 | 
						|
    msdu_data = iot_pkt_data(data_buf) + sizeof(mac_short_header_t);
 | 
						|
    msdu_len = mac_hdr->msdu_len;
 | 
						|
    ret = mac_crypto_handle(1, vdev->sec_key->key[key_idx],
 | 
						|
        vdev->sec_key->keybits, msdu_data, msdu_len, msdu_data, &msdu_len,
 | 
						|
        iv_buf, iv_len, vdev->sec_key->encrypt_type, msdu_data + msdu_len -
 | 
						|
        MAC_CRYPTO_SG_ALIGN_LEN);
 | 
						|
 | 
						|
    if (ret != ERR_OK) {
 | 
						|
        mac_hdr->key_type = ENCRYPT_KEY_TYPE_NONE;
 | 
						|
    } else {
 | 
						|
        mac_hdr->key_type = vdev->sec_key->key_type;
 | 
						|
        mac_hdr->cek_seq = vdev->sec_key->cek_seq[key_idx];
 | 
						|
    }
 | 
						|
 | 
						|
    IOT_ASSERT(ERR_OK == mac_crc_set_msdu_swcrc(proto, data_buf));
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#else /* HW_PLATFORM == HW_PLATFORM_SILICON */
 | 
						|
 | 
						|
uint32_t mac_crypto_check_msdu_buf(mac_vdev_t *vdev,
 | 
						|
    iot_pkt_t **p_data_buf, uint32_t proto)
 | 
						|
{
 | 
						|
    (void)vdev;
 | 
						|
    (void)p_data_buf;
 | 
						|
    (void)proto;
 | 
						|
    return ERR_NOSUPP;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_encrypt_msdu_handle(iot_pkt_t *data_buf,
 | 
						|
    uint8_t *fc, uint32_t proto, uint16_t key_idx)
 | 
						|
{
 | 
						|
    (void)data_buf;
 | 
						|
    (void)fc;
 | 
						|
    (void)proto;
 | 
						|
    (void)key_idx;
 | 
						|
    return ERR_NOSUPP;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* HW_PLATFORM == HW_PLATFORM_SILICON */
 |