162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Glue code for AES encryption optimized for sparc64 crypto opcodes. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This is based largely upon arch/x86/crypto/aesni-intel_glue.c 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2008, Intel Corp. 762306a36Sopenharmony_ci * Author: Huang Ying <ying.huang@intel.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Added RFC4106 AES-GCM support for 128-bit keys under the AEAD 1062306a36Sopenharmony_ci * interface for 64-bit kernels. 1162306a36Sopenharmony_ci * Authors: Adrian Hoban <adrian.hoban@intel.com> 1262306a36Sopenharmony_ci * Gabriele Paoloni <gabriele.paoloni@intel.com> 1362306a36Sopenharmony_ci * Tadeusz Struk (tadeusz.struk@intel.com) 1462306a36Sopenharmony_ci * Aidan O'Mahony (aidan.o.mahony@intel.com) 1562306a36Sopenharmony_ci * Copyright (c) 2010, Intel Corporation. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/crypto.h> 2162306a36Sopenharmony_ci#include <linux/init.h> 2262306a36Sopenharmony_ci#include <linux/module.h> 2362306a36Sopenharmony_ci#include <linux/mm.h> 2462306a36Sopenharmony_ci#include <linux/types.h> 2562306a36Sopenharmony_ci#include <crypto/algapi.h> 2662306a36Sopenharmony_ci#include <crypto/aes.h> 2762306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <asm/fpumacro.h> 3062306a36Sopenharmony_ci#include <asm/pstate.h> 3162306a36Sopenharmony_ci#include <asm/elf.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "opcodes.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistruct aes_ops { 3662306a36Sopenharmony_ci void (*encrypt)(const u64 *key, const u32 *input, u32 *output); 3762306a36Sopenharmony_ci void (*decrypt)(const u64 *key, const u32 *input, u32 *output); 3862306a36Sopenharmony_ci void (*load_encrypt_keys)(const u64 *key); 3962306a36Sopenharmony_ci void (*load_decrypt_keys)(const u64 *key); 4062306a36Sopenharmony_ci void (*ecb_encrypt)(const u64 *key, const u64 *input, u64 *output, 4162306a36Sopenharmony_ci unsigned int len); 4262306a36Sopenharmony_ci void (*ecb_decrypt)(const u64 *key, const u64 *input, u64 *output, 4362306a36Sopenharmony_ci unsigned int len); 4462306a36Sopenharmony_ci void (*cbc_encrypt)(const u64 *key, const u64 *input, u64 *output, 4562306a36Sopenharmony_ci unsigned int len, u64 *iv); 4662306a36Sopenharmony_ci void (*cbc_decrypt)(const u64 *key, const u64 *input, u64 *output, 4762306a36Sopenharmony_ci unsigned int len, u64 *iv); 4862306a36Sopenharmony_ci void (*ctr_crypt)(const u64 *key, const u64 *input, u64 *output, 4962306a36Sopenharmony_ci unsigned int len, u64 *iv); 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistruct crypto_sparc64_aes_ctx { 5362306a36Sopenharmony_ci struct aes_ops *ops; 5462306a36Sopenharmony_ci u64 key[AES_MAX_KEYLENGTH / sizeof(u64)]; 5562306a36Sopenharmony_ci u32 key_length; 5662306a36Sopenharmony_ci u32 expanded_key_length; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciextern void aes_sparc64_encrypt_128(const u64 *key, const u32 *input, 6062306a36Sopenharmony_ci u32 *output); 6162306a36Sopenharmony_ciextern void aes_sparc64_encrypt_192(const u64 *key, const u32 *input, 6262306a36Sopenharmony_ci u32 *output); 6362306a36Sopenharmony_ciextern void aes_sparc64_encrypt_256(const u64 *key, const u32 *input, 6462306a36Sopenharmony_ci u32 *output); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciextern void aes_sparc64_decrypt_128(const u64 *key, const u32 *input, 6762306a36Sopenharmony_ci u32 *output); 6862306a36Sopenharmony_ciextern void aes_sparc64_decrypt_192(const u64 *key, const u32 *input, 6962306a36Sopenharmony_ci u32 *output); 7062306a36Sopenharmony_ciextern void aes_sparc64_decrypt_256(const u64 *key, const u32 *input, 7162306a36Sopenharmony_ci u32 *output); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciextern void aes_sparc64_load_encrypt_keys_128(const u64 *key); 7462306a36Sopenharmony_ciextern void aes_sparc64_load_encrypt_keys_192(const u64 *key); 7562306a36Sopenharmony_ciextern void aes_sparc64_load_encrypt_keys_256(const u64 *key); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciextern void aes_sparc64_load_decrypt_keys_128(const u64 *key); 7862306a36Sopenharmony_ciextern void aes_sparc64_load_decrypt_keys_192(const u64 *key); 7962306a36Sopenharmony_ciextern void aes_sparc64_load_decrypt_keys_256(const u64 *key); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciextern void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input, 8262306a36Sopenharmony_ci u64 *output, unsigned int len); 8362306a36Sopenharmony_ciextern void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input, 8462306a36Sopenharmony_ci u64 *output, unsigned int len); 8562306a36Sopenharmony_ciextern void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input, 8662306a36Sopenharmony_ci u64 *output, unsigned int len); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciextern void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input, 8962306a36Sopenharmony_ci u64 *output, unsigned int len); 9062306a36Sopenharmony_ciextern void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input, 9162306a36Sopenharmony_ci u64 *output, unsigned int len); 9262306a36Sopenharmony_ciextern void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input, 9362306a36Sopenharmony_ci u64 *output, unsigned int len); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciextern void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input, 9662306a36Sopenharmony_ci u64 *output, unsigned int len, 9762306a36Sopenharmony_ci u64 *iv); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciextern void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input, 10062306a36Sopenharmony_ci u64 *output, unsigned int len, 10162306a36Sopenharmony_ci u64 *iv); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciextern void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input, 10462306a36Sopenharmony_ci u64 *output, unsigned int len, 10562306a36Sopenharmony_ci u64 *iv); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciextern void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input, 10862306a36Sopenharmony_ci u64 *output, unsigned int len, 10962306a36Sopenharmony_ci u64 *iv); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciextern void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input, 11262306a36Sopenharmony_ci u64 *output, unsigned int len, 11362306a36Sopenharmony_ci u64 *iv); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciextern void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input, 11662306a36Sopenharmony_ci u64 *output, unsigned int len, 11762306a36Sopenharmony_ci u64 *iv); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciextern void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input, 12062306a36Sopenharmony_ci u64 *output, unsigned int len, 12162306a36Sopenharmony_ci u64 *iv); 12262306a36Sopenharmony_ciextern void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input, 12362306a36Sopenharmony_ci u64 *output, unsigned int len, 12462306a36Sopenharmony_ci u64 *iv); 12562306a36Sopenharmony_ciextern void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input, 12662306a36Sopenharmony_ci u64 *output, unsigned int len, 12762306a36Sopenharmony_ci u64 *iv); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic struct aes_ops aes128_ops = { 13062306a36Sopenharmony_ci .encrypt = aes_sparc64_encrypt_128, 13162306a36Sopenharmony_ci .decrypt = aes_sparc64_decrypt_128, 13262306a36Sopenharmony_ci .load_encrypt_keys = aes_sparc64_load_encrypt_keys_128, 13362306a36Sopenharmony_ci .load_decrypt_keys = aes_sparc64_load_decrypt_keys_128, 13462306a36Sopenharmony_ci .ecb_encrypt = aes_sparc64_ecb_encrypt_128, 13562306a36Sopenharmony_ci .ecb_decrypt = aes_sparc64_ecb_decrypt_128, 13662306a36Sopenharmony_ci .cbc_encrypt = aes_sparc64_cbc_encrypt_128, 13762306a36Sopenharmony_ci .cbc_decrypt = aes_sparc64_cbc_decrypt_128, 13862306a36Sopenharmony_ci .ctr_crypt = aes_sparc64_ctr_crypt_128, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic struct aes_ops aes192_ops = { 14262306a36Sopenharmony_ci .encrypt = aes_sparc64_encrypt_192, 14362306a36Sopenharmony_ci .decrypt = aes_sparc64_decrypt_192, 14462306a36Sopenharmony_ci .load_encrypt_keys = aes_sparc64_load_encrypt_keys_192, 14562306a36Sopenharmony_ci .load_decrypt_keys = aes_sparc64_load_decrypt_keys_192, 14662306a36Sopenharmony_ci .ecb_encrypt = aes_sparc64_ecb_encrypt_192, 14762306a36Sopenharmony_ci .ecb_decrypt = aes_sparc64_ecb_decrypt_192, 14862306a36Sopenharmony_ci .cbc_encrypt = aes_sparc64_cbc_encrypt_192, 14962306a36Sopenharmony_ci .cbc_decrypt = aes_sparc64_cbc_decrypt_192, 15062306a36Sopenharmony_ci .ctr_crypt = aes_sparc64_ctr_crypt_192, 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic struct aes_ops aes256_ops = { 15462306a36Sopenharmony_ci .encrypt = aes_sparc64_encrypt_256, 15562306a36Sopenharmony_ci .decrypt = aes_sparc64_decrypt_256, 15662306a36Sopenharmony_ci .load_encrypt_keys = aes_sparc64_load_encrypt_keys_256, 15762306a36Sopenharmony_ci .load_decrypt_keys = aes_sparc64_load_decrypt_keys_256, 15862306a36Sopenharmony_ci .ecb_encrypt = aes_sparc64_ecb_encrypt_256, 15962306a36Sopenharmony_ci .ecb_decrypt = aes_sparc64_ecb_decrypt_256, 16062306a36Sopenharmony_ci .cbc_encrypt = aes_sparc64_cbc_encrypt_256, 16162306a36Sopenharmony_ci .cbc_decrypt = aes_sparc64_cbc_decrypt_256, 16262306a36Sopenharmony_ci .ctr_crypt = aes_sparc64_ctr_crypt_256, 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciextern void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key, 16662306a36Sopenharmony_ci unsigned int key_len); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, 16962306a36Sopenharmony_ci unsigned int key_len) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci switch (key_len) { 17462306a36Sopenharmony_ci case AES_KEYSIZE_128: 17562306a36Sopenharmony_ci ctx->expanded_key_length = 0xb0; 17662306a36Sopenharmony_ci ctx->ops = &aes128_ops; 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci case AES_KEYSIZE_192: 18062306a36Sopenharmony_ci ctx->expanded_key_length = 0xd0; 18162306a36Sopenharmony_ci ctx->ops = &aes192_ops; 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci case AES_KEYSIZE_256: 18562306a36Sopenharmony_ci ctx->expanded_key_length = 0xf0; 18662306a36Sopenharmony_ci ctx->ops = &aes256_ops; 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci default: 19062306a36Sopenharmony_ci return -EINVAL; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci aes_sparc64_key_expand((const u32 *)in_key, &ctx->key[0], key_len); 19462306a36Sopenharmony_ci ctx->key_length = key_len; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci return 0; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic int aes_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, 20062306a36Sopenharmony_ci unsigned int key_len) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci return aes_set_key(crypto_skcipher_tfm(tfm), in_key, key_len); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic void crypto_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci ctx->ops->encrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic void crypto_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci ctx->ops->decrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic int ecb_encrypt(struct skcipher_request *req) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 22262306a36Sopenharmony_ci const struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 22362306a36Sopenharmony_ci struct skcipher_walk walk; 22462306a36Sopenharmony_ci unsigned int nbytes; 22562306a36Sopenharmony_ci int err; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 22862306a36Sopenharmony_ci if (err) 22962306a36Sopenharmony_ci return err; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ctx->ops->load_encrypt_keys(&ctx->key[0]); 23262306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 23362306a36Sopenharmony_ci ctx->ops->ecb_encrypt(&ctx->key[0], walk.src.virt.addr, 23462306a36Sopenharmony_ci walk.dst.virt.addr, 23562306a36Sopenharmony_ci round_down(nbytes, AES_BLOCK_SIZE)); 23662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci fprs_write(0); 23962306a36Sopenharmony_ci return err; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic int ecb_decrypt(struct skcipher_request *req) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 24562306a36Sopenharmony_ci const struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 24662306a36Sopenharmony_ci const u64 *key_end; 24762306a36Sopenharmony_ci struct skcipher_walk walk; 24862306a36Sopenharmony_ci unsigned int nbytes; 24962306a36Sopenharmony_ci int err; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 25262306a36Sopenharmony_ci if (err) 25362306a36Sopenharmony_ci return err; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci ctx->ops->load_decrypt_keys(&ctx->key[0]); 25662306a36Sopenharmony_ci key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)]; 25762306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 25862306a36Sopenharmony_ci ctx->ops->ecb_decrypt(key_end, walk.src.virt.addr, 25962306a36Sopenharmony_ci walk.dst.virt.addr, 26062306a36Sopenharmony_ci round_down(nbytes, AES_BLOCK_SIZE)); 26162306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci fprs_write(0); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci return err; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic int cbc_encrypt(struct skcipher_request *req) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 27162306a36Sopenharmony_ci const struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 27262306a36Sopenharmony_ci struct skcipher_walk walk; 27362306a36Sopenharmony_ci unsigned int nbytes; 27462306a36Sopenharmony_ci int err; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 27762306a36Sopenharmony_ci if (err) 27862306a36Sopenharmony_ci return err; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci ctx->ops->load_encrypt_keys(&ctx->key[0]); 28162306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 28262306a36Sopenharmony_ci ctx->ops->cbc_encrypt(&ctx->key[0], walk.src.virt.addr, 28362306a36Sopenharmony_ci walk.dst.virt.addr, 28462306a36Sopenharmony_ci round_down(nbytes, AES_BLOCK_SIZE), 28562306a36Sopenharmony_ci walk.iv); 28662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci fprs_write(0); 28962306a36Sopenharmony_ci return err; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic int cbc_decrypt(struct skcipher_request *req) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 29562306a36Sopenharmony_ci const struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 29662306a36Sopenharmony_ci const u64 *key_end; 29762306a36Sopenharmony_ci struct skcipher_walk walk; 29862306a36Sopenharmony_ci unsigned int nbytes; 29962306a36Sopenharmony_ci int err; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 30262306a36Sopenharmony_ci if (err) 30362306a36Sopenharmony_ci return err; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci ctx->ops->load_decrypt_keys(&ctx->key[0]); 30662306a36Sopenharmony_ci key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)]; 30762306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 30862306a36Sopenharmony_ci ctx->ops->cbc_decrypt(key_end, walk.src.virt.addr, 30962306a36Sopenharmony_ci walk.dst.virt.addr, 31062306a36Sopenharmony_ci round_down(nbytes, AES_BLOCK_SIZE), 31162306a36Sopenharmony_ci walk.iv); 31262306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci fprs_write(0); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return err; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic void ctr_crypt_final(const struct crypto_sparc64_aes_ctx *ctx, 32062306a36Sopenharmony_ci struct skcipher_walk *walk) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci u8 *ctrblk = walk->iv; 32362306a36Sopenharmony_ci u64 keystream[AES_BLOCK_SIZE / sizeof(u64)]; 32462306a36Sopenharmony_ci u8 *src = walk->src.virt.addr; 32562306a36Sopenharmony_ci u8 *dst = walk->dst.virt.addr; 32662306a36Sopenharmony_ci unsigned int nbytes = walk->nbytes; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci ctx->ops->ecb_encrypt(&ctx->key[0], (const u64 *)ctrblk, 32962306a36Sopenharmony_ci keystream, AES_BLOCK_SIZE); 33062306a36Sopenharmony_ci crypto_xor_cpy(dst, (u8 *) keystream, src, nbytes); 33162306a36Sopenharmony_ci crypto_inc(ctrblk, AES_BLOCK_SIZE); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic int ctr_crypt(struct skcipher_request *req) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 33762306a36Sopenharmony_ci const struct crypto_sparc64_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 33862306a36Sopenharmony_ci struct skcipher_walk walk; 33962306a36Sopenharmony_ci unsigned int nbytes; 34062306a36Sopenharmony_ci int err; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 34362306a36Sopenharmony_ci if (err) 34462306a36Sopenharmony_ci return err; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci ctx->ops->load_encrypt_keys(&ctx->key[0]); 34762306a36Sopenharmony_ci while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) { 34862306a36Sopenharmony_ci ctx->ops->ctr_crypt(&ctx->key[0], walk.src.virt.addr, 34962306a36Sopenharmony_ci walk.dst.virt.addr, 35062306a36Sopenharmony_ci round_down(nbytes, AES_BLOCK_SIZE), 35162306a36Sopenharmony_ci walk.iv); 35262306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci if (walk.nbytes) { 35562306a36Sopenharmony_ci ctr_crypt_final(ctx, &walk); 35662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, 0); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci fprs_write(0); 35962306a36Sopenharmony_ci return err; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic struct crypto_alg cipher_alg = { 36362306a36Sopenharmony_ci .cra_name = "aes", 36462306a36Sopenharmony_ci .cra_driver_name = "aes-sparc64", 36562306a36Sopenharmony_ci .cra_priority = SPARC_CR_OPCODE_PRIORITY, 36662306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 36762306a36Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 36862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx), 36962306a36Sopenharmony_ci .cra_alignmask = 3, 37062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 37162306a36Sopenharmony_ci .cra_u = { 37262306a36Sopenharmony_ci .cipher = { 37362306a36Sopenharmony_ci .cia_min_keysize = AES_MIN_KEY_SIZE, 37462306a36Sopenharmony_ci .cia_max_keysize = AES_MAX_KEY_SIZE, 37562306a36Sopenharmony_ci .cia_setkey = aes_set_key, 37662306a36Sopenharmony_ci .cia_encrypt = crypto_aes_encrypt, 37762306a36Sopenharmony_ci .cia_decrypt = crypto_aes_decrypt 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci}; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic struct skcipher_alg skcipher_algs[] = { 38362306a36Sopenharmony_ci { 38462306a36Sopenharmony_ci .base.cra_name = "ecb(aes)", 38562306a36Sopenharmony_ci .base.cra_driver_name = "ecb-aes-sparc64", 38662306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 38762306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 38862306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx), 38962306a36Sopenharmony_ci .base.cra_alignmask = 7, 39062306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 39162306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 39262306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 39362306a36Sopenharmony_ci .setkey = aes_set_key_skcipher, 39462306a36Sopenharmony_ci .encrypt = ecb_encrypt, 39562306a36Sopenharmony_ci .decrypt = ecb_decrypt, 39662306a36Sopenharmony_ci }, { 39762306a36Sopenharmony_ci .base.cra_name = "cbc(aes)", 39862306a36Sopenharmony_ci .base.cra_driver_name = "cbc-aes-sparc64", 39962306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 40062306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 40162306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx), 40262306a36Sopenharmony_ci .base.cra_alignmask = 7, 40362306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 40462306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 40562306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 40662306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 40762306a36Sopenharmony_ci .setkey = aes_set_key_skcipher, 40862306a36Sopenharmony_ci .encrypt = cbc_encrypt, 40962306a36Sopenharmony_ci .decrypt = cbc_decrypt, 41062306a36Sopenharmony_ci }, { 41162306a36Sopenharmony_ci .base.cra_name = "ctr(aes)", 41262306a36Sopenharmony_ci .base.cra_driver_name = "ctr-aes-sparc64", 41362306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 41462306a36Sopenharmony_ci .base.cra_blocksize = 1, 41562306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct crypto_sparc64_aes_ctx), 41662306a36Sopenharmony_ci .base.cra_alignmask = 7, 41762306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 41862306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 41962306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 42062306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 42162306a36Sopenharmony_ci .setkey = aes_set_key_skcipher, 42262306a36Sopenharmony_ci .encrypt = ctr_crypt, 42362306a36Sopenharmony_ci .decrypt = ctr_crypt, 42462306a36Sopenharmony_ci .chunksize = AES_BLOCK_SIZE, 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci}; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic bool __init sparc64_has_aes_opcode(void) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci unsigned long cfr; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 43362306a36Sopenharmony_ci return false; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 43662306a36Sopenharmony_ci if (!(cfr & CFR_AES)) 43762306a36Sopenharmony_ci return false; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return true; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic int __init aes_sparc64_mod_init(void) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci int err; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (!sparc64_has_aes_opcode()) { 44762306a36Sopenharmony_ci pr_info("sparc64 aes opcodes not available.\n"); 44862306a36Sopenharmony_ci return -ENODEV; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci pr_info("Using sparc64 aes opcodes optimized AES implementation\n"); 45162306a36Sopenharmony_ci err = crypto_register_alg(&cipher_alg); 45262306a36Sopenharmony_ci if (err) 45362306a36Sopenharmony_ci return err; 45462306a36Sopenharmony_ci err = crypto_register_skciphers(skcipher_algs, 45562306a36Sopenharmony_ci ARRAY_SIZE(skcipher_algs)); 45662306a36Sopenharmony_ci if (err) 45762306a36Sopenharmony_ci crypto_unregister_alg(&cipher_alg); 45862306a36Sopenharmony_ci return err; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic void __exit aes_sparc64_mod_fini(void) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci crypto_unregister_alg(&cipher_alg); 46462306a36Sopenharmony_ci crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cimodule_init(aes_sparc64_mod_init); 46862306a36Sopenharmony_cimodule_exit(aes_sparc64_mod_fini); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 47162306a36Sopenharmony_ciMODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, sparc64 aes opcode accelerated"); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("aes"); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci#include "crop_devid.c" 476