cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aes_cbc.c (3472B)


      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
     16#include "aesp8-ppc.h"
     17
     18struct p8_aes_cbc_ctx {
     19	struct crypto_skcipher *fallback;
     20	struct aes_key enc_key;
     21	struct aes_key dec_key;
     22};
     23
     24static int p8_aes_cbc_init(struct crypto_skcipher *tfm)
     25{
     26	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
     27	struct crypto_skcipher *fallback;
     28
     29	fallback = crypto_alloc_skcipher("cbc(aes)", 0,
     30					 CRYPTO_ALG_NEED_FALLBACK |
     31					 CRYPTO_ALG_ASYNC);
     32	if (IS_ERR(fallback)) {
     33		pr_err("Failed to allocate cbc(aes) fallback: %ld\n",
     34		       PTR_ERR(fallback));
     35		return PTR_ERR(fallback);
     36	}
     37
     38	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
     39				    crypto_skcipher_reqsize(fallback));
     40	ctx->fallback = fallback;
     41	return 0;
     42}
     43
     44static void p8_aes_cbc_exit(struct crypto_skcipher *tfm)
     45{
     46	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
     47
     48	crypto_free_skcipher(ctx->fallback);
     49}
     50
     51static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key,
     52			     unsigned int keylen)
     53{
     54	struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
     55	int ret;
     56
     57	preempt_disable();
     58	pagefault_disable();
     59	enable_kernel_vsx();
     60	ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
     61	ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
     62	disable_kernel_vsx();
     63	pagefault_enable();
     64	preempt_enable();
     65
     66	ret |= crypto_skcipher_setkey(ctx->fallback, key, keylen);
     67
     68	return ret ? -EINVAL : 0;
     69}
     70
     71static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc)
     72{
     73	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
     74	const struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
     75	struct skcipher_walk walk;
     76	unsigned int nbytes;
     77	int ret;
     78
     79	if (!crypto_simd_usable()) {
     80		struct skcipher_request *subreq = skcipher_request_ctx(req);
     81
     82		*subreq = *req;
     83		skcipher_request_set_tfm(subreq, ctx->fallback);
     84		return enc ? crypto_skcipher_encrypt(subreq) :
     85			     crypto_skcipher_decrypt(subreq);
     86	}
     87
     88	ret = skcipher_walk_virt(&walk, req, false);
     89	while ((nbytes = walk.nbytes) != 0) {
     90		preempt_disable();
     91		pagefault_disable();
     92		enable_kernel_vsx();
     93		aes_p8_cbc_encrypt(walk.src.virt.addr,
     94				   walk.dst.virt.addr,
     95				   round_down(nbytes, AES_BLOCK_SIZE),
     96				   enc ? &ctx->enc_key : &ctx->dec_key,
     97				   walk.iv, enc);
     98		disable_kernel_vsx();
     99		pagefault_enable();
    100		preempt_enable();
    101
    102		ret = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE);
    103	}
    104	return ret;
    105}
    106
    107static int p8_aes_cbc_encrypt(struct skcipher_request *req)
    108{
    109	return p8_aes_cbc_crypt(req, 1);
    110}
    111
    112static int p8_aes_cbc_decrypt(struct skcipher_request *req)
    113{
    114	return p8_aes_cbc_crypt(req, 0);
    115}
    116
    117struct skcipher_alg p8_aes_cbc_alg = {
    118	.base.cra_name = "cbc(aes)",
    119	.base.cra_driver_name = "p8_aes_cbc",
    120	.base.cra_module = THIS_MODULE,
    121	.base.cra_priority = 2000,
    122	.base.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
    123	.base.cra_blocksize = AES_BLOCK_SIZE,
    124	.base.cra_ctxsize = sizeof(struct p8_aes_cbc_ctx),
    125	.setkey = p8_aes_cbc_setkey,
    126	.encrypt = p8_aes_cbc_encrypt,
    127	.decrypt = p8_aes_cbc_decrypt,
    128	.init = p8_aes_cbc_init,
    129	.exit = p8_aes_cbc_exit,
    130	.min_keysize = AES_MIN_KEY_SIZE,
    131	.max_keysize = AES_MAX_KEY_SIZE,
    132	.ivsize = AES_BLOCK_SIZE,
    133};