net/mac80211/fils_aead.c

Source file repositories/reference/linux-study-clean/net/mac80211/fils_aead.c

File Facts

System
Linux kernel
Corpus path
net/mac80211/fils_aead.c
Extension
.c
Size
8235 bytes
Lines
320
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * FILS AEAD for (Re)Association Request/Response frames
 * Copyright 2016, Qualcomm Atheros, Inc.
 */

#include <crypto/aes-cbc-macs.h>
#include <crypto/skcipher.h>
#include <crypto/utils.h>

#include "ieee80211_i.h"
#include "fils_aead.h"

static void gf_mulx(u8 *pad)
{
	u64 a = get_unaligned_be64(pad);
	u64 b = get_unaligned_be64(pad + 8);

	put_unaligned_be64((a << 1) | (b >> 63), pad);
	put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8);
}

static int aes_s2v(const u8 *in_key, size_t key_len,
		   size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
{
	u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {};
	struct aes_cmac_key key;
	struct aes_cmac_ctx ctx;
	size_t i;
	int res;

	res = aes_cmac_preparekey(&key, in_key, key_len);
	if (res)
		return res;

	/* D = AES-CMAC(K, <zero>) */
	aes_cmac(&key, tmp, AES_BLOCK_SIZE, d);

	for (i = 0; i < num_elem - 1; i++) {
		/* D = dbl(D) xor AES_CMAC(K, Si) */
		gf_mulx(d); /* dbl */
		aes_cmac(&key, addr[i], len[i], tmp);
		crypto_xor(d, tmp, AES_BLOCK_SIZE);
	}

	aes_cmac_init(&ctx, &key);

	if (len[i] >= AES_BLOCK_SIZE) {
		/* len(Sn) >= 128 */
		/* T = Sn xorend D */
		aes_cmac_update(&ctx, addr[i], len[i] - AES_BLOCK_SIZE);
		crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE,
			   AES_BLOCK_SIZE);
	} else {
		/* len(Sn) < 128 */
		/* T = dbl(D) xor pad(Sn) */
		gf_mulx(d); /* dbl */
		crypto_xor(d, addr[i], len[i]);
		d[len[i]] ^= 0x80;
	}
	/* V = AES-CMAC(K, T) */
	aes_cmac_update(&ctx, d, AES_BLOCK_SIZE);
	aes_cmac_final(&ctx, v);

	memzero_explicit(&key, sizeof(key));
	return 0;
}

/* Note: addr[] and len[] needs to have one extra slot at the end. */
static int aes_siv_encrypt(const u8 *key, size_t key_len,
			   const u8 *plain, size_t plain_len,
			   size_t num_elem, const u8 *addr[],
			   size_t len[], u8 *out)
{
	u8 v[AES_BLOCK_SIZE];
	struct crypto_skcipher *tfm2;
	struct skcipher_request *req;
	int res;
	struct scatterlist src[1], dst[1];
	u8 *tmp;

	key_len /= 2; /* S2V key || CTR key */

	addr[num_elem] = plain;
	len[num_elem] = plain_len;
	num_elem++;

	/* S2V */
	res = aes_s2v(key /* K1 */, key_len, num_elem, addr, len, v);
	if (res)

Annotation

Implementation Notes