net/tls/tls_device_fallback.c

Source file repositories/reference/linux-study-clean/net/tls/tls_device_fallback.c

File Facts

System
Linux kernel
Corpus path
net/tls/tls_device_fallback.c
Extension
.c
Size
13069 bytes
Lines
472
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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

#include <net/tls.h>
#include <crypto/aead.h>
#include <crypto/scatterwalk.h>
#include <net/ip6_checksum.h>
#include <linux/skbuff_ref.h>

#include "tls.h"

static int tls_enc_record(struct aead_request *aead_req,
			  struct crypto_aead *aead, char *aad,
			  char *iv, __be64 rcd_sn,
			  struct scatter_walk *in,
			  struct scatter_walk *out, int *in_len,
			  struct tls_prot_info *prot)
{
	unsigned char buf[TLS_HEADER_SIZE + TLS_MAX_IV_SIZE];
	const struct tls_cipher_desc *cipher_desc;
	struct scatterlist sg_in[3];
	struct scatterlist sg_out[3];
	unsigned int buf_size;
	u16 len;
	int rc;

	cipher_desc = get_cipher_desc(prot->cipher_type);
	DEBUG_NET_WARN_ON_ONCE(!cipher_desc || !cipher_desc->offloadable);

	buf_size = TLS_HEADER_SIZE + cipher_desc->iv;
	len = min_t(int, *in_len, buf_size);

	memcpy_from_scatterwalk(buf, in, len);
	memcpy_to_scatterwalk(out, buf, len);

	*in_len -= len;
	if (!*in_len)
		return 0;

	len = buf[4] | (buf[3] << 8);
	len -= cipher_desc->iv;

	tls_make_aad(aad, len - cipher_desc->tag, (char *)&rcd_sn, buf[0], prot);

	memcpy(iv + cipher_desc->salt, buf + TLS_HEADER_SIZE, cipher_desc->iv);

	sg_init_table(sg_in, ARRAY_SIZE(sg_in));
	sg_init_table(sg_out, ARRAY_SIZE(sg_out));
	sg_set_buf(sg_in, aad, TLS_AAD_SPACE_SIZE);
	sg_set_buf(sg_out, aad, TLS_AAD_SPACE_SIZE);
	scatterwalk_get_sglist(in, sg_in + 1);
	scatterwalk_get_sglist(out, sg_out + 1);

	*in_len -= len;
	if (*in_len < 0) {
		*in_len += cipher_desc->tag;
		/* the input buffer doesn't contain the entire record.
		 * trim len accordingly. The resulting authentication tag
		 * will contain garbage, but we don't care, so we won't
		 * include any of it in the output skb
		 * Note that we assume the output buffer length
		 * is larger then input buffer length + tag size
		 */
		if (*in_len < 0)
			len += *in_len;

		*in_len = 0;
	}

	if (*in_len) {
		scatterwalk_skip(in, len);
		scatterwalk_skip(out, len);
	}

	len -= cipher_desc->tag;
	aead_request_set_crypt(aead_req, sg_in, sg_out, len, iv);

	rc = crypto_aead_encrypt(aead_req);

	return rc;
}

static void tls_init_aead_request(struct aead_request *aead_req,
				  struct crypto_aead *aead)
{
	aead_request_set_tfm(aead_req, aead);
	aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
}

static struct aead_request *tls_alloc_aead_request(struct crypto_aead *aead,
						   gfp_t flags)
{
	unsigned int req_size = sizeof(struct aead_request) +

Annotation

Implementation Notes