2019-05-29 07:18:13 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-02-06 14:57:22 -02:00
/**
* AES routines supporting VMX instructions on the Power 8
*
* Copyright ( C ) 2015 International Business Machines Inc .
*
* Author : Marcelo Henrique Cerri < mhcerri @ br . ibm . com >
*/
# include <linux/types.h>
# include <linux/err.h>
# include <linux/crypto.h>
# include <linux/delay.h>
2019-04-12 22:33:12 -07:00
# include <asm/simd.h>
2015-02-06 14:57:22 -02:00
# include <asm/switch_to.h>
# include <crypto/aes.h>
2020-12-11 13:27:15 +01:00
# include <crypto/internal/cipher.h>
2019-04-12 22:33:12 -07:00
# include <crypto/internal/simd.h>
2015-02-06 14:57:22 -02:00
# include "aesp8-ppc.h"
struct p8_aes_ctx {
2015-06-15 16:55:46 +08:00
struct crypto_cipher * fallback ;
struct aes_key enc_key ;
struct aes_key dec_key ;
2015-02-06 14:57:22 -02:00
} ;
static int p8_aes_init ( struct crypto_tfm * tfm )
{
2017-06-16 11:39:48 +03:00
const char * alg = crypto_tfm_alg_name ( tfm ) ;
2015-06-15 16:55:46 +08:00
struct crypto_cipher * fallback ;
struct p8_aes_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
fallback = crypto_alloc_cipher ( alg , 0 , CRYPTO_ALG_NEED_FALLBACK ) ;
if ( IS_ERR ( fallback ) ) {
printk ( KERN_ERR
" Failed to allocate transformation for '%s': %ld \n " ,
alg , PTR_ERR ( fallback ) ) ;
return PTR_ERR ( fallback ) ;
}
crypto_cipher_set_flags ( fallback ,
crypto_cipher_get_flags ( ( struct
crypto_cipher * )
tfm ) ) ;
ctx - > fallback = fallback ;
return 0 ;
2015-02-06 14:57:22 -02:00
}
static void p8_aes_exit ( struct crypto_tfm * tfm )
{
2015-06-15 16:55:46 +08:00
struct p8_aes_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2015-02-06 14:57:22 -02:00
2015-06-15 16:55:46 +08:00
if ( ctx - > fallback ) {
crypto_free_cipher ( ctx - > fallback ) ;
ctx - > fallback = NULL ;
}
2015-02-06 14:57:22 -02:00
}
static int p8_aes_setkey ( struct crypto_tfm * tfm , const u8 * key ,
2015-06-15 16:55:46 +08:00
unsigned int keylen )
2015-02-06 14:57:22 -02:00
{
2015-06-15 16:55:46 +08:00
int ret ;
struct p8_aes_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2015-06-22 21:04:48 -07:00
preempt_disable ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_disable ( ) ;
2015-07-13 13:51:39 -03:00
enable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
ret = aes_p8_set_encrypt_key ( key , keylen * 8 , & ctx - > enc_key ) ;
2019-04-09 23:46:35 -07:00
ret | = aes_p8_set_decrypt_key ( key , keylen * 8 , & ctx - > dec_key ) ;
2015-10-29 11:44:05 +11:00
disable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_enable ( ) ;
2015-06-22 21:04:48 -07:00
preempt_enable ( ) ;
2015-06-15 16:55:46 +08:00
2019-04-09 23:46:35 -07:00
ret | = crypto_cipher_setkey ( ctx - > fallback , key , keylen ) ;
return ret ? - EINVAL : 0 ;
2015-02-06 14:57:22 -02:00
}
static void p8_aes_encrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
{
2015-06-15 16:55:46 +08:00
struct p8_aes_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2019-04-12 22:33:12 -07:00
if ( ! crypto_simd_usable ( ) ) {
2015-06-15 16:55:46 +08:00
crypto_cipher_encrypt_one ( ctx - > fallback , dst , src ) ;
} else {
2015-06-22 21:04:48 -07:00
preempt_disable ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_disable ( ) ;
2015-07-13 13:51:39 -03:00
enable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
aes_p8_encrypt ( src , dst , & ctx - > enc_key ) ;
2015-10-29 11:44:05 +11:00
disable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_enable ( ) ;
2015-06-22 21:04:48 -07:00
preempt_enable ( ) ;
2015-06-15 16:55:46 +08:00
}
2015-02-06 14:57:22 -02:00
}
static void p8_aes_decrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
{
2015-06-15 16:55:46 +08:00
struct p8_aes_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2019-04-12 22:33:12 -07:00
if ( ! crypto_simd_usable ( ) ) {
2015-06-15 16:55:46 +08:00
crypto_cipher_decrypt_one ( ctx - > fallback , dst , src ) ;
} else {
2015-06-22 21:04:48 -07:00
preempt_disable ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_disable ( ) ;
2015-07-13 13:51:39 -03:00
enable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
aes_p8_decrypt ( src , dst , & ctx - > dec_key ) ;
2015-10-29 11:44:05 +11:00
disable_kernel_vsx ( ) ;
2015-06-15 16:55:46 +08:00
pagefault_enable ( ) ;
2015-06-22 21:04:48 -07:00
preempt_enable ( ) ;
2015-06-15 16:55:46 +08:00
}
2015-02-06 14:57:22 -02:00
}
struct crypto_alg p8_aes_alg = {
2015-06-15 16:55:46 +08:00
. cra_name = " aes " ,
. cra_driver_name = " p8_aes " ,
. cra_module = THIS_MODULE ,
. cra_priority = 1000 ,
. cra_type = NULL ,
. cra_flags = CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_NEED_FALLBACK ,
. cra_alignmask = 0 ,
. cra_blocksize = AES_BLOCK_SIZE ,
. cra_ctxsize = sizeof ( struct p8_aes_ctx ) ,
. cra_init = p8_aes_init ,
. cra_exit = p8_aes_exit ,
. cra_cipher = {
. cia_min_keysize = AES_MIN_KEY_SIZE ,
. cia_max_keysize = AES_MAX_KEY_SIZE ,
. cia_setkey = p8_aes_setkey ,
. cia_encrypt = p8_aes_encrypt ,
. cia_decrypt = p8_aes_decrypt ,
} ,
2015-02-06 14:57:22 -02:00
} ;