1ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman/* 2ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * Host AP crypt: host-based CCMP encryption implementation for Host AP driver 3ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * 4ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 5ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * 6ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * This program is free software; you can redistribute it and/or modify 7ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * it under the terms of the GNU General Public License version 2 as 8ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * published by the Free Software Foundation. See README and COPYING for 9ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * more details. 10ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman */ 11ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 12ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/module.h> 13ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/init.h> 14ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/slab.h> 15ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/random.h> 16ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/skbuff.h> 17ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/netdevice.h> 18ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/if_ether.h> 19ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/if_arp.h> 20a44325f98563c39bc63311db7471b848153e49feLarry Finger#include <linux/string.h> 21ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/wireless.h> 2294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger#include "rtllib.h" 23ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 24ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/crypto.h> 25ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 26cb76215448947ddcc133c4b1c2ff2d4a77e851e0Mike McCormack#include <linux/scatterlist.h> 27ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 28ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#define AES_BLOCK_LEN 16 29ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#define CCMP_HDR_LEN 8 30ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#define CCMP_MIC_LEN 8 31ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#define CCMP_TK_LEN 16 32ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#define CCMP_PN_LEN 6 33ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 3494a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstruct rtllib_ccmp_data { 35ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 key[CCMP_TK_LEN]; 36ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int key_set; 37ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 38ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 tx_pn[CCMP_PN_LEN]; 39ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 rx_pn[CCMP_PN_LEN]; 40ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 41ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u32 dot11RSNAStatsCCMPFormatErrors; 42ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u32 dot11RSNAStatsCCMPReplays; 43ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u32 dot11RSNAStatsCCMPDecryptErrors; 44ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 45ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int key_idx; 46ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 47ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct crypto_tfm *tfm; 48ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 49ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* scratch buffers for virt_to_page() (crypto API) */ 50ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], 51ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; 52ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; 53ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman}; 54ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 55ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm, 56ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman const u8 pt[16], u8 ct[16]) 57ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 58a44325f98563c39bc63311db7471b848153e49feLarry Finger crypto_cipher_encrypt_one((void *)tfm, ct, pt); 59ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 60ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 61a44325f98563c39bc63311db7471b848153e49feLarry Fingerstatic void *rtllib_ccmp_init(int key_idx) 62ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 6394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *priv; 64ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 65929fa2a42e75e0c6ded89c450bd0f668e32190d7Thomas Meyer priv = kzalloc(sizeof(*priv), GFP_ATOMIC); 66ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (priv == NULL) 67ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto fail; 68ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman priv->key_idx = key_idx; 69ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 70a44325f98563c39bc63311db7471b848153e49feLarry Finger priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); 71ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (IS_ERR(priv->tfm)) { 725635b82a553620c511dc6bc8cb0990c0a791e21eMahati Chamarthy pr_debug("rtllib_crypt_ccmp: could not allocate " 73ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman "crypto API aes\n"); 74ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman priv->tfm = NULL; 75ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto fail; 76ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 77ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return priv; 78ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 79ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanfail: 80ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (priv) { 81ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (priv->tfm) 82a44325f98563c39bc63311db7471b848153e49feLarry Finger crypto_free_cipher((void *)priv->tfm); 83ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman kfree(priv); 84ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 85ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 86ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return NULL; 87ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 88ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 89ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 9094a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic void rtllib_ccmp_deinit(void *priv) 91ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 9294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *_priv = priv; 933a6b70c3f3558a2e47d2ca82752f0aed0f3c33c6Matthew Casey 94ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (_priv && _priv->tfm) 95a44325f98563c39bc63311db7471b848153e49feLarry Finger crypto_free_cipher((void *)_priv->tfm); 96ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman kfree(priv); 97ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 98ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 99ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 100ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanstatic inline void xor_block(u8 *b, u8 *a, size_t len) 101ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 102ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int i; 1033a6b70c3f3558a2e47d2ca82752f0aed0f3c33c6Matthew Casey 104ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 0; i < len; i++) 105ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b[i] ^= a[i]; 106ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 107ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 108ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 109ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 110ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanstatic void ccmp_init_blocks(struct crypto_tfm *tfm, 11194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_hdr_4addr *hdr, 112ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *pn, size_t dlen, u8 *b0, u8 *auth, 113ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *s0) 114ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 115ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *pos, qc = 0; 116ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman size_t aad_len; 117ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u16 fc; 118ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int a4_included, qc_included; 119ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 aad[2 * AES_BLOCK_LEN]; 120ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 121ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman fc = le16_to_cpu(hdr->frame_ctl); 12294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == 12394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)); 124ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* 12594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) && 126ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman (WLAN_FC_GET_STYPE(fc) & 0x08)); 127a44325f98563c39bc63311db7471b848153e49feLarry Finger */ 12894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) && 129ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman (WLAN_FC_GET_STYPE(fc) & 0x80)); 130ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad_len = 22; 131ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (a4_included) 132ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad_len += 6; 133ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (qc_included) { 134ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos = (u8 *) &hdr->addr4; 135ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (a4_included) 136ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos += 6; 137ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman qc = *pos & 0x0f; 138ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad_len += 2; 139ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 140ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* CCM Initial Block: 141ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * Flag (Include authentication header, M=3 (8-octet MIC), 142ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * L=1 (2-octet Dlen)) 143ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * Nonce: 0x00 | A2 | PN 144ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * Dlen */ 145ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[0] = 0x59; 146ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[1] = qc; 147ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(b0 + 2, hdr->addr2, ETH_ALEN); 148ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(b0 + 8, pn, CCMP_PN_LEN); 149ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[14] = (dlen >> 8) & 0xff; 150ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[15] = dlen & 0xff; 151ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 152ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* AAD: 153ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * FC with bits 4..6 and 11..13 masked to zero; 14 is always one 154ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * A1 | A2 | A3 155ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * SC with bits 4..15 (seq#) masked to zero 156ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * A4 (if present) 157ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * QC (if present) 158ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman */ 159ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos = (u8 *) hdr; 160ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[0] = 0; /* aad_len >> 8 */ 161ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[1] = aad_len & 0xff; 162ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[2] = pos[0] & 0x8f; 163ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[3] = pos[1] & 0xc7; 164ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); 165ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos = (u8 *) &hdr->seq_ctl; 166ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[22] = pos[0] & 0x0f; 167ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[23] = 0; /* all bits masked */ 168ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memset(aad + 24, 0, 8); 169ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (a4_included) 170ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(aad + 24, hdr->addr4, ETH_ALEN); 171ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (qc_included) { 172ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman aad[a4_included ? 30 : 24] = qc; 173ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* rest of QC masked */ 174ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 175ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 176ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Start with the first block and AAD */ 17794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(tfm, b0, auth); 178ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(auth, aad, AES_BLOCK_LEN); 17994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(tfm, auth, auth); 180ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); 18194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(tfm, auth, auth); 182ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[0] &= 0x07; 183ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[14] = b0[15] = 0; 18494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(tfm, b0, s0); 185ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 186ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 187ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 188ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 18994a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) 190ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 19194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *key = priv; 192ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int data_len, i; 193ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *pos; 19494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_hdr_4addr *hdr; 195a44325f98563c39bc63311db7471b848153e49feLarry Finger struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 196a44325f98563c39bc63311db7471b848153e49feLarry Finger MAX_DEV_ADDR_SIZE); 197ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (skb_headroom(skb) < CCMP_HDR_LEN || 198ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_tailroom(skb) < CCMP_MIC_LEN || 199ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb->len < hdr_len) 200ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 201ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 202ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data_len = skb->len - hdr_len; 203ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos = skb_push(skb, CCMP_HDR_LEN); 204ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memmove(pos, pos + CCMP_HDR_LEN, hdr_len); 205ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos += hdr_len; 206ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 207ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman i = CCMP_PN_LEN - 1; 208ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman while (i >= 0) { 209ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman key->tx_pn[i]++; 210ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (key->tx_pn[i] != 0) 211ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 212ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman i--; 213ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 214ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 215ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[5]; 216ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[4]; 217ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = 0; 218ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; 219ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[3]; 220ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[2]; 221ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[1]; 222ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *pos++ = key->tx_pn[0]; 223ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 224ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 22594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger hdr = (struct rtllib_hdr_4addr *) skb->data; 22694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (!tcb_desc->bHwSec) { 227ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int blocks, last, len; 228ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *mic; 229ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *b0 = key->tx_b0; 230ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *b = key->tx_b; 231ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *e = key->tx_e; 232ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *s0 = key->tx_s0; 233ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 234ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman mic = skb_put(skb, CCMP_MIC_LEN); 235ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 236a44325f98563c39bc63311db7471b848153e49feLarry Finger ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, 237a44325f98563c39bc63311db7471b848153e49feLarry Finger b0, b, s0); 238ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 239ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; 240ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman last = data_len % AES_BLOCK_LEN; 241ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 242ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 1; i <= blocks; i++) { 243ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman len = (i == blocks && last) ? last : AES_BLOCK_LEN; 244ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Authentication */ 245ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(b, pos, len); 24694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(key->tfm, b, b); 247ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Encryption, with counter */ 248ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[14] = (i >> 8) & 0xff; 249ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[15] = i & 0xff; 25094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(key->tfm, b0, e); 251ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(pos, e, len); 252ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos += len; 253ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 254ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 255ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 0; i < CCMP_MIC_LEN; i++) 256ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman mic[i] = b[i] ^ s0[i]; 257ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 258ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 259ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 260ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 261ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 26294a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) 263ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 26494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *key = priv; 265ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 keyidx, *pos; 26694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_hdr_4addr *hdr; 267a44325f98563c39bc63311db7471b848153e49feLarry Finger struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 268a44325f98563c39bc63311db7471b848153e49feLarry Finger MAX_DEV_ADDR_SIZE); 269ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 pn[6]; 270ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 271ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { 272ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman key->dot11RSNAStatsCCMPFormatErrors++; 273ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 274ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 275ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 27694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger hdr = (struct rtllib_hdr_4addr *) skb->data; 277ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos = skb->data + hdr_len; 278ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman keyidx = pos[3]; 279ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (!(keyidx & (1 << 5))) { 280ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (net_ratelimit()) { 2815635b82a553620c511dc6bc8cb0990c0a791e21eMahati Chamarthy pr_debug("CCMP: received packet without ExtIV" 282ac50ddaaeeca4f649c53ce31175aa68d26420138Larry Finger " flag from %pM\n", hdr->addr2); 283ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 284ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman key->dot11RSNAStatsCCMPFormatErrors++; 285ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -2; 286ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 287ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman keyidx >>= 6; 288ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (key->key_idx != keyidx) { 2895635b82a553620c511dc6bc8cb0990c0a791e21eMahati Chamarthy pr_debug("CCMP: RX tkey->key_idx=%d frame " 290ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv); 291ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -6; 292ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 293ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (!key->key_set) { 294ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (net_ratelimit()) { 2955635b82a553620c511dc6bc8cb0990c0a791e21eMahati Chamarthy pr_debug("CCMP: received packet from %pM" 296ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman " with keyid=%d that does not have a configured" 297ac50ddaaeeca4f649c53ce31175aa68d26420138Larry Finger " key\n", hdr->addr2, keyidx); 298ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 299ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -3; 300ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 301ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 302ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[0] = pos[7]; 303ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[1] = pos[6]; 304ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[2] = pos[5]; 305ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[3] = pos[4]; 306ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[4] = pos[1]; 307ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pn[5] = pos[0]; 308ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos += 8; 309ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { 310ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman key->dot11RSNAStatsCCMPReplays++; 311ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -4; 312ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 31394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (!tcb_desc->bHwSec) { 314a44325f98563c39bc63311db7471b848153e49feLarry Finger size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - 315a44325f98563c39bc63311db7471b848153e49feLarry Finger CCMP_MIC_LEN; 316ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; 317ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *b0 = key->rx_b0; 318ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *b = key->rx_b; 319ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *a = key->rx_a; 320ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int i, blocks, last, len; 321ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 322ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 323ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); 324ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(mic, b, CCMP_MIC_LEN); 325ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 326ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; 327ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman last = data_len % AES_BLOCK_LEN; 328ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 329ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 1; i <= blocks; i++) { 330ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman len = (i == blocks && last) ? last : AES_BLOCK_LEN; 331ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Decrypt, with counter */ 332ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[14] = (i >> 8) & 0xff; 333ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman b0[15] = i & 0xff; 33494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(key->tfm, b0, b); 335ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(pos, b, len); 336ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Authentication */ 337ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman xor_block(a, pos, len); 33894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_ccmp_aes_encrypt(key->tfm, a, a); 339ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pos += len; 340ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 341ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 342ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { 343ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (net_ratelimit()) { 3445635b82a553620c511dc6bc8cb0990c0a791e21eMahati Chamarthy pr_debug("CCMP: decrypt failed: STA=" 345ac50ddaaeeca4f649c53ce31175aa68d26420138Larry Finger " %pM\n", hdr->addr2); 346ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 347ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman key->dot11RSNAStatsCCMPDecryptErrors++; 348ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -5; 349ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 350ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 351ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(key->rx_pn, pn, CCMP_PN_LEN); 352ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 353ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Remove hdr and MIC */ 354ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); 355ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_pull(skb, CCMP_HDR_LEN); 356ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_trim(skb, skb->len - CCMP_MIC_LEN); 357ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 358ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return keyidx; 359ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 360ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 361ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 36294a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) 363ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 36494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *data = priv; 365ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int keyidx; 366ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct crypto_tfm *tfm = data->tfm; 367ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 368ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman keyidx = data->key_idx; 369ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memset(data, 0, sizeof(*data)); 370ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->key_idx = keyidx; 371ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->tfm = tfm; 372ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (len == CCMP_TK_LEN) { 373ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(data->key, key, CCMP_TK_LEN); 374ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->key_set = 1; 375ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (seq) { 376ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[0] = seq[5]; 377ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[1] = seq[4]; 378ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[2] = seq[3]; 379ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[3] = seq[2]; 380ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[4] = seq[1]; 381ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->rx_pn[5] = seq[0]; 382ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 383a44325f98563c39bc63311db7471b848153e49feLarry Finger crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); 384ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else if (len == 0) 385ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman data->key_set = 0; 386ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 387ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 388ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 389ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 390ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 391ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 392ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 39394a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic int rtllib_ccmp_get_key(void *key, int len, u8 *seq, void *priv) 394ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 39594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *data = priv; 396ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 397ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (len < CCMP_TK_LEN) 398ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 399ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 400ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (!data->key_set) 401ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 402ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(key, data->key, CCMP_TK_LEN); 403ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 404ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (seq) { 405ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[0] = data->tx_pn[5]; 406ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[1] = data->tx_pn[4]; 407ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[2] = data->tx_pn[3]; 408ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[3] = data->tx_pn[2]; 409ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[4] = data->tx_pn[1]; 410ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman seq[5] = data->tx_pn[0]; 411ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 412ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 413ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return CCMP_TK_LEN; 414ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 415ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 416ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 4176bbefe86796c07fb8a6d28114f1e3f770586ba05David Howellsstatic void rtllib_ccmp_print_stats(struct seq_file *m, void *priv) 418ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 41994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_ccmp_data *ccmp = priv; 4203a6b70c3f3558a2e47d2ca82752f0aed0f3c33c6Matthew Casey 4216bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells seq_printf(m, 4226bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells "key[%d] alg=CCMP key_set=%d " 4236bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells "tx_pn=%pM rx_pn=%pM " 4246bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells "format_errors=%d replays=%d decrypt_errors=%d\n", 4256bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells ccmp->key_idx, ccmp->key_set, 4266bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells ccmp->tx_pn, ccmp->rx_pn, 4276bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells ccmp->dot11RSNAStatsCCMPFormatErrors, 4286bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells ccmp->dot11RSNAStatsCCMPReplays, 4296bbefe86796c07fb8a6d28114f1e3f770586ba05David Howells ccmp->dot11RSNAStatsCCMPDecryptErrors); 430ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 431ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 43232c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennanstatic struct lib80211_crypto_ops rtllib_crypt_ccmp = { 4333b148be0df8e45a0259d7e84001cf02e897af614Sean MacLennan .name = "R-CCMP", 43494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .init = rtllib_ccmp_init, 43594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .deinit = rtllib_ccmp_deinit, 43694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .encrypt_mpdu = rtllib_ccmp_encrypt, 43794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .decrypt_mpdu = rtllib_ccmp_decrypt, 438ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .encrypt_msdu = NULL, 439ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .decrypt_msdu = NULL, 44094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .set_key = rtllib_ccmp_set_key, 44194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .get_key = rtllib_ccmp_get_key, 44294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger .print_stats = rtllib_ccmp_print_stats, 44332c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan .extra_mpdu_prefix_len = CCMP_HDR_LEN, 44432c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan .extra_mpdu_postfix_len = CCMP_MIC_LEN, 445ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .owner = THIS_MODULE, 446ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman}; 447ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 448ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 449327ca222aeed7cda0ba1e378088e1aa4f239ca0fRashika Kheriastatic int __init rtllib_crypto_ccmp_init(void) 450ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 4513b148be0df8e45a0259d7e84001cf02e897af614Sean MacLennan return lib80211_register_crypto_ops(&rtllib_crypt_ccmp); 452ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 453ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 454ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 455327ca222aeed7cda0ba1e378088e1aa4f239ca0fRashika Kheriastatic void __exit rtllib_crypto_ccmp_exit(void) 456ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 4573b148be0df8e45a0259d7e84001cf02e897af614Sean MacLennan lib80211_unregister_crypto_ops(&rtllib_crypt_ccmp); 458ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 459d37e0208df563af9c6fada84e620aabed581b3a8Sean MacLennan 460d37e0208df563af9c6fada84e620aabed581b3a8Sean MacLennanmodule_init(rtllib_crypto_ccmp_init); 461d37e0208df563af9c6fada84e620aabed581b3a8Sean MacLennanmodule_exit(rtllib_crypto_ccmp_exit); 462d37e0208df563af9c6fada84e620aabed581b3a8Sean MacLennan 463d37e0208df563af9c6fada84e620aabed581b3a8Sean MacLennanMODULE_LICENSE("GPL"); 464