Blame view

crypto/ofb.c 2.42 KB
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
1
2
3
4
5
6
7
  // SPDX-License-Identifier: GPL-2.0
  
  /*
   * OFB: Output FeedBack mode
   *
   * Copyright (C) 2018 ARM Limited or its affiliates.
   * All rights reserved.
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
8
9
10
11
12
13
14
15
   */
  
  #include <crypto/algapi.h>
  #include <crypto/internal/skcipher.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
16

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
17
  static int crypto_ofb_crypt(struct skcipher_request *req)
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
18
  {
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
19
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
21f3ca6cd   Eric Biggers   crypto: ofb - con...
20
  	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
b3e3e2db7   Eric Biggers   crypto: ofb - fix...
21
22
23
  	const unsigned int bsize = crypto_cipher_blocksize(cipher);
  	struct skcipher_walk walk;
  	int err;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
24

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
25
  	err = skcipher_walk_virt(&walk, req, false);
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
26

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
27
28
29
30
31
  	while (walk.nbytes >= bsize) {
  		const u8 *src = walk.src.virt.addr;
  		u8 *dst = walk.dst.virt.addr;
  		u8 * const iv = walk.iv;
  		unsigned int nbytes = walk.nbytes;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
32

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
33
34
35
36
37
38
  		do {
  			crypto_cipher_encrypt_one(cipher, iv, iv);
  			crypto_xor_cpy(dst, src, iv, bsize);
  			dst += bsize;
  			src += bsize;
  		} while ((nbytes -= bsize) >= bsize);
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
39

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
40
41
  		err = skcipher_walk_done(&walk, nbytes);
  	}
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
42

b3e3e2db7   Eric Biggers   crypto: ofb - fix...
43
44
45
46
47
48
49
  	if (walk.nbytes) {
  		crypto_cipher_encrypt_one(cipher, walk.iv, walk.iv);
  		crypto_xor_cpy(walk.dst.virt.addr, walk.src.virt.addr, walk.iv,
  			       walk.nbytes);
  		err = skcipher_walk_done(&walk, 0);
  	}
  	return err;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
50
  }
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
51
52
53
  static int crypto_ofb_create(struct crypto_template *tmpl, struct rtattr **tb)
  {
  	struct skcipher_instance *inst;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
54
  	struct crypto_alg *alg;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
55
  	int err;
b3c16bfc6   Herbert Xu   crypto: skcipher ...
56
  	inst = skcipher_alloc_instance_simple(tmpl, tb);
21f3ca6cd   Eric Biggers   crypto: ofb - con...
57
58
  	if (IS_ERR(inst))
  		return PTR_ERR(inst);
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
59

b3c16bfc6   Herbert Xu   crypto: skcipher ...
60
  	alg = skcipher_ialg_simple(inst);
b3e3e2db7   Eric Biggers   crypto: ofb - fix...
61
62
63
64
65
66
67
68
  	/* OFB mode is a stream cipher. */
  	inst->alg.base.cra_blocksize = 1;
  
  	/*
  	 * To simplify the implementation, configure the skcipher walk to only
  	 * give a partial block at the very end, never earlier.
  	 */
  	inst->alg.chunksize = alg->cra_blocksize;
b3e3e2db7   Eric Biggers   crypto: ofb - fix...
69
70
  	inst->alg.encrypt = crypto_ofb_crypt;
  	inst->alg.decrypt = crypto_ofb_crypt;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
71

e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
72
73
  	err = skcipher_register_instance(tmpl, inst);
  	if (err)
21f3ca6cd   Eric Biggers   crypto: ofb - con...
74
  		inst->free(inst);
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
75

e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
76
  	return err;
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  }
  
  static struct crypto_template crypto_ofb_tmpl = {
  	.name = "ofb",
  	.create = crypto_ofb_create,
  	.module = THIS_MODULE,
  };
  
  static int __init crypto_ofb_module_init(void)
  {
  	return crypto_register_template(&crypto_ofb_tmpl);
  }
  
  static void __exit crypto_ofb_module_exit(void)
  {
  	crypto_unregister_template(&crypto_ofb_tmpl);
  }
c4741b230   Eric Biggers   crypto: run initc...
94
  subsys_initcall(crypto_ofb_module_init);
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
95
96
97
  module_exit(crypto_ofb_module_exit);
  
  MODULE_LICENSE("GPL");
21f3ca6cd   Eric Biggers   crypto: ofb - con...
98
  MODULE_DESCRIPTION("OFB block cipher mode of operation");
e497c5189   Gilad Ben-Yossef   crypto: ofb - add...
99
  MODULE_ALIAS_CRYPTO("ofb");