File Index
Files and directories
Sign in
FILE

aes_cbc.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/crypto/aes_cbc.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * AES CBC routines supporting VMX instructions on the Power 8
  4 *
  5 * Copyright (C) 2015 International Business Machines Inc.
  6 *
  7 * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
  8 */
  9
 10#include <asm/simd.h>
 11#include <asm/switch_to.h>
 12#include <crypto/aes.h>
 13#include <crypto/internal/simd.h>
 14#include <crypto/internal/skcipher.h>
 15#include <linux/err.h>
 16#include <linux/kernel.h>
 17#include <linux/module.h>
 18#include <linux/uaccess.h>
 19
 20#include "aesp8-ppc.h"
 21
 22struct p8_aes_cbc_ctx {
 23	struct crypto_skcipher *fallback;
 24	struct aes_key enc_key;
 25	struct aes_key dec_key;
 26};
 27
 28static int p8_aes_cbc_init(struct crypto_skcipher *tfm)
 29{
 30	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 31	struct crypto_skcipher *fallback;
 32
 33	fallback = crypto_alloc_skcipher("cbc(aes)", 0,
 34					 CRYPTO_ALG_NEED_FALLBACK |
 35					 CRYPTO_ALG_ASYNC);
 36	if (IS_ERR(fallback)) {
 37		pr_err("Failed to allocate cbc(aes) fallback: %ld\n",
 38		       PTR_ERR(fallback));
 39		return PTR_ERR(fallback);
 40	}
 41
 42	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
 43				    crypto_skcipher_reqsize(fallback));
 44	ctx->fallback = fallback;
 45	return 0;
 46}
 47
 48static void p8_aes_cbc_exit(struct crypto_skcipher *tfm)
 49{
 50	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 51
 52	crypto_free_skcipher(ctx->fallback);
 53}
 54
 55static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key,
 56			     unsigned int keylen)
 57{
 58	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 59	int ret;
 60
 61	preempt_disable();
 62	pagefault_disable();
 63	enable_kernel_vsx();
 64	ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
 65	ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
 66	disable_kernel_vsx();
 67	pagefault_enable();
 68	preempt_enable();
 69
 70	ret |= crypto_skcipher_setkey(ctx->fallback, key, keylen);
 71
 72	return ret ? -EINVAL : 0;
 73}
 74
 75static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc)
 76{
 77	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 78	const struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 79	struct skcipher_walk walk;
 80	unsigned int nbytes;
 81	int ret;
 82
 83	if (!crypto_simd_usable()) {
 84		struct skcipher_request *subreq = skcipher_request_ctx(req);
 85
 86		*subreq = *req;
 87		skcipher_request_set_tfm(subreq, ctx->fallback);
 88		return enc ? crypto_skcipher_encrypt(subreq) :
 89			     crypto_skcipher_decrypt(subreq);
 90	}
 91
 92	ret = skcipher_walk_virt(&walk, req, false);
 93	while ((nbytes = walk.nbytes) != 0) {
 94		preempt_disable();
 95		pagefault_disable();
 96		enable_kernel_vsx();
 97		aes_p8_cbc_encrypt(walk.src.virt.addr,
 98				   walk.dst.virt.addr,
 99				   round_down(nbytes, AES_BLOCK_SIZE),
100				   enc ? &ctx->enc_key : &ctx->dec_key,
101				   walk.iv, enc);
102		disable_kernel_vsx();
103		pagefault_enable();
104		preempt_enable();
105
106		ret = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE);
107	}
108	return ret;
109}
110
111static int p8_aes_cbc_encrypt(struct skcipher_request *req)
112{
113	return p8_aes_cbc_crypt(req, 1);
114}
115
116static int p8_aes_cbc_decrypt(struct skcipher_request *req)
117{
118	return p8_aes_cbc_crypt(req, 0);
119}
120
121struct skcipher_alg p8_aes_cbc_alg = {
122	.base.cra_name = "cbc(aes)",
123	.base.cra_driver_name = "p8_aes_cbc",
124	.base.cra_module = THIS_MODULE,
125	.base.cra_priority = 2000,
126	.base.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
127	.base.cra_blocksize = AES_BLOCK_SIZE,
128	.base.cra_ctxsize = sizeof(struct p8_aes_cbc_ctx),
129	.setkey = p8_aes_cbc_setkey,
130	.encrypt = p8_aes_cbc_encrypt,
131	.decrypt = p8_aes_cbc_decrypt,
132	.init = p8_aes_cbc_init,
133	.exit = p8_aes_cbc_exit,
134	.min_keysize = AES_MIN_KEY_SIZE,
135	.max_keysize = AES_MAX_KEY_SIZE,
136	.ivsize = AES_BLOCK_SIZE,
137};
~/ Read-only file preview.