Linux Audio

Check our new training course

Loading...
v4.10.11
 
  1/*
  2 * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
  3 * Copyright 2008, Jouni Malinen <j@w1.fi>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation.
  8 */
  9
 10#include <linux/kernel.h>
 11#include <linux/types.h>
 12#include <linux/crypto.h>
 13#include <linux/export.h>
 14#include <linux/err.h>
 15#include <crypto/aes.h>
 16
 17#include <net/mac80211.h>
 18#include "key.h"
 19#include "aes_cmac.h"
 20
 21#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
 22#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
 23#define AAD_LEN 20
 24
 
 25
 26void gf_mulx(u8 *pad)
 27{
 28	int i, carry;
 29
 30	carry = pad[0] & 0x80;
 31	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
 32		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
 33	pad[AES_BLOCK_SIZE - 1] <<= 1;
 34	if (carry)
 35		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
 36}
 37
 38void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
 39		     const u8 *addr[], const size_t *len, u8 *mac,
 40		     size_t mac_len)
 41{
 42	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
 43	const u8 *pos, *end;
 44	size_t i, e, left, total_len;
 45
 46	memset(cbc, 0, AES_BLOCK_SIZE);
 47
 48	total_len = 0;
 49	for (e = 0; e < num_elem; e++)
 50		total_len += len[e];
 51	left = total_len;
 52
 53	e = 0;
 54	pos = addr[0];
 55	end = pos + len[0];
 56
 57	while (left >= AES_BLOCK_SIZE) {
 58		for (i = 0; i < AES_BLOCK_SIZE; i++) {
 59			cbc[i] ^= *pos++;
 60			if (pos >= end) {
 61				e++;
 62				pos = addr[e];
 63				end = pos + len[e];
 64			}
 65		}
 66		if (left > AES_BLOCK_SIZE)
 67			crypto_cipher_encrypt_one(tfm, cbc, cbc);
 68		left -= AES_BLOCK_SIZE;
 69	}
 70
 71	memset(pad, 0, AES_BLOCK_SIZE);
 72	crypto_cipher_encrypt_one(tfm, pad, pad);
 73	gf_mulx(pad);
 74
 75	if (left || total_len == 0) {
 76		for (i = 0; i < left; i++) {
 77			cbc[i] ^= *pos++;
 78			if (pos >= end) {
 79				e++;
 80				pos = addr[e];
 81				end = pos + len[e];
 82			}
 83		}
 84		cbc[left] ^= 0x80;
 85		gf_mulx(pad);
 86	}
 87
 88	for (i = 0; i < AES_BLOCK_SIZE; i++)
 89		pad[i] ^= cbc[i];
 90	crypto_cipher_encrypt_one(tfm, pad, pad);
 91	memcpy(mac, pad, mac_len);
 92}
 93
 94
 95void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
 96			const u8 *data, size_t data_len, u8 *mic)
 97{
 98	const u8 *addr[3];
 99	size_t len[3];
100	u8 zero[CMAC_TLEN];
101
102	memset(zero, 0, CMAC_TLEN);
103	addr[0] = aad;
104	len[0] = AAD_LEN;
105	addr[1] = data;
106	len[1] = data_len - CMAC_TLEN;
107	addr[2] = zero;
108	len[2] = CMAC_TLEN;
 
 
 
 
 
 
109
110	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
111}
112
113void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
114			    const u8 *data, size_t data_len, u8 *mic)
115{
116	const u8 *addr[3];
117	size_t len[3];
118	u8 zero[CMAC_TLEN_256];
119
120	memset(zero, 0, CMAC_TLEN_256);
121	addr[0] = aad;
122	len[0] = AAD_LEN;
123	addr[1] = data;
124	len[1] = data_len - CMAC_TLEN_256;
125	addr[2] = zero;
126	len[2] = CMAC_TLEN_256;
127
128	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
 
 
 
 
 
 
 
 
 
 
 
 
 
129}
130
131struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
132						   size_t key_len)
133{
134	struct crypto_cipher *tfm;
135
136	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
137	if (!IS_ERR(tfm))
138		crypto_cipher_setkey(tfm, key, key_len);
 
 
 
 
 
 
139
140	return tfm;
141}
142
143
144void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
145{
146	crypto_free_cipher(tfm);
147}
v6.13.7
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 * AES-128-CMAC with TLen 16 for IEEE 802.11w BIP
 4 * Copyright 2008, Jouni Malinen <j@w1.fi>
 5 * Copyright (C) 2020 Intel Corporation
 
 
 
 6 */
 7
 8#include <linux/kernel.h>
 9#include <linux/types.h>
10#include <linux/crypto.h>
11#include <linux/export.h>
12#include <linux/err.h>
13#include <crypto/aes.h>
14
15#include <net/mac80211.h>
16#include "key.h"
17#include "aes_cmac.h"
18
19#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
20#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
21#define AAD_LEN 20
22
23static const u8 zero[CMAC_TLEN_256];
24
25void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26			const u8 *data, size_t data_len, u8 *mic)
27{
28	SHASH_DESC_ON_STACK(desc, tfm);
29	u8 out[AES_BLOCK_SIZE];
30	const __le16 *fc;
31
32	desc->tfm = tfm;
33
34	crypto_shash_init(desc);
35	crypto_shash_update(desc, aad, AAD_LEN);
36	fc = (const __le16 *)aad;
37	if (ieee80211_is_beacon(*fc)) {
38		/* mask Timestamp field to zero */
39		crypto_shash_update(desc, zero, 8);
40		crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN);
41	} else {
42		crypto_shash_update(desc, data, data_len - CMAC_TLEN);
43	}
44	crypto_shash_finup(desc, zero, CMAC_TLEN, out);
45
46	memcpy(mic, out, CMAC_TLEN);
47}
48
49void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
50			    const u8 *data, size_t data_len, u8 *mic)
51{
52	SHASH_DESC_ON_STACK(desc, tfm);
53	const __le16 *fc;
 
 
 
 
 
 
 
 
 
54
55	desc->tfm = tfm;
56
57	crypto_shash_init(desc);
58	crypto_shash_update(desc, aad, AAD_LEN);
59	fc = (const __le16 *)aad;
60	if (ieee80211_is_beacon(*fc)) {
61		/* mask Timestamp field to zero */
62		crypto_shash_update(desc, zero, 8);
63		crypto_shash_update(desc, data + 8,
64				    data_len - 8 - CMAC_TLEN_256);
65	} else {
66		crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
67	}
68	crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
69}
70
71struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
72						  size_t key_len)
73{
74	struct crypto_shash *tfm;
75
76	tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
77	if (!IS_ERR(tfm)) {
78		int err = crypto_shash_setkey(tfm, key, key_len);
79
80		if (err) {
81			crypto_free_shash(tfm);
82			return ERR_PTR(err);
83		}
84	}
85
86	return tfm;
87}
88
89void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm)
 
90{
91	crypto_free_shash(tfm);
92}