18
18
#include <linux/percpu.h>
19
19
#include <linux/smp.h>
20
20
#include <asm/byteorder.h>
21
+ #include <asm/processor.h>
21
22
#include <asm/i387.h>
22
23
#include "padlock.h"
23
24
25
+ /* number of data blocks actually fetched for each xcrypt insn */
26
+ static unsigned int ecb_fetch_blocks = 2 ;
27
+ static unsigned int cbc_fetch_blocks = 1 ;
28
+
29
+ #define ecb_fetch_bytes (ecb_fetch_blocks * AES_BLOCK_SIZE)
30
+ #define cbc_fetch_bytes (cbc_fetch_blocks * AES_BLOCK_SIZE)
31
+
24
32
/* Control word. */
25
33
struct cword {
26
34
unsigned int __attribute__ ((__packed__ ))
@@ -173,63 +181,59 @@ static inline void padlock_store_cword(struct cword *cword)
173
181
*/
174
182
175
183
static inline void padlock_xcrypt (const u8 * input , u8 * output , void * key ,
176
- struct cword * control_word )
184
+ struct cword * control_word , int count )
177
185
{
178
186
asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
179
187
: "+S" (input ), "+D" (output )
180
- : "d" (control_word ), "b" (key ), "c" (1 ));
188
+ : "d" (control_word ), "b" (key ), "c" (count ));
181
189
}
182
190
183
- static void aes_crypt_copy (const u8 * in , u8 * out , u32 * key , struct cword * cword )
191
+ static void aes_crypt_copy (const u8 * in , u8 * out , u32 * key ,
192
+ struct cword * cword , int count )
184
193
{
185
- u8 buf [AES_BLOCK_SIZE * 2 + PADLOCK_ALIGNMENT - 1 ];
194
+ /*
195
+ * Padlock prefetches extra data so we must provide mapped input buffers.
196
+ * Assume there are at least 16 bytes of stack already in use.
197
+ */
198
+ u8 buf [AES_BLOCK_SIZE * 7 + PADLOCK_ALIGNMENT - 1 ];
186
199
u8 * tmp = PTR_ALIGN (& buf [0 ], PADLOCK_ALIGNMENT );
187
200
188
- memcpy (tmp , in , AES_BLOCK_SIZE );
189
- padlock_xcrypt (tmp , out , key , cword );
201
+ memcpy (tmp , in , count * AES_BLOCK_SIZE );
202
+ padlock_xcrypt (tmp , out , key , cword , count );
190
203
}
191
204
192
205
static inline void aes_crypt (const u8 * in , u8 * out , u32 * key ,
193
- struct cword * cword )
206
+ struct cword * cword , int count )
194
207
{
195
- /* padlock_xcrypt requires at least two blocks of data. */
196
- if (unlikely (!(((unsigned long )in ^ (PAGE_SIZE - AES_BLOCK_SIZE )) &
197
- (PAGE_SIZE - 1 )))) {
198
- aes_crypt_copy (in , out , key , cword );
208
+ /* Padlock in ECB mode fetches at least ecb_fetch_bytes of data.
209
+ * We could avoid some copying here but it's probably not worth it.
210
+ */
211
+ if (unlikely (((unsigned long )in & PAGE_SIZE ) + ecb_fetch_bytes > PAGE_SIZE )) {
212
+ aes_crypt_copy (in , out , key , cword , count );
199
213
return ;
200
214
}
201
215
202
- padlock_xcrypt (in , out , key , cword );
216
+ padlock_xcrypt (in , out , key , cword , count );
203
217
}
204
218
205
219
static inline void padlock_xcrypt_ecb (const u8 * input , u8 * output , void * key ,
206
220
void * control_word , u32 count )
207
221
{
208
- if (count == 1 ) {
209
- aes_crypt (input , output , key , control_word );
222
+ u32 initial = count & (ecb_fetch_blocks - 1 );
223
+
224
+ if (count < ecb_fetch_blocks ) {
225
+ aes_crypt (input , output , key , control_word , count );
210
226
return ;
211
227
}
212
228
213
- asm volatile ("test $1, %%cl;"
214
- "je 1f;"
215
- #ifndef CONFIG_X86_64
216
- "lea -1(%%ecx), %%eax;"
217
- "mov $1, %%ecx;"
218
- #else
219
- "lea -1(%%rcx), %%rax;"
220
- "mov $1, %%rcx;"
221
- #endif
222
- ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */
223
- #ifndef CONFIG_X86_64
224
- "mov %%eax, %%ecx;"
225
- #else
226
- "mov %%rax, %%rcx;"
227
- #endif
228
- "1:"
229
- ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
229
+ if (initial )
230
+ asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
231
+ : "+S" (input ), "+D" (output )
232
+ : "d" (control_word ), "b" (key ), "c" (initial ));
233
+
234
+ asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
230
235
: "+S" (input ), "+D" (output )
231
- : "d" (control_word ), "b" (key ), "c" (count )
232
- : "ax" );
236
+ : "d" (control_word ), "b" (key ), "c" (count - initial ));
233
237
}
234
238
235
239
static inline u8 * padlock_xcrypt_cbc (const u8 * input , u8 * output , void * key ,
@@ -249,7 +253,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
249
253
250
254
padlock_reset_key (& ctx -> cword .encrypt );
251
255
ts_state = irq_ts_save ();
252
- aes_crypt (in , out , ctx -> E , & ctx -> cword .encrypt );
256
+ aes_crypt (in , out , ctx -> E , & ctx -> cword .encrypt , 1 );
253
257
irq_ts_restore (ts_state );
254
258
padlock_store_cword (& ctx -> cword .encrypt );
255
259
}
@@ -261,7 +265,7 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
261
265
262
266
padlock_reset_key (& ctx -> cword .encrypt );
263
267
ts_state = irq_ts_save ();
264
- aes_crypt (in , out , ctx -> D , & ctx -> cword .decrypt );
268
+ aes_crypt (in , out , ctx -> D , & ctx -> cword .decrypt , 1 );
265
269
irq_ts_restore (ts_state );
266
270
padlock_store_cword (& ctx -> cword .encrypt );
267
271
}
@@ -454,6 +458,7 @@ static struct crypto_alg cbc_aes_alg = {
454
458
static int __init padlock_init (void )
455
459
{
456
460
int ret ;
461
+ struct cpuinfo_x86 * c = & cpu_data (0 );
457
462
458
463
if (!cpu_has_xcrypt ) {
459
464
printk (KERN_NOTICE PFX "VIA PadLock not detected.\n" );
@@ -476,6 +481,12 @@ static int __init padlock_init(void)
476
481
477
482
printk (KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n" );
478
483
484
+ if (c -> x86 == 6 && c -> x86_model == 15 && c -> x86_mask == 2 ) {
485
+ ecb_fetch_blocks = 8 ;
486
+ cbc_fetch_blocks = 4 ; /* NOTE: notused */
487
+ printk (KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n" );
488
+ }
489
+
479
490
out :
480
491
return ret ;
481
492
0 commit comments