1/* 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 */ 25 26#include <linux/string.h> 27#include "skein_api.h" 28 29int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size) 30{ 31 skein_assert_ret(ctx && size, SKEIN_FAIL); 32 33 memset(ctx, 0, sizeof(struct skein_ctx)); 34 ctx->skein_size = size; 35 36 return SKEIN_SUCCESS; 37} 38 39int skein_init(struct skein_ctx *ctx, size_t hash_bit_len) 40{ 41 int ret = SKEIN_FAIL; 42 size_t x_len = 0; 43 u64 *x = NULL; 44 u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL; 45 46 skein_assert_ret(ctx, SKEIN_FAIL); 47 /* 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 :-) . 51 */ 52 x = ctx->m.s256.x; 53 x_len = ctx->skein_size / 8; 54 /* 55 * If size is the same and hash bit length is zero then reuse 56 * the save chaining variables. 57 */ 58 switch (ctx->skein_size) { 59 case SKEIN_256: 60 ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len, 61 tree_info, NULL, 0); 62 break; 63 case SKEIN_512: 64 ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len, 65 tree_info, NULL, 0); 66 break; 67 case SKEIN_1024: 68 ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len, 69 tree_info, NULL, 0); 70 break; 71 } 72 73 if (ret == SKEIN_SUCCESS) { 74 /* 75 * Save chaining variables for this combination of size and 76 * hash_bit_len 77 */ 78 memcpy(ctx->x_save, x, x_len); 79 } 80 return ret; 81} 82 83int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len, 84 size_t hash_bit_len) 85{ 86 int ret = SKEIN_FAIL; 87 u64 *x = NULL; 88 size_t x_len = 0; 89 u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL; 90 91 skein_assert_ret(ctx, SKEIN_FAIL); 92 93 x = ctx->m.s256.x; 94 x_len = ctx->skein_size / 8; 95 96 skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN); 97 98 switch (ctx->skein_size) { 99 case SKEIN_256: 100 ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len, 101 tree_info, 102 (const u8 *)key, key_len); 103 104 break; 105 case SKEIN_512: 106 ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len, 107 tree_info, 108 (const u8 *)key, key_len); 109 break; 110 case SKEIN_1024: 111 ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len, 112 tree_info, 113 (const u8 *)key, key_len); 114 115 break; 116 } 117 if (ret == SKEIN_SUCCESS) { 118 /* 119 * Save chaining variables for this combination of key, 120 * key_len, hash_bit_len 121 */ 122 memcpy(ctx->x_save, x, x_len); 123 } 124 return ret; 125} 126 127void skein_reset(struct skein_ctx *ctx) 128{ 129 size_t x_len = 0; 130 u64 *x; 131 132 /* 133 * The following two lines rely of the fact that the real Skein 134 * contexts are a union in out context and thus have tha maximum 135 * memory available. The beautiy of C :-) . 136 */ 137 x = ctx->m.s256.x; 138 x_len = ctx->skein_size / 8; 139 /* Restore the chaing variable, reset byte counter */ 140 memcpy(x, ctx->x_save, x_len); 141 142 /* Setup context to process the message */ 143 skein_start_new_type(&ctx->m, MSG); 144} 145 146int skein_update(struct skein_ctx *ctx, const u8 *msg, 147 size_t msg_byte_cnt) 148{ 149 int ret = SKEIN_FAIL; 150 151 skein_assert_ret(ctx, SKEIN_FAIL); 152 153 switch (ctx->skein_size) { 154 case SKEIN_256: 155 ret = skein_256_update(&ctx->m.s256, (const u8 *)msg, 156 msg_byte_cnt); 157 break; 158 case SKEIN_512: 159 ret = skein_512_update(&ctx->m.s512, (const u8 *)msg, 160 msg_byte_cnt); 161 break; 162 case SKEIN_1024: 163 ret = skein_1024_update(&ctx->m.s1024, (const u8 *)msg, 164 msg_byte_cnt); 165 break; 166 } 167 return ret; 168 169} 170 171int skein_update_bits(struct skein_ctx *ctx, const u8 *msg, 172 size_t msg_bit_cnt) 173{ 174 /* 175 * I've used the bit pad implementation from skein_test.c (see NIST CD) 176 * and modified it to use the convenience functions and added some 177 * pointer arithmetic. 178 */ 179 size_t length; 180 u8 mask; 181 u8 *up; 182 183 /* 184 * only the final Update() call is allowed do partial bytes, else 185 * assert an error 186 */ 187 skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || 188 msg_bit_cnt == 0, SKEIN_FAIL); 189 190 /* if number of bits is a multiple of bytes - that's easy */ 191 if ((msg_bit_cnt & 0x7) == 0) 192 return skein_update(ctx, msg, msg_bit_cnt >> 3); 193 194 skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1); 195 196 /* 197 * The next line rely on the fact that the real Skein contexts 198 * are a union in our context. After the addition the pointer points to 199 * Skein's real partial block buffer. 200 * If this layout ever changes we have to adapt this as well. 201 */ 202 up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8; 203 204 /* set tweak flag for the skein_final call */ 205 skein_set_bit_pad_flag(ctx->m.h); 206 207 /* now "pad" the final partial byte the way NIST likes */ 208 /* get the b_cnt value (same location for all block sizes) */ 209 length = ctx->m.h.b_cnt; 210 /* internal sanity check: there IS a partial byte in the buffer! */ 211 skein_assert(length != 0); 212 /* partial byte bit mask */ 213 mask = (u8) (1u << (7 - (msg_bit_cnt & 7))); 214 /* apply bit padding on final byte (in the buffer) */ 215 up[length - 1] = (u8)((up[length - 1] & (0 - mask)) | mask); 216 217 return SKEIN_SUCCESS; 218} 219 220int skein_final(struct skein_ctx *ctx, u8 *hash) 221{ 222 int ret = SKEIN_FAIL; 223 224 skein_assert_ret(ctx, SKEIN_FAIL); 225 226 switch (ctx->skein_size) { 227 case SKEIN_256: 228 ret = skein_256_final(&ctx->m.s256, (u8 *)hash); 229 break; 230 case SKEIN_512: 231 ret = skein_512_final(&ctx->m.s512, (u8 *)hash); 232 break; 233 case SKEIN_1024: 234 ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash); 235 break; 236 } 237 return ret; 238} 239