Encrypts or decrypts a buffer using AES-128 in CBC mode.
187 {
188 struct crypto_skcipher *tfm;
189 struct skcipher_request *req;
190 struct scatterlist sg;
191 char *buf = NULL;
192 char *padded_in = NULL;
193 size_t padded_len = 0;
194 int ret = 0;
196
197
200 if (ret != 0) {
201 ERR_MSG(
"Failed to load AES constants: %d\n", ret);
202 return ret;
203 }
204 }
205
206 if (!in || !out || !out_len)
207 return -EINVAL;
208
209
210 *out = NULL;
211 *out_len = 0;
212
214
215 if (encrypt) {
216
218 if (ret != 0)
219 return ret;
220 }
221 else {
222
224 ERR_MSG(
"Decrypt input length must be a multiple of %d\n",
226 return -EINVAL;
227 }
228 padded_in = vmalloc(in_len);
229 if (!padded_in)
230 return -ENOMEM;
231 memcpy(padded_in, in, in_len);
232 padded_len = in_len;
233 }
234
235
236 buf = vmalloc(padded_len);
237 if (!buf) {
238 vfree(padded_in);
239 return -ENOMEM;
240 }
241
242
243 tfm = crypto_alloc_skcipher("cbc(aes)", 0, 0);
244 if (IS_ERR(tfm)) {
245 ret = PTR_ERR(tfm);
246 goto out_free_buffers;
247 }
248
249
250 req = skcipher_request_alloc(tfm, GFP_KERNEL);
251 if (!req) {
252 ret = -ENOMEM;
253 goto out_free_tfm;
254 }
255
256
257 ret = crypto_skcipher_setkey(tfm,
AES_KEY, 16);
258 if (ret != 0) {
259 pr_err("setkey failed: %d\n", ret);
260 goto out_free_req;
261 }
262
263
264 sg_init_one(&sg, padded_in, padded_len);
265 skcipher_request_set_crypt(req, &sg, &sg, padded_len, iv);
266
267
268 if (encrypt)
269 ret = crypto_skcipher_encrypt(req);
270 else
271 ret = crypto_skcipher_decrypt(req);
272
273 if (ret) {
274 ERR_MSG(
"%s failed: %d\n", encrypt ?
"encrypt" :
"decrypt", ret);
275 goto out_free_req;
276 }
277
278
279 memcpy(buf, sg_virt(&sg), padded_len);
280
281 if (!encrypt) {
282
283 char *unpadded_buf;
284 size_t unpadded_len;
285
287 if (ret != 0) {
288 ERR_MSG(
"Failed to remove padding: %d\n", ret);
289 goto out_free_req;
290 }
291
292
293 vfree(buf);
294 buf = unpadded_buf;
295 padded_len = unpadded_len;
296 }
297
298 *out = buf;
299 *out_len = padded_len;
300 buf = NULL;
301
302out_free_req:
303 skcipher_request_free(req);
304out_free_tfm:
305 crypto_free_skcipher(tfm);
306out_free_buffers:
307 vfree(padded_in);
308 vfree(buf);
309
310 return ret;
311}
static int _load_eas_constants(void)
Load AES key and IV constants.
static int add_pkcs7_padding(const char *in, size_t in_len, char **out, size_t *out_len)
Add PKCS#7 padding to a buffer.
static int remove_pkcs7_padding(const char *in, size_t in_len, char **out, size_t *out_len)
Remove PKCS#7 padding from a buffer.
#define ERR_MSG(fmt, args...)