blob: fd186ae6bbf7d61c2d30b7101666f99b787074e7 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*============================================================================
29 FILE: cds_utils.c
30
31 OVERVIEW: This source file contains definitions for CDS crypto APIs
32 The four APIs mentioned in this file are used for
33 initializing, and de-initializing a crypto context, and
34 obtaining truly random data (for keys), as well as
35 SHA1 HMAC, and AES encrypt and decrypt routines.
36
37 The routines include:
38 cds_crypto_init() - Initializes Crypto module
39 cds_crypto_deinit() - De-initializes Crypto module
40 cds_rand_get_bytes() - Generates random byte
41 cds_sha1_hmac_str() - Generate the HMAC-SHA1 of a string given a key
42 cds_encrypt_aes() - Generate AES Encrypted byte stream
43 cds_decrypt_aes() - Decrypts an AES Encrypted byte stream
44
45 DEPENDENCIES:
46 ============================================================================*/
47
48/*----------------------------------------------------------------------------
49 * Include Files
50 * -------------------------------------------------------------------------*/
51
52#include "cdf_trace.h"
53#include "cds_utils.h"
54#include "cdf_memory.h"
55#include "cds_crypto.h"
56
57#include <linux/err.h>
58#include <linux/random.h>
59#include <linux/crypto.h>
60#include <linux/scatterlist.h>
61#include <linux/completion.h>
62#include <linux/ieee80211.h>
63#include <crypto/hash.h>
64#include <crypto/aes.h>
65
66#include "cds_ieee80211_common.h"
67/*----------------------------------------------------------------------------
68 * Preprocessor Definitions and Constants
69 * -------------------------------------------------------------------------*/
70#define AAD_LEN 20
71#define IV_SIZE_AES_128 16
72#define CMAC_IPN_LEN 6
73#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
74
75/*----------------------------------------------------------------------------
76 * Type Declarations
77 * -------------------------------------------------------------------------*/
78/*----------------------------------------------------------------------------
79 * Global Data Definitions
80 * -------------------------------------------------------------------------*/
81/*----------------------------------------------------------------------------
82 * Static Variable Definitions
83 * -------------------------------------------------------------------------*/
84
85/*----------------------------------------------------------------------------
86 Function Definitions and Documentation
87 * -------------------------------------------------------------------------*/
88#ifdef CONFIG_ICNSS
89#ifdef WLAN_FEATURE_11W
90static inline void xor_128(const u8 *a, const u8 *b, u8 *out)
91{
92 u8 i;
93
94 for (i = 0; i < AES_BLOCK_SIZE; i++)
95 out[i] = a[i] ^ b[i];
96}
97
98static inline void leftshift_onebit(const u8 *input, u8 *output)
99{
100 int i, overflow = 0;
101
102 for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
103 output[i] = input[i] << 1;
104 output[i] |= overflow;
105 overflow = (input[i] & 0x80) ? 1 : 0;
106 }
107 return;
108}
109
110static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
111{
112 u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
113 u8 const_rb[AES_BLOCK_SIZE] = {
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
116 };
117 u8 const_zero[AES_BLOCK_SIZE] = {
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
120 };
121
122 crypto_cipher_encrypt_one(tfm, l, const_zero);
123
124 if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
125 leftshift_onebit(l, k1);
126 } else { /* Else k1 = ( l << 1 ) (+) Rb */
127 leftshift_onebit(l, tmp);
128 xor_128(tmp, const_rb, k1);
129 }
130
131 if ((k1[0] & 0x80) == 0) {
132 leftshift_onebit(k1, k2);
133 } else {
134 leftshift_onebit(k1, tmp);
135 xor_128(tmp, const_rb, k2);
136 }
137}
138
139static inline void padding(u8 *lastb, u8 *pad, u16 length)
140{
141 u8 j;
142
143 /* original last block */
144 for (j = 0; j < AES_BLOCK_SIZE; j++) {
145 if (j < length)
146 pad[j] = lastb[j];
147 else if (j == length)
148 pad[j] = 0x80;
149 else
150 pad[j] = 0x00;
151 }
152}
153
154static void cds_cmac_calc_mic(struct crypto_cipher *tfm,
155 u8 *m, u16 length, u8 *mac)
156{
157 u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
158 u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
159 u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
160 int cmpBlk;
161 int i, nBlocks = (length + 15) / AES_BLOCK_SIZE;
162
163 generate_subkey(tfm, k1, k2);
164
165 if (nBlocks == 0) {
166 nBlocks = 1;
167 cmpBlk = 0;
168 } else {
169 cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
170 }
171
172 if (cmpBlk) { /* Last block is complete block */
173 xor_128(&m[AES_BLOCK_SIZE * (nBlocks - 1)], k1, m_last);
174 } else { /* Last block is not complete block */
175 padding(&m[AES_BLOCK_SIZE * (nBlocks - 1)], padded,
176 length % AES_BLOCK_SIZE);
177 xor_128(padded, k2, m_last);
178 }
179
180 for (i = 0; i < AES_BLOCK_SIZE; i++)
181 x[i] = 0;
182
183 for (i = 0; i < (nBlocks - 1); i++) {
184 xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
185 crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
186 }
187
188 xor_128(x, m_last, y);
189 crypto_cipher_encrypt_one(tfm, x, y);
190
191 memcpy(mac, x, CMAC_TLEN);
192}
193#endif
194#endif
195
196/*--------------------------------------------------------------------------
197
198 \brief cds_crypto_init() - Initializes Crypto module
199
200 The cds_crypto_init() function initializes Crypto module.
201
202 \param phCryptProv - pointer to the Crypt handle
203
204 \return CDF_STATUS_SUCCESS - Successfully generated random memory.
205
206 CDF_STATUS_E_FAULT - pbBuf is an invalid pointer.
207
208 CDF_STATUS_E_FAILURE - default return value if it fails due to
209 unknown reasons
210
211 ***CDF_STATUS_E_RESOURCES - System resources (other than memory)
212 are unavailable
213 \sa
214
215 ( *** return value not considered yet )
216 --------------------------------------------------------------------------*/
217CDF_STATUS cds_crypto_init(uint32_t *phCryptProv)
218{
219 CDF_STATUS uResult = CDF_STATUS_E_FAILURE;
220
221 /* This implementation doesn't require a crypto context */
222 *phCryptProv = 0;
223 uResult = CDF_STATUS_SUCCESS;
224 return (uResult);
225}
226
227CDF_STATUS cds_crypto_deinit(uint32_t hCryptProv)
228{
229 CDF_STATUS uResult = CDF_STATUS_E_FAILURE;
230
231 /* CryptReleaseContext succeeded */
232 uResult = CDF_STATUS_SUCCESS;
233
234 return (uResult);
235}
236
237/*--------------------------------------------------------------------------
238
239 \brief cds_rand_get_bytes() - Generates random byte
240
241 The cds_rand_get_bytes() function generate random bytes.
242
243 Buffer should be allocated before calling cds_rand_get_bytes().
244
245 Attempting to initialize an already initialized lock results in
246 a failure.
247
248 \param lock - pointer to the opaque lock object to initialize
249
250 \return CDF_STATUS_SUCCESS - Successfully generated random memory.
251
252 CDF_STATUS_E_FAULT - pbBuf is an invalid pointer.
253
254 CDF_STATUS_E_FAILURE - default return value if it fails due to
255 unknown reasons
256
257 ***CDF_STATUS_E_RESOURCES - System resources (other than memory)
258 are unavailable
259 \sa
260
261 ( *** return value not considered yet )
262 --------------------------------------------------------------------------*/
263CDF_STATUS
264cds_rand_get_bytes(uint32_t cryptHandle, uint8_t *pbBuf, uint32_t numBytes)
265{
266 CDF_STATUS uResult = CDF_STATUS_E_FAILURE;
267
268 /* check for invalid pointer */
269 if (NULL == pbBuf) {
270 uResult = CDF_STATUS_E_FAULT;
271 return (uResult);
272 }
273
274 get_random_bytes(pbBuf, numBytes);
275 /* "Random sequence generated." */
276 uResult = CDF_STATUS_SUCCESS;
277 return (uResult);
278}
279
280#ifdef WLAN_FEATURE_11W
281uint8_t cds_get_mmie_size()
282{
283 return sizeof(struct ieee80211_mmie);
284}
285
286/*--------------------------------------------------------------------------
287
288 \brief cds_increase_seq() - Increase the IPN aka Sequence number by one unit
289
290 The cds_increase_seq() function increases the IPN by one unit.
291
292 \param ipn - pointer to the IPN aka Sequence number [6 bytes]
293
294 --------------------------------------------------------------------------*/
295static void cds_increase_seq(uint8_t *ipn)
296{
297 uint64_t value = 0;
298 if (ipn) {
299 value = (0xffffffffffff) & (*((uint64_t *) ipn));
300 value = value + 1;
301 cdf_mem_copy(ipn, &value, IEEE80211_MMIE_IPNLEN);
302 }
303}
304
305/*--------------------------------------------------------------------------
306
307 \brief cds_attach_mmie() - attches the complete MMIE at the end of frame
308
309 The cds_attach_mmie() calculates the entire MMIE and attaches at the end
310 of Broadcast/Multicast robust management frames.
311
312 \param igtk - pointer group key which will be used to calculate
313 the 8 byte MIC.
314 \param ipn - pointer ipn, it is also known as sequence number
315 \param key_id - key identication number
316 \param frm - pointer to the start of the frame.
317 \param efrm - pointer to the end of the frame.
318 \param frmLen - size of the entire frame.
319
320 \return - this function will return true on success and false on
321 failure.
322
323 --------------------------------------------------------------------------*/
324
325bool
326cds_attach_mmie(uint8_t *igtk, uint8_t *ipn, uint16_t key_id,
327 uint8_t *frm, uint8_t *efrm, uint16_t frmLen)
328{
329 struct ieee80211_mmie *mmie;
330 struct ieee80211_frame *wh;
331 uint8_t aad[AAD_LEN], mic[CMAC_TLEN], *input = NULL;
332 uint8_t previous_ipn[IEEE80211_MMIE_IPNLEN] = { 0 };
333 uint16_t nBytes = 0;
334 int ret = 0;
335 struct crypto_cipher *tfm;
336
337 /* This is how received frame look like
338 *
339 * <------------frmLen---------------------------->
340 *
341 * +---------------+----------------------+-------+
342 * | 802.11 HEADER | Management framebody | MMIE |
343 * +---------------+----------------------+-------+
344 * ^
345 * |
346 * efrm
347 * This is how MMIE from above frame look like
348 *
349 *
350 * <------------ 18 Bytes----------------------------->
351 * +--------+---------+---------+-----------+---------+
352 * |Element | Length | Key id | IPN | MIC |
353 * | id | | | | |
354 * +--------+---------+---------+-----------+---------+
355 * Octet 1 1 2 6 8
356 *
357 */
358
359 /* Check if frame is invalid length */
360 if (((efrm - frm) != frmLen) || (frmLen < sizeof(*wh))) {
361 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
362 "%s: Invalid frame length", __func__);
363 return false;
364 }
365 mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));
366
367 /* Copy Element id */
368 mmie->element_id = IEEE80211_ELEMID_MMIE;
369
370 /* Copy Length */
371 mmie->length = sizeof(*mmie) - 2;
372
373 /* Copy Key id */
374 mmie->key_id = key_id;
375
376 /*
377 * In case of error, revert back to original IPN
378 * to do that copy the original IPN into previous_ipn
379 */
380 cdf_mem_copy(&previous_ipn[0], ipn, IEEE80211_MMIE_IPNLEN);
381 cds_increase_seq(ipn);
382 cdf_mem_copy(mmie->sequence_number, ipn, IEEE80211_MMIE_IPNLEN);
383
384 /*
385 * Calculate MIC and then copy
386 */
387 tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
388 if (IS_ERR(tfm)) {
389 ret = PTR_ERR(tfm);
390 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
391 "%s: crypto_alloc_cipher failed (%d)", __func__, ret);
392 goto err_tfm;
393 }
394
395 ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
396 if (ret) {
397 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
398 "%s: crypto_cipher_setkey failed (%d)", __func__,
399 ret);
400 goto err_tfm;
401 }
402
403 /* Construct AAD */
404 wh = (struct ieee80211_frame *)frm;
405
406 /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */
407
408 /* FC type/subtype */
409 aad[0] = wh->i_fc[0];
410 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
411 aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
412 IEEE80211_FC1_MORE_DATA);
413 /* A1 || A2 || A3 */
414 cdf_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN);
415
416 /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
417 nBytes = AAD_LEN + (frmLen - sizeof(struct ieee80211_frame));
418 input = (uint8_t *) cdf_mem_malloc(nBytes);
419 if (NULL == input) {
420 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
421 "%s: Memory allocation failed", __func__);
422 ret = CDF_STATUS_E_NOMEM;
423 goto err_tfm;
424 }
425
426 /*
427 * Copy the AAD, Management frame body, and
428 * MMIE with 8 bit MIC zeroed out
429 */
430 cdf_mem_zero(input, nBytes);
431 cdf_mem_copy(input, aad, AAD_LEN);
432 /* Copy Management Frame Body and MMIE without MIC */
433 cdf_mem_copy(input + AAD_LEN,
434 (uint8_t *) (efrm -
435 (frmLen - sizeof(struct ieee80211_frame))),
436 nBytes - AAD_LEN - CMAC_TLEN);
437
438 cds_cmac_calc_mic(tfm, input, nBytes, mic);
439 cdf_mem_free(input);
440
441 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_INFO_HIGH,
442 "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
443 mic[0], mic[1], mic[2], mic[3],
444 mic[4], mic[5], mic[6], mic[7]);
445 cdf_mem_copy(mmie->mic, mic, IEEE80211_MMIE_MICLEN);
446
447err_tfm:
448 if (ret) {
449 cdf_mem_copy(ipn, previous_ipn, IEEE80211_MMIE_IPNLEN);
450 }
451
452 if (tfm)
453 cds_crypto_free_cipher(tfm);
454 return !ret ? true : false;
455}
456
457bool
458cds_is_mmie_valid(uint8_t *igtk, uint8_t *ipn, uint8_t *frm, uint8_t *efrm)
459{
460 struct ieee80211_mmie *mmie;
461 struct ieee80211_frame *wh;
462 uint8_t *rx_ipn, aad[AAD_LEN], mic[CMAC_TLEN], *input;
463 uint16_t nBytes = 0;
464 int ret = 0;
465 struct crypto_cipher *tfm;
466
467 /* Check if frame is invalid length */
468 if ((efrm < frm) || ((efrm - frm) < sizeof(*wh))) {
469 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
470 "Invalid frame length");
471 return false;
472 }
473
474 mmie = (struct ieee80211_mmie *)(efrm - sizeof(*mmie));
475
476 /* Check Element ID */
477 if ((mmie->element_id != IEEE80211_ELEMID_MMIE) ||
478 (mmie->length != (sizeof(*mmie) - 2))) {
479 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
480 "IE is not Mgmt MIC IE or Invalid length");
481 /* IE is not Mgmt MIC IE or invalid length */
482 return false;
483 }
484
485 /* Validate IPN */
486 rx_ipn = mmie->sequence_number;
487 if (OS_MEMCMP(rx_ipn, ipn, CMAC_IPN_LEN) <= 0) {
488 /* Replay error */
489 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
490 "Replay error mmie ipn %02X %02X %02X %02X %02X %02X"
491 " drvr ipn %02X %02X %02X %02X %02X %02X",
492 rx_ipn[0], rx_ipn[1], rx_ipn[2], rx_ipn[3], rx_ipn[4],
493 rx_ipn[5], ipn[0], ipn[1], ipn[2], ipn[3], ipn[4],
494 ipn[5]);
495 return false;
496 }
497 tfm = cds_crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
498 if (IS_ERR(tfm)) {
499 ret = PTR_ERR(tfm);
500 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
501 "crypto_alloc_cipher failed (%d)", ret);
502 goto err_tfm;
503 }
504
505 ret = crypto_cipher_setkey(tfm, igtk, AES_KEYSIZE_128);
506 if (ret) {
507 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
508 "crypto_cipher_setkey failed (%d)", ret);
509 goto err_tfm;
510 }
511
512 /* Construct AAD */
513 wh = (struct ieee80211_frame *)frm;
514
515 /* Generate BIP AAD: FC(masked) || A1 || A2 || A3 */
516
517 /* FC type/subtype */
518 aad[0] = wh->i_fc[0];
519 /* Mask FC Retry, PwrMgt, MoreData flags to zero */
520 aad[1] = wh->i_fc[1] & ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
521 IEEE80211_FC1_MORE_DATA);
522 /* A1 || A2 || A3 */
523 cdf_mem_copy(aad + 2, wh->i_addr_all, 3 * IEEE80211_ADDR_LEN);
524
525 /* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) */
526 nBytes = AAD_LEN + (efrm - (uint8_t *) (wh + 1));
527 input = (uint8_t *) cdf_mem_malloc(nBytes);
528 if (NULL == input) {
529 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
530 "Memory allocation failed");
531 ret = CDF_STATUS_E_NOMEM;
532 goto err_tfm;
533 }
534
535 /* Copy the AAD, MMIE with 8 bit MIC zeroed out */
536 cdf_mem_zero(input, nBytes);
537 cdf_mem_copy(input, aad, AAD_LEN);
538 cdf_mem_copy(input + AAD_LEN, (uint8_t *) (wh + 1),
539 nBytes - AAD_LEN - CMAC_TLEN);
540
541 cds_cmac_calc_mic(tfm, input, nBytes, mic);
542 cdf_mem_free(input);
543
544 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
545 "CMAC(T)= %02X %02X %02X %02X %02X %02X %02X %02X",
546 mic[0], mic[1], mic[2], mic[3],
547 mic[4], mic[5], mic[6], mic[7]);
548
549 if (OS_MEMCMP(mic, mmie->mic, CMAC_TLEN) != 0) {
550 /* MMIE MIC mismatch */
551 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
552 "BC/MC MGMT frame MMIE MIC check Failed"
553 " rmic %02X %02X %02X %02X %02X %02X %02X %02X"
554 " cmic %02X %02X %02X %02X %02X %02X %02X %02X",
555 mmie->mic[0], mmie->mic[1], mmie->mic[2],
556 mmie->mic[3], mmie->mic[4], mmie->mic[5],
557 mmie->mic[6], mmie->mic[7], mic[0], mic[1], mic[2],
558 mic[3], mic[4], mic[5], mic[6], mic[7]);
559 return false;
560 }
561
562 /* Update IPN */
563 cdf_mem_copy(ipn, rx_ipn, CMAC_IPN_LEN);
564
565err_tfm:
566 if (tfm)
567 cds_crypto_free_cipher(tfm);
568
569 return !ret ? true : false;
570}
571
572#endif /* WLAN_FEATURE_11W */
573/**
574 * cds_sha1_hmac_str
575 *
576 * FUNCTION:
577 * Generate the HMAC-SHA1 of a string given a key.
578 *
579 * LOGIC:
580 * Standard HMAC processing from RFC 2104. The code is provided in the
581 * appendix of the RFC.
582 *
583 * ASSUMPTIONS:
584 * The RFC is correct.
585 *
586 * @param text text to be hashed
587 * @param textLen length of text
588 * @param key key to use for HMAC
589 * @param keyLen length of key
590 * @param digest holds resultant SHA1 HMAC (20B)
591 *
592 * @return CDF_STATUS_SUCCSS if the operation succeeds
593 *
594 */
595
596struct hmac_sha1_result {
597 struct completion completion;
598 int err;
599};
600
601static void hmac_sha1_complete(struct crypto_async_request *req, int err)
602{
603 struct hmac_sha1_result *r = req->data;
604 if (err == -EINPROGRESS)
605 return;
606 r->err = err;
607 complete(&r->completion);
608}
609
610int
611hmac_sha1(uint8_t *key, uint8_t ksize, char *plaintext, uint8_t psize,
612 uint8_t *output, uint8_t outlen)
613{
614 int ret = 0;
615 struct crypto_ahash *tfm;
616 struct scatterlist sg;
617 struct ahash_request *req;
618 struct hmac_sha1_result tresult;
619 void *hash_buff = NULL;
620
621 unsigned char hash_result[64];
622 int i;
623
624 memset(output, 0, outlen);
625
626 init_completion(&tresult.completion);
627
628 tfm = cds_crypto_alloc_ahash("hmac(sha1)", CRYPTO_ALG_TYPE_AHASH,
629 CRYPTO_ALG_TYPE_AHASH_MASK);
630 if (IS_ERR(tfm)) {
631 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
632 "crypto_alloc_ahash failed");
633 ret = PTR_ERR(tfm);
634 goto err_tfm;
635 }
636
637 req = ahash_request_alloc(tfm, GFP_KERNEL);
638 if (!req) {
639 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
640 "failed to allocate request for hmac(sha1)");
641 ret = -ENOMEM;
642 goto err_req;
643 }
644
645 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
646 hmac_sha1_complete, &tresult);
647
648 hash_buff = kzalloc(psize, GFP_KERNEL);
649 if (!hash_buff) {
650 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
651 "failed to kzalloc hash_buff");
652 ret = -ENOMEM;
653 goto err_hash_buf;
654 }
655
656 memset(hash_result, 0, 64);
657 memcpy(hash_buff, plaintext, psize);
658 sg_init_one(&sg, hash_buff, psize);
659
660 if (ksize) {
661 crypto_ahash_clear_flags(tfm, ~0);
662 ret = cds_crypto_ahash_setkey(tfm, key, ksize);
663 if (ret) {
664 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
665 "crypto_ahash_setkey failed");
666 goto err_setkey;
667 }
668 }
669
670 ahash_request_set_crypt(req, &sg, hash_result, psize);
671 ret = cds_crypto_ahash_digest(req);
672 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "ret 0x%x", ret);
673
674 switch (ret) {
675 case 0:
676 for (i = 0; i < outlen; i++)
677 output[i] = hash_result[i];
678 break;
679 case -EINPROGRESS:
680 case -EBUSY:
681 ret = wait_for_completion_interruptible(&tresult.completion);
682 if (!ret && !tresult.err) {
683 INIT_COMPLETION(tresult.completion);
684 break;
685 } else {
686 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
687 "wait_for_completion_interruptible failed");
688 if (!ret)
689 ret = tresult.err;
690 goto out;
691 }
692 default:
693 goto out;
694 }
695
696out:
697err_setkey:
698 kfree(hash_buff);
699err_hash_buf:
700 ahash_request_free(req);
701err_req:
702 cds_crypto_free_ahash(tfm);
703err_tfm:
704 return ret;
705}
706
707CDF_STATUS cds_sha1_hmac_str(uint32_t cryptHandle, /* Handle */
708 uint8_t *pText, /* pointer to data stream */
709 uint32_t textLen, /* length of data stream */
710 uint8_t *pKey, /* pointer to authentication key */
711 uint32_t keyLen, /* length of authentication key */
712 uint8_t digest[CDS_DIGEST_SHA1_SIZE])
713{ /* caller digest to be filled in */
714 int ret = 0;
715
716 ret = hmac_sha1(pKey, /* uint8_t *key, */
717 (uint8_t) keyLen, /* uint8_t ksize, */
718 (char *)pText, /* char *plaintext, */
719 (uint8_t) textLen, /* uint8_t psize, */
720 digest, /* uint8_t *output, */
721 CDS_DIGEST_SHA1_SIZE /* uint8_t outlen */
722 );
723
724 if (ret != 0) {
725 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
726 "hmac_sha1() call failed");
727 return CDF_STATUS_E_FAULT;
728 }
729
730 return CDF_STATUS_SUCCESS;
731}
732
733/**
734 * cds_md5_hmac_str
735 *
736 * FUNCTION:
737 * Generate the HMAC-MD5 of a string given a key.
738 *
739 * LOGIC:
740 * Standard HMAC processing from RFC 2104. The code is provided in the
741 * appendix of the RFC.
742 *
743 * ASSUMPTIONS:
744 * The RFC is correct.
745 *
746 * @param text text to be hashed
747 * @param textLen length of text
748 * @param key key to use for HMAC
749 * @param keyLen length of key
750 * @param digest holds resultant MD5 HMAC (20B)
751 *
752 * @return CDF_STATUS_SUCCSS if the operation succeeds
753 *
754 */
755struct hmac_md5_result {
756 struct completion completion;
757 int err;
758};
759
760static void hmac_md5_complete(struct crypto_async_request *req, int err)
761{
762 struct hmac_md5_result *r = req->data;
763 if (err == -EINPROGRESS)
764 return;
765 r->err = err;
766 complete(&r->completion);
767}
768
769int
770hmac_md5(uint8_t *key, uint8_t ksize, char *plaintext, uint8_t psize,
771 uint8_t *output, uint8_t outlen)
772{
773 int ret = 0;
774 struct crypto_ahash *tfm;
775 struct scatterlist sg;
776 struct ahash_request *req;
777 struct hmac_md5_result tresult = {.err = 0 };
778 void *hash_buff = NULL;
779
780 unsigned char hash_result[64];
781 int i;
782
783 memset(output, 0, outlen);
784
785 init_completion(&tresult.completion);
786
787 tfm = cds_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH,
788 CRYPTO_ALG_TYPE_AHASH_MASK);
789 if (IS_ERR(tfm)) {
790 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
791 "crypto_alloc_ahash failed");
792 ret = PTR_ERR(tfm);
793 goto err_tfm;
794 }
795
796 req = ahash_request_alloc(tfm, GFP_KERNEL);
797 if (!req) {
798 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
799 "failed to allocate request for hmac(md5)");
800 ret = -ENOMEM;
801 goto err_req;
802 }
803
804 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
805 hmac_md5_complete, &tresult);
806
807 hash_buff = kzalloc(psize, GFP_KERNEL);
808 if (!hash_buff) {
809 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
810 "failed to kzalloc hash_buff");
811 ret = -ENOMEM;
812 goto err_hash_buf;
813 }
814
815 memset(hash_result, 0, 64);
816 memcpy(hash_buff, plaintext, psize);
817 sg_init_one(&sg, hash_buff, psize);
818
819 if (ksize) {
820 crypto_ahash_clear_flags(tfm, ~0);
821 ret = cds_crypto_ahash_setkey(tfm, key, ksize);
822 if (ret) {
823 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
824 "crypto_ahash_setkey failed");
825 goto err_setkey;
826 }
827 }
828
829 ahash_request_set_crypt(req, &sg, hash_result, psize);
830 ret = cds_crypto_ahash_digest(req);
831
832 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, "ret 0x%x", ret);
833
834 switch (ret) {
835 case 0:
836 for (i = 0; i < outlen; i++)
837 output[i] = hash_result[i];
838 break;
839 case -EINPROGRESS:
840 case -EBUSY:
841 ret = wait_for_completion_interruptible(&tresult.completion);
842 if (!ret && !tresult.err) {
843 INIT_COMPLETION(tresult.completion);
844 break;
845 } else {
846 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
847 "wait_for_completion_interruptible failed");
848 if (!ret)
849 ret = tresult.err;
850 goto out;
851 }
852 default:
853 goto out;
854 }
855
856out:
857err_setkey:
858 kfree(hash_buff);
859err_hash_buf:
860 ahash_request_free(req);
861err_req:
862 cds_crypto_free_ahash(tfm);
863err_tfm:
864 return ret;
865}
866
867CDF_STATUS cds_md5_hmac_str(uint32_t cryptHandle, /* Handle */
868 uint8_t *pText, /* pointer to data stream */
869 uint32_t textLen, /* length of data stream */
870 uint8_t *pKey, /* pointer to authentication key */
871 uint32_t keyLen, /* length of authentication key */
872 uint8_t digest[CDS_DIGEST_MD5_SIZE])
873{ /* caller digest to be filled in */
874 int ret = 0;
875
876 ret = hmac_md5(pKey, /* uint8_t *key, */
877 (uint8_t) keyLen, /* uint8_t ksize, */
878 (char *)pText, /* char *plaintext, */
879 (uint8_t) textLen, /* uint8_t psize, */
880 digest, /* uint8_t *output, */
881 CDS_DIGEST_MD5_SIZE /* uint8_t outlen */
882 );
883
884 if (ret != 0) {
885 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
886 "hmac_md5() call failed");
887 return CDF_STATUS_E_FAULT;
888 }
889
890 return CDF_STATUS_SUCCESS;
891}
892
893struct ecb_aes_result {
894 struct completion completion;
895 int err;
896};
897
898static void ecb_aes_complete(struct crypto_async_request *req, int err)
899{
900 struct ecb_aes_result *r = req->data;
901 if (err == -EINPROGRESS)
902 return;
903 r->err = err;
904 complete(&r->completion);
905}
906
907/*--------------------------------------------------------------------------
908
909 \brief cds_encrypt_aes() - Generate AES Encrypted byte stream
910
911 The cds_encrypt_aes() function generates the encrypted byte stream for given text.
912
913 Buffer should be allocated before calling cds_rand_get_bytes().
914
915 Attempting to initialize an already initialized lock results in
916 a failure.
917
918 \param lock - pointer to the opaque lock object to initialize
919
920 \return CDF_STATUS_SUCCESS - Successfully generated random memory.
921
922 CDF_STATUS_E_FAULT - pbBuf is an invalid pointer.
923
924 CDF_STATUS_E_FAILURE - default return value if it fails due to
925 unknown reasons
926
927 ***CDF_STATUS_E_RESOURCES - System resources (other than memory)
928 are unavailable
929 \sa
930
931 ( *** return value not considered yet )
932 --------------------------------------------------------------------------*/
933
934CDF_STATUS cds_encrypt_aes(uint32_t cryptHandle, /* Handle */
935 uint8_t *pPlainText, /* pointer to data stream */
936 uint8_t *pCiphertext, uint8_t *pKey)
937{ /* pointer to authentication key */
938 struct ecb_aes_result result;
939 struct ablkcipher_request *req;
940 struct crypto_ablkcipher *tfm;
941 int ret = 0;
942 char iv[IV_SIZE_AES_128];
943 struct scatterlist sg_in;
944 struct scatterlist sg_out;
945
946 init_completion(&result.completion);
947
948 tfm = cds_crypto_alloc_ablkcipher("cbc(aes)", 0, 0);
949 if (IS_ERR(tfm)) {
950 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
951 "crypto_alloc_ablkcipher failed");
952 ret = PTR_ERR(tfm);
953 goto err_tfm;
954 }
955
956 req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
957 if (!req) {
958 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
959 "Failed to allocate request for cbc(aes)");
960 ret = -ENOMEM;
961 goto err_req;
962 }
963
964 ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
965 ecb_aes_complete, &result);
966
967 crypto_ablkcipher_clear_flags(tfm, ~0);
968
969 ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128);
970 if (ret) {
971 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
972 "crypto_cipher_setkey failed");
973 goto err_setkey;
974 }
975
976 memset(iv, 0, IV_SIZE_AES_128);
977
978 sg_init_one(&sg_in, pPlainText, AES_BLOCK_SIZE);
979
980 sg_init_one(&sg_out, pCiphertext, AES_BLOCK_SIZE);
981
982 ablkcipher_request_set_crypt(req, &sg_in, &sg_out, AES_BLOCK_SIZE, iv);
983
984 crypto_ablkcipher_encrypt(req);
985
986/* ------------------------------------- */
987err_setkey:
988 cds_ablkcipher_request_free(req);
989err_req:
990 cds_crypto_free_ablkcipher(tfm);
991err_tfm:
992 /* return ret; */
993 if (ret != 0) {
994 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
995 "%s() call failed", __func__);
996 return CDF_STATUS_E_FAULT;
997 }
998
999 return CDF_STATUS_SUCCESS;
1000}
1001
1002/*--------------------------------------------------------------------------
1003
1004 \brief cds_decrypt_aes() - Decrypts an AES Encrypted byte stream
1005
1006 The cds_decrypt_aes() function decrypts the encrypted byte stream.
1007
1008 Buffer should be allocated before calling cds_rand_get_bytes().
1009
1010 Attempting to initialize an already initialized lock results in
1011 a failure.
1012
1013 \param lock - pointer to the opaque lock object to initialize
1014
1015 \return CDF_STATUS_SUCCESS - Successfully generated random memory.
1016
1017 CDF_STATUS_E_FAULT - pbBuf is an invalid pointer.
1018
1019 CDF_STATUS_E_FAILURE - default return value if it fails due to
1020 unknown reasons
1021
1022 ***CDF_STATUS_E_RESOURCES - System resources (other than memory)
1023 are unavailable
1024 \sa
1025
1026 ( *** return value not considered yet )
1027 --------------------------------------------------------------------------*/
1028
1029CDF_STATUS cds_decrypt_aes(uint32_t cryptHandle, /* Handle */
1030 uint8_t *pText, /* pointer to data stream */
1031 uint8_t *pDecrypted, uint8_t *pKey)
1032{ /* pointer to authentication key */
1033/* CDF_STATUS uResult = CDF_STATUS_E_FAILURE; */
1034 struct ecb_aes_result result;
1035 struct ablkcipher_request *req;
1036 struct crypto_ablkcipher *tfm;
1037 int ret = 0;
1038 char iv[IV_SIZE_AES_128];
1039 struct scatterlist sg_in;
1040 struct scatterlist sg_out;
1041
1042 init_completion(&result.completion);
1043
1044 tfm = cds_crypto_alloc_ablkcipher("cbc(aes)", 0, 0);
1045 if (IS_ERR(tfm)) {
1046 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1047 "crypto_alloc_ablkcipher failed");
1048 ret = PTR_ERR(tfm);
1049 goto err_tfm;
1050 }
1051
1052 req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
1053 if (!req) {
1054 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1055 "Failed to allocate request for cbc(aes)");
1056 ret = -ENOMEM;
1057 goto err_req;
1058 }
1059
1060 ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1061 ecb_aes_complete, &result);
1062
1063 crypto_ablkcipher_clear_flags(tfm, ~0);
1064
1065 ret = crypto_ablkcipher_setkey(tfm, pKey, AES_KEYSIZE_128);
1066 if (ret) {
1067 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1068 "crypto_cipher_setkey failed");
1069 goto err_setkey;
1070 }
1071
1072 memset(iv, 0, IV_SIZE_AES_128);
1073
1074 sg_init_one(&sg_in, pText, AES_BLOCK_SIZE);
1075
1076 sg_init_one(&sg_out, pDecrypted, AES_BLOCK_SIZE);
1077
1078 ablkcipher_request_set_crypt(req, &sg_in, &sg_out, AES_BLOCK_SIZE, iv);
1079
1080 crypto_ablkcipher_decrypt(req);
1081
1082/* ------------------------------------- */
1083err_setkey:
1084 cds_ablkcipher_request_free(req);
1085err_req:
1086 cds_crypto_free_ablkcipher(tfm);
1087err_tfm:
1088 /* return ret; */
1089 if (ret != 0) {
1090 CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR,
1091 "%s() call failed", __func__);
1092 return CDF_STATUS_E_FAULT;
1093 }
1094
1095 return CDF_STATUS_SUCCESS;
1096}
1097
1098uint32_t cds_chan_to_freq(uint8_t chan)
1099{
1100 if (chan < CDS_24_GHZ_CHANNEL_14) /* ch 0 - ch 13 */
1101 return CDS_24_GHZ_BASE_FREQ + chan * CDS_CHAN_SPACING_5MHZ;
1102 else if (chan == CDS_24_GHZ_CHANNEL_14) /* ch 14 */
1103 return CDS_CHAN_14_FREQ;
1104 else if (chan < CDS_24_GHZ_CHANNEL_27) /* ch 15 - ch 26 */
1105 return CDS_CHAN_15_FREQ +
1106 (chan - CDS_24_GHZ_CHANNEL_15) * CDS_CHAN_SPACING_20MHZ;
1107 else if (chan == CDS_5_GHZ_CHANNEL_170)
1108 return CDS_CHAN_170_FREQ;
1109 else
1110 return CDS_5_GHZ_BASE_FREQ + chan * CDS_CHAN_SPACING_5MHZ;
1111}
1112
1113uint8_t cds_freq_to_chan(uint32_t freq)
1114{
1115 uint8_t chan;
1116
1117 if (freq > CDS_24_GHZ_BASE_FREQ && freq < CDS_CHAN_14_FREQ)
1118 chan = ((freq - CDS_24_GHZ_BASE_FREQ) / CDS_CHAN_SPACING_5MHZ);
1119 else if (freq == CDS_CHAN_14_FREQ)
1120 chan = CDS_24_GHZ_CHANNEL_14;
1121 else if ((freq > CDS_24_GHZ_BASE_FREQ) && (freq < CDS_5_GHZ_BASE_FREQ))
1122 chan = (((freq - CDS_CHAN_15_FREQ) / CDS_CHAN_SPACING_20MHZ) +
1123 CDS_24_GHZ_CHANNEL_15);
1124 else
1125 chan = (freq - CDS_5_GHZ_BASE_FREQ) / CDS_CHAN_SPACING_5MHZ;
1126 return chan;
1127}
1128
1129uint8_t cds_chan_to_band(uint32_t chan)
1130{
1131 if (chan <= CDS_24_GHZ_CHANNEL_14)
1132 return CDS_BAND_2GHZ;
1133
1134 return CDS_BAND_5GHZ;
1135}