Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AES routines supporting VMX instructions on the Power 8
0004  *
0005  * Copyright (C) 2015 International Business Machines Inc.
0006  *
0007  * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
0008  */
0009 
0010 #include <linux/types.h>
0011 #include <linux/err.h>
0012 #include <linux/crypto.h>
0013 #include <linux/delay.h>
0014 #include <asm/simd.h>
0015 #include <asm/switch_to.h>
0016 #include <crypto/aes.h>
0017 #include <crypto/internal/cipher.h>
0018 #include <crypto/internal/simd.h>
0019 
0020 #include "aesp8-ppc.h"
0021 
0022 struct p8_aes_ctx {
0023     struct crypto_cipher *fallback;
0024     struct aes_key enc_key;
0025     struct aes_key dec_key;
0026 };
0027 
0028 static int p8_aes_init(struct crypto_tfm *tfm)
0029 {
0030     const char *alg = crypto_tfm_alg_name(tfm);
0031     struct crypto_cipher *fallback;
0032     struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
0033 
0034     fallback = crypto_alloc_cipher(alg, 0, CRYPTO_ALG_NEED_FALLBACK);
0035     if (IS_ERR(fallback)) {
0036         printk(KERN_ERR
0037                "Failed to allocate transformation for '%s': %ld\n",
0038                alg, PTR_ERR(fallback));
0039         return PTR_ERR(fallback);
0040     }
0041 
0042     crypto_cipher_set_flags(fallback,
0043                 crypto_cipher_get_flags((struct
0044                              crypto_cipher *)
0045                             tfm));
0046     ctx->fallback = fallback;
0047 
0048     return 0;
0049 }
0050 
0051 static void p8_aes_exit(struct crypto_tfm *tfm)
0052 {
0053     struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
0054 
0055     if (ctx->fallback) {
0056         crypto_free_cipher(ctx->fallback);
0057         ctx->fallback = NULL;
0058     }
0059 }
0060 
0061 static int p8_aes_setkey(struct crypto_tfm *tfm, const u8 *key,
0062              unsigned int keylen)
0063 {
0064     int ret;
0065     struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
0066 
0067     preempt_disable();
0068     pagefault_disable();
0069     enable_kernel_vsx();
0070     ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
0071     ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
0072     disable_kernel_vsx();
0073     pagefault_enable();
0074     preempt_enable();
0075 
0076     ret |= crypto_cipher_setkey(ctx->fallback, key, keylen);
0077 
0078     return ret ? -EINVAL : 0;
0079 }
0080 
0081 static void p8_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0082 {
0083     struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
0084 
0085     if (!crypto_simd_usable()) {
0086         crypto_cipher_encrypt_one(ctx->fallback, dst, src);
0087     } else {
0088         preempt_disable();
0089         pagefault_disable();
0090         enable_kernel_vsx();
0091         aes_p8_encrypt(src, dst, &ctx->enc_key);
0092         disable_kernel_vsx();
0093         pagefault_enable();
0094         preempt_enable();
0095     }
0096 }
0097 
0098 static void p8_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0099 {
0100     struct p8_aes_ctx *ctx = crypto_tfm_ctx(tfm);
0101 
0102     if (!crypto_simd_usable()) {
0103         crypto_cipher_decrypt_one(ctx->fallback, dst, src);
0104     } else {
0105         preempt_disable();
0106         pagefault_disable();
0107         enable_kernel_vsx();
0108         aes_p8_decrypt(src, dst, &ctx->dec_key);
0109         disable_kernel_vsx();
0110         pagefault_enable();
0111         preempt_enable();
0112     }
0113 }
0114 
0115 struct crypto_alg p8_aes_alg = {
0116     .cra_name = "aes",
0117     .cra_driver_name = "p8_aes",
0118     .cra_module = THIS_MODULE,
0119     .cra_priority = 1000,
0120     .cra_type = NULL,
0121     .cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK,
0122     .cra_alignmask = 0,
0123     .cra_blocksize = AES_BLOCK_SIZE,
0124     .cra_ctxsize = sizeof(struct p8_aes_ctx),
0125     .cra_init = p8_aes_init,
0126     .cra_exit = p8_aes_exit,
0127     .cra_cipher = {
0128                .cia_min_keysize = AES_MIN_KEY_SIZE,
0129                .cia_max_keysize = AES_MAX_KEY_SIZE,
0130                .cia_setkey = p8_aes_setkey,
0131                .cia_encrypt = p8_aes_encrypt,
0132                .cia_decrypt = p8_aes_decrypt,
0133     },
0134 };