0001
0002
0003
0004
0005
0006
0007
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 };