Blame view

crypto/seqiv.c 4.54 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
2
3
4
5
6
7
8
  /*
   * seqiv: Sequence Number IV Generator
   *
   * This generator generates an IV based on a sequence number by xoring it
   * with a salt.  This algorithm is mainly useful for CTR and similar modes.
   *
   * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
9
   */
661cfd0e5   Herbert Xu   crypto: seqiv - U...
10
  #include <crypto/internal/geniv.h>
856e3f409   Herbert Xu   crypto: seqiv - A...
11
  #include <crypto/scatterwalk.h>
3a01d0ee2   Herbert Xu   crypto: skcipher ...
12
  #include <crypto/skcipher.h>
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
13
14
15
16
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
17
  #include <linux/slab.h>
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
18
  #include <linux/string.h>
856e3f409   Herbert Xu   crypto: seqiv - A...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err)
  {
  	struct aead_request *subreq = aead_request_ctx(req);
  	struct crypto_aead *geniv;
  
  	if (err == -EINPROGRESS)
  		return;
  
  	if (err)
  		goto out;
  
  	geniv = crypto_aead_reqtfm(req);
  	memcpy(req->iv, subreq->iv, crypto_aead_ivsize(geniv));
  
  out:
453431a54   Waiman Long   mm, treewide: ren...
34
  	kfree_sensitive(subreq->iv);
856e3f409   Herbert Xu   crypto: seqiv - A...
35
36
37
38
39
40
41
42
43
44
  }
  
  static void seqiv_aead_encrypt_complete(struct crypto_async_request *base,
  					int err)
  {
  	struct aead_request *req = base->data;
  
  	seqiv_aead_encrypt_complete2(req, err);
  	aead_request_complete(req, err);
  }
856e3f409   Herbert Xu   crypto: seqiv - A...
45
46
47
  static int seqiv_aead_encrypt(struct aead_request *req)
  {
  	struct crypto_aead *geniv = crypto_aead_reqtfm(req);
659e7f528   Herbert Xu   crypto: seqiv - U...
48
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
856e3f409   Herbert Xu   crypto: seqiv - A...
49
50
51
52
  	struct aead_request *subreq = aead_request_ctx(req);
  	crypto_completion_t compl;
  	void *data;
  	u8 *info;
dd04446e4   Herbert Xu   crypto: seqiv - S...
53
  	unsigned int ivsize = 8;
856e3f409   Herbert Xu   crypto: seqiv - A...
54
  	int err;
dd04446e4   Herbert Xu   crypto: seqiv - S...
55
56
  	if (req->cryptlen < ivsize)
  		return -EINVAL;
659e7f528   Herbert Xu   crypto: seqiv - U...
57
  	aead_request_set_tfm(subreq, ctx->child);
856e3f409   Herbert Xu   crypto: seqiv - A...
58
59
60
61
  
  	compl = req->base.complete;
  	data = req->base.data;
  	info = req->iv;
856e3f409   Herbert Xu   crypto: seqiv - A...
62
  	if (req->src != req->dst) {
8d6053984   Kees Cook   crypto: null - Re...
63
  		SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->sknull);
856e3f409   Herbert Xu   crypto: seqiv - A...
64

8d6053984   Kees Cook   crypto: null - Re...
65
  		skcipher_request_set_sync_tfm(nreq, ctx->sknull);
ef22871f2   Herbert Xu   crypto: seqiv - U...
66
67
68
69
70
71
72
  		skcipher_request_set_callback(nreq, req->base.flags,
  					      NULL, NULL);
  		skcipher_request_set_crypt(nreq, req->src, req->dst,
  					   req->assoclen + req->cryptlen,
  					   NULL);
  
  		err = crypto_skcipher_encrypt(nreq);
856e3f409   Herbert Xu   crypto: seqiv - A...
73
74
75
76
77
78
  		if (err)
  			return err;
  	}
  
  	if (unlikely(!IS_ALIGNED((unsigned long)info,
  				 crypto_aead_alignmask(geniv) + 1))) {
7e33d4d48   YueHaibing   crypto: seqiv - U...
79
80
81
  		info = kmemdup(req->iv, ivsize, req->base.flags &
  			       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
  			       GFP_ATOMIC);
856e3f409   Herbert Xu   crypto: seqiv - A...
82
83
  		if (!info)
  			return -ENOMEM;
856e3f409   Herbert Xu   crypto: seqiv - A...
84
85
86
87
88
89
90
  		compl = seqiv_aead_encrypt_complete;
  		data = req;
  	}
  
  	aead_request_set_callback(subreq, req->base.flags, compl, data);
  	aead_request_set_crypt(subreq, req->dst, req->dst,
  			       req->cryptlen - ivsize, info);
374d4ad18   Herbert Xu   crypto: aead - Re...
91
  	aead_request_set_ad(subreq, req->assoclen + ivsize);
856e3f409   Herbert Xu   crypto: seqiv - A...
92
93
94
95
96
97
98
99
100
  
  	crypto_xor(info, ctx->salt, ivsize);
  	scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
  
  	err = crypto_aead_encrypt(subreq);
  	if (unlikely(info != req->iv))
  		seqiv_aead_encrypt_complete2(req, err);
  	return err;
  }
