1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C)2006 USAGI/WIDE Project
6 * Kazunori Miyazawa <miyazawa@linux-ipv6.org>
9 #include <crypto/internal/cipher.h>
10 #include <crypto/internal/hash.h>
11 #include <linux/err.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 static u_int32_t ks
[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
16 0x02020202, 0x02020202, 0x02020202, 0x02020202,
17 0x03030303, 0x03030303, 0x03030303, 0x03030303};
20 * +------------------------
22 * +------------------------
24 * +------------------------
25 * | consts (block size * 2)
26 * +------------------------
29 struct crypto_cipher
*child
;
34 * +------------------------
36 * +------------------------
38 * +------------------------
40 * +------------------------
42 * +------------------------
44 struct xcbc_desc_ctx
{
49 #define XCBC_BLOCKSIZE 16
51 static int crypto_xcbc_digest_setkey(struct crypto_shash
*parent
,
52 const u8
*inkey
, unsigned int keylen
)
54 unsigned long alignmask
= crypto_shash_alignmask(parent
);
55 struct xcbc_tfm_ctx
*ctx
= crypto_shash_ctx(parent
);
56 u8
*consts
= PTR_ALIGN(&ctx
->ctx
[0], alignmask
+ 1);
58 u8 key1
[XCBC_BLOCKSIZE
];
59 int bs
= sizeof(key1
);
61 if ((err
= crypto_cipher_setkey(ctx
->child
, inkey
, keylen
)))
64 crypto_cipher_encrypt_one(ctx
->child
, consts
, (u8
*)ks
+ bs
);
65 crypto_cipher_encrypt_one(ctx
->child
, consts
+ bs
, (u8
*)ks
+ bs
* 2);
66 crypto_cipher_encrypt_one(ctx
->child
, key1
, (u8
*)ks
);
68 return crypto_cipher_setkey(ctx
->child
, key1
, bs
);
72 static int crypto_xcbc_digest_init(struct shash_desc
*pdesc
)
74 unsigned long alignmask
= crypto_shash_alignmask(pdesc
->tfm
);
75 struct xcbc_desc_ctx
*ctx
= shash_desc_ctx(pdesc
);
76 int bs
= crypto_shash_blocksize(pdesc
->tfm
);
77 u8
*prev
= PTR_ALIGN(&ctx
->ctx
[0], alignmask
+ 1) + bs
;
85 static int crypto_xcbc_digest_update(struct shash_desc
*pdesc
, const u8
*p
,
88 struct crypto_shash
*parent
= pdesc
->tfm
;
89 unsigned long alignmask
= crypto_shash_alignmask(parent
);
90 struct xcbc_tfm_ctx
*tctx
= crypto_shash_ctx(parent
);
91 struct xcbc_desc_ctx
*ctx
= shash_desc_ctx(pdesc
);
92 struct crypto_cipher
*tfm
= tctx
->child
;
93 int bs
= crypto_shash_blocksize(parent
);
94 u8
*odds
= PTR_ALIGN(&ctx
->ctx
[0], alignmask
+ 1);
97 /* checking the data can fill the block */
98 if ((ctx
->len
+ len
) <= bs
) {
99 memcpy(odds
+ ctx
->len
, p
, len
);
104 /* filling odds with new data and encrypting it */
105 memcpy(odds
+ ctx
->len
, p
, bs
- ctx
->len
);
106 len
-= bs
- ctx
->len
;
109 crypto_xor(prev
, odds
, bs
);
110 crypto_cipher_encrypt_one(tfm
, prev
, prev
);
112 /* clearing the length */
115 /* encrypting the rest of data */
117 crypto_xor(prev
, p
, bs
);
118 crypto_cipher_encrypt_one(tfm
, prev
, prev
);
123 /* keeping the surplus of blocksize */
125 memcpy(odds
, p
, len
);
132 static int crypto_xcbc_digest_final(struct shash_desc
*pdesc
, u8
*out
)
134 struct crypto_shash
*parent
= pdesc
->tfm
;
135 unsigned long alignmask
= crypto_shash_alignmask(parent
);
136 struct xcbc_tfm_ctx
*tctx
= crypto_shash_ctx(parent
);
137 struct xcbc_desc_ctx
*ctx
= shash_desc_ctx(pdesc
);
138 struct crypto_cipher
*tfm
= tctx
->child
;
139 int bs
= crypto_shash_blocksize(parent
);
140 u8
*consts
= PTR_ALIGN(&tctx
->ctx
[0], alignmask
+ 1);
141 u8
*odds
= PTR_ALIGN(&ctx
->ctx
[0], alignmask
+ 1);
142 u8
*prev
= odds
+ bs
;
143 unsigned int offset
= 0;
145 if (ctx
->len
!= bs
) {
147 u8
*p
= odds
+ ctx
->len
;
152 rlen
= bs
- ctx
->len
-1;
159 crypto_xor(prev
, odds
, bs
);
160 crypto_xor(prev
, consts
+ offset
, bs
);
162 crypto_cipher_encrypt_one(tfm
, out
, prev
);
167 static int xcbc_init_tfm(struct crypto_tfm
*tfm
)
169 struct crypto_cipher
*cipher
;
170 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
171 struct crypto_cipher_spawn
*spawn
= crypto_instance_ctx(inst
);
172 struct xcbc_tfm_ctx
*ctx
= crypto_tfm_ctx(tfm
);
174 cipher
= crypto_spawn_cipher(spawn
);
176 return PTR_ERR(cipher
);
183 static void xcbc_exit_tfm(struct crypto_tfm
*tfm
)
185 struct xcbc_tfm_ctx
*ctx
= crypto_tfm_ctx(tfm
);
186 crypto_free_cipher(ctx
->child
);
189 static int xcbc_create(struct crypto_template
*tmpl
, struct rtattr
**tb
)
191 struct shash_instance
*inst
;
192 struct crypto_cipher_spawn
*spawn
;
193 struct crypto_alg
*alg
;
194 unsigned long alignmask
;
198 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_SHASH
, &mask
);
202 inst
= kzalloc(sizeof(*inst
) + sizeof(*spawn
), GFP_KERNEL
);
205 spawn
= shash_instance_ctx(inst
);
207 err
= crypto_grab_cipher(spawn
, shash_crypto_instance(inst
),
208 crypto_attr_alg_name(tb
[1]), 0, mask
);
211 alg
= crypto_spawn_cipher_alg(spawn
);
214 if (alg
->cra_blocksize
!= XCBC_BLOCKSIZE
)
217 err
= crypto_inst_setname(shash_crypto_instance(inst
), tmpl
->name
, alg
);
221 alignmask
= alg
->cra_alignmask
| 3;
222 inst
->alg
.base
.cra_alignmask
= alignmask
;
223 inst
->alg
.base
.cra_priority
= alg
->cra_priority
;
224 inst
->alg
.base
.cra_blocksize
= alg
->cra_blocksize
;
226 inst
->alg
.digestsize
= alg
->cra_blocksize
;
227 inst
->alg
.descsize
= ALIGN(sizeof(struct xcbc_desc_ctx
),
228 crypto_tfm_ctx_alignment()) +
230 ~(crypto_tfm_ctx_alignment() - 1)) +
231 alg
->cra_blocksize
* 2;
233 inst
->alg
.base
.cra_ctxsize
= ALIGN(sizeof(struct xcbc_tfm_ctx
),
235 alg
->cra_blocksize
* 2;
236 inst
->alg
.base
.cra_init
= xcbc_init_tfm
;
237 inst
->alg
.base
.cra_exit
= xcbc_exit_tfm
;
239 inst
->alg
.init
= crypto_xcbc_digest_init
;
240 inst
->alg
.update
= crypto_xcbc_digest_update
;
241 inst
->alg
.final
= crypto_xcbc_digest_final
;
242 inst
->alg
.setkey
= crypto_xcbc_digest_setkey
;
244 inst
->free
= shash_free_singlespawn_instance
;
246 err
= shash_register_instance(tmpl
, inst
);
249 shash_free_singlespawn_instance(inst
);
254 static struct crypto_template crypto_xcbc_tmpl
= {
256 .create
= xcbc_create
,
257 .module
= THIS_MODULE
,
260 static int __init
crypto_xcbc_module_init(void)
262 return crypto_register_template(&crypto_xcbc_tmpl
);
265 static void __exit
crypto_xcbc_module_exit(void)
267 crypto_unregister_template(&crypto_xcbc_tmpl
);
270 subsys_initcall(crypto_xcbc_module_init
);
271 module_exit(crypto_xcbc_module_exit
);
273 MODULE_LICENSE("GPL");
274 MODULE_DESCRIPTION("XCBC keyed hash algorithm");
275 MODULE_ALIAS_CRYPTO("xcbc");
276 MODULE_IMPORT_NS(CRYPTO_INTERNAL
);