123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- * Copyright (c) 2010 Werner Dittmann
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
- #include <linux/string.h>
- #include "skein_api.h"
- int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size)
- {
- skein_assert_ret(ctx && size, SKEIN_FAIL);
- memset(ctx, 0, sizeof(struct skein_ctx));
- ctx->skein_size = size;
- return SKEIN_SUCCESS;
- }
- int skein_init(struct skein_ctx *ctx, size_t hash_bit_len)
- {
- int ret = SKEIN_FAIL;
- size_t x_len = 0;
- u64 *x = NULL;
- u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
- skein_assert_ret(ctx, SKEIN_FAIL);
- /*
- * The following two lines rely of the fact that the real Skein
- * contexts are a union in out context and thus have tha maximum
- * memory available. The beauty of C :-) .
- */
- x = ctx->m.s256.x;
- x_len = ctx->skein_size / 8;
- /*
- * If size is the same and hash bit length is zero then reuse
- * the save chaining variables.
- */
- switch (ctx->skein_size) {
- case SKEIN_256:
- ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
- tree_info, NULL, 0);
- break;
- case SKEIN_512:
- ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
- tree_info, NULL, 0);
- break;
- case SKEIN_1024:
- ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
- tree_info, NULL, 0);
- break;
- }
- if (ret == SKEIN_SUCCESS) {
- /*
- * Save chaining variables for this combination of size and
- * hash_bit_len
- */
- memcpy(ctx->x_save, x, x_len);
- }
- return ret;
- }
- int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
- size_t hash_bit_len)
- {
- int ret = SKEIN_FAIL;
- u64 *x = NULL;
- size_t x_len = 0;
- u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
- skein_assert_ret(ctx, SKEIN_FAIL);
- x = ctx->m.s256.x;
- x_len = ctx->skein_size / 8;
- skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN);
- switch (ctx->skein_size) {
- case SKEIN_256:
- ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
- tree_info,
- (const u8 *)key, key_len);
- break;
- case SKEIN_512:
- ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
- tree_info,
- (const u8 *)key, key_len);
- break;
- case SKEIN_1024:
- ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
- tree_info,
- (const u8 *)key, key_len);
- break;
- }
- if (ret == SKEIN_SUCCESS) {
- /*
- * Save chaining variables for this combination of key,
- * key_len, hash_bit_len
- */
- memcpy(ctx->x_save, x, x_len);
- }
- return ret;
- }
- void skein_reset(struct skein_ctx *ctx)
- {
- size_t x_len = 0;
- u64 *x;
- /*
- * The following two lines rely of the fact that the real Skein
- * contexts are a union in out context and thus have tha maximum
- * memory available. The beautiy of C :-) .
- */
- x = ctx->m.s256.x;
- x_len = ctx->skein_size / 8;
- /* Restore the chaing variable, reset byte counter */
- memcpy(x, ctx->x_save, x_len);
- /* Setup context to process the message */
- skein_start_new_type(&ctx->m, MSG);
- }
- int skein_update(struct skein_ctx *ctx, const u8 *msg,
- size_t msg_byte_cnt)
- {
- int ret = SKEIN_FAIL;
- skein_assert_ret(ctx, SKEIN_FAIL);
- switch (ctx->skein_size) {
- case SKEIN_256:
- ret = skein_256_update(&ctx->m.s256, (const u8 *)msg,
- msg_byte_cnt);
- break;
- case SKEIN_512:
- ret = skein_512_update(&ctx->m.s512, (const u8 *)msg,
- msg_byte_cnt);
- break;
- case SKEIN_1024:
- ret = skein_1024_update(&ctx->m.s1024, (const u8 *)msg,
- msg_byte_cnt);
- break;
- }
- return ret;
- }
- int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
- size_t msg_bit_cnt)
- {
- /*
- * I've used the bit pad implementation from skein_test.c (see NIST CD)
- * and modified it to use the convenience functions and added some
- * pointer arithmetic.
- */
- size_t length;
- u8 mask;
- u8 *up;
- /*
- * only the final Update() call is allowed do partial bytes, else
- * assert an error
- */
- skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 ||
- msg_bit_cnt == 0, SKEIN_FAIL);
- /* if number of bits is a multiple of bytes - that's easy */
- if ((msg_bit_cnt & 0x7) == 0)
- return skein_update(ctx, msg, msg_bit_cnt >> 3);
- skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1);
- /*
- * The next line rely on the fact that the real Skein contexts
- * are a union in our context. After the addition the pointer points to
- * Skein's real partial block buffer.
- * If this layout ever changes we have to adapt this as well.
- */
- up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8;
- /* set tweak flag for the skein_final call */
- skein_set_bit_pad_flag(ctx->m.h);
- /* now "pad" the final partial byte the way NIST likes */
- /* get the b_cnt value (same location for all block sizes) */
- length = ctx->m.h.b_cnt;
- /* internal sanity check: there IS a partial byte in the buffer! */
- skein_assert(length != 0);
- /* partial byte bit mask */
- mask = (u8) (1u << (7 - (msg_bit_cnt & 7)));
- /* apply bit padding on final byte (in the buffer) */
- up[length - 1] = (u8)((up[length - 1] & (0 - mask)) | mask);
- return SKEIN_SUCCESS;
- }
- int skein_final(struct skein_ctx *ctx, u8 *hash)
- {
- int ret = SKEIN_FAIL;
- skein_assert_ret(ctx, SKEIN_FAIL);
- switch (ctx->skein_size) {
- case SKEIN_256:
- ret = skein_256_final(&ctx->m.s256, (u8 *)hash);
- break;
- case SKEIN_512:
- ret = skein_512_final(&ctx->m.s512, (u8 *)hash);
- break;
- case SKEIN_1024:
- ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash);
- break;
- }
- return ret;
- }
|