856e3f409   Herbert Xu   crypto: seqiv - A...
101
102
103
  static int seqiv_aead_decrypt(struct aead_request *req)
  {
  	struct crypto_aead *geniv = crypto_aead_reqtfm(req);
659e7f528   Herbert Xu   crypto: seqiv - U...
104
  	struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
856e3f409   Herbert Xu   crypto: seqiv - A...
105
106
107
  	struct aead_request *subreq = aead_request_ctx(req);
  	crypto_completion_t compl;
  	void *data;
dd04446e4   Herbert Xu   crypto: seqiv - S...
108
109
110
111
  	unsigned int ivsize = 8;
  
  	if (req->cryptlen < ivsize + crypto_aead_authsize(geniv))
  		return -EINVAL;
856e3f409   Herbert Xu   crypto: seqiv - A...
112

659e7f528   Herbert Xu   crypto: seqiv - U...
113
  	aead_request_set_tfm(subreq, ctx->child);
856e3f409   Herbert Xu   crypto: seqiv - A...
114
115
116
  
  	compl = req->base.complete;
  	data = req->base.data;
856e3f409   Herbert Xu   crypto: seqiv - A...
117
118
119
  	aead_request_set_callback(subreq, req->base.flags, compl, data);
  	aead_request_set_crypt(subreq, req->src, req->dst,
  			       req->cryptlen - ivsize, req->iv);
374d4ad18   Herbert Xu   crypto: aead - Re...
120
  	aead_request_set_ad(subreq, req->assoclen + ivsize);
856e3f409   Herbert Xu   crypto: seqiv - A...
121
122
  
  	scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
856e3f409   Herbert Xu   crypto: seqiv - A...
123
124
125
  
  	return crypto_aead_decrypt(subreq);
  }
0677157b2   Herbert Xu   crypto: seqiv - U...
126
  static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
14df4d804   Herbert Xu   [CRYPTO] seqiv: A...
127
  {
856e3f409   Herbert Xu   crypto: seqiv - A...
128
  	struct aead_instance *inst;
0677157b2   Herbert Xu   crypto: seqiv - U...
129
  	int err;
14df4d804   Herbert Xu   [CRYPTO] seqiv: A...
130

e72b48c5e   Eric Biggers   crypto: geniv - r...
131
  	inst = aead_geniv_alloc(tmpl, tb);
14df4d804   Herbert Xu   [CRYPTO] seqiv: A...
132
133
  
  	if (IS_ERR(inst))
0677157b2   Herbert Xu   crypto: seqiv - U...
134
  		return PTR_ERR(inst);
0677157b2   Herbert Xu   crypto: seqiv - U...
135
  	err = -EINVAL;
dd04446e4   Herbert Xu   crypto: seqiv - S...
136
  	if (inst->alg.ivsize != sizeof(u64))
0677157b2   Herbert Xu   crypto: seqiv - U...
137
  		goto free_inst;
c0ecf8916   Herbert Xu   crypto: seqiv - E...
138

b7dcfab4a   Herbert Xu   crypto: seqiv - M...
139
  	inst->alg.encrypt = seqiv_aead_encrypt;
856e3f409   Herbert Xu   crypto: seqiv - A...
140
  	inst->alg.decrypt = seqiv_aead_decrypt;
14df4d804   Herbert Xu   [CRYPTO] seqiv: A...
141

659e7f528   Herbert Xu   crypto: seqiv - U...
142
143
  	inst->alg.init = aead_init_geniv;
  	inst->alg.exit = aead_exit_geniv;
856e3f409   Herbert Xu   crypto: seqiv - A...
144

659e7f528   Herbert Xu   crypto: seqiv - U...
145
  	inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
5964f26c9   Herbert Xu   crypto: seqiv - R...
146
  	inst->alg.base.cra_ctxsize += inst->alg.ivsize;
856e3f409   Herbert Xu   crypto: seqiv - A...
147

0677157b2   Herbert Xu   crypto: seqiv - U...
148
  	err = aead_register_instance(tmpl, inst);
0f8f6d86d   Eric Biggers   crypto: geniv - c...
149
  	if (err) {
0677157b2   Herbert Xu   crypto: seqiv - U...
150
  free_inst:
0f8f6d86d   Eric Biggers   crypto: geniv - c...
151
152
153
  		inst->free(inst);
  	}
  	return err;
14df4d804   Herbert Xu   [CRYPTO] seqiv: A...
154
  }
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
155
156
  static struct crypto_template seqiv_tmpl = {
  	.name = "seqiv",
4688111e7   Eric Biggers   crypto: seqiv - r...
157
  	.create = seqiv_aead_create,
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
158
159
160
161
162
  	.module = THIS_MODULE,
  };
  
  static int __init seqiv_module_init(void)
  {
8a2cd1c4a   Herbert Xu   crypto: seqiv - R...
163
  	return crypto_register_template(&seqiv_tmpl);
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
164
165
166
167
168
169
  }
  
  static void __exit seqiv_module_exit(void)
  {
  	crypto_unregister_template(&seqiv_tmpl);
  }
c4741b230   Eric Biggers   crypto: run initc...
170
  subsys_initcall(seqiv_module_init);
0a270321d   Herbert Xu   [CRYPTO] seqiv: A...
171
172
173
174
  module_exit(seqiv_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Sequence Number IV Generator");
4943ba16b   Kees Cook   crypto: include c...
175
  MODULE_ALIAS_CRYPTO("seqiv");