1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Cryptographic API.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Support for VIA PadLock hardware crypto engine.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2004 Michal Ludvig <michal@logix.cz>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <crypto/algapi.h>
12*4882a593Smuzhiyun #include <crypto/aes.h>
13*4882a593Smuzhiyun #include <crypto/internal/skcipher.h>
14*4882a593Smuzhiyun #include <crypto/padlock.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/errno.h>
19*4882a593Smuzhiyun #include <linux/interrupt.h>
20*4882a593Smuzhiyun #include <linux/kernel.h>
21*4882a593Smuzhiyun #include <linux/mm.h>
22*4882a593Smuzhiyun #include <linux/percpu.h>
23*4882a593Smuzhiyun #include <linux/smp.h>
24*4882a593Smuzhiyun #include <linux/slab.h>
25*4882a593Smuzhiyun #include <asm/cpu_device_id.h>
26*4882a593Smuzhiyun #include <asm/byteorder.h>
27*4882a593Smuzhiyun #include <asm/processor.h>
28*4882a593Smuzhiyun #include <asm/fpu/api.h>
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /*
31*4882a593Smuzhiyun * Number of data blocks actually fetched for each xcrypt insn.
32*4882a593Smuzhiyun * Processors with prefetch errata will fetch extra blocks.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun static unsigned int ecb_fetch_blocks = 2;
35*4882a593Smuzhiyun #define MAX_ECB_FETCH_BLOCKS (8)
36*4882a593Smuzhiyun #define ecb_fetch_bytes (ecb_fetch_blocks * AES_BLOCK_SIZE)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun static unsigned int cbc_fetch_blocks = 1;
39*4882a593Smuzhiyun #define MAX_CBC_FETCH_BLOCKS (4)
40*4882a593Smuzhiyun #define cbc_fetch_bytes (cbc_fetch_blocks * AES_BLOCK_SIZE)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* Control word. */
43*4882a593Smuzhiyun struct cword {
44*4882a593Smuzhiyun unsigned int __attribute__ ((__packed__))
45*4882a593Smuzhiyun rounds:4,
46*4882a593Smuzhiyun algo:3,
47*4882a593Smuzhiyun keygen:1,
48*4882a593Smuzhiyun interm:1,
49*4882a593Smuzhiyun encdec:1,
50*4882a593Smuzhiyun ksize:2;
51*4882a593Smuzhiyun } __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* Whenever making any changes to the following
54*4882a593Smuzhiyun * structure *make sure* you keep E, d_data
55*4882a593Smuzhiyun * and cword aligned on 16 Bytes boundaries and
56*4882a593Smuzhiyun * the Hardware can access 16 * 16 bytes of E and d_data
57*4882a593Smuzhiyun * (only the first 15 * 16 bytes matter but the HW reads
58*4882a593Smuzhiyun * more).
59*4882a593Smuzhiyun */
60*4882a593Smuzhiyun struct aes_ctx {
61*4882a593Smuzhiyun u32 E[AES_MAX_KEYLENGTH_U32]
62*4882a593Smuzhiyun __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
63*4882a593Smuzhiyun u32 d_data[AES_MAX_KEYLENGTH_U32]
64*4882a593Smuzhiyun __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
65*4882a593Smuzhiyun struct {
66*4882a593Smuzhiyun struct cword encrypt;
67*4882a593Smuzhiyun struct cword decrypt;
68*4882a593Smuzhiyun } cword;
69*4882a593Smuzhiyun u32 *D;
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun static DEFINE_PER_CPU(struct cword *, paes_last_cword);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* Tells whether the ACE is capable to generate
75*4882a593Smuzhiyun the extended key for a given key_len. */
76*4882a593Smuzhiyun static inline int
aes_hw_extkey_available(uint8_t key_len)77*4882a593Smuzhiyun aes_hw_extkey_available(uint8_t key_len)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun /* TODO: We should check the actual CPU model/stepping
80*4882a593Smuzhiyun as it's possible that the capability will be
81*4882a593Smuzhiyun added in the next CPU revisions. */
82*4882a593Smuzhiyun if (key_len == 16)
83*4882a593Smuzhiyun return 1;
84*4882a593Smuzhiyun return 0;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
aes_ctx_common(void * ctx)87*4882a593Smuzhiyun static inline struct aes_ctx *aes_ctx_common(void *ctx)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun unsigned long addr = (unsigned long)ctx;
90*4882a593Smuzhiyun unsigned long align = PADLOCK_ALIGNMENT;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (align <= crypto_tfm_ctx_alignment())
93*4882a593Smuzhiyun align = 1;
94*4882a593Smuzhiyun return (struct aes_ctx *)ALIGN(addr, align);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
aes_ctx(struct crypto_tfm * tfm)97*4882a593Smuzhiyun static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun return aes_ctx_common(crypto_tfm_ctx(tfm));
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
skcipher_aes_ctx(struct crypto_skcipher * tfm)102*4882a593Smuzhiyun static inline struct aes_ctx *skcipher_aes_ctx(struct crypto_skcipher *tfm)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun return aes_ctx_common(crypto_skcipher_ctx(tfm));
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
aes_set_key(struct crypto_tfm * tfm,const u8 * in_key,unsigned int key_len)107*4882a593Smuzhiyun static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
108*4882a593Smuzhiyun unsigned int key_len)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct aes_ctx *ctx = aes_ctx(tfm);
111*4882a593Smuzhiyun const __le32 *key = (const __le32 *)in_key;
112*4882a593Smuzhiyun struct crypto_aes_ctx gen_aes;
113*4882a593Smuzhiyun int cpu;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (key_len % 8)
116*4882a593Smuzhiyun return -EINVAL;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun * If the hardware is capable of generating the extended key
120*4882a593Smuzhiyun * itself we must supply the plain key for both encryption
121*4882a593Smuzhiyun * and decryption.
122*4882a593Smuzhiyun */
123*4882a593Smuzhiyun ctx->D = ctx->E;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun ctx->E[0] = le32_to_cpu(key[0]);
126*4882a593Smuzhiyun ctx->E[1] = le32_to_cpu(key[1]);
127*4882a593Smuzhiyun ctx->E[2] = le32_to_cpu(key[2]);
128*4882a593Smuzhiyun ctx->E[3] = le32_to_cpu(key[3]);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* Prepare control words. */
131*4882a593Smuzhiyun memset(&ctx->cword, 0, sizeof(ctx->cword));
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun ctx->cword.decrypt.encdec = 1;
134*4882a593Smuzhiyun ctx->cword.encrypt.rounds = 10 + (key_len - 16) / 4;
135*4882a593Smuzhiyun ctx->cword.decrypt.rounds = ctx->cword.encrypt.rounds;
136*4882a593Smuzhiyun ctx->cword.encrypt.ksize = (key_len - 16) / 8;
137*4882a593Smuzhiyun ctx->cword.decrypt.ksize = ctx->cword.encrypt.ksize;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Don't generate extended keys if the hardware can do it. */
140*4882a593Smuzhiyun if (aes_hw_extkey_available(key_len))
141*4882a593Smuzhiyun goto ok;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun ctx->D = ctx->d_data;
144*4882a593Smuzhiyun ctx->cword.encrypt.keygen = 1;
145*4882a593Smuzhiyun ctx->cword.decrypt.keygen = 1;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (aes_expandkey(&gen_aes, in_key, key_len))
148*4882a593Smuzhiyun return -EINVAL;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH);
151*4882a593Smuzhiyun memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun ok:
154*4882a593Smuzhiyun for_each_online_cpu(cpu)
155*4882a593Smuzhiyun if (&ctx->cword.encrypt == per_cpu(paes_last_cword, cpu) ||
156*4882a593Smuzhiyun &ctx->cword.decrypt == per_cpu(paes_last_cword, cpu))
157*4882a593Smuzhiyun per_cpu(paes_last_cword, cpu) = NULL;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
aes_set_key_skcipher(struct crypto_skcipher * tfm,const u8 * in_key,unsigned int key_len)162*4882a593Smuzhiyun static int aes_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key,
163*4882a593Smuzhiyun unsigned int key_len)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun return aes_set_key(crypto_skcipher_tfm(tfm), in_key, key_len);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* ====== Encryption/decryption routines ====== */
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /* These are the real call to PadLock. */
padlock_reset_key(struct cword * cword)171*4882a593Smuzhiyun static inline void padlock_reset_key(struct cword *cword)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun int cpu = raw_smp_processor_id();
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (cword != per_cpu(paes_last_cword, cpu))
176*4882a593Smuzhiyun #ifndef CONFIG_X86_64
177*4882a593Smuzhiyun asm volatile ("pushfl; popfl");
178*4882a593Smuzhiyun #else
179*4882a593Smuzhiyun asm volatile ("pushfq; popfq");
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
padlock_store_cword(struct cword * cword)183*4882a593Smuzhiyun static inline void padlock_store_cword(struct cword *cword)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun per_cpu(paes_last_cword, raw_smp_processor_id()) = cword;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /*
189*4882a593Smuzhiyun * While the padlock instructions don't use FP/SSE registers, they
190*4882a593Smuzhiyun * generate a spurious DNA fault when CR0.TS is '1'. Fortunately,
191*4882a593Smuzhiyun * the kernel doesn't use CR0.TS.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun
rep_xcrypt_ecb(const u8 * input,u8 * output,void * key,struct cword * control_word,int count)194*4882a593Smuzhiyun static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key,
195*4882a593Smuzhiyun struct cword *control_word, int count)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
198*4882a593Smuzhiyun : "+S"(input), "+D"(output)
199*4882a593Smuzhiyun : "d"(control_word), "b"(key), "c"(count));
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
rep_xcrypt_cbc(const u8 * input,u8 * output,void * key,u8 * iv,struct cword * control_word,int count)202*4882a593Smuzhiyun static inline u8 *rep_xcrypt_cbc(const u8 *input, u8 *output, void *key,
203*4882a593Smuzhiyun u8 *iv, struct cword *control_word, int count)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */
206*4882a593Smuzhiyun : "+S" (input), "+D" (output), "+a" (iv)
207*4882a593Smuzhiyun : "d" (control_word), "b" (key), "c" (count));
208*4882a593Smuzhiyun return iv;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
ecb_crypt_copy(const u8 * in,u8 * out,u32 * key,struct cword * cword,int count)211*4882a593Smuzhiyun static void ecb_crypt_copy(const u8 *in, u8 *out, u32 *key,
212*4882a593Smuzhiyun struct cword *cword, int count)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun /*
215*4882a593Smuzhiyun * Padlock prefetches extra data so we must provide mapped input buffers.
216*4882a593Smuzhiyun * Assume there are at least 16 bytes of stack already in use.
217*4882a593Smuzhiyun */
218*4882a593Smuzhiyun u8 buf[AES_BLOCK_SIZE * (MAX_ECB_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1];
219*4882a593Smuzhiyun u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun memcpy(tmp, in, count * AES_BLOCK_SIZE);
222*4882a593Smuzhiyun rep_xcrypt_ecb(tmp, out, key, cword, count);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
cbc_crypt_copy(const u8 * in,u8 * out,u32 * key,u8 * iv,struct cword * cword,int count)225*4882a593Smuzhiyun static u8 *cbc_crypt_copy(const u8 *in, u8 *out, u32 *key,
226*4882a593Smuzhiyun u8 *iv, struct cword *cword, int count)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun /*
229*4882a593Smuzhiyun * Padlock prefetches extra data so we must provide mapped input buffers.
230*4882a593Smuzhiyun * Assume there are at least 16 bytes of stack already in use.
231*4882a593Smuzhiyun */
232*4882a593Smuzhiyun u8 buf[AES_BLOCK_SIZE * (MAX_CBC_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1];
233*4882a593Smuzhiyun u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun memcpy(tmp, in, count * AES_BLOCK_SIZE);
236*4882a593Smuzhiyun return rep_xcrypt_cbc(tmp, out, key, iv, cword, count);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
ecb_crypt(const u8 * in,u8 * out,u32 * key,struct cword * cword,int count)239*4882a593Smuzhiyun static inline void ecb_crypt(const u8 *in, u8 *out, u32 *key,
240*4882a593Smuzhiyun struct cword *cword, int count)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun /* Padlock in ECB mode fetches at least ecb_fetch_bytes of data.
243*4882a593Smuzhiyun * We could avoid some copying here but it's probably not worth it.
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun if (unlikely(offset_in_page(in) + ecb_fetch_bytes > PAGE_SIZE)) {
246*4882a593Smuzhiyun ecb_crypt_copy(in, out, key, cword, count);
247*4882a593Smuzhiyun return;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun rep_xcrypt_ecb(in, out, key, cword, count);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
cbc_crypt(const u8 * in,u8 * out,u32 * key,u8 * iv,struct cword * cword,int count)253*4882a593Smuzhiyun static inline u8 *cbc_crypt(const u8 *in, u8 *out, u32 *key,
254*4882a593Smuzhiyun u8 *iv, struct cword *cword, int count)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun /* Padlock in CBC mode fetches at least cbc_fetch_bytes of data. */
257*4882a593Smuzhiyun if (unlikely(offset_in_page(in) + cbc_fetch_bytes > PAGE_SIZE))
258*4882a593Smuzhiyun return cbc_crypt_copy(in, out, key, iv, cword, count);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun return rep_xcrypt_cbc(in, out, key, iv, cword, count);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
padlock_xcrypt_ecb(const u8 * input,u8 * output,void * key,void * control_word,u32 count)263*4882a593Smuzhiyun static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
264*4882a593Smuzhiyun void *control_word, u32 count)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun u32 initial = count & (ecb_fetch_blocks - 1);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (count < ecb_fetch_blocks) {
269*4882a593Smuzhiyun ecb_crypt(input, output, key, control_word, count);
270*4882a593Smuzhiyun return;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun count -= initial;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (initial)
276*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
277*4882a593Smuzhiyun : "+S"(input), "+D"(output)
278*4882a593Smuzhiyun : "d"(control_word), "b"(key), "c"(initial));
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
281*4882a593Smuzhiyun : "+S"(input), "+D"(output)
282*4882a593Smuzhiyun : "d"(control_word), "b"(key), "c"(count));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
padlock_xcrypt_cbc(const u8 * input,u8 * output,void * key,u8 * iv,void * control_word,u32 count)285*4882a593Smuzhiyun static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
286*4882a593Smuzhiyun u8 *iv, void *control_word, u32 count)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun u32 initial = count & (cbc_fetch_blocks - 1);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (count < cbc_fetch_blocks)
291*4882a593Smuzhiyun return cbc_crypt(input, output, key, iv, control_word, count);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun count -= initial;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun if (initial)
296*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */
297*4882a593Smuzhiyun : "+S" (input), "+D" (output), "+a" (iv)
298*4882a593Smuzhiyun : "d" (control_word), "b" (key), "c" (initial));
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */
301*4882a593Smuzhiyun : "+S" (input), "+D" (output), "+a" (iv)
302*4882a593Smuzhiyun : "d" (control_word), "b" (key), "c" (count));
303*4882a593Smuzhiyun return iv;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
padlock_aes_encrypt(struct crypto_tfm * tfm,u8 * out,const u8 * in)306*4882a593Smuzhiyun static void padlock_aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun struct aes_ctx *ctx = aes_ctx(tfm);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.encrypt);
311*4882a593Smuzhiyun ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1);
312*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.encrypt);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
padlock_aes_decrypt(struct crypto_tfm * tfm,u8 * out,const u8 * in)315*4882a593Smuzhiyun static void padlock_aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct aes_ctx *ctx = aes_ctx(tfm);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.encrypt);
320*4882a593Smuzhiyun ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1);
321*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.encrypt);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun static struct crypto_alg aes_alg = {
325*4882a593Smuzhiyun .cra_name = "aes",
326*4882a593Smuzhiyun .cra_driver_name = "aes-padlock",
327*4882a593Smuzhiyun .cra_priority = PADLOCK_CRA_PRIORITY,
328*4882a593Smuzhiyun .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
329*4882a593Smuzhiyun .cra_blocksize = AES_BLOCK_SIZE,
330*4882a593Smuzhiyun .cra_ctxsize = sizeof(struct aes_ctx),
331*4882a593Smuzhiyun .cra_alignmask = PADLOCK_ALIGNMENT - 1,
332*4882a593Smuzhiyun .cra_module = THIS_MODULE,
333*4882a593Smuzhiyun .cra_u = {
334*4882a593Smuzhiyun .cipher = {
335*4882a593Smuzhiyun .cia_min_keysize = AES_MIN_KEY_SIZE,
336*4882a593Smuzhiyun .cia_max_keysize = AES_MAX_KEY_SIZE,
337*4882a593Smuzhiyun .cia_setkey = aes_set_key,
338*4882a593Smuzhiyun .cia_encrypt = padlock_aes_encrypt,
339*4882a593Smuzhiyun .cia_decrypt = padlock_aes_decrypt,
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun };
343*4882a593Smuzhiyun
ecb_aes_encrypt(struct skcipher_request * req)344*4882a593Smuzhiyun static int ecb_aes_encrypt(struct skcipher_request *req)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
347*4882a593Smuzhiyun struct aes_ctx *ctx = skcipher_aes_ctx(tfm);
348*4882a593Smuzhiyun struct skcipher_walk walk;
349*4882a593Smuzhiyun unsigned int nbytes;
350*4882a593Smuzhiyun int err;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.encrypt);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun err = skcipher_walk_virt(&walk, req, false);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun while ((nbytes = walk.nbytes) != 0) {
357*4882a593Smuzhiyun padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
358*4882a593Smuzhiyun ctx->E, &ctx->cword.encrypt,
359*4882a593Smuzhiyun nbytes / AES_BLOCK_SIZE);
360*4882a593Smuzhiyun nbytes &= AES_BLOCK_SIZE - 1;
361*4882a593Smuzhiyun err = skcipher_walk_done(&walk, nbytes);
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.encrypt);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return err;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
ecb_aes_decrypt(struct skcipher_request * req)369*4882a593Smuzhiyun static int ecb_aes_decrypt(struct skcipher_request *req)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
372*4882a593Smuzhiyun struct aes_ctx *ctx = skcipher_aes_ctx(tfm);
373*4882a593Smuzhiyun struct skcipher_walk walk;
374*4882a593Smuzhiyun unsigned int nbytes;
375*4882a593Smuzhiyun int err;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.decrypt);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun err = skcipher_walk_virt(&walk, req, false);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun while ((nbytes = walk.nbytes) != 0) {
382*4882a593Smuzhiyun padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
383*4882a593Smuzhiyun ctx->D, &ctx->cword.decrypt,
384*4882a593Smuzhiyun nbytes / AES_BLOCK_SIZE);
385*4882a593Smuzhiyun nbytes &= AES_BLOCK_SIZE - 1;
386*4882a593Smuzhiyun err = skcipher_walk_done(&walk, nbytes);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.encrypt);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun return err;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun static struct skcipher_alg ecb_aes_alg = {
395*4882a593Smuzhiyun .base.cra_name = "ecb(aes)",
396*4882a593Smuzhiyun .base.cra_driver_name = "ecb-aes-padlock",
397*4882a593Smuzhiyun .base.cra_priority = PADLOCK_COMPOSITE_PRIORITY,
398*4882a593Smuzhiyun .base.cra_blocksize = AES_BLOCK_SIZE,
399*4882a593Smuzhiyun .base.cra_ctxsize = sizeof(struct aes_ctx),
400*4882a593Smuzhiyun .base.cra_alignmask = PADLOCK_ALIGNMENT - 1,
401*4882a593Smuzhiyun .base.cra_module = THIS_MODULE,
402*4882a593Smuzhiyun .min_keysize = AES_MIN_KEY_SIZE,
403*4882a593Smuzhiyun .max_keysize = AES_MAX_KEY_SIZE,
404*4882a593Smuzhiyun .setkey = aes_set_key_skcipher,
405*4882a593Smuzhiyun .encrypt = ecb_aes_encrypt,
406*4882a593Smuzhiyun .decrypt = ecb_aes_decrypt,
407*4882a593Smuzhiyun };
408*4882a593Smuzhiyun
cbc_aes_encrypt(struct skcipher_request * req)409*4882a593Smuzhiyun static int cbc_aes_encrypt(struct skcipher_request *req)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
412*4882a593Smuzhiyun struct aes_ctx *ctx = skcipher_aes_ctx(tfm);
413*4882a593Smuzhiyun struct skcipher_walk walk;
414*4882a593Smuzhiyun unsigned int nbytes;
415*4882a593Smuzhiyun int err;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.encrypt);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun err = skcipher_walk_virt(&walk, req, false);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun while ((nbytes = walk.nbytes) != 0) {
422*4882a593Smuzhiyun u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr,
423*4882a593Smuzhiyun walk.dst.virt.addr, ctx->E,
424*4882a593Smuzhiyun walk.iv, &ctx->cword.encrypt,
425*4882a593Smuzhiyun nbytes / AES_BLOCK_SIZE);
426*4882a593Smuzhiyun memcpy(walk.iv, iv, AES_BLOCK_SIZE);
427*4882a593Smuzhiyun nbytes &= AES_BLOCK_SIZE - 1;
428*4882a593Smuzhiyun err = skcipher_walk_done(&walk, nbytes);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.decrypt);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun return err;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
cbc_aes_decrypt(struct skcipher_request * req)436*4882a593Smuzhiyun static int cbc_aes_decrypt(struct skcipher_request *req)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
439*4882a593Smuzhiyun struct aes_ctx *ctx = skcipher_aes_ctx(tfm);
440*4882a593Smuzhiyun struct skcipher_walk walk;
441*4882a593Smuzhiyun unsigned int nbytes;
442*4882a593Smuzhiyun int err;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun padlock_reset_key(&ctx->cword.encrypt);
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun err = skcipher_walk_virt(&walk, req, false);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun while ((nbytes = walk.nbytes) != 0) {
449*4882a593Smuzhiyun padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr,
450*4882a593Smuzhiyun ctx->D, walk.iv, &ctx->cword.decrypt,
451*4882a593Smuzhiyun nbytes / AES_BLOCK_SIZE);
452*4882a593Smuzhiyun nbytes &= AES_BLOCK_SIZE - 1;
453*4882a593Smuzhiyun err = skcipher_walk_done(&walk, nbytes);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun padlock_store_cword(&ctx->cword.encrypt);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun return err;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun static struct skcipher_alg cbc_aes_alg = {
462*4882a593Smuzhiyun .base.cra_name = "cbc(aes)",
463*4882a593Smuzhiyun .base.cra_driver_name = "cbc-aes-padlock",
464*4882a593Smuzhiyun .base.cra_priority = PADLOCK_COMPOSITE_PRIORITY,
465*4882a593Smuzhiyun .base.cra_blocksize = AES_BLOCK_SIZE,
466*4882a593Smuzhiyun .base.cra_ctxsize = sizeof(struct aes_ctx),
467*4882a593Smuzhiyun .base.cra_alignmask = PADLOCK_ALIGNMENT - 1,
468*4882a593Smuzhiyun .base.cra_module = THIS_MODULE,
469*4882a593Smuzhiyun .min_keysize = AES_MIN_KEY_SIZE,
470*4882a593Smuzhiyun .max_keysize = AES_MAX_KEY_SIZE,
471*4882a593Smuzhiyun .ivsize = AES_BLOCK_SIZE,
472*4882a593Smuzhiyun .setkey = aes_set_key_skcipher,
473*4882a593Smuzhiyun .encrypt = cbc_aes_encrypt,
474*4882a593Smuzhiyun .decrypt = cbc_aes_decrypt,
475*4882a593Smuzhiyun };
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun static const struct x86_cpu_id padlock_cpu_id[] = {
478*4882a593Smuzhiyun X86_MATCH_FEATURE(X86_FEATURE_XCRYPT, NULL),
479*4882a593Smuzhiyun {}
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id);
482*4882a593Smuzhiyun
padlock_init(void)483*4882a593Smuzhiyun static int __init padlock_init(void)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun int ret;
486*4882a593Smuzhiyun struct cpuinfo_x86 *c = &cpu_data(0);
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (!x86_match_cpu(padlock_cpu_id))
489*4882a593Smuzhiyun return -ENODEV;
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (!boot_cpu_has(X86_FEATURE_XCRYPT_EN)) {
492*4882a593Smuzhiyun printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
493*4882a593Smuzhiyun return -ENODEV;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun if ((ret = crypto_register_alg(&aes_alg)) != 0)
497*4882a593Smuzhiyun goto aes_err;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun if ((ret = crypto_register_skcipher(&ecb_aes_alg)) != 0)
500*4882a593Smuzhiyun goto ecb_aes_err;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun if ((ret = crypto_register_skcipher(&cbc_aes_alg)) != 0)
503*4882a593Smuzhiyun goto cbc_aes_err;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n");
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun if (c->x86 == 6 && c->x86_model == 15 && c->x86_stepping == 2) {
508*4882a593Smuzhiyun ecb_fetch_blocks = MAX_ECB_FETCH_BLOCKS;
509*4882a593Smuzhiyun cbc_fetch_blocks = MAX_CBC_FETCH_BLOCKS;
510*4882a593Smuzhiyun printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n");
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun out:
514*4882a593Smuzhiyun return ret;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun cbc_aes_err:
517*4882a593Smuzhiyun crypto_unregister_skcipher(&ecb_aes_alg);
518*4882a593Smuzhiyun ecb_aes_err:
519*4882a593Smuzhiyun crypto_unregister_alg(&aes_alg);
520*4882a593Smuzhiyun aes_err:
521*4882a593Smuzhiyun printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n");
522*4882a593Smuzhiyun goto out;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
padlock_fini(void)525*4882a593Smuzhiyun static void __exit padlock_fini(void)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun crypto_unregister_skcipher(&cbc_aes_alg);
528*4882a593Smuzhiyun crypto_unregister_skcipher(&ecb_aes_alg);
529*4882a593Smuzhiyun crypto_unregister_alg(&aes_alg);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun module_init(padlock_init);
533*4882a593Smuzhiyun module_exit(padlock_fini);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun MODULE_DESCRIPTION("VIA PadLock AES algorithm support");
536*4882a593Smuzhiyun MODULE_LICENSE("GPL");
537*4882a593Smuzhiyun MODULE_AUTHOR("Michal Ludvig");
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun MODULE_ALIAS_CRYPTO("aes");
540