From e25c64c047d4353d829c7c4903017d7c7a397dff Mon Sep 17 00:00:00 2001 From: Ashok Ponnaiah Date: Mon, 9 Apr 2018 15:34:14 +0530 Subject: [PATCH] qcacmn: Fix ccmp sw encrypt and decrypt Fixed ccmp sw encrypt and decrypt Change-Id: Ic0bff6cb764747f31fbb2354e170978144f178d6 Crs-Fixed: 2204858 --- .../crypto/src/wlan_crypto_aes_i.h | 5 +- .../crypto/src/wlan_crypto_ccmp.c | 32 ++++++++----- .../crypto/src/wlan_crypto_ccmp_sw.c | 47 ++++++++++++------- .../crypto/src/wlan_crypto_def_i.h | 20 ++++++++ .../crypto/src/wlan_crypto_global_api.c | 11 +++-- .../crypto/src/wlan_crypto_tkip.c | 4 +- .../cmn_services/crypto/src/wlan_crypto_wep.c | 4 +- 7 files changed, 85 insertions(+), 38 deletions(-) diff --git a/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h b/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h index 2ae94af96e4e..ca4a243ce2f0 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_aes_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */ /* * AES (Rijndael) cipher @@ -22,6 +22,9 @@ #include "wlan_crypto_global_def.h" +#define CCMP_IV_SIZE (WLAN_CRYPTO_IV_LEN + WLAN_CRYPTO_KEYID_LEN \ + + WLAN_CRYPTO_EXT_IV_LEN) + #define AES_BLOCK_SIZE 16 #define wpa_printf(args...) do { } while (0) #define wpa_hexdump(l, t, b, le) do { } while (0) diff --git a/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c b/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c index 09ebd800b459..e9047c8af2c2 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_ccmp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 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 @@ -73,14 +73,14 @@ static QDF_STATUS ccmp_encap(struct wlan_crypto_key *key, /* XXX wrap at 48 bits */ key->keytsc++; - ivp[0] = key->keytsc >> 0; /* PN0 */ - ivp[1] = key->keytsc >> 8; /* PN1 */ - ivp[2] = 0; /* Reserved */ - ivp[3] = key->keyix | WLAN_CRYPTO_EXT_IV_BIT; /* KeyID | ExtID */ - ivp[4] = key->keytsc >> 16; /* PN2 */ - ivp[5] = key->keytsc >> 24; /* PN3 */ - ivp[6] = key->keytsc >> 32; /* PN4 */ - ivp[7] = key->keytsc >> 40; /* PN5 */ + ivp[0] = key->keytsc >> 0; /* PN0 */ + ivp[1] = key->keytsc >> 8; /* PN1 */ + ivp[2] = 0; /* Reserved */ + ivp[3] = (key->keyix << 6)| WLAN_CRYPTO_EXT_IV_BIT;/* KeyID | ExtID */ + ivp[4] = key->keytsc >> 16; /* PN2 */ + ivp[5] = key->keytsc >> 24; /* PN3 */ + ivp[6] = key->keytsc >> 32; /* PN4 */ + ivp[7] = key->keytsc >> 40; /* PN5 */ /* * Finally, do software encrypt if neeed. @@ -89,7 +89,7 @@ static QDF_STATUS ccmp_encap(struct wlan_crypto_key *key, if (!wlan_crypto_ccmp_encrypt(key->keyval, qdf_nbuf_data(wbuf), qdf_nbuf_len(wbuf), hdrlen)) { - return 0; + return QDF_STATUS_CRYPTO_ENCRYPT_FAILED; } } @@ -204,9 +204,15 @@ static QDF_STATUS ccmp_decap(struct wlan_crypto_key *key, /* * Copy up 802.11 header and strip crypto bits. */ - qdf_mem_move(origHdr + cipher_table->header, origHdr, hdrlen); - qdf_nbuf_pull_head(wbuf, cipher_table->header); - qdf_nbuf_trim_tail(wbuf, cipher_table->trailer); + if (!(key->flags & WLAN_CRYPTO_KEY_SWDECRYPT)) { + qdf_mem_move(origHdr + cipher_table->header, origHdr, hdrlen); + qdf_nbuf_pull_head(wbuf, cipher_table->header); + qdf_nbuf_trim_tail(wbuf, cipher_table->trailer + + cipher_table->miclen); + } else { + qdf_nbuf_trim_tail(wbuf, cipher_table->header + + cipher_table->miclen); + } if (update_keyrsc) { /* diff --git a/umac/cmn_services/crypto/src/wlan_crypto_ccmp_sw.c b/umac/cmn_services/crypto/src/wlan_crypto_ccmp_sw.c index dbf045daffe9..46716d1fa213 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_ccmp_sw.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_ccmp_sw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */ /* * CTR with CBC-MAC Protocol (CCMP) @@ -85,7 +85,7 @@ uint8_t *wlan_crypto_ccmp_decrypt(const uint8_t *tk, size_t mlen; uint8_t *plain; - if (data_len < 8 + 8) + if (data_len < CCMP_IV_SIZE + WLAN_CRYPTO_MIC_LEN) return NULL; plain = qdf_mem_malloc(data_len + AES_BLOCK_SIZE); @@ -94,15 +94,19 @@ uint8_t *wlan_crypto_ccmp_decrypt(const uint8_t *tk, return NULL; } - mlen = data_len - 8 - 8; + mlen = data_len - CCMP_IV_SIZE - WLAN_CRYPTO_MIC_LEN; qdf_mem_set(aad, sizeof(aad), 0); ccmp_aad_nonce(hdr, data, aad, &aad_len, nonce); wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); - if (wlan_crypto_aes_ccm_ad(tk, 16, nonce, 8, data + 8, mlen, - aad, aad_len, data + 8 + mlen, plain) < 0) { + if (wlan_crypto_aes_ccm_ad(tk, 16, nonce, + WLAN_CRYPTO_MIC_LEN, + data + CCMP_IV_SIZE, mlen, + aad, aad_len, + data + CCMP_IV_SIZE + mlen, + plain) < 0) { /*uint16_t seq_ctrl = qdf_le16_to_cpu(hdr->seq_ctrl); wpa_printf(MSG_INFO, "Invalid CCMP MIC in frame: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", @@ -141,15 +145,16 @@ uint8_t *wlan_crypto_ccmp_encrypt(const uint8_t *tk, uint8_t *frame, if (len < hdrlen || hdrlen < 24) return NULL; - plen = len - hdrlen; + plen = len - hdrlen - CCMP_IV_SIZE - WLAN_CRYPTO_MIC_LEN; - crypt = qdf_mem_malloc(hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE); + crypt = qdf_mem_malloc(hdrlen + CCMP_IV_SIZE + plen + + WLAN_CRYPTO_MIC_LEN + AES_BLOCK_SIZE); if (crypt == NULL) { qdf_print("%s[%d] mem alloc failed\n", __func__, __LINE__); return NULL; } - qdf_mem_copy(crypt, frame, hdrlen); + qdf_mem_copy(crypt, frame, hdrlen + CCMP_IV_SIZE); hdr = (struct ieee80211_hdr *) crypt; hdr->frame_control |= qdf_cpu_to_le16(WLAN_FC_ISWEP); @@ -160,14 +165,16 @@ uint8_t *wlan_crypto_ccmp_encrypt(const uint8_t *tk, uint8_t *frame, wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); - if (wlan_crypto_aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, + if (wlan_crypto_aes_ccm_ae(tk, 16, nonce, WLAN_CRYPTO_MIC_LEN, + frame + hdrlen + CCMP_IV_SIZE, plen, aad, aad_len, pos, pos + plen) < 0) { qdf_mem_free(crypt); return NULL; } qdf_mem_copy(frame, crypt, len); - wpa_hexdump(MSG_EXCESSIVE, "CCMP encrypted", crypt + hdrlen + 8, plen); + wpa_hexdump(MSG_EXCESSIVE, "CCMP encrypted", + crypt + hdrlen + CCMP_IV_SIZE, plen); qdf_mem_free(crypt); return frame; @@ -183,7 +190,7 @@ uint8_t *wlan_crypto_ccmp_256_decrypt(const uint8_t *tk, size_t mlen; uint8_t *plain; - if (data_len < 8 + 16) + if (data_len < CCMP_IV_SIZE + WLAN_CRYPTO_MIC256_LEN) return NULL; plain = qdf_mem_malloc(data_len + AES_BLOCK_SIZE); @@ -192,15 +199,18 @@ uint8_t *wlan_crypto_ccmp_256_decrypt(const uint8_t *tk, return NULL; } - mlen = data_len - 8 - 16; + mlen = data_len - CCMP_IV_SIZE - WLAN_CRYPTO_MIC256_LEN; qdf_mem_set(aad, sizeof(aad), 0); ccmp_aad_nonce(hdr, data, aad, &aad_len, nonce); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13); - if (wlan_crypto_aes_ccm_ad(tk, 32, nonce, 16, data + 8, mlen, - aad, aad_len, data + 8 + mlen, plain) < 0) { + if (wlan_crypto_aes_ccm_ad(tk, 32, nonce, WLAN_CRYPTO_MIC256_LEN, + data + CCMP_IV_SIZE, mlen, + aad, aad_len, + data + CCMP_IV_SIZE + mlen, + plain) < 0) { /*uint16_t seq_ctrl = qdf_le16_to_cpu(hdr->seq_ctrl); wpa_printf(MSG_INFO, "Invalid CCMP-256 MIC in frame: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", @@ -231,7 +241,8 @@ uint8_t *wlan_crypto_ccmp_256_encrypt(const uint8_t *tk, uint8_t *frame, return NULL; plen = len - hdrlen; - crypt = qdf_mem_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE); + crypt = qdf_mem_malloc(hdrlen + CCMP_IV_SIZE + plen + + WLAN_CRYPTO_MIC256_LEN + AES_BLOCK_SIZE); if (crypt == NULL) { qdf_print("%s[%d] mem alloc failed\n", __func__, __LINE__); return NULL; @@ -255,7 +266,8 @@ uint8_t *wlan_crypto_ccmp_256_encrypt(const uint8_t *tk, uint8_t *frame, wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13); - if (wlan_crypto_aes_ccm_ae(tk, 32, nonce, 16, frame + hdrlen, plen, + if (wlan_crypto_aes_ccm_ae(tk, 32, nonce, WLAN_CRYPTO_MIC256_LEN, + frame + hdrlen, plen, aad, aad_len, pos, pos + plen) < 0) { qdf_mem_free(crypt); return NULL; @@ -264,7 +276,8 @@ uint8_t *wlan_crypto_ccmp_256_encrypt(const uint8_t *tk, uint8_t *frame, wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 encrypted", crypt + hdrlen + 8, plen); - *encrypted_len = hdrlen + 8 + plen + 16; + *encrypted_len = hdrlen + CCMP_IV_SIZE + + plen + WLAN_CRYPTO_MIC256_LEN; return crypt; } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h index 4d1d0af471d8..dd77767cb4bd 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -493,6 +493,26 @@ static inline int ieee80211_hdrsize(const void *data) return size; } +/** + * wlan_crypto_get_keyid - get keyid from frame + * @data: frame + * + * This function parse frame and returns keyid + * + * Return: keyid + */ +static inline uint16_t wlan_crypto_get_keyid(uint8_t *data) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; + + if (hdr->frame_control & WLAN_FC_ISWEP) { + uint8_t *iv; + iv = data + ieee80211_hdrsize(data); + return ((iv[3] >> 6) & 0x3); + } else + return WLAN_CRYPTO_KEYIX_NONE; +} + /** * wlan_get_tid - get tid of the frame * @data: frame diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 62f69814691b..6e32e298e080 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -266,7 +266,6 @@ int32_t wlan_crypto_get_param(struct wlan_objmgr_vdev *vdev, return value; } - /** * wlan_crypto_get_peer_param - called to get value for param from peer * @peer: peer @@ -1093,6 +1092,7 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_peer *peer; uint8_t bssid_mac[WLAN_ALEN]; + uint8_t keyid; wlan_vdev_obj_lock(vdev); qdf_mem_copy(bssid_mac, wlan_vdev_mlme_get_macaddr(vdev), WLAN_ALEN); @@ -1104,6 +1104,11 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, } wlan_vdev_obj_unlock(vdev); + keyid = wlan_crypto_get_keyid((uint8_t *)qdf_nbuf_data(wbuf)); + + if (keyid >= WLAN_CRYPTO_MAXKEYIDX) + return QDF_STATUS_E_INVAL; + /* FILS Decap required only for (Re-)Assoc request */ peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_CRYPTO_ID); @@ -1125,7 +1130,7 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } - key = crypto_priv->key[crypto_priv->def_tx_keyid]; + key = crypto_priv->key[keyid]; if (!key) return QDF_STATUS_E_INVAL; @@ -1150,7 +1155,7 @@ QDF_STATUS wlan_crypto_decap(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } - key = crypto_priv->key[crypto_priv->def_tx_keyid]; + key = crypto_priv->key[keyid]; if (!key) return QDF_STATUS_E_INVAL; } diff --git a/umac/cmn_services/crypto/src/wlan_crypto_tkip.c b/umac/cmn_services/crypto/src/wlan_crypto_tkip.c index 4392bec22e13..df7e06da3fe0 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_tkip.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_tkip.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 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 @@ -69,7 +69,7 @@ static QDF_STATUS tkip_encap(struct wlan_crypto_key *key, ivp[0] = key->keytsc >> 8; /* TSC1 */ ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */ ivp[2] = key->keytsc >> 0; /* TSC0*/ - ivp[3] = key->keyix | WLAN_CRYPTO_EXT_IV_BIT; /* KeyID | ExtID */ + ivp[3] = (key->keyix << 6) | WLAN_CRYPTO_EXT_IV_BIT; /* KeyID | ExtID */ ivp[4] = key->keytsc >> 16; /* PN2 */ ivp[5] = key->keytsc >> 24; /* PN3 */ ivp[6] = key->keytsc >> 32; /* PN4 */ diff --git a/umac/cmn_services/crypto/src/wlan_crypto_wep.c b/umac/cmn_services/crypto/src/wlan_crypto_wep.c index 149c0199c3b6..323680866381 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_wep.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_wep.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 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 @@ -80,7 +80,7 @@ static QDF_STATUS wep_encap(struct wlan_crypto_key *key, ivp[1] = key->keyrsc[0] >> 8; ivp[2] = key->keyrsc[0] >> 16; #endif - ivp[3] = key->keyix; + ivp[3] = key->keyix << 6; /* * Finally, do software encrypt if neeed.