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