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