xref: /openbmc/linux/crypto/cbc.c (revision 4f6cce39)
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 
13 #include <crypto/cbc.h>
14 #include <crypto/internal/skcipher.h>
15 #include <linux/err.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/log2.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 
22 struct crypto_cbc_ctx {
23 	struct crypto_cipher *child;
24 };
25 
26 static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key,
27 			     unsigned int keylen)
28 {
29 	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent);
30 	struct crypto_cipher *child = ctx->child;
31 	int err;
32 
33 	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
34 	crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) &
35 				       CRYPTO_TFM_REQ_MASK);
36 	err = crypto_cipher_setkey(child, key, keylen);
37 	crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) &
38 					  CRYPTO_TFM_RES_MASK);
39 	return err;
40 }
41 
42 static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm,
43 					  const u8 *src, u8 *dst)
44 {
45 	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
46 
47 	crypto_cipher_encrypt_one(ctx->child, dst, src);
48 }
49 
50 static int crypto_cbc_encrypt(struct skcipher_request *req)
51 {
52 	return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one);
53 }
54 
55 static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm,
56 					  const u8 *src, u8 *dst)
57 {
58 	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
59 
60 	crypto_cipher_decrypt_one(ctx->child, dst, src);
61 }
62 
63 static int crypto_cbc_decrypt(struct skcipher_request *req)
64 {
65 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
66 	struct skcipher_walk walk;
67 	int err;
68 
69 	err = skcipher_walk_virt(&walk, req, false);
70 
71 	while (walk.nbytes) {
72 		err = crypto_cbc_decrypt_blocks(&walk, tfm,
73 						crypto_cbc_decrypt_one);
74 		err = skcipher_walk_done(&walk, err);
75 	}
76 
77 	return err;
78 }
79 
80 static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm)
81 {
82 	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
83 	struct crypto_spawn *spawn = skcipher_instance_ctx(inst);
84 	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
85 	struct crypto_cipher *cipher;
86 
87 	cipher = crypto_spawn_cipher(spawn);
88 	if (IS_ERR(cipher))
89 		return PTR_ERR(cipher);
90 
91 	ctx->child = cipher;
92 	return 0;
93 }
94 
95 static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm)
96 {
97 	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
98 
99 	crypto_free_cipher(ctx->child);
100 }
101 
102 static void crypto_cbc_free(struct skcipher_instance *inst)
103 {
104 	crypto_drop_skcipher(skcipher_instance_ctx(inst));
105 	kfree(inst);
106 }
107 
108 static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
109 {
110 	struct skcipher_instance *inst;
111 	struct crypto_spawn *spawn;
112 	struct crypto_alg *alg;
113 	int err;
114 
115 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER);
116 	if (err)
117 		return err;
118 
119 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
120 	if (!inst)
121 		return -ENOMEM;
122 
123 	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
124 				  CRYPTO_ALG_TYPE_MASK);
125 	err = PTR_ERR(alg);
126 	if (IS_ERR(alg))
127 		goto err_free_inst;
128 
129 	spawn = skcipher_instance_ctx(inst);
130 	err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
131 				CRYPTO_ALG_TYPE_MASK);
132 	crypto_mod_put(alg);
133 	if (err)
134 		goto err_free_inst;
135 
136 	err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg);
137 	if (err)
138 		goto err_drop_spawn;
139 
140 	err = -EINVAL;
141 	if (!is_power_of_2(alg->cra_blocksize))
142 		goto err_drop_spawn;
143 
144 	inst->alg.base.cra_priority = alg->cra_priority;
145 	inst->alg.base.cra_blocksize = alg->cra_blocksize;
146 	inst->alg.base.cra_alignmask = alg->cra_alignmask;
147 
148 	inst->alg.ivsize = alg->cra_blocksize;
149 	inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize;
150 	inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize;
151 
152 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx);
153 
154 	inst->alg.init = crypto_cbc_init_tfm;
155 	inst->alg.exit = crypto_cbc_exit_tfm;
156 
157 	inst->alg.setkey = crypto_cbc_setkey;
158 	inst->alg.encrypt = crypto_cbc_encrypt;
159 	inst->alg.decrypt = crypto_cbc_decrypt;
160 
161 	inst->free = crypto_cbc_free;
162 
163 	err = skcipher_register_instance(tmpl, inst);
164 	if (err)
165 		goto err_drop_spawn;
166 
167 out:
168 	return err;
169 
170 err_drop_spawn:
171 	crypto_drop_spawn(spawn);
172 err_free_inst:
173 	kfree(inst);
174 	goto out;
175 }
176 
177 static struct crypto_template crypto_cbc_tmpl = {
178 	.name = "cbc",
179 	.create = crypto_cbc_create,
180 	.module = THIS_MODULE,
181 };
182 
183 static int __init crypto_cbc_module_init(void)
184 {
185 	return crypto_register_template(&crypto_cbc_tmpl);
186 }
187 
188 static void __exit crypto_cbc_module_exit(void)
189 {
190 	crypto_unregister_template(&crypto_cbc_tmpl);
191 }
192 
193 module_init(crypto_cbc_module_init);
194 module_exit(crypto_cbc_module_exit);
195 
196 MODULE_LICENSE("GPL");
197 MODULE_DESCRIPTION("CBC block cipher algorithm");
198 MODULE_ALIAS_CRYPTO("cbc");
199