1/*
2 * Cryptographic API.
3 *
4 * Skein256 Hash Algorithm.
5 *
6 * Derived from cryptoapi implementation, adapted for in-place
7 * scatterlist interface.
8 *
9 * Copyright (c) Eric Rost <eric.rost@mybabylon.net>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
14 * any later version.
15 *
16 */
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <crypto/internal/hash.h>
21#include "skein_base.h"
22
23
24static int skein256_init(struct shash_desc *desc)
25{
26	return skein_256_init((struct skein_256_ctx *) shash_desc_ctx(desc),
27			SKEIN256_DIGEST_BIT_SIZE);
28}
29
30static int skein256_update(struct shash_desc *desc, const u8 *data,
31			unsigned int len)
32{
33	return skein_256_update((struct skein_256_ctx *)shash_desc_ctx(desc),
34				data, len);
35}
36
37static int skein256_final(struct shash_desc *desc, u8 *out)
38{
39	return skein_256_final((struct skein_256_ctx *)shash_desc_ctx(desc),
40				out);
41}
42
43static int skein256_export(struct shash_desc *desc, void *out)
44{
45	struct skein_256_ctx *sctx = shash_desc_ctx(desc);
46
47	memcpy(out, sctx, sizeof(*sctx));
48	return 0;
49}
50
51static int skein256_import(struct shash_desc *desc, const void *in)
52{
53	struct skein_256_ctx *sctx = shash_desc_ctx(desc);
54
55	memcpy(sctx, in, sizeof(*sctx));
56	return 0;
57}
58
59static int skein512_init(struct shash_desc *desc)
60{
61	return skein_512_init((struct skein_512_ctx *)shash_desc_ctx(desc),
62				SKEIN512_DIGEST_BIT_SIZE);
63}
64
65static int skein512_update(struct shash_desc *desc, const u8 *data,
66			unsigned int len)
67{
68	return skein_512_update((struct skein_512_ctx *)shash_desc_ctx(desc),
69				data, len);
70}
71
72static int skein512_final(struct shash_desc *desc, u8 *out)
73{
74	return skein_512_final((struct skein_512_ctx *)shash_desc_ctx(desc),
75				out);
76}
77
78static int skein512_export(struct shash_desc *desc, void *out)
79{
80	struct skein_512_ctx *sctx = shash_desc_ctx(desc);
81
82	memcpy(out, sctx, sizeof(*sctx));
83	return 0;
84}
85
86static int skein512_import(struct shash_desc *desc, const void *in)
87{
88	struct skein_512_ctx *sctx = shash_desc_ctx(desc);
89
90	memcpy(sctx, in, sizeof(*sctx));
91	return 0;
92}
93
94static int skein1024_init(struct shash_desc *desc)
95{
96	return skein_1024_init((struct skein_1024_ctx *)shash_desc_ctx(desc),
97				SKEIN1024_DIGEST_BIT_SIZE);
98}
99
100static int skein1024_update(struct shash_desc *desc, const u8 *data,
101			unsigned int len)
102{
103	return skein_1024_update((struct skein_1024_ctx *)shash_desc_ctx(desc),
104				data, len);
105}
106
107static int skein1024_final(struct shash_desc *desc, u8 *out)
108{
109	return skein_1024_final((struct skein_1024_ctx *)shash_desc_ctx(desc),
110			out);
111}
112
113static int skein1024_export(struct shash_desc *desc, void *out)
114{
115	struct skein_1024_ctx *sctx = shash_desc_ctx(desc);
116
117	memcpy(out, sctx, sizeof(*sctx));
118	return 0;
119}
120
121static int skein1024_import(struct shash_desc *desc, const void *in)
122{
123	struct skein_1024_ctx *sctx = shash_desc_ctx(desc);
124
125	memcpy(sctx, in, sizeof(*sctx));
126	return 0;
127}
128
129static struct shash_alg alg256 = {
130	.digestsize	=	(SKEIN256_DIGEST_BIT_SIZE / 8),
131	.init		=	skein256_init,
132	.update		=	skein256_update,
133	.final		=	skein256_final,
134	.export		=	skein256_export,
135	.import		=	skein256_import,
136	.descsize	=	sizeof(struct skein_256_ctx),
137	.statesize	=	sizeof(struct skein_256_ctx),
138	.base		=	{
139		.cra_name		=	"skein256",
140		.cra_driver_name	=	"skein",
141		.cra_flags		=	CRYPTO_ALG_TYPE_SHASH,
142		.cra_blocksize		=	SKEIN_256_BLOCK_BYTES,
143		.cra_module		=	THIS_MODULE,
144	}
145};
146
147static struct shash_alg alg512 = {
148	.digestsize	=	(SKEIN512_DIGEST_BIT_SIZE / 8),
149	.init		=	skein512_init,
150	.update		=	skein512_update,
151	.final		=	skein512_final,
152	.export		=	skein512_export,
153	.import		=	skein512_import,
154	.descsize	=	sizeof(struct skein_512_ctx),
155	.statesize	=	sizeof(struct skein_512_ctx),
156	.base		=	{
157		.cra_name		=	"skein512",
158		.cra_driver_name	=	"skein",
159		.cra_flags		=	CRYPTO_ALG_TYPE_SHASH,
160		.cra_blocksize		=	SKEIN_512_BLOCK_BYTES,
161		.cra_module		=	THIS_MODULE,
162	}
163};
164
165static struct shash_alg alg1024 = {
166	.digestsize	=	(SKEIN1024_DIGEST_BIT_SIZE / 8),
167	.init		=	skein1024_init,
168	.update		=	skein1024_update,
169	.final		=	skein1024_final,
170	.export		=	skein1024_export,
171	.import		=	skein1024_import,
172	.descsize	=	sizeof(struct skein_1024_ctx),
173	.statesize	=	sizeof(struct skein_1024_ctx),
174	.base		=	{
175		.cra_name		=	"skein1024",
176		.cra_driver_name	=	"skein",
177		.cra_flags		=	CRYPTO_ALG_TYPE_SHASH,
178		.cra_blocksize		=	SKEIN_1024_BLOCK_BYTES,
179		.cra_module		=	THIS_MODULE,
180	}
181};
182
183static int __init skein_generic_init(void)
184{
185	if (crypto_register_shash(&alg256))
186		goto out;
187	if (crypto_register_shash(&alg512))
188		goto unreg256;
189	if (crypto_register_shash(&alg1024))
190		goto unreg512;
191
192	return 0;
193
194unreg512:
195	crypto_unregister_shash(&alg512);
196unreg256:
197	crypto_unregister_shash(&alg256);
198out:
199	return -1;
200}
201
202static void __exit skein_generic_fini(void)
203{
204	crypto_unregister_shash(&alg256);
205	crypto_unregister_shash(&alg512);
206	crypto_unregister_shash(&alg1024);
207}
208
209module_init(skein_generic_init);
210module_exit(skein_generic_fini);
211
212MODULE_LICENSE("GPL");
213MODULE_DESCRIPTION("Skein Hash Algorithm");
214
215MODULE_ALIAS("skein");
216