diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/cipher.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/crypto/cipher.c b/crypto/cipher.c index f573c59ed9dc..d8ca0ec8d0be 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c | |||
@@ -388,12 +388,60 @@ int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) | |||
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
390 | 390 | ||
391 | static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, | ||
392 | const u8 *), | ||
393 | struct crypto_tfm *tfm, | ||
394 | u8 *dst, const u8 *src) | ||
395 | { | ||
396 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
397 | unsigned int size = crypto_tfm_alg_blocksize(tfm); | ||
398 | u8 buffer[size + alignmask]; | ||
399 | u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
400 | |||
401 | memcpy(tmp, src, size); | ||
402 | fn(tfm, tmp, tmp); | ||
403 | memcpy(dst, tmp, size); | ||
404 | } | ||
405 | |||
406 | static void cipher_encrypt_unaligned(struct crypto_tfm *tfm, | ||
407 | u8 *dst, const u8 *src) | ||
408 | { | ||
409 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
410 | struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; | ||
411 | |||
412 | if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { | ||
413 | cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src); | ||
414 | return; | ||
415 | } | ||
416 | |||
417 | cipher->cia_encrypt(tfm, dst, src); | ||
418 | } | ||
419 | |||
420 | static void cipher_decrypt_unaligned(struct crypto_tfm *tfm, | ||
421 | u8 *dst, const u8 *src) | ||
422 | { | ||
423 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
424 | struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; | ||
425 | |||
426 | if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { | ||
427 | cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src); | ||
428 | return; | ||
429 | } | ||
430 | |||
431 | cipher->cia_decrypt(tfm, dst, src); | ||
432 | } | ||
433 | |||
391 | int crypto_init_cipher_ops(struct crypto_tfm *tfm) | 434 | int crypto_init_cipher_ops(struct crypto_tfm *tfm) |
392 | { | 435 | { |
393 | int ret = 0; | 436 | int ret = 0; |
394 | struct cipher_tfm *ops = &tfm->crt_cipher; | 437 | struct cipher_tfm *ops = &tfm->crt_cipher; |
438 | struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; | ||
395 | 439 | ||
396 | ops->cit_setkey = setkey; | 440 | ops->cit_setkey = setkey; |
441 | ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ? | ||
442 | cipher_encrypt_unaligned : cipher->cia_encrypt; | ||
443 | ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ? | ||
444 | cipher_decrypt_unaligned : cipher->cia_decrypt; | ||
397 | 445 | ||
398 | switch (tfm->crt_cipher.cit_mode) { | 446 | switch (tfm->crt_cipher.cit_mode) { |
399 | case CRYPTO_TFM_MODE_ECB: | 447 | case CRYPTO_TFM_MODE_ECB: |