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.c (3251B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AES 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 <linux/types.h>
     11#include <linux/err.h>
     12#include <linux/crypto.h>
     13#include <linux/delay.h>
     14#include <asm/simd.h>
     15#include <asm/switch_to.h>
     16#include <crypto/aes.h>
     17#include <crypto/internal/cipher.h>
     18#include <crypto/internal/simd.h>
     19
     20#include "aesp8-ppc.h"
     21
     22struct p8_aes_ctx {
     23	struct crypto_cipher *fallback;
     24	struct aes_key enc_key;
     25	struct aes_key dec_key;
     26};
     27
     28static int p8_aes_init(struct crypto_tfm *tfm)
     29{
     30	const char *alg = crypto_tfm_alg_name(tfm);
     31	struct crypto_cipher *fallback;
     32	struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
     33
     34	fallback = crypto_alloc_cipher(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
     35	if (IS_ERR(fallback)) {
     36		printk(KERN_ERR
     37		       "Failed to allocate transformation for '%s': %ld\n",
     38		       alg, PTR_ERR(fallback));
     39		return PTR_ERR(fallback);
     40	}
     41
     42	crypto_cipher_set_flags(fallback,
     43				crypto_cipher_get_flags((struct
     44							 crypto_cipher *)
     45							tfm));
     46	ctx->fallback = fallback;
     47
     48	return 0;
     49}
     50
     51static void p8_aes_exit(struct crypto_tfm *tfm)
     52{
     53	struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
     54
     55	if (ctx->fallback) {
     56		crypto_free_cipher(ctx->fallback);
     57		ctx->fallback = NULL;
     58	}
     59}
     60
     61static int p8_aes_setkey(struct crypto_tfm *tfm, const u8 *key,
     62			 unsigned int keylen)
     63{
     64	int ret;
     65	struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
     66
     67	preempt_disable();
     68	pagefault_disable();
     69	enable_kernel_vsx();
     70	ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
     71	ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
     72	disable_kernel_vsx();
     73	pagefault_enable();
     74	preempt_enable();
     75
     76	ret |= crypto_cipher_setkey(ctx->fallback, key, keylen);
     77
     78	return ret ? -EINVAL : 0;
     79}
     80
     81static void p8_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
     82{
     83	struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
     84
     85	if (!crypto_simd_usable()) {
     86		crypto_cipher_encrypt_one(ctx->fallback, dst, src);
     87	} else {
     88		preempt_disable();
     89		pagefault_disable();
     90		enable_kernel_vsx();
     91		aes_p8_encrypt(src, dst, &ctx->enc_key);
     92		disable_kernel_vsx();
     93		pagefault_enable();
     94		preempt_enable();
     95	}
     96}
     97
     98static void p8_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
     99{
    100	struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
    101
    102	if (!crypto_simd_usable()) {
    103		crypto_cipher_decrypt_one(ctx->fallback, dst, src);
    104	} else {
    105		preempt_disable();
    106		pagefault_disable();
    107		enable_kernel_vsx();
    108		aes_p8_decrypt(src, dst, &ctx->dec_key);
    109		disable_kernel_vsx();
    110		pagefault_enable();
    111		preempt_enable();
    112	}
    113}
    114
    115struct crypto_alg p8_aes_alg = {
    116	.cra_name = "aes",
    117	.cra_driver_name = "p8_aes",
    118	.cra_module = THIS_MODULE,
    119	.cra_priority = 1000,
    120	.cra_type = NULL,
    121	.cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK,
    122	.cra_alignmask = 0,
    123	.cra_blocksize = AES_BLOCK_SIZE,
    124	.cra_ctxsize = sizeof(struct p8_aes_ctx),
    125	.cra_init = p8_aes_init,
    126	.cra_exit = p8_aes_exit,
    127	.cra_cipher = {
    128		       .cia_min_keysize = AES_MIN_KEY_SIZE,
    129		       .cia_max_keysize = AES_MAX_KEY_SIZE,
    130		       .cia_setkey = p8_aes_setkey,
    131		       .cia_encrypt = p8_aes_encrypt,
    132		       .cia_decrypt = p8_aes_decrypt,
    133	},
    134};