/*
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.

*/

#define SKEIN_ERR_CHECK 1
#include <cryptcommon/skeinApi.h>
#include <string.h>
#include <stdio.h>

int skeinCtxPrepare(SkeinCtx_t* ctx, SkeinSize_t size)
{
    Skein_Assert(ctx && size, SKEIN_FAIL);

    memset(ctx ,0, sizeof(SkeinCtx_t));
    ctx->skeinSize = size;

    return SKEIN_SUCCESS;
}

int skeinInit(SkeinCtx_t* ctx, size_t hashBitLen)
{
    int ret = SKEIN_FAIL;
    size_t Xlen = 0;
    u64b_t*  X = NULL;
    uint64_t treeInfo = SKEIN_CFG_TREE_INFO_SEQUENTIAL;

    Skein_Assert(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;
    Xlen = (size_t)(ctx->skeinSize/8);
    /*
     * If size is the same and hash bit length is zero then reuse
     * the save chaining variables.
     */
    switch (ctx->skeinSize) {
    case Skein256:
        ret = Skein_256_InitExt(&ctx->m.s256, hashBitLen,
                                treeInfo, NULL, 0);
        break;
    case Skein512:
        ret = Skein_512_InitExt(&ctx->m.s512, hashBitLen,
                                treeInfo, NULL, 0);
        break;
    case Skein1024:
        ret = Skein1024_InitExt(&ctx->m.s1024, hashBitLen,
                                treeInfo, NULL, 0);
        break;
    }

    if (ret == SKEIN_SUCCESS) {
        /* Save chaining variables for this combination of size and hashBitLen */
        memcpy(ctx->XSave, X, Xlen);
    }
    return ret;
}

int skeinMacInit(SkeinCtx_t* ctx, const uint8_t *key, size_t keyLen,
                 size_t hashBitLen)
{
    int ret = SKEIN_FAIL;
    u64b_t*  X = NULL;
    size_t Xlen = 0;
    uint64_t treeInfo = SKEIN_CFG_TREE_INFO_SEQUENTIAL;

    Skein_Assert(ctx, SKEIN_FAIL);

    X = ctx->m.s256.X;
    Xlen = (size_t)(ctx->skeinSize/8);

    Skein_Assert(hashBitLen, SKEIN_BAD_HASHLEN);

    switch (ctx->skeinSize) {
    case Skein256:
        ret = Skein_256_InitExt(&ctx->m.s256, hashBitLen,
                                treeInfo,
                                (const u08b_t*)key, keyLen);

        break;
    case Skein512:
        ret = Skein_512_InitExt(&ctx->m.s512, hashBitLen,
                                treeInfo,
                                (const u08b_t*)key, keyLen);
        break;
    case Skein1024:
        ret = Skein1024_InitExt(&ctx->m.s1024, hashBitLen,
                                treeInfo,
                                (const u08b_t*)key, keyLen);

        break;
    }
    if (ret == SKEIN_SUCCESS) {
        /* Save chaining variables for this combination of key, keyLen, hashBitLen */
        memcpy(ctx->XSave, X, Xlen);
    }
    return ret;
}

void skeinReset(SkeinCtx_t* ctx)
{
    size_t Xlen = 0;
    u64b_t*  X = NULL;

    /*
     * 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;
    Xlen = (size_t)(ctx->skeinSize/8);
    /*
     * If size is the same and hash bit length is zero then reuse
     * the save chaining variables.
     */
    /* Restore the chaing variable, reset byte counter */
    memcpy(X, ctx->XSave, Xlen);

    /* Setup context to process the message */
    Skein_Start_New_Type(&ctx->m, MSG);
}

int skeinUpdate(SkeinCtx_t *ctx, const uint8_t *msg,
                size_t msgByteCnt)
{
    int ret = SKEIN_FAIL;
    Skein_Assert(ctx, SKEIN_FAIL);

    switch (ctx->skeinSize) {
    case Skein256:
        ret = Skein_256_Update(&ctx->m.s256, (const u08b_t*)msg, msgByteCnt);
        break;
    case Skein512:
        ret = Skein_512_Update(&ctx->m.s512, (const u08b_t*)msg, msgByteCnt);
        break;
    case Skein1024:
        ret = Skein1024_Update(&ctx->m.s1024, (const u08b_t*)msg, msgByteCnt);
        break;
    }
    return ret;

}

int skeinUpdateBits(SkeinCtx_t *ctx, const uint8_t *msg,
                    size_t msgBitCnt)
{
    /*
     * 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;
    uint8_t mask;
    uint8_t* up;

    /* only the final Update() call is allowed do partial bytes, else assert an error */
    Skein_Assert((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || msgBitCnt == 0, SKEIN_FAIL);

    /* if number of bits is a multiple of bytes - that's easy */
    if ((msgBitCnt & 0x7) == 0) {
        return skeinUpdate(ctx, msg, msgBitCnt >> 3);
    }
    skeinUpdate(ctx, msg, (msgBitCnt >> 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 = (uint8_t*)ctx->m.s256.X + ctx->skeinSize / 8;

    Skein_Set_Bit_Pad_Flag(ctx->m.h);                       /* set tweak flag for the skeinFinal call */

    /* now "pad" the final partial byte the way NIST likes */
    length = ctx->m.h.bCnt;                                 /* get the bCnt value (same location for all block sizes) */
    Skein_assert(length != 0);                              /* internal sanity check: there IS a partial byte in the buffer! */
    mask = (uint8_t) (1u << (7 - (msgBitCnt & 7)));         /* partial byte bit mask */
    up[length-1]  = (uint8_t)((up[length-1] & (0-mask))|mask);   /* apply bit padding on final byte (in the buffer) */

    return SKEIN_SUCCESS;
}

int skeinFinal(SkeinCtx_t* ctx, uint8_t* hash)
{
    int ret = SKEIN_FAIL;
    Skein_Assert(ctx, SKEIN_FAIL);

    switch (ctx->skeinSize) {
    case Skein256:
        ret = Skein_256_Final(&ctx->m.s256, (u08b_t*)hash);
        break;
    case Skein512:
        ret = Skein_512_Final(&ctx->m.s512, (u08b_t*)hash);
        break;
    case Skein1024:
        ret = Skein1024_Final(&ctx->m.s1024, (u08b_t*)hash);
        break;
    }
    return ret;
}
