1/*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Copyright (c) 2002-2004 Atheros Communications, Inc.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * $FreeBSD: releng/12.0/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c 326695 2017-12-08 15:57:29Z pfg $
20 */
21#include "opt_ah.h"
22
23#include "ah.h"
24#include "ah_internal.h"
25
26#include "ar5210/ar5210.h"
27#include "ar5210/ar5210reg.h"
28
29#define	AR_KEYTABLE_SIZE	64
30#define	KEY_XOR			0xaa
31
32/*
33 * Return the size of the hardware key cache.
34 */
35u_int
36ar5210GetKeyCacheSize(struct ath_hal *ah)
37{
38	return AR_KEYTABLE_SIZE;
39}
40
41/*
42 * Return the size of the hardware key cache.
43 */
44HAL_BOOL
45ar5210IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
46{
47	if (entry < AR_KEYTABLE_SIZE) {
48		uint32_t val = OS_REG_READ(ah, AR_KEYTABLE_MAC1(entry));
49		if (val & AR_KEYTABLE_VALID)
50			return AH_TRUE;
51	}
52	return AH_FALSE;
53}
54
55/*
56 * Clear the specified key cache entry.
57 */
58HAL_BOOL
59ar5210ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
60{
61	if (entry < AR_KEYTABLE_SIZE) {
62		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
63		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
64		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
65		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
66		OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
67		OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), 0);
68		OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
69		OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
70		return AH_TRUE;
71	}
72	return AH_FALSE;
73}
74
75/*
76 * Sets the mac part of the specified key cache entry and mark it valid.
77 */
78HAL_BOOL
79ar5210SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
80{
81	uint32_t macHi, macLo;
82
83	if (entry < AR_KEYTABLE_SIZE) {
84		/*
85		 * Set MAC address -- shifted right by 1.  MacLo is
86		 * the 4 MSBs, and MacHi is the 2 LSBs.
87		 */
88		if (mac != AH_NULL) {
89			macHi = (mac[5] << 8) | mac[4];
90			macLo = (mac[3] << 24)| (mac[2] << 16)
91			      | (mac[1] << 8) | mac[0];
92			macLo >>= 1;
93			macLo |= (macHi & 1) << 31;	/* carry */
94			macHi >>= 1;
95		} else {
96			macLo = macHi = 0;
97		}
98
99		OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
100		OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry),
101			macHi | AR_KEYTABLE_VALID);
102		return AH_TRUE;
103	}
104	return AH_FALSE;
105}
106
107/*
108 * Sets the contents of the specified key cache entry.
109 */
110HAL_BOOL
111ar5210SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
112                       const HAL_KEYVAL *k, const uint8_t *mac, int xorKey)
113{
114	uint32_t key0, key1, key2, key3, key4;
115	uint32_t keyType;
116	uint32_t xorMask= xorKey ?
117		(KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
118
119	if (entry >= AR_KEYTABLE_SIZE)
120		return AH_FALSE;
121	if (k->kv_type != HAL_CIPHER_WEP) {
122		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
123		    __func__, k->kv_type);
124		return AH_FALSE;
125	}
126
127	/* NB: only WEP supported */
128	if (k->kv_len < 40 / NBBY)
129		return AH_FALSE;
130	if (k->kv_len <= 40 / NBBY)
131		keyType = AR_KEYTABLE_TYPE_40;
132	else if (k->kv_len <= 104 / NBBY)
133		keyType = AR_KEYTABLE_TYPE_104;
134	else
135		keyType = AR_KEYTABLE_TYPE_128;
136
137	key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
138	key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
139	key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
140	key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
141	key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
142	if (k->kv_len <= 104 / NBBY)
143		key4 &= 0xff;
144
145	/*
146	 * Note: WEP key cache hardware requires that each double-word
147	 * pair be written in even/odd order (since the destination is
148	 * a 64-bit register).  Don't reorder these writes w/o
149	 * understanding this!
150	 */
151	OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
152	OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
153	OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
154	OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
155	OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
156	OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
157	return ar5210SetKeyCacheEntryMac(ah, entry, mac);
158}
159