6 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
14 #include <linux/kernel.h>
15 #include <linux/crypto.h>
16 #include <linux/errno.h>
18 #include <linux/slab.h>
19 #include <asm/scatterlist.h>
21 #include "scatterwalk.h"
23 typedef void (cryptfn_t
)(void *, u8
*, const u8
*);
24 typedef void (procfn_t
)(struct crypto_tfm
*, u8
*,
25 u8
*, cryptfn_t
, int enc
, void *, int);
27 static inline void xor_64(u8
*a
, const u8
*b
)
29 ((u32
*)a
)[0] ^= ((u32
*)b
)[0];
30 ((u32
*)a
)[1] ^= ((u32
*)b
)[1];
33 static inline void xor_128(u8
*a
, const u8
*b
)
35 ((u32
*)a
)[0] ^= ((u32
*)b
)[0];
36 ((u32
*)a
)[1] ^= ((u32
*)b
)[1];
37 ((u32
*)a
)[2] ^= ((u32
*)b
)[2];
38 ((u32
*)a
)[3] ^= ((u32
*)b
)[3];
43 * Generic encrypt/decrypt wrapper for ciphers, handles operations across
44 * multiple page boundaries by using temporary blocks. In user context,
45 * the kernel is given a chance to schedule us once per block.
47 static int crypt(struct crypto_tfm
*tfm
,
48 struct scatterlist
*dst
,
49 struct scatterlist
*src
,
50 unsigned int nbytes
, cryptfn_t crfn
,
51 procfn_t prfn
, int enc
, void *info
)
53 struct scatter_walk walk_in
, walk_out
;
54 const unsigned int bsize
= crypto_tfm_alg_blocksize(tfm
);
62 tfm
->crt_flags
|= CRYPTO_TFM_RES_BAD_BLOCK_LEN
;
66 scatterwalk_start(&walk_in
, src
);
67 scatterwalk_start(&walk_out
, dst
);
73 scatterwalk_map(&walk_in
, 0);
74 scatterwalk_map(&walk_out
, 1);
75 src_p
= scatterwalk_whichbuf(&walk_in
, bsize
, tmp_src
);
76 dst_p
= scatterwalk_whichbuf(&walk_out
, bsize
, tmp_dst
);
77 in_place
= scatterwalk_samebuf(&walk_in
, &walk_out
,
82 scatterwalk_copychunks(src_p
, &walk_in
, bsize
, 0);
84 prfn(tfm
, dst_p
, src_p
, crfn
, enc
, info
, in_place
);
86 scatterwalk_done(&walk_in
, 0, nbytes
);
88 scatterwalk_copychunks(dst_p
, &walk_out
, bsize
, 1);
89 scatterwalk_done(&walk_out
, 1, nbytes
);
98 static void cbc_process(struct crypto_tfm
*tfm
, u8
*dst
, u8
*src
,
99 cryptfn_t fn
, int enc
, void *info
, int in_place
)
103 /* Null encryption */
108 tfm
->crt_u
.cipher
.cit_xor_block(iv
, src
);
109 fn(crypto_tfm_ctx(tfm
), dst
, iv
);
110 memcpy(iv
, dst
, crypto_tfm_alg_blocksize(tfm
));
112 u8 stack
[in_place
? crypto_tfm_alg_blocksize(tfm
) : 0];
113 u8
*buf
= in_place
? stack
: dst
;
115 fn(crypto_tfm_ctx(tfm
), buf
, src
);
116 tfm
->crt_u
.cipher
.cit_xor_block(buf
, iv
);
117 memcpy(iv
, src
, crypto_tfm_alg_blocksize(tfm
));
119 memcpy(dst
, buf
, crypto_tfm_alg_blocksize(tfm
));
123 static void ecb_process(struct crypto_tfm
*tfm
, u8
*dst
, u8
*src
,
124 cryptfn_t fn
, int enc
, void *info
, int in_place
)
126 fn(crypto_tfm_ctx(tfm
), dst
, src
);
129 static int setkey(struct crypto_tfm
*tfm
, const u8
*key
, unsigned int keylen
)
131 struct cipher_alg
*cia
= &tfm
->__crt_alg
->cra_cipher
;
133 if (keylen
< cia
->cia_min_keysize
|| keylen
> cia
->cia_max_keysize
) {
134 tfm
->crt_flags
|= CRYPTO_TFM_RES_BAD_KEY_LEN
;
137 return cia
->cia_setkey(crypto_tfm_ctx(tfm
), key
, keylen
,
141 static int ecb_encrypt(struct crypto_tfm
*tfm
,
142 struct scatterlist
*dst
,
143 struct scatterlist
*src
, unsigned int nbytes
)
145 return crypt(tfm
, dst
, src
, nbytes
,
146 tfm
->__crt_alg
->cra_cipher
.cia_encrypt
,
147 ecb_process
, 1, NULL
);
150 static int ecb_decrypt(struct crypto_tfm
*tfm
,
151 struct scatterlist
*dst
,
152 struct scatterlist
*src
,
155 return crypt(tfm
, dst
, src
, nbytes
,
156 tfm
->__crt_alg
->cra_cipher
.cia_decrypt
,
157 ecb_process
, 1, NULL
);
160 static int cbc_encrypt(struct crypto_tfm
*tfm
,
161 struct scatterlist
*dst
,
162 struct scatterlist
*src
,
165 return crypt(tfm
, dst
, src
, nbytes
,
166 tfm
->__crt_alg
->cra_cipher
.cia_encrypt
,
167 cbc_process
, 1, tfm
->crt_cipher
.cit_iv
);
170 static int cbc_encrypt_iv(struct crypto_tfm
*tfm
,
171 struct scatterlist
*dst
,
172 struct scatterlist
*src
,
173 unsigned int nbytes
, u8
*iv
)
175 return crypt(tfm
, dst
, src
, nbytes
,
176 tfm
->__crt_alg
->cra_cipher
.cia_encrypt
,
180 static int cbc_decrypt(struct crypto_tfm
*tfm
,
181 struct scatterlist
*dst
,
182 struct scatterlist
*src
,
185 return crypt(tfm
, dst
, src
, nbytes
,
186 tfm
->__crt_alg
->cra_cipher
.cia_decrypt
,
187 cbc_process
, 0, tfm
->crt_cipher
.cit_iv
);
190 static int cbc_decrypt_iv(struct crypto_tfm
*tfm
,
191 struct scatterlist
*dst
,
192 struct scatterlist
*src
,
193 unsigned int nbytes
, u8
*iv
)
195 return crypt(tfm
, dst
, src
, nbytes
,
196 tfm
->__crt_alg
->cra_cipher
.cia_decrypt
,
200 static int nocrypt(struct crypto_tfm
*tfm
,
201 struct scatterlist
*dst
,
202 struct scatterlist
*src
,
208 static int nocrypt_iv(struct crypto_tfm
*tfm
,
209 struct scatterlist
*dst
,
210 struct scatterlist
*src
,
211 unsigned int nbytes
, u8
*iv
)
216 int crypto_init_cipher_flags(struct crypto_tfm
*tfm
, u32 flags
)
218 u32 mode
= flags
& CRYPTO_TFM_MODE_MASK
;
220 tfm
->crt_cipher
.cit_mode
= mode
? mode
: CRYPTO_TFM_MODE_ECB
;
221 if (flags
& CRYPTO_TFM_REQ_WEAK_KEY
)
222 tfm
->crt_flags
= CRYPTO_TFM_REQ_WEAK_KEY
;
227 int crypto_init_cipher_ops(struct crypto_tfm
*tfm
)
230 struct cipher_tfm
*ops
= &tfm
->crt_cipher
;
232 ops
->cit_setkey
= setkey
;
234 switch (tfm
->crt_cipher
.cit_mode
) {
235 case CRYPTO_TFM_MODE_ECB
:
236 ops
->cit_encrypt
= ecb_encrypt
;
237 ops
->cit_decrypt
= ecb_decrypt
;
240 case CRYPTO_TFM_MODE_CBC
:
241 ops
->cit_encrypt
= cbc_encrypt
;
242 ops
->cit_decrypt
= cbc_decrypt
;
243 ops
->cit_encrypt_iv
= cbc_encrypt_iv
;
244 ops
->cit_decrypt_iv
= cbc_decrypt_iv
;
247 case CRYPTO_TFM_MODE_CFB
:
248 ops
->cit_encrypt
= nocrypt
;
249 ops
->cit_decrypt
= nocrypt
;
250 ops
->cit_encrypt_iv
= nocrypt_iv
;
251 ops
->cit_decrypt_iv
= nocrypt_iv
;
254 case CRYPTO_TFM_MODE_CTR
:
255 ops
->cit_encrypt
= nocrypt
;
256 ops
->cit_decrypt
= nocrypt
;
257 ops
->cit_encrypt_iv
= nocrypt_iv
;
258 ops
->cit_decrypt_iv
= nocrypt_iv
;
265 if (ops
->cit_mode
== CRYPTO_TFM_MODE_CBC
) {
267 switch (crypto_tfm_alg_blocksize(tfm
)) {
269 ops
->cit_xor_block
= xor_64
;
273 ops
->cit_xor_block
= xor_128
;
277 printk(KERN_WARNING
"%s: block size %u not supported\n",
278 crypto_tfm_alg_name(tfm
),
279 crypto_tfm_alg_blocksize(tfm
));
284 ops
->cit_ivsize
= crypto_tfm_alg_blocksize(tfm
);
285 ops
->cit_iv
= kmalloc(ops
->cit_ivsize
, GFP_KERNEL
);
286 if (ops
->cit_iv
== NULL
)
294 void crypto_exit_cipher_ops(struct crypto_tfm
*tfm
)
296 if (tfm
->crt_cipher
.cit_iv
)
297 kfree(tfm
->crt_cipher
.cit_iv
);