Blame view

crypto/ecb.c 4.87 KB
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  /*
   * ECB: Electronic CodeBook mode
   *
   * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   *
   */
  
  #include <crypto/algapi.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/scatterlist.h>
  #include <linux/slab.h>
  
  struct crypto_ecb_ctx {
  	struct crypto_cipher *child;
  };
  
  static int crypto_ecb_setkey(struct crypto_tfm *parent, const u8 *key,
  			     unsigned int keylen)
  {
  	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(parent);
  	struct crypto_cipher *child = ctx->child;
  	int err;
  
  	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
  				       CRYPTO_TFM_REQ_MASK);
  	err = crypto_cipher_setkey(child, key, keylen);
  	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
  				     CRYPTO_TFM_RES_MASK);
  	return err;
  }
  
  static int crypto_ecb_crypt(struct blkcipher_desc *desc,
  			    struct blkcipher_walk *walk,
  			    struct crypto_cipher *tfm,
  			    void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
  {
  	int bsize = crypto_cipher_blocksize(tfm);
  	unsigned int nbytes;
  	int err;
  
  	err = blkcipher_walk_virt(desc, walk);
  
  	while ((nbytes = walk->nbytes)) {
  		u8 *wsrc = walk->src.virt.addr;
  		u8 *wdst = walk->dst.virt.addr;
  
  		do {
  			fn(crypto_cipher_tfm(tfm), wdst, wsrc);
5b37c19e3   Richard Hartmann   crypto: ecb - Fix...
58

db131ef90   Herbert Xu   [CRYPTO] cipher: ...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  			wsrc += bsize;
  			wdst += bsize;
  		} while ((nbytes -= bsize) >= bsize);
  
  		err = blkcipher_walk_done(desc, walk, nbytes);
  	}
  
  	return err;
  }
  
  static int crypto_ecb_encrypt(struct blkcipher_desc *desc,
  			      struct scatterlist *dst, struct scatterlist *src,
  			      unsigned int nbytes)
  {
  	struct blkcipher_walk walk;
  	struct crypto_blkcipher *tfm = desc->tfm;
  	struct crypto_ecb_ctx *ctx = crypto_blkcipher_ctx(tfm);
  	struct crypto_cipher *child = ctx->child;
  
  	blkcipher_walk_init(&walk, dst, src, nbytes);
  	return crypto_ecb_crypt(desc, &walk, child,
  				crypto_cipher_alg(child)->cia_encrypt);
  }
  
  static int crypto_ecb_decrypt(struct blkcipher_desc *desc,
  			      struct scatterlist *dst, struct scatterlist *src,
  			      unsigned int nbytes)
  {
  	struct blkcipher_walk walk;
  	struct crypto_blkcipher *tfm = desc->tfm;
  	struct crypto_ecb_ctx *ctx = crypto_blkcipher_ctx(tfm);
  	struct crypto_cipher *child = ctx->child;
  
  	blkcipher_walk_init(&walk, dst, src, nbytes);
  	return crypto_ecb_crypt(desc, &walk, child,
  				crypto_cipher_alg(child)->cia_decrypt);
  }
  
  static int crypto_ecb_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_instance *inst = (void *)tfm->__crt_alg;
  	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
2e306ee01   Herbert Xu   [CRYPTO] api: Add...
102
  	struct crypto_cipher *cipher;
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
103

2e306ee01   Herbert Xu   [CRYPTO] api: Add...
104
105
106
  	cipher = crypto_spawn_cipher(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
107

2e306ee01   Herbert Xu   [CRYPTO] api: Add...
108
  	ctx->child = cipher;
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
109
110
111
112
113
114
115
116
  	return 0;
  }
  
  static void crypto_ecb_exit_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
  	crypto_free_cipher(ctx->child);
  }
ebc610e5b   Herbert Xu   [CRYPTO] template...
117
  static struct crypto_instance *crypto_ecb_alloc(struct rtattr **tb)
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
118
119
120
  {
  	struct crypto_instance *inst;
  	struct crypto_alg *alg;
ebc610e5b   Herbert Xu   [CRYPTO] template...
121
122
123
124
125
  	int err;
  
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
  	if (err)
  		return ERR_PTR(err);
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
126

ebc610e5b   Herbert Xu   [CRYPTO] template...
127
128
  	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
  				  CRYPTO_ALG_TYPE_MASK);
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
129
  	if (IS_ERR(alg))
e231c2ee6   David Howells   Convert ERR_PTR(P...
130
  		return ERR_CAST(alg);
db131ef90   Herbert Xu   [CRYPTO] cipher: ...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  
  	inst = crypto_alloc_instance("ecb", alg);
  	if (IS_ERR(inst))
  		goto out_put_alg;
  
  	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
  	inst->alg.cra_priority = alg->cra_priority;
  	inst->alg.cra_blocksize = alg->cra_blocksize;
  	inst->alg.cra_alignmask = alg->cra_alignmask;
  	inst->alg.cra_type = &crypto_blkcipher_type;
  
  	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
  	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
  
  	inst->alg.cra_ctxsize = sizeof(struct crypto_ecb_ctx);
  
  	inst->alg.cra_init = crypto_ecb_init_tfm;
  	inst->alg.cra_exit = crypto_ecb_exit_tfm;
  
  	inst->alg.cra_blkcipher.setkey = crypto_ecb_setkey;
  	inst->alg.cra_blkcipher.encrypt = crypto_ecb_encrypt;
  	inst->alg.cra_blkcipher.decrypt = crypto_ecb_decrypt;
  
  out_put_alg:
  	crypto_mod_put(alg);
  	return inst;
  }
  
  static void crypto_ecb_free(struct crypto_instance *inst)
  {
  	crypto_drop_spawn(crypto_instance_ctx(inst));
  	kfree(inst);
  }
  
  static struct crypto_template crypto_ecb_tmpl = {
  	.name = "ecb",
  	.alloc = crypto_ecb_alloc,
  	.free = crypto_ecb_free,
  	.module = THIS_MODULE,
  };
  
  static int __init crypto_ecb_module_init(void)
  {
  	return crypto_register_template(&crypto_ecb_tmpl);
  }
  
  static void __exit crypto_ecb_module_exit(void)
  {
  	crypto_unregister_template(&crypto_ecb_tmpl);
  }
  
  module_init(crypto_ecb_module_init);
  module_exit(crypto_ecb_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("ECB block cipher algorithm");