cbc.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * CBC: Cipher Block Chaining mode
  3. *
  4. * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. *
  11. */
  12. #include <crypto/cbc.h>
  13. #include <crypto/internal/skcipher.h>
  14. #include <linux/err.h>
  15. #include <linux/init.h>
  16. #include <linux/kernel.h>
  17. #include <linux/log2.h>
  18. #include <linux/module.h>
  19. #include <linux/slab.h>
  20. struct crypto_cbc_ctx {
  21. struct crypto_cipher *child;
  22. };
  23. static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key,
  24. unsigned int keylen)
  25. {
  26. struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent);
  27. struct crypto_cipher *child = ctx->child;
  28. int err;
  29. crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  30. crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) &
  31. CRYPTO_TFM_REQ_MASK);
  32. err = crypto_cipher_setkey(child, key, keylen);
  33. crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) &
  34. CRYPTO_TFM_RES_MASK);
  35. return err;
  36. }
  37. static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm,
  38. const u8 *src, u8 *dst)
  39. {
  40. struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
  41. crypto_cipher_encrypt_one(ctx->child, dst, src);
  42. }
  43. static int crypto_cbc_encrypt(struct skcipher_request *req)
  44. {
  45. return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one);
  46. }
  47. static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm,
  48. const u8 *src, u8 *dst)
  49. {
  50. struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
  51. crypto_cipher_decrypt_one(ctx->child, dst, src);
  52. }
  53. static int crypto_cbc_decrypt(struct skcipher_request *req)
  54. {
  55. struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  56. struct skcipher_walk walk;
  57. int err;
  58. err = skcipher_walk_virt(&walk, req, false);
  59. while (walk.nbytes) {
  60. err = crypto_cbc_decrypt_blocks(&walk, tfm,
  61. crypto_cbc_decrypt_one);
  62. err = skcipher_walk_done(&walk, err);
  63. }
  64. return err;
  65. }
  66. static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm)
  67. {
  68. struct skcipher_instance *inst = skcipher_alg_instance(tfm);
  69. struct crypto_spawn *spawn = skcipher_instance_ctx(inst);
  70. struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
  71. struct crypto_cipher *cipher;
  72. cipher = crypto_spawn_cipher(spawn);
  73. if (IS_ERR(cipher))
  74. return PTR_ERR(cipher);
  75. ctx->child = cipher;
  76. return 0;
  77. }
  78. static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm)
  79. {
  80. struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
  81. crypto_free_cipher(ctx->child);
  82. }
  83. static void crypto_cbc_free(struct skcipher_instance *inst)
  84. {
  85. crypto_drop_skcipher(skcipher_instance_ctx(inst));
  86. kfree(inst);
  87. }
  88. static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
  89. {
  90. struct skcipher_instance *inst;
  91. struct crypto_spawn *spawn;
  92. struct crypto_alg *alg;
  93. int err;
  94. err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER);
  95. if (err)
  96. return err;
  97. inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  98. if (!inst)
  99. return -ENOMEM;
  100. alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
  101. CRYPTO_ALG_TYPE_MASK);
  102. err = PTR_ERR(alg);
  103. if (IS_ERR(alg))
  104. goto err_free_inst;
  105. spawn = skcipher_instance_ctx(inst);
  106. err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
  107. CRYPTO_ALG_TYPE_MASK);
  108. crypto_mod_put(alg);
  109. if (err)
  110. goto err_free_inst;
  111. err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg);
  112. if (err)
  113. goto err_drop_spawn;
  114. err = -EINVAL;
  115. if (!is_power_of_2(alg->cra_blocksize))
  116. goto err_drop_spawn;
  117. inst->alg.base.cra_priority = alg->cra_priority;
  118. inst->alg.base.cra_blocksize = alg->cra_blocksize;
  119. inst->alg.base.cra_alignmask = alg->cra_alignmask;
  120. inst->alg.ivsize = alg->cra_blocksize;
  121. inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize;
  122. inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize;
  123. inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx);
  124. inst->alg.init = crypto_cbc_init_tfm;
  125. inst->alg.exit = crypto_cbc_exit_tfm;
  126. inst->alg.setkey = crypto_cbc_setkey;
  127. inst->alg.encrypt = crypto_cbc_encrypt;
  128. inst->alg.decrypt = crypto_cbc_decrypt;
  129. inst->free = crypto_cbc_free;
  130. err = skcipher_register_instance(tmpl, inst);
  131. if (err)
  132. goto err_drop_spawn;
  133. out:
  134. return err;
  135. err_drop_spawn:
  136. crypto_drop_spawn(spawn);
  137. err_free_inst:
  138. kfree(inst);
  139. goto out;
  140. }
  141. static struct crypto_template crypto_cbc_tmpl = {
  142. .name = "cbc",
  143. .create = crypto_cbc_create,
  144. .module = THIS_MODULE,
  145. };
  146. static int __init crypto_cbc_module_init(void)
  147. {
  148. return crypto_register_template(&crypto_cbc_tmpl);
  149. }
  150. static void __exit crypto_cbc_module_exit(void)
  151. {
  152. crypto_unregister_template(&crypto_cbc_tmpl);
  153. }
  154. module_init(crypto_cbc_module_init);
  155. module_exit(crypto_cbc_module_exit);
  156. MODULE_LICENSE("GPL");
  157. MODULE_DESCRIPTION("CBC block cipher algorithm");
  158. MODULE_ALIAS_CRYPTO("cbc");