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 */
|