summaryrefslogtreecommitdiffstats
path: root/drivers/staging/skein/skeinApi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/skein/skeinApi.c')
-rwxr-xr-xdrivers/staging/skein/skeinApi.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/staging/skein/skeinApi.c b/drivers/staging/skein/skeinApi.c
new file mode 100755
index 000000000000..7b963758d32c
--- /dev/null
+++ b/drivers/staging/skein/skeinApi.c
@@ -0,0 +1,221 @@
+/*
+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 <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 = 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 = 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 = ctx->skeinSize/8;
+ /* 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;
+}