Skip to content

Commit f6bccf6

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: crypto: skcipher - Use RNG interface instead of get_random_bytes crypto: rng - RNG interface and implementation crypto: api - Add fips_enable flag crypto: skcipher - Move IV generators into their own modules crypto: cryptomgr - Test ciphers using ECB crypto: api - Use test infrastructure crypto: cryptomgr - Add test infrastructure crypto: tcrypt - Add alg_test interface crypto: tcrypt - Abort and only log if there is an error crypto: crc32c - Use Intel CRC32 instruction crypto: tcrypt - Avoid using contiguous pages crypto: api - Display larval objects properly crypto: api - Export crypto_alg_lookup instead of __crypto_alg_lookup crypto: Kconfig - Replace leading spaces with tabs
2 parents 3af73d3 + a0f000e commit f6bccf6

File tree

25 files changed

+12249
-10059
lines changed

25 files changed

+12249
-10059
lines changed

arch/x86/crypto/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
1010
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
1111
obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
1212

13+
obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
14+
1315
aes-i586-y := aes-i586-asm_32.o aes_glue.o
1416
twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
1517
salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o

arch/x86/crypto/crc32c-intel.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Using hardware provided CRC32 instruction to accelerate the CRC32 disposal.
3+
* CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE)
4+
* CRC32 is a new instruction in Intel SSE4.2, the reference can be found at:
5+
* http://www.intel.com/products/processor/manuals/
6+
* Intel(R) 64 and IA-32 Architectures Software Developer's Manual
7+
* Volume 2A: Instruction Set Reference, A-M
8+
*
9+
* Copyright (c) 2008 Austin Zhang <[email protected]>
10+
* Copyright (c) 2008 Kent Liu <[email protected]>
11+
*
12+
* This program is free software; you can redistribute it and/or modify it
13+
* under the terms of the GNU General Public License as published by the Free
14+
* Software Foundation; either version 2 of the License, or (at your option)
15+
* any later version.
16+
*
17+
*/
18+
#include <linux/init.h>
19+
#include <linux/module.h>
20+
#include <linux/string.h>
21+
#include <linux/kernel.h>
22+
#include <crypto/internal/hash.h>
23+
24+
#include <asm/cpufeature.h>
25+
26+
#define CHKSUM_BLOCK_SIZE 1
27+
#define CHKSUM_DIGEST_SIZE 4
28+
29+
#define SCALE_F sizeof(unsigned long)
30+
31+
#ifdef CONFIG_X86_64
32+
#define REX_PRE "0x48, "
33+
#else
34+
#define REX_PRE
35+
#endif
36+
37+
static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
38+
{
39+
while (length--) {
40+
__asm__ __volatile__(
41+
".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
42+
:"=S"(crc)
43+
:"0"(crc), "c"(*data)
44+
);
45+
data++;
46+
}
47+
48+
return crc;
49+
}
50+
51+
static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len)
52+
{
53+
unsigned int iquotient = len / SCALE_F;
54+
unsigned int iremainder = len % SCALE_F;
55+
unsigned long *ptmp = (unsigned long *)p;
56+
57+
while (iquotient--) {
58+
__asm__ __volatile__(
59+
".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;"
60+
:"=S"(crc)
61+
:"0"(crc), "c"(*ptmp)
62+
);
63+
ptmp++;
64+
}
65+
66+
if (iremainder)
67+
crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp,
68+
iremainder);
69+
70+
return crc;
71+
}
72+
73+
/*
74+
* Setting the seed allows arbitrary accumulators and flexible XOR policy
75+
* If your algorithm starts with ~0, then XOR with ~0 before you set
76+
* the seed.
77+
*/
78+
static int crc32c_intel_setkey(struct crypto_ahash *hash, const u8 *key,
79+
unsigned int keylen)
80+
{
81+
u32 *mctx = crypto_ahash_ctx(hash);
82+
83+
if (keylen != sizeof(u32)) {
84+
crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
85+
return -EINVAL;
86+
}
87+
*mctx = le32_to_cpup((__le32 *)key);
88+
return 0;
89+
}
90+
91+
static int crc32c_intel_init(struct ahash_request *req)
92+
{
93+
u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
94+
u32 *crcp = ahash_request_ctx(req);
95+
96+
*crcp = *mctx;
97+
98+
return 0;
99+
}
100+
101+
static int crc32c_intel_update(struct ahash_request *req)
102+
{
103+
struct crypto_hash_walk walk;
104+
u32 *crcp = ahash_request_ctx(req);
105+
u32 crc = *crcp;
106+
int nbytes;
107+
108+
for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
109+
nbytes = crypto_hash_walk_done(&walk, 0))
110+
crc = crc32c_intel_le_hw(crc, walk.data, nbytes);
111+
112+
*crcp = crc;
113+
return 0;
114+
}
115+
116+
static int crc32c_intel_final(struct ahash_request *req)
117+
{
118+
u32 *crcp = ahash_request_ctx(req);
119+
120+
*(__le32 *)req->result = ~cpu_to_le32p(crcp);
121+
return 0;
122+
}
123+
124+
static int crc32c_intel_digest(struct ahash_request *req)
125+
{
126+
struct crypto_hash_walk walk;
127+
u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
128+
u32 crc = *mctx;
129+
int nbytes;
130+
131+
for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
132+
nbytes = crypto_hash_walk_done(&walk, 0))
133+
crc = crc32c_intel_le_hw(crc, walk.data, nbytes);
134+
135+
*(__le32 *)req->result = ~cpu_to_le32(crc);
136+
return 0;
137+
}
138+
139+
static int crc32c_intel_cra_init(struct crypto_tfm *tfm)
140+
{
141+
u32 *key = crypto_tfm_ctx(tfm);
142+
143+
*key = ~0;
144+
145+
tfm->crt_ahash.reqsize = sizeof(u32);
146+
147+
return 0;
148+
}
149+
150+
static struct crypto_alg alg = {
151+
.cra_name = "crc32c",
152+
.cra_driver_name = "crc32c-intel",
153+
.cra_priority = 200,
154+
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
155+
.cra_blocksize = CHKSUM_BLOCK_SIZE,
156+
.cra_alignmask = 3,
157+
.cra_ctxsize = sizeof(u32),
158+
.cra_module = THIS_MODULE,
159+
.cra_list = LIST_HEAD_INIT(alg.cra_list),
160+
.cra_init = crc32c_intel_cra_init,
161+
.cra_type = &crypto_ahash_type,
162+
.cra_u = {
163+
.ahash = {
164+
.digestsize = CHKSUM_DIGEST_SIZE,
165+
.setkey = crc32c_intel_setkey,
166+
.init = crc32c_intel_init,
167+
.update = crc32c_intel_update,
168+
.final = crc32c_intel_final,
169+
.digest = crc32c_intel_digest,
170+
}
171+
}
172+
};
173+
174+
175+
static int __init crc32c_intel_mod_init(void)
176+
{
177+
if (cpu_has_xmm4_2)
178+
return crypto_register_alg(&alg);
179+
else
180+
return -ENODEV;
181+
}
182+
183+
static void __exit crc32c_intel_mod_fini(void)
184+
{
185+
crypto_unregister_alg(&alg);
186+
}
187+
188+
module_init(crc32c_intel_mod_init);
189+
module_exit(crc32c_intel_mod_fini);
190+
191+
MODULE_AUTHOR("Austin Zhang <[email protected]>, Kent Liu <[email protected]>");
192+
MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware.");
193+
MODULE_LICENSE("GPL");
194+
195+
MODULE_ALIAS("crc32c");
196+
MODULE_ALIAS("crc32c-intel");
197+

0 commit comments

Comments
 (0)