arch/arm64/crypto/sm4-ce-ccm-glue.c

Source file repositories/reference/linux-study-clean/arch/arm64/crypto/sm4-ce-ccm-glue.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/crypto/sm4-ce-ccm-glue.c
Extension
.c
Size
6775 bytes
Lines
286
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct __packed { __be16 l; __be32 h; } aadlen;
	u32 assoclen = req->assoclen;
	struct scatter_walk walk;
	unsigned int len;

	if (assoclen < 0xff00) {
		aadlen.l = cpu_to_be16(assoclen);
		len = 2;
	} else {
		aadlen.l = cpu_to_be16(0xfffe);
		put_unaligned_be32(assoclen, &aadlen.h);
		len = 6;
	}

	sm4_ce_crypt_block(ctx->rkey_enc, mac, mac);
	crypto_xor(mac, (const u8 *)&aadlen, len);

	scatterwalk_start(&walk, req->src);

	do {
		unsigned int n, orig_n;
		const u8 *p;

		orig_n = scatterwalk_next(&walk, assoclen);
		p = walk.addr;
		n = orig_n;

		while (n > 0) {
			unsigned int l, nblocks;

			if (len == SM4_BLOCK_SIZE) {
				if (n < SM4_BLOCK_SIZE) {
					sm4_ce_crypt_block(ctx->rkey_enc,
							   mac, mac);

					len = 0;
				} else {
					nblocks = n / SM4_BLOCK_SIZE;
					sm4_ce_cbcmac_update(ctx->rkey_enc,
							     mac, p, nblocks);

					p += nblocks * SM4_BLOCK_SIZE;
					n %= SM4_BLOCK_SIZE;

					continue;
				}
			}

			l = min(n, SM4_BLOCK_SIZE - len);
			if (l) {
				crypto_xor(mac + len, p, l);
				len += l;
				p += l;
				n -= l;
			}
		}

		scatterwalk_done_src(&walk, orig_n);
		assoclen -= orig_n;
	} while (assoclen);
}

static int ccm_crypt(struct aead_request *req, struct skcipher_walk *walk,
		     u32 *rkey_enc, u8 mac[],
		     void (*sm4_ce_ccm_crypt)(const u32 *rkey_enc, u8 *dst,
					const u8 *src, u8 *iv,
					unsigned int nbytes, u8 *mac))
{
	u8 __aligned(8) ctr0[SM4_BLOCK_SIZE];
	int err = 0;

	/* preserve the initial ctr0 for the TAG */
	memcpy(ctr0, walk->iv, SM4_BLOCK_SIZE);
	crypto_inc(walk->iv, SM4_BLOCK_SIZE);

	scoped_ksimd() {
		if (req->assoclen)
			ccm_calculate_auth_mac(req, mac);

		while (walk->nbytes) {
			unsigned int tail = walk->nbytes % SM4_BLOCK_SIZE;

			if (walk->nbytes == walk->total)
				tail = 0;

			sm4_ce_ccm_crypt(rkey_enc, walk->dst.virt.addr,
					 walk->src.virt.addr, walk->iv,
					 walk->nbytes - tail, mac);

			err = skcipher_walk_done(walk, tail);

Annotation

Implementation Notes