cbc.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * CBC: Cipher Block Chaining mode
  4. *
  5. * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au>
  6. */
  7. #include <crypto/internal/skcipher.h>
  8. #include <linux/err.h>
  9. #include <linux/init.h>
  10. #include <linux/kernel.h>
  11. #include <linux/log2.h>
  12. #include <linux/module.h>
  13. static int crypto_cbc_encrypt_segment(struct crypto_lskcipher *tfm,
  14. const u8 *src, u8 *dst, unsigned nbytes,
  15. u8 *iv)
  16. {
  17. unsigned int bsize = crypto_lskcipher_blocksize(tfm);
  18. for (; nbytes >= bsize; src += bsize, dst += bsize, nbytes -= bsize) {
  19. crypto_xor(iv, src, bsize);
  20. crypto_lskcipher_encrypt(tfm, iv, dst, bsize, NULL);
  21. memcpy(iv, dst, bsize);
  22. }
  23. return nbytes;
  24. }
  25. static int crypto_cbc_encrypt_inplace(struct crypto_lskcipher *tfm,
  26. u8 *src, unsigned nbytes, u8 *oiv)
  27. {
  28. unsigned int bsize = crypto_lskcipher_blocksize(tfm);
  29. u8 *iv = oiv;
  30. if (nbytes < bsize)
  31. goto out;
  32. do {
  33. crypto_xor(src, iv, bsize);
  34. crypto_lskcipher_encrypt(tfm, src, src, bsize, NULL);
  35. iv = src;
  36. src += bsize;
  37. } while ((nbytes -= bsize) >= bsize);
  38. memcpy(oiv, iv, bsize);
  39. out:
  40. return nbytes;
  41. }
  42. static int crypto_cbc_encrypt(struct crypto_lskcipher *tfm, const u8 *src,
  43. u8 *dst, unsigned len, u8 *iv, u32 flags)
  44. {
  45. struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
  46. bool final = flags & CRYPTO_LSKCIPHER_FLAG_FINAL;
  47. struct crypto_lskcipher *cipher = *ctx;
  48. int rem;
  49. if (src == dst)
  50. rem = crypto_cbc_encrypt_inplace(cipher, dst, len, iv);
  51. else
  52. rem = crypto_cbc_encrypt_segment(cipher, src, dst, len, iv);
  53. return rem && final ? -EINVAL : rem;
  54. }
  55. static int crypto_cbc_decrypt_segment(struct crypto_lskcipher *tfm,
  56. const u8 *src, u8 *dst, unsigned nbytes,
  57. u8 *oiv)
  58. {
  59. unsigned int bsize = crypto_lskcipher_blocksize(tfm);
  60. const u8 *iv = oiv;
  61. if (nbytes < bsize)
  62. goto out;
  63. do {
  64. crypto_lskcipher_decrypt(tfm, src, dst, bsize, NULL);
  65. crypto_xor(dst, iv, bsize);
  66. iv = src;
  67. src += bsize;
  68. dst += bsize;
  69. } while ((nbytes -= bsize) >= bsize);
  70. memcpy(oiv, iv, bsize);
  71. out:
  72. return nbytes;
  73. }
  74. static int crypto_cbc_decrypt_inplace(struct crypto_lskcipher *tfm,
  75. u8 *src, unsigned nbytes, u8 *iv)
  76. {
  77. unsigned int bsize = crypto_lskcipher_blocksize(tfm);
  78. u8 last_iv[MAX_CIPHER_BLOCKSIZE];
  79. if (nbytes < bsize)
  80. goto out;
  81. /* Start of the last block. */
  82. src += nbytes - (nbytes & (bsize - 1)) - bsize;
  83. memcpy(last_iv, src, bsize);
  84. for (;;) {
  85. crypto_lskcipher_decrypt(tfm, src, src, bsize, NULL);
  86. if ((nbytes -= bsize) < bsize)
  87. break;
  88. crypto_xor(src, src - bsize, bsize);
  89. src -= bsize;
  90. }
  91. crypto_xor(src, iv, bsize);
  92. memcpy(iv, last_iv, bsize);
  93. out:
  94. return nbytes;
  95. }
  96. static int crypto_cbc_decrypt(struct crypto_lskcipher *tfm, const u8 *src,
  97. u8 *dst, unsigned len, u8 *iv, u32 flags)
  98. {
  99. struct crypto_lskcipher **ctx = crypto_lskcipher_ctx(tfm);
  100. bool final = flags & CRYPTO_LSKCIPHER_FLAG_FINAL;
  101. struct crypto_lskcipher *cipher = *ctx;
  102. int rem;
  103. if (src == dst)
  104. rem = crypto_cbc_decrypt_inplace(cipher, dst, len, iv);
  105. else
  106. rem = crypto_cbc_decrypt_segment(cipher, src, dst, len, iv);
  107. return rem && final ? -EINVAL : rem;
  108. }
  109. static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
  110. {
  111. struct lskcipher_instance *inst;
  112. int err;
  113. inst = lskcipher_alloc_instance_simple(tmpl, tb);
  114. if (IS_ERR(inst))
  115. return PTR_ERR(inst);
  116. err = -EINVAL;
  117. if (!is_power_of_2(inst->alg.co.base.cra_blocksize))
  118. goto out_free_inst;
  119. if (inst->alg.co.statesize)
  120. goto out_free_inst;
  121. inst->alg.encrypt = crypto_cbc_encrypt;
  122. inst->alg.decrypt = crypto_cbc_decrypt;
  123. err = lskcipher_register_instance(tmpl, inst);
  124. if (err) {
  125. out_free_inst:
  126. inst->free(inst);
  127. }
  128. return err;
  129. }
  130. static struct crypto_template crypto_cbc_tmpl = {
  131. .name = "cbc",
  132. .create = crypto_cbc_create,
  133. .module = THIS_MODULE,
  134. };
  135. static int __init crypto_cbc_module_init(void)
  136. {
  137. return crypto_register_template(&crypto_cbc_tmpl);
  138. }
  139. static void __exit crypto_cbc_module_exit(void)
  140. {
  141. crypto_unregister_template(&crypto_cbc_tmpl);
  142. }
  143. subsys_initcall(crypto_cbc_module_init);
  144. module_exit(crypto_cbc_module_exit);
  145. MODULE_LICENSE("GPL");
  146. MODULE_DESCRIPTION("CBC block cipher mode of operation");
  147. MODULE_ALIAS_CRYPTO("cbc");