2 * Glue Code for SSE2 assembler versions of Serpent Cipher
4 * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6 * Glue code based on aesni-intel_glue.c by:
7 * Copyright (C) 2008, Intel Corp.
8 * Author: Huang Ying <ying.huang@intel.com>
10 * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
11 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
12 * CTR part based on code (crypto/ctr.c) by:
13 * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include <linux/module.h>
33 #include <linux/types.h>
34 #include <linux/crypto.h>
35 #include <linux/err.h>
36 #include <crypto/algapi.h>
37 #include <crypto/b128ops.h>
38 #include <crypto/internal/simd.h>
39 #include <crypto/serpent.h>
40 #include <asm/crypto/serpent-sse2.h>
41 #include <asm/crypto/glue_helper.h>
43 static int serpent_setkey_skcipher(struct crypto_skcipher
*tfm
,
44 const u8
*key
, unsigned int keylen
)
46 return __serpent_setkey(crypto_skcipher_ctx(tfm
), key
, keylen
);
49 static void serpent_decrypt_cbc_xway(void *ctx
, u128
*dst
, const u128
*src
)
51 u128 ivs
[SERPENT_PARALLEL_BLOCKS
- 1];
54 for (j
= 0; j
< SERPENT_PARALLEL_BLOCKS
- 1; j
++)
57 serpent_dec_blk_xway(ctx
, (u8
*)dst
, (u8
*)src
);
59 for (j
= 0; j
< SERPENT_PARALLEL_BLOCKS
- 1; j
++)
60 u128_xor(dst
+ (j
+ 1), dst
+ (j
+ 1), ivs
+ j
);
63 static void serpent_crypt_ctr(void *ctx
, u128
*dst
, const u128
*src
, le128
*iv
)
67 le128_to_be128(&ctrblk
, iv
);
70 __serpent_encrypt(ctx
, (u8
*)&ctrblk
, (u8
*)&ctrblk
);
71 u128_xor(dst
, src
, (u128
*)&ctrblk
);
74 static void serpent_crypt_ctr_xway(void *ctx
, u128
*dst
, const u128
*src
,
77 be128 ctrblks
[SERPENT_PARALLEL_BLOCKS
];
80 for (i
= 0; i
< SERPENT_PARALLEL_BLOCKS
; i
++) {
84 le128_to_be128(&ctrblks
[i
], iv
);
88 serpent_enc_blk_xway_xor(ctx
, (u8
*)dst
, (u8
*)ctrblks
);
91 static const struct common_glue_ctx serpent_enc
= {
93 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
96 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
97 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_enc_blk_xway
) }
100 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_encrypt
) }
104 static const struct common_glue_ctx serpent_ctr
= {
106 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
109 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
110 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway
) }
113 .fn_u
= { .ctr
= GLUE_CTR_FUNC_CAST(serpent_crypt_ctr
) }
117 static const struct common_glue_ctx serpent_dec
= {
119 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
122 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
123 .fn_u
= { .ecb
= GLUE_FUNC_CAST(serpent_dec_blk_xway
) }
126 .fn_u
= { .ecb
= GLUE_FUNC_CAST(__serpent_decrypt
) }
130 static const struct common_glue_ctx serpent_dec_cbc
= {
132 .fpu_blocks_limit
= SERPENT_PARALLEL_BLOCKS
,
135 .num_blocks
= SERPENT_PARALLEL_BLOCKS
,
136 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway
) }
139 .fn_u
= { .cbc
= GLUE_CBC_FUNC_CAST(__serpent_decrypt
) }
143 static int ecb_encrypt(struct skcipher_request
*req
)
145 return glue_ecb_req_128bit(&serpent_enc
, req
);
148 static int ecb_decrypt(struct skcipher_request
*req
)
150 return glue_ecb_req_128bit(&serpent_dec
, req
);
153 static int cbc_encrypt(struct skcipher_request
*req
)
155 return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt
),
159 static int cbc_decrypt(struct skcipher_request
*req
)
161 return glue_cbc_decrypt_req_128bit(&serpent_dec_cbc
, req
);
164 static int ctr_crypt(struct skcipher_request
*req
)
166 return glue_ctr_req_128bit(&serpent_ctr
, req
);
169 static struct skcipher_alg serpent_algs
[] = {
171 .base
.cra_name
= "__ecb(serpent)",
172 .base
.cra_driver_name
= "__ecb-serpent-sse2",
173 .base
.cra_priority
= 400,
174 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
175 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
176 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
177 .base
.cra_module
= THIS_MODULE
,
178 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
179 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
180 .setkey
= serpent_setkey_skcipher
,
181 .encrypt
= ecb_encrypt
,
182 .decrypt
= ecb_decrypt
,
184 .base
.cra_name
= "__cbc(serpent)",
185 .base
.cra_driver_name
= "__cbc-serpent-sse2",
186 .base
.cra_priority
= 400,
187 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
188 .base
.cra_blocksize
= SERPENT_BLOCK_SIZE
,
189 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
190 .base
.cra_module
= THIS_MODULE
,
191 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
192 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
193 .ivsize
= SERPENT_BLOCK_SIZE
,
194 .setkey
= serpent_setkey_skcipher
,
195 .encrypt
= cbc_encrypt
,
196 .decrypt
= cbc_decrypt
,
198 .base
.cra_name
= "__ctr(serpent)",
199 .base
.cra_driver_name
= "__ctr-serpent-sse2",
200 .base
.cra_priority
= 400,
201 .base
.cra_flags
= CRYPTO_ALG_INTERNAL
,
202 .base
.cra_blocksize
= 1,
203 .base
.cra_ctxsize
= sizeof(struct serpent_ctx
),
204 .base
.cra_module
= THIS_MODULE
,
205 .min_keysize
= SERPENT_MIN_KEY_SIZE
,
206 .max_keysize
= SERPENT_MAX_KEY_SIZE
,
207 .ivsize
= SERPENT_BLOCK_SIZE
,
208 .chunksize
= SERPENT_BLOCK_SIZE
,
209 .setkey
= serpent_setkey_skcipher
,
210 .encrypt
= ctr_crypt
,
211 .decrypt
= ctr_crypt
,
215 static struct simd_skcipher_alg
*serpent_simd_algs
[ARRAY_SIZE(serpent_algs
)];
217 static int __init
serpent_sse2_init(void)
219 if (!boot_cpu_has(X86_FEATURE_XMM2
)) {
220 printk(KERN_INFO
"SSE2 instructions are not detected.\n");
224 return simd_register_skciphers_compat(serpent_algs
,
225 ARRAY_SIZE(serpent_algs
),
229 static void __exit
serpent_sse2_exit(void)
231 simd_unregister_skciphers(serpent_algs
, ARRAY_SIZE(serpent_algs
),
235 module_init(serpent_sse2_init
);
236 module_exit(serpent_sse2_exit
);
238 MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
239 MODULE_LICENSE("GPL");
240 MODULE_ALIAS_CRYPTO("serpent");