diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-06 20:04:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-06 20:04:06 -0400 |
commit | 359ea2f1352a77177540a213283bc7489f546ced (patch) | |
tree | 95a313a9d920e432bafcdf68a9c7fb0812aa389b /drivers | |
parent | 960b8466548c9bc6f718b5f470c1a58000fab09d (diff) | |
parent | e1d5dea1dfbfe484358c40db7f233ed6b5605646 (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/crypto/padlock-aes.c | 153 | ||||
-rw-r--r-- | drivers/crypto/padlock.h | 22 |
2 files changed, 105 insertions, 70 deletions
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index ed708b4427b0..71407c578afe 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/errno.h> | 49 | #include <linux/errno.h> |
50 | #include <linux/crypto.h> | 50 | #include <linux/crypto.h> |
51 | #include <linux/interrupt.h> | 51 | #include <linux/interrupt.h> |
52 | #include <linux/kernel.h> | ||
52 | #include <asm/byteorder.h> | 53 | #include <asm/byteorder.h> |
53 | #include "padlock.h" | 54 | #include "padlock.h" |
54 | 55 | ||
@@ -59,8 +60,12 @@ | |||
59 | #define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) | 60 | #define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) |
60 | 61 | ||
61 | struct aes_ctx { | 62 | struct aes_ctx { |
62 | uint32_t e_data[AES_EXTENDED_KEY_SIZE+4]; | 63 | uint32_t e_data[AES_EXTENDED_KEY_SIZE]; |
63 | uint32_t d_data[AES_EXTENDED_KEY_SIZE+4]; | 64 | uint32_t d_data[AES_EXTENDED_KEY_SIZE]; |
65 | struct { | ||
66 | struct cword encrypt; | ||
67 | struct cword decrypt; | ||
68 | } cword; | ||
64 | uint32_t *E; | 69 | uint32_t *E; |
65 | uint32_t *D; | 70 | uint32_t *D; |
66 | int key_length; | 71 | int key_length; |
@@ -280,10 +285,15 @@ aes_hw_extkey_available(uint8_t key_len) | |||
280 | return 0; | 285 | return 0; |
281 | } | 286 | } |
282 | 287 | ||
288 | static inline struct aes_ctx *aes_ctx(void *ctx) | ||
289 | { | ||
290 | return (struct aes_ctx *)ALIGN((unsigned long)ctx, PADLOCK_ALIGNMENT); | ||
291 | } | ||
292 | |||
283 | static int | 293 | static int |
284 | aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) | 294 | aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) |
285 | { | 295 | { |
286 | struct aes_ctx *ctx = ctx_arg; | 296 | struct aes_ctx *ctx = aes_ctx(ctx_arg); |
287 | uint32_t i, t, u, v, w; | 297 | uint32_t i, t, u, v, w; |
288 | uint32_t P[AES_EXTENDED_KEY_SIZE]; | 298 | uint32_t P[AES_EXTENDED_KEY_SIZE]; |
289 | uint32_t rounds; | 299 | uint32_t rounds; |
@@ -295,25 +305,36 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t | |||
295 | 305 | ||
296 | ctx->key_length = key_len; | 306 | ctx->key_length = key_len; |
297 | 307 | ||
308 | /* | ||
309 | * If the hardware is capable of generating the extended key | ||
310 | * itself we must supply the plain key for both encryption | ||
311 | * and decryption. | ||
312 | */ | ||
298 | ctx->E = ctx->e_data; | 313 | ctx->E = ctx->e_data; |
299 | ctx->D = ctx->d_data; | 314 | ctx->D = ctx->e_data; |
300 | |||
301 | /* Ensure 16-Bytes alignmentation of keys for VIA PadLock. */ | ||
302 | if ((int)(ctx->e_data) & 0x0F) | ||
303 | ctx->E += 4 - (((int)(ctx->e_data) & 0x0F) / sizeof (ctx->e_data[0])); | ||
304 | |||
305 | if ((int)(ctx->d_data) & 0x0F) | ||
306 | ctx->D += 4 - (((int)(ctx->d_data) & 0x0F) / sizeof (ctx->d_data[0])); | ||
307 | 315 | ||
308 | E_KEY[0] = uint32_t_in (in_key); | 316 | E_KEY[0] = uint32_t_in (in_key); |
309 | E_KEY[1] = uint32_t_in (in_key + 4); | 317 | E_KEY[1] = uint32_t_in (in_key + 4); |
310 | E_KEY[2] = uint32_t_in (in_key + 8); | 318 | E_KEY[2] = uint32_t_in (in_key + 8); |
311 | E_KEY[3] = uint32_t_in (in_key + 12); | 319 | E_KEY[3] = uint32_t_in (in_key + 12); |
312 | 320 | ||
321 | /* Prepare control words. */ | ||
322 | memset(&ctx->cword, 0, sizeof(ctx->cword)); | ||
323 | |||
324 | ctx->cword.decrypt.encdec = 1; | ||
325 | ctx->cword.encrypt.rounds = 10 + (key_len - 16) / 4; | ||
326 | ctx->cword.decrypt.rounds = ctx->cword.encrypt.rounds; | ||
327 | ctx->cword.encrypt.ksize = (key_len - 16) / 8; | ||
328 | ctx->cword.decrypt.ksize = ctx->cword.encrypt.ksize; | ||
329 | |||
313 | /* Don't generate extended keys if the hardware can do it. */ | 330 | /* Don't generate extended keys if the hardware can do it. */ |
314 | if (aes_hw_extkey_available(key_len)) | 331 | if (aes_hw_extkey_available(key_len)) |
315 | return 0; | 332 | return 0; |
316 | 333 | ||
334 | ctx->D = ctx->d_data; | ||
335 | ctx->cword.encrypt.keygen = 1; | ||
336 | ctx->cword.decrypt.keygen = 1; | ||
337 | |||
317 | switch (key_len) { | 338 | switch (key_len) { |
318 | case 16: | 339 | case 16: |
319 | t = E_KEY[3]; | 340 | t = E_KEY[3]; |
@@ -369,10 +390,9 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t | |||
369 | 390 | ||
370 | /* ====== Encryption/decryption routines ====== */ | 391 | /* ====== Encryption/decryption routines ====== */ |
371 | 392 | ||
372 | /* This is the real call to PadLock. */ | 393 | /* These are the real call to PadLock. */ |
373 | static inline void | 394 | static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, |
374 | padlock_xcrypt_ecb(uint8_t *input, uint8_t *output, uint8_t *key, | 395 | void *control_word, u32 count) |
375 | void *control_word, uint32_t count) | ||
376 | { | 396 | { |
377 | asm volatile ("pushfl; popfl"); /* enforce key reload. */ | 397 | asm volatile ("pushfl; popfl"); /* enforce key reload. */ |
378 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ | 398 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ |
@@ -380,60 +400,70 @@ padlock_xcrypt_ecb(uint8_t *input, uint8_t *output, uint8_t *key, | |||
380 | : "d"(control_word), "b"(key), "c"(count)); | 400 | : "d"(control_word), "b"(key), "c"(count)); |
381 | } | 401 | } |
382 | 402 | ||
383 | static void | 403 | static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, |
384 | aes_padlock(void *ctx_arg, uint8_t *out_arg, const uint8_t *in_arg, int encdec) | 404 | u8 *iv, void *control_word, u32 count) |
385 | { | 405 | { |
386 | /* Don't blindly modify this structure - the items must | 406 | /* Enforce key reload. */ |
387 | fit on 16-Bytes boundaries! */ | 407 | asm volatile ("pushfl; popfl"); |
388 | struct padlock_xcrypt_data { | 408 | /* rep xcryptcbc */ |
389 | uint8_t buf[AES_BLOCK_SIZE]; | 409 | asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" |
390 | union cword cword; | 410 | : "+S" (input), "+D" (output), "+a" (iv) |
391 | }; | 411 | : "d" (control_word), "b" (key), "c" (count)); |
392 | 412 | return iv; | |
393 | struct aes_ctx *ctx = ctx_arg; | ||
394 | char bigbuf[sizeof(struct padlock_xcrypt_data) + 16]; | ||
395 | struct padlock_xcrypt_data *data; | ||
396 | void *key; | ||
397 | |||
398 | /* Place 'data' at the first 16-Bytes aligned address in 'bigbuf'. */ | ||
399 | if (((long)bigbuf) & 0x0F) | ||
400 | data = (void*)(bigbuf + 16 - ((long)bigbuf & 0x0F)); | ||
401 | else | ||
402 | data = (void*)bigbuf; | ||
403 | |||
404 | /* Prepare Control word. */ | ||
405 | memset (data, 0, sizeof(struct padlock_xcrypt_data)); | ||
406 | data->cword.b.encdec = !encdec; /* in the rest of cryptoapi ENC=1/DEC=0 */ | ||
407 | data->cword.b.rounds = 10 + (ctx->key_length - 16) / 4; | ||
408 | data->cword.b.ksize = (ctx->key_length - 16) / 8; | ||
409 | |||
410 | /* Is the hardware capable to generate the extended key? */ | ||
411 | if (!aes_hw_extkey_available(ctx->key_length)) | ||
412 | data->cword.b.keygen = 1; | ||
413 | |||
414 | /* ctx->E starts with a plain key - if the hardware is capable | ||
415 | to generate the extended key itself we must supply | ||
416 | the plain key for both Encryption and Decryption. */ | ||
417 | if (encdec == CRYPTO_DIR_ENCRYPT || data->cword.b.keygen == 0) | ||
418 | key = ctx->E; | ||
419 | else | ||
420 | key = ctx->D; | ||
421 | |||
422 | memcpy(data->buf, in_arg, AES_BLOCK_SIZE); | ||
423 | padlock_xcrypt_ecb(data->buf, data->buf, key, &data->cword, 1); | ||
424 | memcpy(out_arg, data->buf, AES_BLOCK_SIZE); | ||
425 | } | 413 | } |
426 | 414 | ||
427 | static void | 415 | static void |
428 | aes_encrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) | 416 | aes_encrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) |
429 | { | 417 | { |
430 | aes_padlock(ctx_arg, out, in, CRYPTO_DIR_ENCRYPT); | 418 | struct aes_ctx *ctx = aes_ctx(ctx_arg); |
419 | padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1); | ||
431 | } | 420 | } |
432 | 421 | ||
433 | static void | 422 | static void |
434 | aes_decrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) | 423 | aes_decrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) |
435 | { | 424 | { |
436 | aes_padlock(ctx_arg, out, in, CRYPTO_DIR_DECRYPT); | 425 | struct aes_ctx *ctx = aes_ctx(ctx_arg); |
426 | padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); | ||
427 | } | ||
428 | |||
429 | static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, | ||
430 | const u8 *in, unsigned int nbytes) | ||
431 | { | ||
432 | struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); | ||
433 | padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, | ||
434 | nbytes / AES_BLOCK_SIZE); | ||
435 | return nbytes & ~(AES_BLOCK_SIZE - 1); | ||
436 | } | ||
437 | |||
438 | static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, | ||
439 | const u8 *in, unsigned int nbytes) | ||
440 | { | ||
441 | struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); | ||
442 | padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, | ||
443 | nbytes / AES_BLOCK_SIZE); | ||
444 | return nbytes & ~(AES_BLOCK_SIZE - 1); | ||
445 | } | ||
446 | |||
447 | static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, | ||
448 | const u8 *in, unsigned int nbytes) | ||
449 | { | ||
450 | struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); | ||
451 | u8 *iv; | ||
452 | |||
453 | iv = padlock_xcrypt_cbc(in, out, ctx->E, desc->info, | ||
454 | &ctx->cword.encrypt, nbytes / AES_BLOCK_SIZE); | ||
455 | memcpy(desc->info, iv, AES_BLOCK_SIZE); | ||
456 | |||
457 | return nbytes & ~(AES_BLOCK_SIZE - 1); | ||
458 | } | ||
459 | |||
460 | static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, | ||
461 | const u8 *in, unsigned int nbytes) | ||
462 | { | ||
463 | struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); | ||
464 | padlock_xcrypt_cbc(in, out, ctx->D, desc->info, &ctx->cword.decrypt, | ||
465 | nbytes / AES_BLOCK_SIZE); | ||
466 | return nbytes & ~(AES_BLOCK_SIZE - 1); | ||
437 | } | 467 | } |
438 | 468 | ||
439 | static struct crypto_alg aes_alg = { | 469 | static struct crypto_alg aes_alg = { |
@@ -441,6 +471,7 @@ static struct crypto_alg aes_alg = { | |||
441 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | 471 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
442 | .cra_blocksize = AES_BLOCK_SIZE, | 472 | .cra_blocksize = AES_BLOCK_SIZE, |
443 | .cra_ctxsize = sizeof(struct aes_ctx), | 473 | .cra_ctxsize = sizeof(struct aes_ctx), |
474 | .cra_alignmask = PADLOCK_ALIGNMENT - 1, | ||
444 | .cra_module = THIS_MODULE, | 475 | .cra_module = THIS_MODULE, |
445 | .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), | 476 | .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), |
446 | .cra_u = { | 477 | .cra_u = { |
@@ -449,7 +480,11 @@ static struct crypto_alg aes_alg = { | |||
449 | .cia_max_keysize = AES_MAX_KEY_SIZE, | 480 | .cia_max_keysize = AES_MAX_KEY_SIZE, |
450 | .cia_setkey = aes_set_key, | 481 | .cia_setkey = aes_set_key, |
451 | .cia_encrypt = aes_encrypt, | 482 | .cia_encrypt = aes_encrypt, |
452 | .cia_decrypt = aes_decrypt | 483 | .cia_decrypt = aes_decrypt, |
484 | .cia_encrypt_ecb = aes_encrypt_ecb, | ||
485 | .cia_decrypt_ecb = aes_decrypt_ecb, | ||
486 | .cia_encrypt_cbc = aes_encrypt_cbc, | ||
487 | .cia_decrypt_cbc = aes_decrypt_cbc, | ||
453 | } | 488 | } |
454 | } | 489 | } |
455 | }; | 490 | }; |
diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h index 7a500605e449..3cf2b7a12348 100644 --- a/drivers/crypto/padlock.h +++ b/drivers/crypto/padlock.h | |||
@@ -13,18 +13,18 @@ | |||
13 | #ifndef _CRYPTO_PADLOCK_H | 13 | #ifndef _CRYPTO_PADLOCK_H |
14 | #define _CRYPTO_PADLOCK_H | 14 | #define _CRYPTO_PADLOCK_H |
15 | 15 | ||
16 | #define PADLOCK_ALIGNMENT 16 | ||
17 | |||
16 | /* Control word. */ | 18 | /* Control word. */ |
17 | union cword { | 19 | struct cword { |
18 | uint32_t cword[4]; | 20 | int __attribute__ ((__packed__)) |
19 | struct { | 21 | rounds:4, |
20 | int rounds:4; | 22 | algo:3, |
21 | int algo:3; | 23 | keygen:1, |
22 | int keygen:1; | 24 | interm:1, |
23 | int interm:1; | 25 | encdec:1, |
24 | int encdec:1; | 26 | ksize:2; |
25 | int ksize:2; | 27 | } __attribute__ ((__aligned__(PADLOCK_ALIGNMENT))); |
26 | } b; | ||
27 | }; | ||
28 | 28 | ||
29 | #define PFX "padlock: " | 29 | #define PFX "padlock: " |
30 | 30 | ||