diff options
Diffstat (limited to 'drivers/crypto/padlock-aes.c')
-rw-r--r-- | drivers/crypto/padlock-aes.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 54a2a166e566..bf2917d197a0 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <asm/byteorder.h> | 18 | #include <asm/byteorder.h> |
19 | #include <asm/i387.h> | ||
19 | #include "padlock.h" | 20 | #include "padlock.h" |
20 | 21 | ||
21 | /* Control word. */ | 22 | /* Control word. */ |
@@ -141,6 +142,12 @@ static inline void padlock_reset_key(void) | |||
141 | asm volatile ("pushfl; popfl"); | 142 | asm volatile ("pushfl; popfl"); |
142 | } | 143 | } |
143 | 144 | ||
145 | /* | ||
146 | * While the padlock instructions don't use FP/SSE registers, they | ||
147 | * generate a spurious DNA fault when cr0.ts is '1'. These instructions | ||
148 | * should be used only inside the irq_ts_save/restore() context | ||
149 | */ | ||
150 | |||
144 | static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, | 151 | static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, |
145 | void *control_word) | 152 | void *control_word) |
146 | { | 153 | { |
@@ -205,15 +212,23 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, | |||
205 | static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 212 | static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
206 | { | 213 | { |
207 | struct aes_ctx *ctx = aes_ctx(tfm); | 214 | struct aes_ctx *ctx = aes_ctx(tfm); |
215 | int ts_state; | ||
208 | padlock_reset_key(); | 216 | padlock_reset_key(); |
217 | |||
218 | ts_state = irq_ts_save(); | ||
209 | aes_crypt(in, out, ctx->E, &ctx->cword.encrypt); | 219 | aes_crypt(in, out, ctx->E, &ctx->cword.encrypt); |
220 | irq_ts_restore(ts_state); | ||
210 | } | 221 | } |
211 | 222 | ||
212 | static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 223 | static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
213 | { | 224 | { |
214 | struct aes_ctx *ctx = aes_ctx(tfm); | 225 | struct aes_ctx *ctx = aes_ctx(tfm); |
226 | int ts_state; | ||
215 | padlock_reset_key(); | 227 | padlock_reset_key(); |
228 | |||
229 | ts_state = irq_ts_save(); | ||
216 | aes_crypt(in, out, ctx->D, &ctx->cword.decrypt); | 230 | aes_crypt(in, out, ctx->D, &ctx->cword.decrypt); |
231 | irq_ts_restore(ts_state); | ||
217 | } | 232 | } |
218 | 233 | ||
219 | static struct crypto_alg aes_alg = { | 234 | static struct crypto_alg aes_alg = { |
@@ -244,12 +259,14 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc, | |||
244 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); | 259 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); |
245 | struct blkcipher_walk walk; | 260 | struct blkcipher_walk walk; |
246 | int err; | 261 | int err; |
262 | int ts_state; | ||
247 | 263 | ||
248 | padlock_reset_key(); | 264 | padlock_reset_key(); |
249 | 265 | ||
250 | blkcipher_walk_init(&walk, dst, src, nbytes); | 266 | blkcipher_walk_init(&walk, dst, src, nbytes); |
251 | err = blkcipher_walk_virt(desc, &walk); | 267 | err = blkcipher_walk_virt(desc, &walk); |
252 | 268 | ||
269 | ts_state = irq_ts_save(); | ||
253 | while ((nbytes = walk.nbytes)) { | 270 | while ((nbytes = walk.nbytes)) { |
254 | padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, | 271 | padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, |
255 | ctx->E, &ctx->cword.encrypt, | 272 | ctx->E, &ctx->cword.encrypt, |
@@ -257,6 +274,7 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc, | |||
257 | nbytes &= AES_BLOCK_SIZE - 1; | 274 | nbytes &= AES_BLOCK_SIZE - 1; |
258 | err = blkcipher_walk_done(desc, &walk, nbytes); | 275 | err = blkcipher_walk_done(desc, &walk, nbytes); |
259 | } | 276 | } |
277 | irq_ts_restore(ts_state); | ||
260 | 278 | ||
261 | return err; | 279 | return err; |
262 | } | 280 | } |
@@ -268,12 +286,14 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc, | |||
268 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); | 286 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); |
269 | struct blkcipher_walk walk; | 287 | struct blkcipher_walk walk; |
270 | int err; | 288 | int err; |
289 | int ts_state; | ||
271 | 290 | ||
272 | padlock_reset_key(); | 291 | padlock_reset_key(); |
273 | 292 | ||
274 | blkcipher_walk_init(&walk, dst, src, nbytes); | 293 | blkcipher_walk_init(&walk, dst, src, nbytes); |
275 | err = blkcipher_walk_virt(desc, &walk); | 294 | err = blkcipher_walk_virt(desc, &walk); |
276 | 295 | ||
296 | ts_state = irq_ts_save(); | ||
277 | while ((nbytes = walk.nbytes)) { | 297 | while ((nbytes = walk.nbytes)) { |
278 | padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, | 298 | padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, |
279 | ctx->D, &ctx->cword.decrypt, | 299 | ctx->D, &ctx->cword.decrypt, |
@@ -281,7 +301,7 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc, | |||
281 | nbytes &= AES_BLOCK_SIZE - 1; | 301 | nbytes &= AES_BLOCK_SIZE - 1; |
282 | err = blkcipher_walk_done(desc, &walk, nbytes); | 302 | err = blkcipher_walk_done(desc, &walk, nbytes); |
283 | } | 303 | } |
284 | 304 | irq_ts_restore(ts_state); | |
285 | return err; | 305 | return err; |
286 | } | 306 | } |
287 | 307 | ||
@@ -314,12 +334,14 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, | |||
314 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); | 334 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); |
315 | struct blkcipher_walk walk; | 335 | struct blkcipher_walk walk; |
316 | int err; | 336 | int err; |
337 | int ts_state; | ||
317 | 338 | ||
318 | padlock_reset_key(); | 339 | padlock_reset_key(); |
319 | 340 | ||
320 | blkcipher_walk_init(&walk, dst, src, nbytes); | 341 | blkcipher_walk_init(&walk, dst, src, nbytes); |
321 | err = blkcipher_walk_virt(desc, &walk); | 342 | err = blkcipher_walk_virt(desc, &walk); |
322 | 343 | ||
344 | ts_state = irq_ts_save(); | ||
323 | while ((nbytes = walk.nbytes)) { | 345 | while ((nbytes = walk.nbytes)) { |
324 | u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr, | 346 | u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr, |
325 | walk.dst.virt.addr, ctx->E, | 347 | walk.dst.virt.addr, ctx->E, |
@@ -329,6 +351,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, | |||
329 | nbytes &= AES_BLOCK_SIZE - 1; | 351 | nbytes &= AES_BLOCK_SIZE - 1; |
330 | err = blkcipher_walk_done(desc, &walk, nbytes); | 352 | err = blkcipher_walk_done(desc, &walk, nbytes); |
331 | } | 353 | } |
354 | irq_ts_restore(ts_state); | ||
332 | 355 | ||
333 | return err; | 356 | return err; |
334 | } | 357 | } |
@@ -340,12 +363,14 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, | |||
340 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); | 363 | struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); |
341 | struct blkcipher_walk walk; | 364 | struct blkcipher_walk walk; |
342 | int err; | 365 | int err; |
366 | int ts_state; | ||
343 | 367 | ||
344 | padlock_reset_key(); | 368 | padlock_reset_key(); |
345 | 369 | ||
346 | blkcipher_walk_init(&walk, dst, src, nbytes); | 370 | blkcipher_walk_init(&walk, dst, src, nbytes); |
347 | err = blkcipher_walk_virt(desc, &walk); | 371 | err = blkcipher_walk_virt(desc, &walk); |
348 | 372 | ||
373 | ts_state = irq_ts_save(); | ||
349 | while ((nbytes = walk.nbytes)) { | 374 | while ((nbytes = walk.nbytes)) { |
350 | padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr, | 375 | padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr, |
351 | ctx->D, walk.iv, &ctx->cword.decrypt, | 376 | ctx->D, walk.iv, &ctx->cword.decrypt, |
@@ -354,6 +379,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, | |||
354 | err = blkcipher_walk_done(desc, &walk, nbytes); | 379 | err = blkcipher_walk_done(desc, &walk, nbytes); |
355 | } | 380 | } |
356 | 381 | ||
382 | irq_ts_restore(ts_state); | ||
357 | return err; | 383 | return err; |
358 | } | 384 | } |
359 | 385 | ||