]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/skein/skein_api.c
Merge remote-tracking branches 'asoc/topic/cs35l35', 'asoc/topic/cs53l30', 'asoc...
[mirror_ubuntu-artful-kernel.git] / drivers / staging / skein / skein_api.c
CommitLineData
449bb812 1/*
7d27a184
DD
2 * Copyright (c) 2010 Werner Dittmann
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
449bb812 25
c2c7426b 26#include <linux/string.h>
85dfd522 27#include "skein_api.h"
449bb812 28
68ace624 29int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size)
449bb812 30{
0264b7b7 31 skein_assert_ret(ctx && size, SKEIN_FAIL);
449bb812 32
2d375457 33 memset(ctx, 0, sizeof(struct skein_ctx));
95f1840a 34 ctx->skein_size = size;
449bb812 35
39bd42b0 36 return SKEIN_SUCCESS;
449bb812
JC
37}
38
95f1840a 39int skein_init(struct skein_ctx *ctx, size_t hash_bit_len)
449bb812 40{
39bd42b0 41 int ret = SKEIN_FAIL;
007dfe5a
JE
42 size_t x_len = 0;
43 u64 *x = NULL;
95f1840a 44 u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
39bd42b0 45
0264b7b7 46 skein_assert_ret(ctx, SKEIN_FAIL);
39bd42b0 47 /*
60eb8175
JC
48 * The following two lines rely of the fact that the real Skein
49 * contexts are a union in out context and thus have tha maximum
50 * memory available. The beauty of C :-) .
39bd42b0 51 */
007dfe5a 52 x = ctx->m.s256.x;
9efbbfad 53 x_len = ctx->skein_size / 8;
39bd42b0
JC
54 /*
55 * If size is the same and hash bit length is zero then reuse
56 * the save chaining variables.
57 */
95f1840a 58 switch (ctx->skein_size) {
9435d3ac 59 case SKEIN_256:
95f1840a
AS
60 ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
61 tree_info, NULL, 0);
39bd42b0 62 break;
9435d3ac 63 case SKEIN_512:
95f1840a
AS
64 ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
65 tree_info, NULL, 0);
39bd42b0 66 break;
9435d3ac 67 case SKEIN_1024:
95f1840a
AS
68 ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
69 tree_info, NULL, 0);
39bd42b0
JC
70 break;
71 }
72
73 if (ret == SKEIN_SUCCESS) {
60eb8175
JC
74 /*
75 * Save chaining variables for this combination of size and
95f1840a 76 * hash_bit_len
60eb8175 77 */
007dfe5a 78 memcpy(ctx->x_save, x, x_len);
39bd42b0
JC
79 }
80 return ret;
449bb812
JC
81}
82
95f1840a
AS
83int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
84 size_t hash_bit_len)
449bb812 85{
39bd42b0 86 int ret = SKEIN_FAIL;
007dfe5a
JE
87 u64 *x = NULL;
88 size_t x_len = 0;
95f1840a 89 u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
39bd42b0 90
0264b7b7 91 skein_assert_ret(ctx, SKEIN_FAIL);
39bd42b0 92
007dfe5a 93 x = ctx->m.s256.x;
9efbbfad 94 x_len = ctx->skein_size / 8;
39bd42b0 95
0264b7b7 96 skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN);
39bd42b0 97
95f1840a 98 switch (ctx->skein_size) {
9435d3ac 99 case SKEIN_256:
95f1840a 100 ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
1af172fa 101 tree_info, key, key_len);
39bd42b0
JC
102
103 break;
9435d3ac 104 case SKEIN_512:
95f1840a 105 ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
1af172fa 106 tree_info, key, key_len);
39bd42b0 107 break;
9435d3ac 108 case SKEIN_1024:
95f1840a 109 ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
1af172fa 110 tree_info, key, key_len);
39bd42b0
JC
111
112 break;
113 }
114 if (ret == SKEIN_SUCCESS) {
60eb8175
JC
115 /*
116 * Save chaining variables for this combination of key,
95f1840a 117 * key_len, hash_bit_len
60eb8175 118 */
007dfe5a 119 memcpy(ctx->x_save, x, x_len);
39bd42b0
JC
120 }
121 return ret;
449bb812
JC
122}
123
68ace624 124void skein_reset(struct skein_ctx *ctx)
449bb812 125{
007dfe5a 126 size_t x_len = 0;
779fcc84 127 u64 *x;
39bd42b0
JC
128
129 /*
60eb8175
JC
130 * The following two lines rely of the fact that the real Skein
131 * contexts are a union in out context and thus have tha maximum
132 * memory available. The beautiy of C :-) .
39bd42b0 133 */
007dfe5a 134 x = ctx->m.s256.x;
9efbbfad 135 x_len = ctx->skein_size / 8;
39bd42b0 136 /* Restore the chaing variable, reset byte counter */
007dfe5a 137 memcpy(x, ctx->x_save, x_len);
39bd42b0
JC
138
139 /* Setup context to process the message */
0264b7b7 140 skein_start_new_type(&ctx->m, MSG);
449bb812
JC
141}
142
68ace624 143int skein_update(struct skein_ctx *ctx, const u8 *msg,
95f1840a 144 size_t msg_byte_cnt)
449bb812 145{
39bd42b0 146 int ret = SKEIN_FAIL;
95f1840a 147
0264b7b7 148 skein_assert_ret(ctx, SKEIN_FAIL);
39bd42b0 149
95f1840a 150 switch (ctx->skein_size) {
9435d3ac 151 case SKEIN_256:
1af172fa 152 ret = skein_256_update(&ctx->m.s256, msg, msg_byte_cnt);
39bd42b0 153 break;
9435d3ac 154 case SKEIN_512:
1af172fa 155 ret = skein_512_update(&ctx->m.s512, msg, msg_byte_cnt);
39bd42b0 156 break;
9435d3ac 157 case SKEIN_1024:
1af172fa 158 ret = skein_1024_update(&ctx->m.s1024, msg, msg_byte_cnt);
39bd42b0
JC
159 break;
160 }
161 return ret;
449bb812
JC
162}
163
68ace624 164int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
95f1840a 165 size_t msg_bit_cnt)
449bb812 166{
39bd42b0
JC
167 /*
168 * I've used the bit pad implementation from skein_test.c (see NIST CD)
60eb8175
JC
169 * and modified it to use the convenience functions and added some
170 * pointer arithmetic.
39bd42b0
JC
171 */
172 size_t length;
173 u8 mask;
174 u8 *up;
175
60eb8175
JC
176 /*
177 * only the final Update() call is allowed do partial bytes, else
178 * assert an error
179 */
0264b7b7
AS
180 skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 ||
181 msg_bit_cnt == 0, SKEIN_FAIL);
39bd42b0
JC
182
183 /* if number of bits is a multiple of bytes - that's easy */
95f1840a
AS
184 if ((msg_bit_cnt & 0x7) == 0)
185 return skein_update(ctx, msg, msg_bit_cnt >> 3);
7584a878 186
95f1840a 187 skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1);
39bd42b0
JC
188
189 /*
190 * The next line rely on the fact that the real Skein contexts
191 * are a union in our context. After the addition the pointer points to
192 * Skein's real partial block buffer.
193 * If this layout ever changes we have to adapt this as well.
194 */
007dfe5a 195 up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8;
39bd42b0 196
68ace624 197 /* set tweak flag for the skein_final call */
0264b7b7 198 skein_set_bit_pad_flag(ctx->m.h);
39bd42b0
JC
199
200 /* now "pad" the final partial byte the way NIST likes */
95f1840a
AS
201 /* get the b_cnt value (same location for all block sizes) */
202 length = ctx->m.h.b_cnt;
60eb8175 203 /* internal sanity check: there IS a partial byte in the buffer! */
0264b7b7 204 skein_assert(length != 0);
60eb8175 205 /* partial byte bit mask */
e602a808 206 mask = (u8)(1u << (7 - (msg_bit_cnt & 7)));
60eb8175 207 /* apply bit padding on final byte (in the buffer) */
1af172fa 208 up[length - 1] = (up[length - 1] & (0 - mask)) | mask;
39bd42b0
JC
209
210 return SKEIN_SUCCESS;
449bb812
JC
211}
212
68ace624 213int skein_final(struct skein_ctx *ctx, u8 *hash)
449bb812 214{
39bd42b0 215 int ret = SKEIN_FAIL;
95f1840a 216
0264b7b7 217 skein_assert_ret(ctx, SKEIN_FAIL);
39bd42b0 218
95f1840a 219 switch (ctx->skein_size) {
9435d3ac 220 case SKEIN_256:
1af172fa 221 ret = skein_256_final(&ctx->m.s256, hash);
39bd42b0 222 break;
9435d3ac 223 case SKEIN_512:
1af172fa 224 ret = skein_512_final(&ctx->m.s512, hash);
39bd42b0 225 break;
9435d3ac 226 case SKEIN_1024:
1af172fa 227 ret = skein_1024_final(&ctx->m.s1024, hash);
39bd42b0
JC
228 break;
229 }
230 return ret;
449bb812 231}