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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* 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_REQ 4
|
||||||
#define FIXED_PARAM_OFFSET_ASSOC_RSP 6
|
#define FIXED_PARAM_OFFSET_ASSOC_RSP 6
|
||||||
|
|
||||||
|
#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
|
||||||
#define AAD_LEN 20
|
#define AAD_LEN 20
|
||||||
#define IEEE80211_MMIE_GMAC_MICLEN 16
|
#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
|
* Return: 0 if success else Error number
|
||||||
*/
|
*/
|
||||||
int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
|
int qdf_crypto_aes_gmac(const uint8_t *key, uint16_t key_length,
|
||||||
uint8_t *iv, uint8_t *aad, uint8_t *data,
|
uint8_t *iv, const uint8_t *aad,
|
||||||
uint16_t data_len, uint8_t *mic);
|
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
|
#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
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* 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;
|
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
|
* set_desc_flags() - set flags variable in the shash_desc struct
|
||||||
* @desc: pointer to 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
|
#endif
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
|
||||||
int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
|
int qdf_crypto_aes_gmac(const uint8_t *key, uint16_t key_length,
|
||||||
uint8_t *iv, uint8_t *aad, uint8_t *data,
|
uint8_t *iv, const uint8_t *aad,
|
||||||
uint16_t data_len, uint8_t *mic)
|
const uint8_t *data, uint16_t data_len, uint8_t *mic)
|
||||||
{
|
{
|
||||||
struct crypto_aead *tfm;
|
struct crypto_aead *tfm;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#define _WLAN_CRYPTO_GLOBAL_API_H_
|
#define _WLAN_CRYPTO_GLOBAL_API_H_
|
||||||
|
|
||||||
#include "wlan_crypto_global_def.h"
|
#include "wlan_crypto_global_def.h"
|
||||||
|
#include <qdf_crypto.h>
|
||||||
/**
|
/**
|
||||||
* wlan_crypto_set_vdev_param - called by ucfg to set crypto param
|
* wlan_crypto_set_vdev_param - called by ucfg to set crypto param
|
||||||
* @vdev: vdev
|
* @vdev: vdev
|
||||||
@@ -726,18 +727,22 @@ QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
|
|||||||
uint16_t ie_len);
|
uint16_t ie_len);
|
||||||
#ifdef WLAN_CRYPTO_GCM_OS_DERIVATIVE
|
#ifdef WLAN_CRYPTO_GCM_OS_DERIVATIVE
|
||||||
static inline int wlan_crypto_aes_gmac(const uint8_t *key, size_t key_len,
|
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,
|
const uint8_t *aad, size_t aad_len,
|
||||||
uint8_t *tag)
|
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
|
#endif
|
||||||
#ifdef WLAN_CRYPTO_OMAC1_OS_DERIVATIVE
|
#ifdef WLAN_CRYPTO_OMAC1_OS_DERIVATIVE
|
||||||
static inline int omac1_aes_128(const uint8_t *key, const uint8_t *data,
|
static inline int omac1_aes_128(const uint8_t *key, const uint8_t *data,
|
||||||
size_t data_len, uint8_t *mac)
|
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,
|
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 *frm,
|
||||||
uint8_t *efrm){
|
uint8_t *efrm){
|
||||||
struct wlan_crypto_mmie *mmie = NULL;
|
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_crypto_key *key;
|
||||||
struct wlan_frame_hdr *hdr;
|
struct wlan_frame_hdr *hdr;
|
||||||
uint16_t mic_len, hdrlen, len;
|
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_copy(buf + 20, frm + hdrlen, len - hdrlen);
|
||||||
qdf_mem_zero(buf + (len - hdrlen + 20 - mic_len), mic_len);
|
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) {
|
if (crypto_priv->igtk_key_type == WLAN_CRYPTO_CIPHER_AES_CMAC) {
|
||||||
ret = omac1_aes_128(key->keyval, buf,
|
ret = omac1_aes_128(key->keyval, buf,
|
||||||
len - hdrlen + aad_len, mic);
|
len - hdrlen + aad_len, mic);
|
||||||
@@ -2181,16 +2185,19 @@ bool wlan_crypto_is_mmie_valid(struct wlan_objmgr_vdev *vdev,
|
|||||||
qdf_mem_free(buf);
|
qdf_mem_free(buf);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
qdf_mem_free(mic);
|
||||||
crypto_err("genarate mmie failed");
|
crypto_err("genarate mmie failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qdf_mem_cmp(mic, mmie->mic, mic_len) != 0) {
|
if (qdf_mem_cmp(mic, mmie->mic, mic_len) != 0) {
|
||||||
|
qdf_mem_free(mic);
|
||||||
crypto_err("mmie mismatch");
|
crypto_err("mmie mismatch");
|
||||||
/* MMIE MIC mismatch */
|
/* MMIE MIC mismatch */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qdf_mem_free(mic);
|
||||||
/* Update the receive sequence number */
|
/* Update the receive sequence number */
|
||||||
qdf_mem_copy(key->keyrsc, ipn, 6);
|
qdf_mem_copy(key->keyrsc, ipn, 6);
|
||||||
crypto_debug("mmie matched");
|
crypto_debug("mmie matched");
|
||||||
|
Reference in New Issue
Block a user