qcacmn: In crypto use QDF api to calculate MIC for OS derivatives
For WLAN_CRYPTO_OMAC1_OS_DERIVATIVE and WLAN_CRYPTO_GCM_OS_DERIVATIVE set use QDF API to calculate MIC Change-Id: I5971eb39414a292534981753805df6d9beb54be0 CRs-Fixed: 2664275
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -47,6 +47,7 @@ extern "C" {
|
||||
#define FIXED_PARAM_OFFSET_ASSOC_REQ 4
|
||||
#define FIXED_PARAM_OFFSET_ASSOC_RSP 6
|
||||
|
||||
#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
|
||||
#define AAD_LEN 20
|
||||
#define IEEE80211_MMIE_GMAC_MICLEN 16
|
||||
|
||||
@@ -152,9 +153,21 @@ int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
|
||||
*
|
||||
* Return: 0 if success else Error number
|
||||
*/
|
||||
int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
|
||||
uint8_t *iv, uint8_t *aad, uint8_t *data,
|
||||
uint16_t data_len, uint8_t *mic);
|
||||
int qdf_crypto_aes_gmac(const uint8_t *key, uint16_t key_length,
|
||||
uint8_t *iv, const uint8_t *aad,
|
||||
const uint8_t *data, uint16_t data_len, uint8_t *mic);
|
||||
|
||||
/**
|
||||
* qdf_crypto_aes_128_cmac: This API calculates MIC for AES 128 CMAC
|
||||
* @key: key used for operation
|
||||
* @data: Pointer to data
|
||||
* @len: Length of data
|
||||
* @mic: Pointer to MIC
|
||||
*
|
||||
* Return: 0 if success else Error number
|
||||
*/
|
||||
int qdf_crypto_aes_128_cmac(const uint8_t *key, const uint8_t *data,
|
||||
uint16_t len, uint8_t *mic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -95,6 +95,136 @@ void qdf_update_dbl(uint8_t *d)
|
||||
d[AES_BLOCK_SIZE - 1] ^= 0x87;
|
||||
}
|
||||
|
||||
static inline void xor_128(const uint8_t *a, const uint8_t *b, uint8_t *out)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
out[i] = a[i] ^ b[i];
|
||||
}
|
||||
|
||||
static inline void leftshift_onebit(const uint8_t *input, uint8_t *output)
|
||||
{
|
||||
int i, overflow = 0;
|
||||
|
||||
for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
|
||||
output[i] = input[i] << 1;
|
||||
output[i] |= overflow;
|
||||
overflow = (input[i] & 0x80) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_subkey(struct crypto_cipher *tfm, uint8_t *k1, uint8_t *k2)
|
||||
{
|
||||
uint8_t l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
|
||||
const uint8_t const_rb[AES_BLOCK_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
|
||||
};
|
||||
const uint8_t const_zero[AES_BLOCK_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
crypto_cipher_encrypt_one(tfm, l, const_zero);
|
||||
|
||||
if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
|
||||
leftshift_onebit(l, k1);
|
||||
} else { /* Else k1 = ( l << 1 ) (+) Rb */
|
||||
leftshift_onebit(l, tmp);
|
||||
xor_128(tmp, const_rb, k1);
|
||||
}
|
||||
|
||||
if ((k1[0] & 0x80) == 0) {
|
||||
leftshift_onebit(k1, k2);
|
||||
} else {
|
||||
leftshift_onebit(k1, tmp);
|
||||
xor_128(tmp, const_rb, k2);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void padding(const uint8_t *lastb, uint8_t *pad, uint16_t length)
|
||||
{
|
||||
uint8_t j;
|
||||
|
||||
/* original last block */
|
||||
for (j = 0; j < AES_BLOCK_SIZE; j++) {
|
||||
if (j < length)
|
||||
pad[j] = lastb[j];
|
||||
else if (j == length)
|
||||
pad[j] = 0x80;
|
||||
else
|
||||
pad[j] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
int qdf_crypto_aes_128_cmac(const uint8_t *key, const uint8_t *data,
|
||||
uint16_t len, uint8_t *mic)
|
||||
{
|
||||
uint8_t x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
|
||||
uint8_t m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
|
||||
uint8_t k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
|
||||
int cmp_blk;
|
||||
int i, num_block = (len + 15) / AES_BLOCK_SIZE;
|
||||
struct crypto_cipher *tfm;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Calculate MIC and then copy
|
||||
*/
|
||||
tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm)) {
|
||||
ret = PTR_ERR(tfm);
|
||||
qdf_err("crypto_alloc_cipher failed (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = crypto_cipher_setkey(tfm, key, AES_KEYSIZE_128);
|
||||
if (ret) {
|
||||
qdf_err("crypto_cipher_setkey failed (%d)", ret);
|
||||
crypto_free_cipher(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
generate_subkey(tfm, k1, k2);
|
||||
|
||||
if (num_block == 0) {
|
||||
num_block = 1;
|
||||
cmp_blk = 0;
|
||||
} else {
|
||||
cmp_blk = ((len % AES_BLOCK_SIZE) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (cmp_blk) {
|
||||
/* Last block is complete block */
|
||||
xor_128(&data[AES_BLOCK_SIZE * (num_block - 1)], k1, m_last);
|
||||
} else {
|
||||
/* Last block is not complete block */
|
||||
padding(&data[AES_BLOCK_SIZE * (num_block - 1)], padded,
|
||||
len % AES_BLOCK_SIZE);
|
||||
xor_128(padded, k2, m_last);
|
||||
}
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
x[i] = 0;
|
||||
|
||||
for (i = 0; i < (num_block - 1); i++) {
|
||||
/* y = Mi (+) x */
|
||||
xor_128(x, &data[AES_BLOCK_SIZE * i], y);
|
||||
/* x = AES-128(KEY, y) */
|
||||
crypto_cipher_encrypt_one(tfm, x, y);
|
||||
}
|
||||
|
||||
xor_128(x, m_last, y);
|
||||
crypto_cipher_encrypt_one(tfm, x, y);
|
||||
|
||||
crypto_free_cipher(tfm);
|
||||
|
||||
memcpy(mic, x, CMAC_TLEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_desc_flags() - set flags variable in the shash_desc struct
|
||||
* @desc: pointer to shash_desc struct
|
||||
@@ -377,9 +507,9 @@ int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
|
||||
int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
|
||||
uint8_t *iv, uint8_t *aad, uint8_t *data,
|
||||
uint16_t data_len, uint8_t *mic)
|
||||
int qdf_crypto_aes_gmac(const uint8_t *key, uint16_t key_length,
|
||||
uint8_t *iv, const uint8_t *aad,
|
||||
const uint8_t *data, uint16_t data_len, uint8_t *mic)
|
||||
{
|
||||
struct crypto_aead *tfm;
|
||||
int ret = 0;
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#define _WLAN_CRYPTO_GLOBAL_API_H_
|
||||
|
||||
#include "wlan_crypto_global_def.h"
|
||||
#include <qdf_crypto.h>
|
||||
/**
|
||||
* wlan_crypto_set_vdev_param - called by ucfg to set crypto param
|
||||
* @vdev: vdev
|
||||
@@ -726,18 +727,22 @@ QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
|
||||
uint16_t ie_len);
|
||||
#ifdef WLAN_CRYPTO_GCM_OS_DERIVATIVE
|
||||
static inline int wlan_crypto_aes_gmac(const uint8_t *key, size_t key_len,
|
||||
const uint8_t *iv, size_t iv_len,
|
||||
uint8_t *iv, size_t iv_len,
|
||||
const uint8_t *aad, size_t aad_len,
|
||||
uint8_t *tag)
|
||||
{
|
||||
return 0;
|
||||
return qdf_crypto_aes_gmac(key, key_len, iv, aad,
|
||||
aad + AAD_LEN,
|
||||
aad_len - AAD_LEN -
|
||||
IEEE80211_MMIE_GMAC_MICLEN,
|
||||
tag);
|
||||
}
|
||||
#endif
|
||||
#ifdef WLAN_CRYPTO_OMAC1_OS_DERIVATIVE
|
||||
static inline int omac1_aes_128(const uint8_t *key, const uint8_t *data,
|
||||
size_t data_len, uint8_t *mac)
|
||||
{
|
||||
return 0;
|
||||
return qdf_crypto_aes_128_cmac(key, data, data_len, mac);
|
||||
}
|
||||
|
||||
static inline int omac1_aes_256(const uint8_t *key, const uint8_t *data,
|
||||
|
@@ -2068,7 +2068,7 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
|
||||
uint8_t *frm,
|
||||
uint8_t *efrm){
|
||||
struct wlan_crypto_mmie *mmie = NULL;
|
||||
uint8_t *ipn, *aad, *buf, mic[16], nounce[12];
|
||||
uint8_t *ipn, *aad, *buf, *mic, nounce[12];
|
||||
struct wlan_crypto_key *key;
|
||||
struct wlan_frame_hdr *hdr;
|
||||
uint16_t mic_len, hdrlen, len;
|
||||
@@ -2160,7 +2160,11 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
|
||||
*/
|
||||
qdf_mem_copy(buf + 20, frm + hdrlen, len - hdrlen);
|
||||
qdf_mem_zero(buf + (len - hdrlen + 20 - mic_len), mic_len);
|
||||
qdf_mem_zero(mic, 16);
|
||||
mic = qdf_mem_malloc(mic_len);
|
||||
if (!mic) {
|
||||
qdf_mem_free(buf);
|
||||
return false;
|
||||
}
|
||||
if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
|
||||
ret = omac1_aes_128(key->keyval, buf,
|
||||
len - hdrlen + aad_len, mic);
|
||||
@@ -2181,16 +2185,19 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_mem_free(buf);
|
||||
|
||||
if (ret < 0) {
|
||||
qdf_mem_free(mic);
|
||||
crypto_err("genarate mmie failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qdf_mem_cmp(mic, mmie->mic, mic_len) != 0) {
|
||||
qdf_mem_free(mic);
|
||||
crypto_err("mmie mismatch");
|
||||
/* MMIE MIC mismatch */
|
||||
return false;
|
||||
}
|
||||
|
||||
qdf_mem_free(mic);
|
||||
/* Update the receive sequence number */
|
||||
qdf_mem_copy(key->keyrsc, ipn, 6);
|
||||
crypto_debug("mmie matched");
|
||||
|
Reference in New Issue
Block a user