Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/crypto/serpent_sse2_glue.c
121833 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Glue Code for SSE2 assembler versions of Serpent Cipher
4
*
5
* Copyright (c) 2011 Jussi Kivilinna <[email protected]>
6
*
7
* Glue code based on aesni-intel_glue.c by:
8
* Copyright (C) 2008, Intel Corp.
9
* Author: Huang Ying <[email protected]>
10
*
11
* CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
12
* Copyright (c) 2006 Herbert Xu <[email protected]>
13
*/
14
15
#include <linux/module.h>
16
#include <linux/types.h>
17
#include <linux/crypto.h>
18
#include <linux/err.h>
19
#include <crypto/algapi.h>
20
#include <crypto/b128ops.h>
21
#include <crypto/serpent.h>
22
23
#include "serpent-sse2.h"
24
#include "ecb_cbc_helpers.h"
25
26
static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
27
const u8 *key, unsigned int keylen)
28
{
29
return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
30
}
31
32
static void serpent_decrypt_cbc_xway(const void *ctx, u8 *dst, const u8 *src)
33
{
34
u8 buf[SERPENT_PARALLEL_BLOCKS - 1][SERPENT_BLOCK_SIZE];
35
const u8 *s = src;
36
37
if (dst == src)
38
s = memcpy(buf, src, sizeof(buf));
39
serpent_dec_blk_xway(ctx, dst, src);
40
crypto_xor(dst + SERPENT_BLOCK_SIZE, s, sizeof(buf));
41
}
42
43
static int ecb_encrypt(struct skcipher_request *req)
44
{
45
ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
46
ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_enc_blk_xway);
47
ECB_BLOCK(1, __serpent_encrypt);
48
ECB_WALK_END();
49
}
50
51
static int ecb_decrypt(struct skcipher_request *req)
52
{
53
ECB_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
54
ECB_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_dec_blk_xway);
55
ECB_BLOCK(1, __serpent_decrypt);
56
ECB_WALK_END();
57
}
58
59
static int cbc_encrypt(struct skcipher_request *req)
60
{
61
CBC_WALK_START(req, SERPENT_BLOCK_SIZE, -1);
62
CBC_ENC_BLOCK(__serpent_encrypt);
63
CBC_WALK_END();
64
}
65
66
static int cbc_decrypt(struct skcipher_request *req)
67
{
68
CBC_WALK_START(req, SERPENT_BLOCK_SIZE, SERPENT_PARALLEL_BLOCKS);
69
CBC_DEC_BLOCK(SERPENT_PARALLEL_BLOCKS, serpent_decrypt_cbc_xway);
70
CBC_DEC_BLOCK(1, __serpent_decrypt);
71
CBC_WALK_END();
72
}
73
74
static struct skcipher_alg serpent_algs[] = {
75
{
76
.base.cra_name = "ecb(serpent)",
77
.base.cra_driver_name = "ecb-serpent-sse2",
78
.base.cra_priority = 400,
79
.base.cra_blocksize = SERPENT_BLOCK_SIZE,
80
.base.cra_ctxsize = sizeof(struct serpent_ctx),
81
.base.cra_module = THIS_MODULE,
82
.min_keysize = SERPENT_MIN_KEY_SIZE,
83
.max_keysize = SERPENT_MAX_KEY_SIZE,
84
.setkey = serpent_setkey_skcipher,
85
.encrypt = ecb_encrypt,
86
.decrypt = ecb_decrypt,
87
}, {
88
.base.cra_name = "cbc(serpent)",
89
.base.cra_driver_name = "cbc-serpent-sse2",
90
.base.cra_priority = 400,
91
.base.cra_blocksize = SERPENT_BLOCK_SIZE,
92
.base.cra_ctxsize = sizeof(struct serpent_ctx),
93
.base.cra_module = THIS_MODULE,
94
.min_keysize = SERPENT_MIN_KEY_SIZE,
95
.max_keysize = SERPENT_MAX_KEY_SIZE,
96
.ivsize = SERPENT_BLOCK_SIZE,
97
.setkey = serpent_setkey_skcipher,
98
.encrypt = cbc_encrypt,
99
.decrypt = cbc_decrypt,
100
},
101
};
102
103
static int __init serpent_sse2_init(void)
104
{
105
if (!boot_cpu_has(X86_FEATURE_XMM2)) {
106
printk(KERN_INFO "SSE2 instructions are not detected.\n");
107
return -ENODEV;
108
}
109
110
return crypto_register_skciphers(serpent_algs,
111
ARRAY_SIZE(serpent_algs));
112
}
113
114
static void __exit serpent_sse2_exit(void)
115
{
116
crypto_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs));
117
}
118
119
module_init(serpent_sse2_init);
120
module_exit(serpent_sse2_exit);
121
122
MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
123
MODULE_LICENSE("GPL");
124
MODULE_ALIAS_CRYPTO("serpent");
125
126