Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at master 149 lines 4.9 kB view raw
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * AES accelerated using the sparc64 aes opcodes 4 * 5 * Copyright (C) 2008, Intel Corp. 6 * Copyright (c) 2010, Intel Corporation. 7 * Copyright 2026 Google LLC 8 */ 9 10#include <asm/fpumacro.h> 11#include <asm/opcodes.h> 12#include <asm/pstate.h> 13#include <asm/elf.h> 14 15static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_aes_opcodes); 16 17EXPORT_SYMBOL_GPL(aes_sparc64_key_expand); 18EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_128); 19EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_192); 20EXPORT_SYMBOL_GPL(aes_sparc64_load_encrypt_keys_256); 21EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_128); 22EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_192); 23EXPORT_SYMBOL_GPL(aes_sparc64_load_decrypt_keys_256); 24EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_128); 25EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_192); 26EXPORT_SYMBOL_GPL(aes_sparc64_ecb_encrypt_256); 27EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_128); 28EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_192); 29EXPORT_SYMBOL_GPL(aes_sparc64_ecb_decrypt_256); 30EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_128); 31EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_192); 32EXPORT_SYMBOL_GPL(aes_sparc64_cbc_encrypt_256); 33EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_128); 34EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_192); 35EXPORT_SYMBOL_GPL(aes_sparc64_cbc_decrypt_256); 36EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_128); 37EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_192); 38EXPORT_SYMBOL_GPL(aes_sparc64_ctr_crypt_256); 39 40void aes_sparc64_encrypt_128(const u64 *key, const u32 *input, u32 *output); 41void aes_sparc64_encrypt_192(const u64 *key, const u32 *input, u32 *output); 42void aes_sparc64_encrypt_256(const u64 *key, const u32 *input, u32 *output); 43void aes_sparc64_decrypt_128(const u64 *key, const u32 *input, u32 *output); 44void aes_sparc64_decrypt_192(const u64 *key, const u32 *input, u32 *output); 45void aes_sparc64_decrypt_256(const u64 *key, const u32 *input, u32 *output); 46 47static void aes_preparekey_arch(union aes_enckey_arch *k, 48 union aes_invkey_arch *inv_k, 49 const u8 *in_key, int key_len, int nrounds) 50{ 51 if (static_branch_likely(&have_aes_opcodes)) { 52 u32 aligned_key[AES_MAX_KEY_SIZE / 4]; 53 54 if (IS_ALIGNED((uintptr_t)in_key, 4)) { 55 aes_sparc64_key_expand((const u32 *)in_key, 56 k->sparc_rndkeys, key_len); 57 } else { 58 memcpy(aligned_key, in_key, key_len); 59 aes_sparc64_key_expand(aligned_key, 60 k->sparc_rndkeys, key_len); 61 memzero_explicit(aligned_key, key_len); 62 } 63 /* 64 * Note that nothing needs to be written to inv_k (if it's 65 * non-NULL) here, since the SPARC64 assembly code uses 66 * k->sparc_rndkeys for both encryption and decryption. 67 */ 68 } else { 69 aes_expandkey_generic(k->rndkeys, 70 inv_k ? inv_k->inv_rndkeys : NULL, 71 in_key, key_len); 72 } 73} 74 75static void aes_sparc64_encrypt(const struct aes_enckey *key, 76 const u32 *input, u32 *output) 77{ 78 if (key->len == AES_KEYSIZE_128) 79 aes_sparc64_encrypt_128(key->k.sparc_rndkeys, input, output); 80 else if (key->len == AES_KEYSIZE_192) 81 aes_sparc64_encrypt_192(key->k.sparc_rndkeys, input, output); 82 else 83 aes_sparc64_encrypt_256(key->k.sparc_rndkeys, input, output); 84} 85 86static void aes_encrypt_arch(const struct aes_enckey *key, 87 u8 out[AES_BLOCK_SIZE], 88 const u8 in[AES_BLOCK_SIZE]) 89{ 90 u32 bounce_buf[AES_BLOCK_SIZE / 4]; 91 92 if (static_branch_likely(&have_aes_opcodes)) { 93 if (IS_ALIGNED((uintptr_t)in | (uintptr_t)out, 4)) { 94 aes_sparc64_encrypt(key, (const u32 *)in, (u32 *)out); 95 } else { 96 memcpy(bounce_buf, in, AES_BLOCK_SIZE); 97 aes_sparc64_encrypt(key, bounce_buf, bounce_buf); 98 memcpy(out, bounce_buf, AES_BLOCK_SIZE); 99 } 100 } else { 101 aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in); 102 } 103} 104 105static void aes_sparc64_decrypt(const struct aes_key *key, 106 const u32 *input, u32 *output) 107{ 108 if (key->len == AES_KEYSIZE_128) 109 aes_sparc64_decrypt_128(key->k.sparc_rndkeys, input, output); 110 else if (key->len == AES_KEYSIZE_192) 111 aes_sparc64_decrypt_192(key->k.sparc_rndkeys, input, output); 112 else 113 aes_sparc64_decrypt_256(key->k.sparc_rndkeys, input, output); 114} 115 116static void aes_decrypt_arch(const struct aes_key *key, 117 u8 out[AES_BLOCK_SIZE], 118 const u8 in[AES_BLOCK_SIZE]) 119{ 120 u32 bounce_buf[AES_BLOCK_SIZE / 4]; 121 122 if (static_branch_likely(&have_aes_opcodes)) { 123 if (IS_ALIGNED((uintptr_t)in | (uintptr_t)out, 4)) { 124 aes_sparc64_decrypt(key, (const u32 *)in, (u32 *)out); 125 } else { 126 memcpy(bounce_buf, in, AES_BLOCK_SIZE); 127 aes_sparc64_decrypt(key, bounce_buf, bounce_buf); 128 memcpy(out, bounce_buf, AES_BLOCK_SIZE); 129 } 130 } else { 131 aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds, 132 out, in); 133 } 134} 135 136#define aes_mod_init_arch aes_mod_init_arch 137static void aes_mod_init_arch(void) 138{ 139 unsigned long cfr; 140 141 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 142 return; 143 144 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 145 if (!(cfr & CFR_AES)) 146 return; 147 148 static_branch_enable(&have_aes_opcodes); 149}