Files
kunlun/plc/halmac/crypto/mac_crypto.c
2024-09-28 14:24:04 +08:00

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