Merge 5e41463ef4
into b3b7491615
This commit is contained in:
commit
502eec6abf
|
@ -43,8 +43,6 @@ dist_noinst_DATA += README.md RELEASES.md
|
||||||
dist_noinst_DATA += module/lua/README.zfs module/os/linux/spl/README.md
|
dist_noinst_DATA += module/lua/README.zfs module/os/linux/spl/README.md
|
||||||
|
|
||||||
# Include all the extra licensing information for modules
|
# Include all the extra licensing information for modules
|
||||||
dist_noinst_DATA += module/icp/algs/skein/THIRDPARTYLICENSE
|
|
||||||
dist_noinst_DATA += module/icp/algs/skein/THIRDPARTYLICENSE.descrip
|
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
||||||
|
|
|
@ -1,30 +1,36 @@
|
||||||
/*
|
/*
|
||||||
* Interface declarations for Skein hashing.
|
* CDDL HEADER START
|
||||||
* Source code author: Doug Whiting, 2008.
|
|
||||||
* This algorithm and source code is released to the public domain.
|
|
||||||
*
|
*
|
||||||
* The following compile-time switches may be defined to control some
|
* The contents of this file are subject to the terms of the
|
||||||
* tradeoffs between speed, code size, error checking, and security.
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* The "default" note explains what happens when the switch is not defined.
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or https://opensource.org/licenses/CDDL-1.0.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
* SKEIN_DEBUG -- make callouts from inside Skein code
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
* to examine/display intermediate values.
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
* [default: no callouts (no overhead)]
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
*
|
*
|
||||||
* SKEIN_ERR_CHECK -- how error checking is handled inside Skein
|
* CDDL HEADER END
|
||||||
* code. If not defined, most error checking
|
|
||||||
* is disabled (for performance). Otherwise,
|
|
||||||
* the switch value is interpreted as:
|
|
||||||
* 0: use assert() to flag errors
|
|
||||||
* 1: return SKEIN_FAIL to flag errors
|
|
||||||
*/
|
*/
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
#ifndef _SYS_SKEIN_H_
|
/*
|
||||||
#define _SYS_SKEIN_H_
|
* Implementation of the Skein 512-bit hash function, based
|
||||||
|
* on the public domain implementation by Doug Whiting.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008,2013 Doug Whiting
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_SKEIN_H
|
||||||
|
#define _SYS_SKEIN_H
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
#include <sys/types.h> /* get size_t definition */
|
#include <sys/types.h>
|
||||||
#else
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -34,74 +40,34 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
#define SKEIN_512_STATE_WORDS 8
|
||||||
SKEIN_SUCCESS = 0, /* return codes from Skein calls */
|
|
||||||
SKEIN_FAIL = 1,
|
|
||||||
SKEIN_BAD_HASHLEN = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SKEIN_MODIFIER_WORDS (2) /* number of modifier (tweak) words */
|
|
||||||
|
|
||||||
#define SKEIN_256_STATE_WORDS (4)
|
|
||||||
#define SKEIN_512_STATE_WORDS (8)
|
|
||||||
#define SKEIN1024_STATE_WORDS (16)
|
|
||||||
#define SKEIN_MAX_STATE_WORDS (16)
|
|
||||||
|
|
||||||
#define SKEIN_256_STATE_BYTES (8 * SKEIN_256_STATE_WORDS)
|
|
||||||
#define SKEIN_512_STATE_BYTES (8 * SKEIN_512_STATE_WORDS)
|
#define SKEIN_512_STATE_BYTES (8 * SKEIN_512_STATE_WORDS)
|
||||||
#define SKEIN1024_STATE_BYTES (8 * SKEIN1024_STATE_WORDS)
|
|
||||||
|
|
||||||
#define SKEIN_256_STATE_BITS (64 * SKEIN_256_STATE_WORDS)
|
|
||||||
#define SKEIN_512_STATE_BITS (64 * SKEIN_512_STATE_WORDS)
|
|
||||||
#define SKEIN1024_STATE_BITS (64 * SKEIN1024_STATE_WORDS)
|
|
||||||
|
|
||||||
#define SKEIN_256_BLOCK_BYTES (8 * SKEIN_256_STATE_WORDS)
|
|
||||||
#define SKEIN_512_BLOCK_BYTES (8 * SKEIN_512_STATE_WORDS)
|
#define SKEIN_512_BLOCK_BYTES (8 * SKEIN_512_STATE_WORDS)
|
||||||
#define SKEIN1024_BLOCK_BYTES (8 * SKEIN1024_STATE_WORDS)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t hashBitLen; /* size of hash result, in bits */
|
size_t hashBitLen; /* size of hash result, in bits */
|
||||||
size_t bCnt; /* current byte count in buffer b[] */
|
size_t bCnt; /* current byte count in buffer b[] */
|
||||||
/* tweak words: T[0]=byte cnt, T[1]=flags */
|
uint64_t T[2]; /* tweak words: T[0]=byte cnt, T[1]=flags */
|
||||||
uint64_t T[SKEIN_MODIFIER_WORDS];
|
|
||||||
} Skein_Ctxt_Hdr_t;
|
} Skein_Ctxt_Hdr_t;
|
||||||
|
|
||||||
typedef struct { /* 256-bit Skein hash context structure */
|
|
||||||
Skein_Ctxt_Hdr_t h; /* common header context variables */
|
|
||||||
uint64_t X[SKEIN_256_STATE_WORDS]; /* chaining variables */
|
|
||||||
/* partial block buffer (8-byte aligned) */
|
|
||||||
uint8_t b[SKEIN_256_BLOCK_BYTES];
|
|
||||||
} Skein_256_Ctxt_t;
|
|
||||||
|
|
||||||
typedef struct { /* 512-bit Skein hash context structure */
|
typedef struct { /* 512-bit Skein hash context structure */
|
||||||
Skein_Ctxt_Hdr_t h; /* common header context variables */
|
Skein_Ctxt_Hdr_t h; /* common header context variables */
|
||||||
uint64_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */
|
uint64_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */
|
||||||
/* partial block buffer (8-byte aligned) */
|
/* partial block buffer (8-byte aligned) */
|
||||||
uint8_t b[SKEIN_512_BLOCK_BYTES];
|
uint8_t b[SKEIN_512_BLOCK_BYTES];
|
||||||
} Skein_512_Ctxt_t;
|
} SKEIN_CTX;
|
||||||
|
|
||||||
typedef struct { /* 1024-bit Skein hash context structure */
|
/* Skein APIs for (incremental) "straight hashing" */
|
||||||
Skein_Ctxt_Hdr_t h; /* common header context variables */
|
extern void Skein_512_Init(SKEIN_CTX *ctx, size_t hashBitLen);
|
||||||
uint64_t X[SKEIN1024_STATE_WORDS]; /* chaining variables */
|
extern void Skein_512_Update(SKEIN_CTX *ctx, const uint8_t *msg, size_t cnt);
|
||||||
/* partial block buffer (8-byte aligned) */
|
extern void Skein_512_Final(SKEIN_CTX *ctx, uint8_t *hashVal);
|
||||||
uint8_t b[SKEIN1024_BLOCK_BYTES];
|
|
||||||
} Skein1024_Ctxt_t;
|
|
||||||
|
|
||||||
/* Skein APIs for (incremental) "straight hashing" */
|
/*
|
||||||
int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen);
|
* Skein APIs for MAC and tree hash:
|
||||||
int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen);
|
* Final_Pad: pad, do final block, but no OUTPUT type
|
||||||
int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen);
|
* Output: do just the output stage
|
||||||
|
*/
|
||||||
int Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg,
|
extern void Skein_512_Final_Pad(SKEIN_CTX *ctx, uint8_t *hashVal);
|
||||||
size_t msgByteCnt);
|
|
||||||
int Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg,
|
|
||||||
size_t msgByteCnt);
|
|
||||||
int Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg,
|
|
||||||
size_t msgByteCnt);
|
|
||||||
|
|
||||||
int Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skein APIs for "extended" initialization: MAC keys, tree hashing.
|
* Skein APIs for "extended" initialization: MAC keys, tree hashing.
|
||||||
|
@ -117,58 +83,11 @@ int Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal);
|
||||||
* to precompute the MAC IV, then a copy of the context saved and
|
* to precompute the MAC IV, then a copy of the context saved and
|
||||||
* reused for each new MAC computation.
|
* reused for each new MAC computation.
|
||||||
*/
|
*/
|
||||||
int Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen,
|
extern void Skein_512_InitExt(SKEIN_CTX *ctx, size_t hashBitLen,
|
||||||
uint64_t treeInfo, const uint8_t *key, size_t keyBytes);
|
uint64_t treeInfo, const uint8_t *key, size_t keyBytes);
|
||||||
int Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen,
|
|
||||||
uint64_t treeInfo, const uint8_t *key, size_t keyBytes);
|
|
||||||
int Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen,
|
|
||||||
uint64_t treeInfo, const uint8_t *key, size_t keyBytes);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skein APIs for MAC and tree hash:
|
|
||||||
* Final_Pad: pad, do final block, but no OUTPUT type
|
|
||||||
* Output: do just the output stage
|
|
||||||
*/
|
|
||||||
int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
|
|
||||||
#ifndef SKEIN_TREE_HASH
|
|
||||||
#define SKEIN_TREE_HASH (1)
|
|
||||||
#endif
|
|
||||||
#if SKEIN_TREE_HASH
|
|
||||||
int Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
int Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When you initialize a Skein KCF hashing method you can pass this param
|
|
||||||
* structure in cm_param to fine-tune the algorithm's defaults.
|
|
||||||
*/
|
|
||||||
typedef struct skein_param {
|
|
||||||
size_t sp_digest_bitlen; /* length of digest in bits */
|
|
||||||
} skein_param_t;
|
|
||||||
|
|
||||||
/* Module definitions */
|
|
||||||
#ifdef SKEIN_MODULE_IMPL
|
|
||||||
#define CKM_SKEIN_256_MAC "CKM_SKEIN_256_MAC"
|
|
||||||
#define CKM_SKEIN_512_MAC "CKM_SKEIN_512_MAC"
|
|
||||||
#define CKM_SKEIN1024_MAC "CKM_SKEIN1024_MAC"
|
|
||||||
|
|
||||||
typedef enum skein_mech_type {
|
|
||||||
SKEIN_256_MAC_MECH_INFO_TYPE,
|
|
||||||
SKEIN_512_MAC_MECH_INFO_TYPE,
|
|
||||||
SKEIN1024_MAC_MECH_INFO_TYPE
|
|
||||||
} skein_mech_type_t;
|
|
||||||
|
|
||||||
#define VALID_SKEIN_MAC_MECH(__mech) \
|
|
||||||
((int)(__mech) >= SKEIN_256_MAC_MECH_INFO_TYPE && \
|
|
||||||
(__mech) <= SKEIN1024_MAC_MECH_INFO_TYPE)
|
|
||||||
#endif /* SKEIN_MODULE_IMPL */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _SYS_SKEIN_H_ */
|
#endif /* _SYS_SKEIN_H */
|
||||||
|
|
|
@ -27,7 +27,6 @@ nodist_libicp_la_SOURCES = \
|
||||||
module/icp/algs/sha2/sha512_impl.c \
|
module/icp/algs/sha2/sha512_impl.c \
|
||||||
module/icp/algs/skein/skein.c \
|
module/icp/algs/skein/skein.c \
|
||||||
module/icp/algs/skein/skein_block.c \
|
module/icp/algs/skein/skein_block.c \
|
||||||
module/icp/algs/skein/skein_iv.c \
|
|
||||||
module/icp/illumos-crypto.c \
|
module/icp/illumos-crypto.c \
|
||||||
module/icp/io/aes.c \
|
module/icp/io/aes.c \
|
||||||
module/icp/io/sha2_mod.c \
|
module/icp/io/sha2_mod.c \
|
||||||
|
|
|
@ -110,7 +110,6 @@ ICP_OBJS := \
|
||||||
algs/sha2/sha512_impl.o \
|
algs/sha2/sha512_impl.o \
|
||||||
algs/skein/skein.o \
|
algs/skein/skein.o \
|
||||||
algs/skein/skein_block.o \
|
algs/skein/skein_block.o \
|
||||||
algs/skein/skein_iv.o \
|
|
||||||
api/kcf_cipher.o \
|
api/kcf_cipher.o \
|
||||||
api/kcf_ctxops.o \
|
api/kcf_ctxops.o \
|
||||||
api/kcf_mac.o \
|
api/kcf_mac.o \
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Implementation of the Skein hash function.
|
|
||||||
Source code author: Doug Whiting, 2008.
|
|
||||||
This algorithm and source code is released to the public domain.
|
|
|
@ -1 +0,0 @@
|
||||||
LICENSE TERMS OF SKEIN HASH ALGORITHM IMPLEMENTATION
|
|
|
@ -1,300 +1,77 @@
|
||||||
/*
|
/*
|
||||||
* Implementation of the Skein hash function.
|
* CDDL HEADER START
|
||||||
* Source code author: Doug Whiting, 2008.
|
*
|
||||||
* This algorithm and source code is released to the public domain.
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/skein.h> /* get the Skein API definitions */
|
|
||||||
#include "skein_impl.h" /* get internal definitions */
|
|
||||||
|
|
||||||
/* 256-bit Skein */
|
|
||||||
/* init the context for a straight hashing operation */
|
|
||||||
int
|
|
||||||
Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t b[SKEIN_256_STATE_BYTES];
|
|
||||||
uint64_t w[SKEIN_256_STATE_WORDS];
|
|
||||||
} cfg; /* config block */
|
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
|
||||||
|
|
||||||
switch (hashBitLen) { /* use pre-computed values, where available */
|
|
||||||
#ifndef SKEIN_NO_PRECOMP
|
|
||||||
case 256:
|
|
||||||
memcpy(ctx->X, SKEIN_256_IV_256, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 224:
|
|
||||||
memcpy(ctx->X, SKEIN_256_IV_224, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 160:
|
|
||||||
memcpy(ctx->X, SKEIN_256_IV_160, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
memcpy(ctx->X, SKEIN_256_IV_128, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
/* here if there is no precomputed IV value available */
|
|
||||||
/*
|
|
||||||
* build/process the config block, type == CONFIG (could be
|
|
||||||
* precomputed)
|
|
||||||
*/
|
|
||||||
/* set tweaks: T0=0; T1=CFG | FINAL */
|
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
|
||||||
|
|
||||||
/* set the schema, version */
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
|
||||||
/* hash result length in bits */
|
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen);
|
|
||||||
cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
|
|
||||||
/* zero pad config block */
|
|
||||||
memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
|
||||||
/* zero the chaining variables */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* The chaining vars ctx->X are now initialized for the given
|
|
||||||
* hashBitLen.
|
|
||||||
* Set up to process the data message portion of the hash (default)
|
|
||||||
*/
|
|
||||||
Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init the context for a MAC and/or tree hash operation */
|
|
||||||
/*
|
/*
|
||||||
* [identical to Skein_256_Init() when keyBytes == 0 &&
|
* Implementation of the Skein 512-bit hash function, based
|
||||||
* treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
|
* on the public domain implementation by Doug Whiting.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008,2013 Doug Whiting
|
||||||
|
* Copyright (c) 2023 Tino Reichardt <milky-zfs@mcmilk.de>
|
||||||
*/
|
*/
|
||||||
int
|
|
||||||
Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
|
||||||
const uint8_t *key, size_t keyBytes)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t b[SKEIN_256_STATE_BYTES];
|
|
||||||
uint64_t w[SKEIN_256_STATE_WORDS];
|
|
||||||
} cfg; /* config block */
|
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
#include <sys/zfs_context.h>
|
||||||
Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
|
#include <sys/skein.h>
|
||||||
|
|
||||||
/* compute the initial chaining values ctx->X[], based on key */
|
#include "skein_impl.h"
|
||||||
if (keyBytes == 0) { /* is there a key? */
|
|
||||||
/* no key: use all zeroes as key for config block */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
} else { /* here to pre-process a key */
|
|
||||||
|
|
||||||
Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
|
|
||||||
/* do a mini-Init right here */
|
|
||||||
/* set output hash bit count = state size */
|
|
||||||
ctx->h.hashBitLen = 8 * sizeof (ctx->X);
|
|
||||||
/* set tweaks: T0 = 0; T1 = KEY type */
|
|
||||||
Skein_Start_New_Type(ctx, KEY);
|
|
||||||
/* zero the initial chaining variables */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
/* hash the key */
|
|
||||||
(void) Skein_256_Update(ctx, key, keyBytes);
|
|
||||||
/* put result into cfg.b[] */
|
|
||||||
(void) Skein_256_Final_Pad(ctx, cfg.b);
|
|
||||||
/* copy over into ctx->X[] */
|
|
||||||
memcpy(ctx->X, cfg.b, sizeof (cfg.b));
|
|
||||||
#if SKEIN_NEED_SWAP
|
|
||||||
{
|
|
||||||
uint_t i;
|
|
||||||
/* convert key bytes to context words */
|
|
||||||
for (i = 0; i < SKEIN_256_STATE_WORDS; i++)
|
|
||||||
ctx->X[i] = Skein_Swap64(ctx->X[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* build/process the config block, type == CONFIG (could be
|
|
||||||
* precomputed for each key)
|
|
||||||
*/
|
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
|
||||||
|
|
||||||
memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
|
|
||||||
/* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
|
|
||||||
cfg.w[2] = Skein_Swap64(treeInfo);
|
|
||||||
|
|
||||||
Skein_Show_Key(256, &ctx->h, key, keyBytes);
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
|
||||||
Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
|
||||||
|
|
||||||
/* The chaining vars ctx->X are now initialized */
|
|
||||||
/* Set up to process the data message portion of the hash (default) */
|
|
||||||
ctx->h.bCnt = 0; /* buffer b[] starts out empty */
|
|
||||||
Skein_Start_New_Type(ctx, MSG);
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* process the input bytes */
|
|
||||||
int
|
|
||||||
Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* process full blocks, if any */
|
|
||||||
if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) {
|
|
||||||
/* finish up any buffered message data */
|
|
||||||
if (ctx->h.bCnt) {
|
|
||||||
/* # bytes free in buffer b[] */
|
|
||||||
n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt;
|
|
||||||
if (n) {
|
|
||||||
/* check on our logic here */
|
|
||||||
Skein_assert(n < msgByteCnt);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, n);
|
|
||||||
msgByteCnt -= n;
|
|
||||||
msg += n;
|
|
||||||
ctx->h.bCnt += n;
|
|
||||||
}
|
|
||||||
Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
|
|
||||||
Skein_256_Process_Block(ctx, ctx->b, 1,
|
|
||||||
SKEIN_256_BLOCK_BYTES);
|
|
||||||
ctx->h.bCnt = 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* now process any remaining full blocks, directly from input
|
|
||||||
* message data
|
|
||||||
*/
|
|
||||||
if (msgByteCnt > SKEIN_256_BLOCK_BYTES) {
|
|
||||||
/* number of full blocks to process */
|
|
||||||
n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES;
|
|
||||||
Skein_256_Process_Block(ctx, msg, n,
|
|
||||||
SKEIN_256_BLOCK_BYTES);
|
|
||||||
msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
|
|
||||||
msg += n * SKEIN_256_BLOCK_BYTES;
|
|
||||||
}
|
|
||||||
Skein_assert(ctx->h.bCnt == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy any remaining source message data bytes into b[] */
|
|
||||||
if (msgByteCnt) {
|
|
||||||
Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
|
|
||||||
ctx->h.bCnt += msgByteCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finalize the hash computation and output the result */
|
|
||||||
int
|
|
||||||
Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
size_t i, n, byteCnt;
|
|
||||||
uint64_t X[SKEIN_256_STATE_WORDS];
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
|
||||||
/* zero pad b[] if necessary */
|
|
||||||
if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
|
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
|
||||||
SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* process the final block */
|
|
||||||
Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* now output the result */
|
|
||||||
/* total number of output bytes */
|
|
||||||
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
|
|
||||||
|
|
||||||
/* run Threefish in "counter mode" to generate output */
|
|
||||||
/* zero out b[], so it can hold the counter */
|
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
|
||||||
/* keep a local copy of counter mode "key" */
|
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
|
||||||
for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
|
|
||||||
/* build the counter block */
|
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
|
||||||
Skein_Start_New_Type(ctx, OUT_FINAL);
|
|
||||||
/* run "counter mode" */
|
|
||||||
Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
|
|
||||||
/* number of output bytes left to go */
|
|
||||||
n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
|
|
||||||
if (n >= SKEIN_256_BLOCK_BYTES)
|
|
||||||
n = SKEIN_256_BLOCK_BYTES;
|
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
|
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
|
||||||
Skein_Show_Final(256, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN_256_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
|
||||||
}
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 512-bit Skein */
|
/* 512-bit Skein */
|
||||||
|
|
||||||
/* init the context for a straight hashing operation */
|
/* blkSize = 512 bits. hashSize = 256 bits */
|
||||||
int
|
const uint64_t SKEIN_512_IV_256[] = {
|
||||||
Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
|
SKEIN_MK_64(0xCCD044A1, 0x2FDB3E13),
|
||||||
{
|
SKEIN_MK_64(0xE8359030, 0x1A79A9EB),
|
||||||
union {
|
SKEIN_MK_64(0x55AEA061, 0x4F816E6F),
|
||||||
uint8_t b[SKEIN_512_STATE_BYTES];
|
SKEIN_MK_64(0x2A2767A4, 0xAE9B94DB),
|
||||||
uint64_t w[SKEIN_512_STATE_WORDS];
|
SKEIN_MK_64(0xEC06025E, 0x74DD7683),
|
||||||
} cfg; /* config block */
|
SKEIN_MK_64(0xE7A436CD, 0xC4746251),
|
||||||
|
SKEIN_MK_64(0xC36FBAF9, 0x393AD185),
|
||||||
|
SKEIN_MK_64(0x3EEDBA18, 0x33EDFC13)
|
||||||
|
};
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
/* blkSize = 512 bits. hashSize = 512 bits */
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
const uint64_t SKEIN_512_IV_512[] = {
|
||||||
|
SKEIN_MK_64(0x4903ADFF, 0x749C51CE),
|
||||||
|
SKEIN_MK_64(0x0D95DE39, 0x9746DF03),
|
||||||
|
SKEIN_MK_64(0x8FD19341, 0x27C79BCE),
|
||||||
|
SKEIN_MK_64(0x9A255629, 0xFF352CB1),
|
||||||
|
SKEIN_MK_64(0x5DB62599, 0xDF6CA7B0),
|
||||||
|
SKEIN_MK_64(0xEABE394C, 0xA9D5C3F4),
|
||||||
|
SKEIN_MK_64(0x991112C7, 0x1A75B523),
|
||||||
|
SKEIN_MK_64(0xAE18A40B, 0x660FCC33)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* init the context for a straight hashing operation */
|
||||||
|
void
|
||||||
|
Skein_512_Init(SKEIN_CTX * ctx, size_t hashBitLen)
|
||||||
|
{
|
||||||
|
/* output hash bit count */
|
||||||
|
ctx->h.hashBitLen = hashBitLen;
|
||||||
|
|
||||||
switch (hashBitLen) { /* use pre-computed values, where available */
|
switch (hashBitLen) { /* use pre-computed values, where available */
|
||||||
#ifndef SKEIN_NO_PRECOMP
|
|
||||||
case 512:
|
case 512:
|
||||||
memcpy(ctx->X, SKEIN_512_IV_512, sizeof (ctx->X));
|
memcpy(ctx->X, SKEIN_512_IV_512, sizeof (ctx->X));
|
||||||
break;
|
break;
|
||||||
case 384:
|
|
||||||
memcpy(ctx->X, SKEIN_512_IV_384, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 256:
|
case 256:
|
||||||
memcpy(ctx->X, SKEIN_512_IV_256, sizeof (ctx->X));
|
memcpy(ctx->X, SKEIN_512_IV_256, sizeof (ctx->X));
|
||||||
break;
|
break;
|
||||||
case 224:
|
|
||||||
memcpy(ctx->X, SKEIN_512_IV_224, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* here if there is no precomputed IV value available
|
|
||||||
* build/process the config block, type == CONFIG (could be
|
|
||||||
* precomputed)
|
|
||||||
*/
|
|
||||||
/* set tweaks: T0=0; T1=CFG | FINAL */
|
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
|
||||||
|
|
||||||
/* set the schema, version */
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
|
||||||
/* hash result length in bits */
|
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen);
|
|
||||||
cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
|
|
||||||
/* zero pad config block */
|
|
||||||
memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
|
||||||
/* zero the chaining variables */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -303,17 +80,11 @@ Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
|
||||||
* hash (default)
|
* hash (default)
|
||||||
*/
|
*/
|
||||||
Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
|
Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init the context for a MAC and/or tree hash operation */
|
/* init the context for a MAC and/or tree hash operation */
|
||||||
/*
|
void
|
||||||
* [identical to Skein_512_Init() when keyBytes == 0 &&
|
Skein_512_InitExt(SKEIN_CTX *ctx, size_t hashBitLen, uint64_t treeInfo,
|
||||||
* treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
|
||||||
const uint8_t *key, size_t keyBytes)
|
const uint8_t *key, size_t keyBytes)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
|
@ -321,16 +92,11 @@ Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
||||||
uint64_t w[SKEIN_512_STATE_WORDS];
|
uint64_t w[SKEIN_512_STATE_WORDS];
|
||||||
} cfg; /* config block */
|
} cfg; /* config block */
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
|
||||||
Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* compute the initial chaining values ctx->X[], based on key */
|
/* compute the initial chaining values ctx->X[], based on key */
|
||||||
if (keyBytes == 0) { /* is there a key? */
|
if (keyBytes == 0) { /* is there a key? */
|
||||||
/* no key: use all zeroes as key for config block */
|
/* no key: use all zeroes as key for config block */
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
memset(ctx->X, 0, sizeof (ctx->X));
|
||||||
} else { /* here to pre-process a key */
|
} else { /* here to pre-process a key */
|
||||||
|
|
||||||
Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
|
|
||||||
/* do a mini-Init right here */
|
/* do a mini-Init right here */
|
||||||
/* set output hash bit count = state size */
|
/* set output hash bit count = state size */
|
||||||
ctx->h.hashBitLen = 8 * sizeof (ctx->X);
|
ctx->h.hashBitLen = 8 * sizeof (ctx->X);
|
||||||
|
@ -338,9 +104,10 @@ Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
||||||
Skein_Start_New_Type(ctx, KEY);
|
Skein_Start_New_Type(ctx, KEY);
|
||||||
/* zero the initial chaining variables */
|
/* zero the initial chaining variables */
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
memset(ctx->X, 0, sizeof (ctx->X));
|
||||||
(void) Skein_512_Update(ctx, key, keyBytes); /* hash the key */
|
/* hash the key */
|
||||||
|
Skein_512_Update(ctx, key, keyBytes);
|
||||||
/* put result into cfg.b[] */
|
/* put result into cfg.b[] */
|
||||||
(void) Skein_512_Final_Pad(ctx, cfg.b);
|
Skein_512_Final_Pad(ctx, cfg.b);
|
||||||
/* copy over into ctx->X[] */
|
/* copy over into ctx->X[] */
|
||||||
memcpy(ctx->X, cfg.b, sizeof (cfg.b));
|
memcpy(ctx->X, cfg.b, sizeof (cfg.b));
|
||||||
#if SKEIN_NEED_SWAP
|
#if SKEIN_NEED_SWAP
|
||||||
|
@ -359,14 +126,14 @@ Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
Skein_Start_New_Type(ctx, CFG_FINAL);
|
||||||
|
|
||||||
memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
|
/* pre-pad cfg.w[] with zeroes */
|
||||||
|
memset(&cfg.w, 0, sizeof (cfg.w));
|
||||||
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
|
cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
|
||||||
/* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
|
/* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
|
||||||
cfg.w[2] = Skein_Swap64(treeInfo);
|
cfg.w[2] = Skein_Swap64(treeInfo);
|
||||||
|
|
||||||
Skein_Show_Key(512, &ctx->h, key, keyBytes);
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
/* compute the initial chaining values from config block */
|
||||||
Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
||||||
|
|
||||||
|
@ -374,19 +141,14 @@ Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
||||||
/* Set up to process the data message portion of the hash (default) */
|
/* Set up to process the data message portion of the hash (default) */
|
||||||
ctx->h.bCnt = 0; /* buffer b[] starts out empty */
|
ctx->h.bCnt = 0; /* buffer b[] starts out empty */
|
||||||
Skein_Start_New_Type(ctx, MSG);
|
Skein_Start_New_Type(ctx, MSG);
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process the input bytes */
|
/* process the input bytes */
|
||||||
int
|
void
|
||||||
Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
|
Skein_512_Update(SKEIN_CTX *ctx, const uint8_t *msg, size_t msgByteCnt)
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* process full blocks, if any */
|
/* process full blocks, if any */
|
||||||
if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) {
|
if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) {
|
||||||
/* finish up any buffered message data */
|
/* finish up any buffered message data */
|
||||||
|
@ -395,13 +157,11 @@ Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
|
||||||
n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
|
n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
|
||||||
if (n) {
|
if (n) {
|
||||||
/* check on our logic here */
|
/* check on our logic here */
|
||||||
Skein_assert(n < msgByteCnt);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, n);
|
memcpy(&ctx->b[ctx->h.bCnt], msg, n);
|
||||||
msgByteCnt -= n;
|
msgByteCnt -= n;
|
||||||
msg += n;
|
msg += n;
|
||||||
ctx->h.bCnt += n;
|
ctx->h.bCnt += n;
|
||||||
}
|
}
|
||||||
Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
|
|
||||||
Skein_512_Process_Block(ctx, ctx->b, 1,
|
Skein_512_Process_Block(ctx, ctx->b, 1,
|
||||||
SKEIN_512_BLOCK_BYTES);
|
SKEIN_512_BLOCK_BYTES);
|
||||||
ctx->h.bCnt = 0;
|
ctx->h.bCnt = 0;
|
||||||
|
@ -418,30 +178,24 @@ Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
|
||||||
msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
|
msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
|
||||||
msg += n * SKEIN_512_BLOCK_BYTES;
|
msg += n * SKEIN_512_BLOCK_BYTES;
|
||||||
}
|
}
|
||||||
Skein_assert(ctx->h.bCnt == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy any remaining source message data bytes into b[] */
|
/* copy any remaining source message data bytes into b[] */
|
||||||
if (msgByteCnt) {
|
if (msgByteCnt) {
|
||||||
Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
|
memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
|
||||||
ctx->h.bCnt += msgByteCnt;
|
ctx->h.bCnt += msgByteCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finalize the hash computation and output the result */
|
/* finalize the hash computation and output the result */
|
||||||
int
|
void
|
||||||
Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
|
Skein_512_Final(SKEIN_CTX *ctx, uint8_t *hashVal)
|
||||||
{
|
{
|
||||||
size_t i, n, byteCnt;
|
size_t i, n, byteCnt;
|
||||||
uint64_t X[SKEIN_512_STATE_WORDS];
|
uint64_t X[SKEIN_512_STATE_WORDS];
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
||||||
|
|
||||||
/* zero pad b[] if necessary */
|
/* zero pad b[] if necessary */
|
||||||
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
|
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
memset(&ctx->b[ctx->h.bCnt], 0,
|
||||||
|
@ -457,8 +211,10 @@ Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
|
||||||
/* run Threefish in "counter mode" to generate output */
|
/* run Threefish in "counter mode" to generate output */
|
||||||
/* zero out b[], so it can hold the counter */
|
/* zero out b[], so it can hold the counter */
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
memset(ctx->b, 0, sizeof (ctx->b));
|
||||||
|
|
||||||
/* keep a local copy of counter mode "key" */
|
/* keep a local copy of counter mode "key" */
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
memcpy(X, ctx->X, sizeof (X));
|
||||||
|
|
||||||
for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
|
for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
|
||||||
/* build the counter block */
|
/* build the counter block */
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
||||||
|
@ -469,434 +225,32 @@ Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
|
||||||
n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
|
n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
|
||||||
if (n >= SKEIN_512_BLOCK_BYTES)
|
if (n >= SKEIN_512_BLOCK_BYTES)
|
||||||
n = SKEIN_512_BLOCK_BYTES;
|
n = SKEIN_512_BLOCK_BYTES;
|
||||||
|
/* "output" the ctr mode bytes */
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
|
Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
ctx->X, n);
|
||||||
Skein_Show_Final(512, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN_512_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
/* restore the counter mode key for next time */
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
memcpy(ctx->X, X, sizeof (X));
|
||||||
}
|
}
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1024-bit Skein */
|
|
||||||
|
|
||||||
/* init the context for a straight hashing operation */
|
|
||||||
int
|
|
||||||
Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t b[SKEIN1024_STATE_BYTES];
|
|
||||||
uint64_t w[SKEIN1024_STATE_WORDS];
|
|
||||||
} cfg; /* config block */
|
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
|
||||||
|
|
||||||
switch (hashBitLen) { /* use pre-computed values, where available */
|
|
||||||
#ifndef SKEIN_NO_PRECOMP
|
|
||||||
case 512:
|
|
||||||
memcpy(ctx->X, SKEIN1024_IV_512, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 384:
|
|
||||||
memcpy(ctx->X, SKEIN1024_IV_384, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
case 1024:
|
|
||||||
memcpy(ctx->X, SKEIN1024_IV_1024, sizeof (ctx->X));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
/* here if there is no precomputed IV value available */
|
|
||||||
/*
|
|
||||||
* build/process the config block, type == CONFIG (could be
|
|
||||||
* precomputed)
|
|
||||||
*/
|
|
||||||
/* set tweaks: T0=0; T1=CFG | FINAL */
|
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
|
||||||
|
|
||||||
/* set the schema, version */
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
|
||||||
/* hash result length in bits */
|
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen);
|
|
||||||
cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
|
|
||||||
/* zero pad config block */
|
|
||||||
memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
|
||||||
/* zero the chaining variables */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The chaining vars ctx->X are now initialized for the given
|
|
||||||
* hashBitLen. Set up to process the data message portion of the hash
|
|
||||||
* (default)
|
|
||||||
*/
|
|
||||||
Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init the context for a MAC and/or tree hash operation */
|
|
||||||
/*
|
|
||||||
* [identical to Skein1024_Init() when keyBytes == 0 &&
|
|
||||||
* treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
|
|
||||||
const uint8_t *key, size_t keyBytes)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t b[SKEIN1024_STATE_BYTES];
|
|
||||||
uint64_t w[SKEIN1024_STATE_WORDS];
|
|
||||||
} cfg; /* config block */
|
|
||||||
|
|
||||||
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
|
|
||||||
Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* compute the initial chaining values ctx->X[], based on key */
|
|
||||||
if (keyBytes == 0) { /* is there a key? */
|
|
||||||
/* no key: use all zeroes as key for config block */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
} else { /* here to pre-process a key */
|
|
||||||
Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
|
|
||||||
/* do a mini-Init right here */
|
|
||||||
/* set output hash bit count = state size */
|
|
||||||
ctx->h.hashBitLen = 8 * sizeof (ctx->X);
|
|
||||||
/* set tweaks: T0 = 0; T1 = KEY type */
|
|
||||||
Skein_Start_New_Type(ctx, KEY);
|
|
||||||
/* zero the initial chaining variables */
|
|
||||||
memset(ctx->X, 0, sizeof (ctx->X));
|
|
||||||
(void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */
|
|
||||||
/* put result into cfg.b[] */
|
|
||||||
(void) Skein1024_Final_Pad(ctx, cfg.b);
|
|
||||||
/* copy over into ctx->X[] */
|
|
||||||
memcpy(ctx->X, cfg.b, sizeof (cfg.b));
|
|
||||||
#if SKEIN_NEED_SWAP
|
|
||||||
{
|
|
||||||
uint_t i;
|
|
||||||
/* convert key bytes to context words */
|
|
||||||
for (i = 0; i < SKEIN1024_STATE_WORDS; i++)
|
|
||||||
ctx->X[i] = Skein_Swap64(ctx->X[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* build/process the config block, type == CONFIG (could be
|
|
||||||
* precomputed for each key)
|
|
||||||
*/
|
|
||||||
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
|
|
||||||
Skein_Start_New_Type(ctx, CFG_FINAL);
|
|
||||||
|
|
||||||
memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
|
|
||||||
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
|
|
||||||
/* hash result length in bits */
|
|
||||||
cfg.w[1] = Skein_Swap64(hashBitLen);
|
|
||||||
/* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
|
|
||||||
cfg.w[2] = Skein_Swap64(treeInfo);
|
|
||||||
|
|
||||||
Skein_Show_Key(1024, &ctx->h, key, keyBytes);
|
|
||||||
|
|
||||||
/* compute the initial chaining values from config block */
|
|
||||||
Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
|
|
||||||
|
|
||||||
/* The chaining vars ctx->X are now initialized */
|
|
||||||
/* Set up to process the data message portion of the hash (default) */
|
|
||||||
ctx->h.bCnt = 0; /* buffer b[] starts out empty */
|
|
||||||
Skein_Start_New_Type(ctx, MSG);
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* process the input bytes */
|
|
||||||
int
|
|
||||||
Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* process full blocks, if any */
|
|
||||||
if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) {
|
|
||||||
/* finish up any buffered message data */
|
|
||||||
if (ctx->h.bCnt) {
|
|
||||||
/* # bytes free in buffer b[] */
|
|
||||||
n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt;
|
|
||||||
if (n) {
|
|
||||||
/* check on our logic here */
|
|
||||||
Skein_assert(n < msgByteCnt);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, n);
|
|
||||||
msgByteCnt -= n;
|
|
||||||
msg += n;
|
|
||||||
ctx->h.bCnt += n;
|
|
||||||
}
|
|
||||||
Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
|
|
||||||
Skein1024_Process_Block(ctx, ctx->b, 1,
|
|
||||||
SKEIN1024_BLOCK_BYTES);
|
|
||||||
ctx->h.bCnt = 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* now process any remaining full blocks, directly from
|
|
||||||
* input message data
|
|
||||||
*/
|
|
||||||
if (msgByteCnt > SKEIN1024_BLOCK_BYTES) {
|
|
||||||
/* number of full blocks to process */
|
|
||||||
n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES;
|
|
||||||
Skein1024_Process_Block(ctx, msg, n,
|
|
||||||
SKEIN1024_BLOCK_BYTES);
|
|
||||||
msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
|
|
||||||
msg += n * SKEIN1024_BLOCK_BYTES;
|
|
||||||
}
|
|
||||||
Skein_assert(ctx->h.bCnt == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy any remaining source message data bytes into b[] */
|
|
||||||
if (msgByteCnt) {
|
|
||||||
Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
|
|
||||||
memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
|
|
||||||
ctx->h.bCnt += msgByteCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finalize the hash computation and output the result */
|
|
||||||
int
|
|
||||||
Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
size_t i, n, byteCnt;
|
|
||||||
uint64_t X[SKEIN1024_STATE_WORDS];
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
|
||||||
/* zero pad b[] if necessary */
|
|
||||||
if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
|
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
|
||||||
SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* process the final block */
|
|
||||||
Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* now output the result */
|
|
||||||
/* total number of output bytes */
|
|
||||||
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
|
|
||||||
|
|
||||||
/* run Threefish in "counter mode" to generate output */
|
|
||||||
/* zero out b[], so it can hold the counter */
|
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
|
||||||
/* keep a local copy of counter mode "key" */
|
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
|
||||||
for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
|
|
||||||
/* build the counter block */
|
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
|
||||||
Skein_Start_New_Type(ctx, OUT_FINAL);
|
|
||||||
/* run "counter mode" */
|
|
||||||
Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
|
|
||||||
/* number of output bytes left to go */
|
|
||||||
n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
|
|
||||||
if (n >= SKEIN1024_BLOCK_BYTES)
|
|
||||||
n = SKEIN1024_BLOCK_BYTES;
|
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
|
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
|
||||||
Skein_Show_Final(1024, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN1024_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
|
||||||
}
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Functions to support MAC/tree hashing */
|
|
||||||
/* (this code is identical for Optimized and Reference versions) */
|
|
||||||
|
|
||||||
/* finalize the hash computation and output the block, no OUTPUT stage */
|
|
||||||
int
|
|
||||||
Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
|
||||||
/* zero pad b[] if necessary */
|
|
||||||
if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
|
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
|
||||||
SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
|
|
||||||
/* process the final block */
|
|
||||||
Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* "output" the state bytes */
|
|
||||||
Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES);
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finalize the hash computation and output the block, no OUTPUT stage */
|
/* finalize the hash computation and output the block, no OUTPUT stage */
|
||||||
int
|
void
|
||||||
Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
|
Skein_512_Final_Pad(SKEIN_CTX *ctx, uint8_t *hashVal)
|
||||||
{
|
{
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
|
||||||
|
|
||||||
/* zero pad b[] if necessary */
|
/* zero pad b[] if necessary */
|
||||||
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
|
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
memset(&ctx->b[ctx->h.bCnt], 0,
|
||||||
SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
|
SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
|
||||||
|
|
||||||
/* process the final block */
|
/* process the final block */
|
||||||
Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
||||||
|
|
||||||
/* "output" the state bytes */
|
/* "output" the state bytes */
|
||||||
Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
|
Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finalize the hash computation and output the block, no OUTPUT stage */
|
|
||||||
int
|
|
||||||
Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* tag as the final block */
|
|
||||||
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
|
|
||||||
/* zero pad b[] if necessary */
|
|
||||||
if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
|
|
||||||
memset(&ctx->b[ctx->h.bCnt], 0,
|
|
||||||
SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
|
|
||||||
/* process the final block */
|
|
||||||
Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
|
|
||||||
|
|
||||||
/* "output" the state bytes */
|
|
||||||
Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES);
|
|
||||||
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SKEIN_TREE_HASH
|
|
||||||
/* just do the OUTPUT stage */
|
|
||||||
int
|
|
||||||
Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
size_t i, n, byteCnt;
|
|
||||||
uint64_t X[SKEIN_256_STATE_WORDS];
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* now output the result */
|
|
||||||
/* total number of output bytes */
|
|
||||||
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
|
|
||||||
|
|
||||||
/* run Threefish in "counter mode" to generate output */
|
|
||||||
/* zero out b[], so it can hold the counter */
|
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
|
||||||
/* keep a local copy of counter mode "key" */
|
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
|
||||||
for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
|
|
||||||
/* build the counter block */
|
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
|
||||||
Skein_Start_New_Type(ctx, OUT_FINAL);
|
|
||||||
/* run "counter mode" */
|
|
||||||
Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
|
|
||||||
/* number of output bytes left to go */
|
|
||||||
n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
|
|
||||||
if (n >= SKEIN_256_BLOCK_BYTES)
|
|
||||||
n = SKEIN_256_BLOCK_BYTES;
|
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
|
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
|
||||||
Skein_Show_Final(256, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN_256_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
|
||||||
}
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* just do the OUTPUT stage */
|
|
||||||
int
|
|
||||||
Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
size_t i, n, byteCnt;
|
|
||||||
uint64_t X[SKEIN_512_STATE_WORDS];
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* now output the result */
|
|
||||||
/* total number of output bytes */
|
|
||||||
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
|
|
||||||
|
|
||||||
/* run Threefish in "counter mode" to generate output */
|
|
||||||
/* zero out b[], so it can hold the counter */
|
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
|
||||||
/* keep a local copy of counter mode "key" */
|
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
|
||||||
for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
|
|
||||||
/* build the counter block */
|
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
|
||||||
Skein_Start_New_Type(ctx, OUT_FINAL);
|
|
||||||
/* run "counter mode" */
|
|
||||||
Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
|
|
||||||
/* number of output bytes left to go */
|
|
||||||
n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
|
|
||||||
if (n >= SKEIN_512_BLOCK_BYTES)
|
|
||||||
n = SKEIN_512_BLOCK_BYTES;
|
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
|
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
|
||||||
Skein_Show_Final(256, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN_512_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
|
||||||
}
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* just do the OUTPUT stage */
|
|
||||||
int
|
|
||||||
Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
|
|
||||||
{
|
|
||||||
size_t i, n, byteCnt;
|
|
||||||
uint64_t X[SKEIN1024_STATE_WORDS];
|
|
||||||
|
|
||||||
/* catch uninitialized context */
|
|
||||||
Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
|
|
||||||
|
|
||||||
/* now output the result */
|
|
||||||
/* total number of output bytes */
|
|
||||||
byteCnt = (ctx->h.hashBitLen + 7) >> 3;
|
|
||||||
|
|
||||||
/* run Threefish in "counter mode" to generate output */
|
|
||||||
/* zero out b[], so it can hold the counter */
|
|
||||||
memset(ctx->b, 0, sizeof (ctx->b));
|
|
||||||
/* keep a local copy of counter mode "key" */
|
|
||||||
memcpy(X, ctx->X, sizeof (X));
|
|
||||||
for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
|
|
||||||
/* build the counter block */
|
|
||||||
*(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
|
|
||||||
Skein_Start_New_Type(ctx, OUT_FINAL);
|
|
||||||
/* run "counter mode" */
|
|
||||||
Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
|
|
||||||
/* number of output bytes left to go */
|
|
||||||
n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
|
|
||||||
if (n >= SKEIN1024_BLOCK_BYTES)
|
|
||||||
n = SKEIN1024_BLOCK_BYTES;
|
|
||||||
Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
|
|
||||||
ctx->X, n); /* "output" the ctr mode bytes */
|
|
||||||
Skein_Show_Final(256, &ctx->h, n,
|
|
||||||
hashVal + i * SKEIN1024_BLOCK_BYTES);
|
|
||||||
/* restore the counter mode key for next time */
|
|
||||||
memcpy(ctx->X, X, sizeof (X));
|
|
||||||
}
|
|
||||||
return (SKEIN_SUCCESS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
EXPORT_SYMBOL(Skein_512_Init);
|
EXPORT_SYMBOL(Skein_512_Init);
|
||||||
EXPORT_SYMBOL(Skein_512_InitExt);
|
EXPORT_SYMBOL(Skein_512_InitExt);
|
||||||
|
|
|
@ -1,49 +1,54 @@
|
||||||
/*
|
/*
|
||||||
* Implementation of the Skein block functions.
|
* CDDL HEADER START
|
||||||
* Source code author: Doug Whiting, 2008.
|
*
|
||||||
* This algorithm and source code is released to the public domain.
|
* The contents of this file are subject to the terms of the
|
||||||
* Compile-time switches:
|
* Common Development and Distribution License (the "License").
|
||||||
* SKEIN_USE_ASM -- set bits (256/512/1024) to select which
|
* You may not use this file except in compliance with the License.
|
||||||
* versions use ASM code for block processing
|
*
|
||||||
* [default: use C for all block sizes]
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of the Skein 512-bit hash function, based
|
||||||
|
* on the public domain implementation by Doug Whiting.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008,2013 Doug Whiting
|
||||||
|
* Copyright (c) 2023 Tino Reichardt <milky-zfs@mcmilk.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/zfs_context.h>
|
||||||
#include <sys/skein.h>
|
#include <sys/skein.h>
|
||||||
#include "skein_impl.h"
|
|
||||||
#include <sys/isa_defs.h> /* for _ILP32 */
|
|
||||||
|
|
||||||
#ifndef SKEIN_USE_ASM
|
#include "skein_impl.h"
|
||||||
#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */
|
|
||||||
#endif
|
#define rotl64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||||
|
|
||||||
#ifndef SKEIN_LOOP
|
#ifndef SKEIN_LOOP
|
||||||
|
#if defined(_ILP32) || defined(__powerpc) /* Assume small stack */
|
||||||
/*
|
/*
|
||||||
* The low-level checksum routines use a lot of stack space. On systems where
|
* The low-level checksum routines use a lot of stack space. On systems where
|
||||||
* small stacks frame are enforced (like 32-bit kernel builds), do not unroll
|
* small stacks frame are enforced (like 32-bit kernel builds), do not unroll
|
||||||
* checksum calculations to save stack space.
|
* checksum calculations to save stack space.
|
||||||
*
|
*
|
||||||
* Even with no loops unrolled, we still can exceed the 1k stack frame limit
|
|
||||||
* in Skein1024_Process_Block() (it hits 1272 bytes on ARM32). We can
|
|
||||||
* safely ignore it though, since that the checksum functions will be called
|
|
||||||
* from a worker thread that won't be using much stack. That's why we have
|
|
||||||
* the #pragma here to ignore the warning.
|
|
||||||
*/
|
|
||||||
#if defined(_ILP32) || defined(__powerpc) /* Assume small stack */
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* We're running on 32-bit, don't unroll loops to save stack frame space
|
|
||||||
*
|
|
||||||
* Due to the ways the calculations on SKEIN_LOOP are done in
|
* Due to the ways the calculations on SKEIN_LOOP are done in
|
||||||
* Skein_*_Process_Block(), a value of 111 disables unrolling loops
|
* Skein_*_Process_Block(), a value of 111 disables unrolling loops
|
||||||
* in any of those functions.
|
* in any of those functions.
|
||||||
*/
|
*/
|
||||||
#define SKEIN_LOOP 111
|
#define SKEIN_LOOP 111
|
||||||
#else
|
#else
|
||||||
/* We're compiling with large stacks */
|
/* We're compiling with large stacks, so with unroll */
|
||||||
#define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */
|
#define SKEIN_LOOP 001
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -54,217 +59,9 @@
|
||||||
#define ks (kw + KW_KEY_BASE)
|
#define ks (kw + KW_KEY_BASE)
|
||||||
#define ts (kw + KW_TWK_BASE)
|
#define ts (kw + KW_TWK_BASE)
|
||||||
|
|
||||||
/* no debugging in Illumos version */
|
|
||||||
#define DebugSaveTweak(ctx)
|
|
||||||
|
|
||||||
/* Skein_256 */
|
|
||||||
#if !(SKEIN_USE_ASM & 256)
|
|
||||||
void
|
|
||||||
Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr,
|
|
||||||
size_t blkCnt, size_t byteCntAdd)
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
WCNT = SKEIN_256_STATE_WORDS
|
|
||||||
};
|
|
||||||
#undef RCNT
|
|
||||||
#define RCNT (SKEIN_256_ROUNDS_TOTAL / 8)
|
|
||||||
|
|
||||||
#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
|
|
||||||
#define SKEIN_UNROLL_256 (((SKEIN_LOOP) / 100) % 10)
|
|
||||||
#else
|
|
||||||
#define SKEIN_UNROLL_256 (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SKEIN_UNROLL_256
|
|
||||||
#if (RCNT % SKEIN_UNROLL_256)
|
|
||||||
#error "Invalid SKEIN_UNROLL_256" /* sanity check on unroll count */
|
|
||||||
#endif
|
|
||||||
size_t r;
|
|
||||||
/* key schedule words : chaining vars + tweak + "rotation" */
|
|
||||||
uint64_t kw[WCNT + 4 + RCNT * 2];
|
|
||||||
#else
|
|
||||||
uint64_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */
|
|
||||||
#endif
|
|
||||||
/* local copy of context vars, for speed */
|
|
||||||
uint64_t X0, X1, X2, X3;
|
|
||||||
uint64_t w[WCNT]; /* local copy of input block */
|
|
||||||
#ifdef SKEIN_DEBUG
|
|
||||||
/* use for debugging (help compiler put Xn in registers) */
|
|
||||||
const uint64_t *Xptr[4];
|
|
||||||
Xptr[0] = &X0;
|
|
||||||
Xptr[1] = &X1;
|
|
||||||
Xptr[2] = &X2;
|
|
||||||
Xptr[3] = &X3;
|
|
||||||
#endif
|
|
||||||
Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
|
|
||||||
ts[0] = ctx->h.T[0];
|
|
||||||
ts[1] = ctx->h.T[1];
|
|
||||||
do {
|
|
||||||
/*
|
|
||||||
* this implementation only supports 2**64 input bytes
|
|
||||||
* (no carry out here)
|
|
||||||
*/
|
|
||||||
ts[0] += byteCntAdd; /* update processed length */
|
|
||||||
|
|
||||||
/* precompute the key schedule for this block */
|
|
||||||
ks[0] = ctx->X[0];
|
|
||||||
ks[1] = ctx->X[1];
|
|
||||||
ks[2] = ctx->X[2];
|
|
||||||
ks[3] = ctx->X[3];
|
|
||||||
ks[4] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ SKEIN_KS_PARITY;
|
|
||||||
|
|
||||||
ts[2] = ts[0] ^ ts[1];
|
|
||||||
|
|
||||||
/* get input block in little-endian format */
|
|
||||||
Skein_Get64_LSB_First(w, blkPtr, WCNT);
|
|
||||||
DebugSaveTweak(ctx);
|
|
||||||
Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts);
|
|
||||||
|
|
||||||
X0 = w[0] + ks[0]; /* do the first full key injection */
|
|
||||||
X1 = w[1] + ks[1] + ts[0];
|
|
||||||
X2 = w[2] + ks[2] + ts[1];
|
|
||||||
X3 = w[3] + ks[3];
|
|
||||||
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
|
|
||||||
Xptr); /* show starting state values */
|
|
||||||
|
|
||||||
blkPtr += SKEIN_256_BLOCK_BYTES;
|
|
||||||
|
|
||||||
/* run the rounds */
|
|
||||||
|
|
||||||
#define Round256(p0, p1, p2, p3, ROT, rNum) \
|
|
||||||
X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0; \
|
|
||||||
X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2; \
|
|
||||||
|
|
||||||
#if SKEIN_UNROLL_256 == 0
|
|
||||||
#define R256(p0, p1, p2, p3, ROT, rNum) /* fully unrolled */ \
|
|
||||||
Round256(p0, p1, p2, p3, ROT, rNum) \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rNum, Xptr);
|
|
||||||
|
|
||||||
#define I256(R) \
|
|
||||||
X0 += ks[((R) + 1) % 5]; /* inject the key schedule value */ \
|
|
||||||
X1 += ks[((R) + 2) % 5] + ts[((R) + 1) % 3]; \
|
|
||||||
X2 += ks[((R) + 3) % 5] + ts[((R) + 2) % 3]; \
|
|
||||||
X3 += ks[((R) + 4) % 5] + (R) + 1; \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
#else /* looping version */
|
|
||||||
#define R256(p0, p1, p2, p3, ROT, rNum) \
|
|
||||||
Round256(p0, p1, p2, p3, ROT, rNum) \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rNum, Xptr);
|
|
||||||
|
|
||||||
#define I256(R) \
|
|
||||||
X0 += ks[r + (R) + 0]; /* inject the key schedule value */ \
|
|
||||||
X1 += ks[r + (R) + 1] + ts[r + (R) + 0]; \
|
|
||||||
X2 += ks[r + (R) + 2] + ts[r + (R) + 1]; \
|
|
||||||
X3 += ks[r + (R) + 3] + r + (R); \
|
|
||||||
ks[r + (R) + 4] = ks[r + (R) - 1]; /* rotate key schedule */ \
|
|
||||||
ts[r + (R) + 2] = ts[r + (R) - 1]; \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
|
|
||||||
/* loop through it */
|
|
||||||
for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_256)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#define R256_8_rounds(R) \
|
|
||||||
R256(0, 1, 2, 3, R_256_0, 8 * (R) + 1); \
|
|
||||||
R256(0, 3, 2, 1, R_256_1, 8 * (R) + 2); \
|
|
||||||
R256(0, 1, 2, 3, R_256_2, 8 * (R) + 3); \
|
|
||||||
R256(0, 3, 2, 1, R_256_3, 8 * (R) + 4); \
|
|
||||||
I256(2 * (R)); \
|
|
||||||
R256(0, 1, 2, 3, R_256_4, 8 * (R) + 5); \
|
|
||||||
R256(0, 3, 2, 1, R_256_5, 8 * (R) + 6); \
|
|
||||||
R256(0, 1, 2, 3, R_256_6, 8 * (R) + 7); \
|
|
||||||
R256(0, 3, 2, 1, R_256_7, 8 * (R) + 8); \
|
|
||||||
I256(2 * (R) + 1);
|
|
||||||
|
|
||||||
R256_8_rounds(0);
|
|
||||||
|
|
||||||
#define R256_Unroll_R(NN) \
|
|
||||||
((SKEIN_UNROLL_256 == 0 && SKEIN_256_ROUNDS_TOTAL / 8 > (NN)) || \
|
|
||||||
(SKEIN_UNROLL_256 > (NN)))
|
|
||||||
|
|
||||||
#if R256_Unroll_R(1)
|
|
||||||
R256_8_rounds(1);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(2)
|
|
||||||
R256_8_rounds(2);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(3)
|
|
||||||
R256_8_rounds(3);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(4)
|
|
||||||
R256_8_rounds(4);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(5)
|
|
||||||
R256_8_rounds(5);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(6)
|
|
||||||
R256_8_rounds(6);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(7)
|
|
||||||
R256_8_rounds(7);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(8)
|
|
||||||
R256_8_rounds(8);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(9)
|
|
||||||
R256_8_rounds(9);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(10)
|
|
||||||
R256_8_rounds(10);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(11)
|
|
||||||
R256_8_rounds(11);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(12)
|
|
||||||
R256_8_rounds(12);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(13)
|
|
||||||
R256_8_rounds(13);
|
|
||||||
#endif
|
|
||||||
#if R256_Unroll_R(14)
|
|
||||||
R256_8_rounds(14);
|
|
||||||
#endif
|
|
||||||
#if (SKEIN_UNROLL_256 > 14)
|
|
||||||
#error "need more unrolling in Skein_256_Process_Block"
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* do the final "feedforward" xor, update context chaining vars
|
|
||||||
*/
|
|
||||||
ctx->X[0] = X0 ^ w[0];
|
|
||||||
ctx->X[1] = X1 ^ w[1];
|
|
||||||
ctx->X[2] = X2 ^ w[2];
|
|
||||||
ctx->X[3] = X3 ^ w[3];
|
|
||||||
|
|
||||||
Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
|
|
||||||
|
|
||||||
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
|
|
||||||
} while (--blkCnt);
|
|
||||||
ctx->h.T[0] = ts[0];
|
|
||||||
ctx->h.T[1] = ts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
|
|
||||||
size_t
|
|
||||||
Skein_256_Process_Block_CodeSize(void)
|
|
||||||
{
|
|
||||||
return ((uint8_t *)Skein_256_Process_Block_CodeSize) -
|
|
||||||
((uint8_t *)Skein_256_Process_Block);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint_t
|
|
||||||
Skein_256_Unroll_Cnt(void)
|
|
||||||
{
|
|
||||||
return (SKEIN_UNROLL_256);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Skein_512 */
|
/* Skein_512 */
|
||||||
#if !(SKEIN_USE_ASM & 512)
|
|
||||||
void
|
void
|
||||||
Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
Skein_512_Process_Block(SKEIN_CTX *ctx, const uint8_t *blkPtr,
|
||||||
size_t blkCnt, size_t byteCntAdd)
|
size_t blkCnt, size_t byteCntAdd)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
|
@ -291,21 +88,7 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
#endif
|
#endif
|
||||||
/* local copy of vars, for speed */
|
/* local copy of vars, for speed */
|
||||||
uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
|
uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
|
||||||
uint64_t w[WCNT]; /* local copy of input block */
|
uint64_t w[WCNT]; /* local copy of input block */
|
||||||
#ifdef SKEIN_DEBUG
|
|
||||||
/* use for debugging (help compiler put Xn in registers) */
|
|
||||||
const uint64_t *Xptr[8];
|
|
||||||
Xptr[0] = &X0;
|
|
||||||
Xptr[1] = &X1;
|
|
||||||
Xptr[2] = &X2;
|
|
||||||
Xptr[3] = &X3;
|
|
||||||
Xptr[4] = &X4;
|
|
||||||
Xptr[5] = &X5;
|
|
||||||
Xptr[6] = &X6;
|
|
||||||
Xptr[7] = &X7;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
|
|
||||||
ts[0] = ctx->h.T[0];
|
ts[0] = ctx->h.T[0];
|
||||||
ts[1] = ctx->h.T[1];
|
ts[1] = ctx->h.T[1];
|
||||||
do {
|
do {
|
||||||
|
@ -331,8 +114,6 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
|
|
||||||
/* get input block in little-endian format */
|
/* get input block in little-endian format */
|
||||||
Skein_Get64_LSB_First(w, blkPtr, WCNT);
|
Skein_Get64_LSB_First(w, blkPtr, WCNT);
|
||||||
DebugSaveTweak(ctx);
|
|
||||||
Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts);
|
|
||||||
|
|
||||||
X0 = w[0] + ks[0]; /* do the first full key injection */
|
X0 = w[0] + ks[0]; /* do the first full key injection */
|
||||||
X1 = w[1] + ks[1];
|
X1 = w[1] + ks[1];
|
||||||
|
@ -345,19 +126,16 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
|
|
||||||
blkPtr += SKEIN_512_BLOCK_BYTES;
|
blkPtr += SKEIN_512_BLOCK_BYTES;
|
||||||
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
|
|
||||||
Xptr);
|
|
||||||
/* run the rounds */
|
/* run the rounds */
|
||||||
#define Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
#define Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
||||||
X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0;\
|
X##p0 += X##p1; X##p1 = rotl64(X##p1, ROT##_0); X##p1 ^= X##p0;\
|
||||||
X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2;\
|
X##p2 += X##p3; X##p3 = rotl64(X##p3, ROT##_1); X##p3 ^= X##p2;\
|
||||||
X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4;\
|
X##p4 += X##p5; X##p5 = rotl64(X##p5, ROT##_2); X##p5 ^= X##p4;\
|
||||||
X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6;
|
X##p6 += X##p7; X##p7 = rotl64(X##p7, ROT##_3); X##p7 ^= X##p6;
|
||||||
|
|
||||||
#if SKEIN_UNROLL_512 == 0
|
#if SKEIN_UNROLL_512 == 0
|
||||||
#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) /* unrolled */ \
|
#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) /* unrolled */ \
|
||||||
Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum)
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rNum, Xptr);
|
|
||||||
|
|
||||||
#define I512(R) \
|
#define I512(R) \
|
||||||
X0 += ks[((R) + 1) % 9]; /* inject the key schedule value */\
|
X0 += ks[((R) + 1) % 9]; /* inject the key schedule value */\
|
||||||
|
@ -367,12 +145,10 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
X4 += ks[((R) + 5) % 9]; \
|
X4 += ks[((R) + 5) % 9]; \
|
||||||
X5 += ks[((R) + 6) % 9] + ts[((R) + 1) % 3]; \
|
X5 += ks[((R) + 6) % 9] + ts[((R) + 1) % 3]; \
|
||||||
X6 += ks[((R) + 7) % 9] + ts[((R) + 2) % 3]; \
|
X6 += ks[((R) + 7) % 9] + ts[((R) + 2) % 3]; \
|
||||||
X7 += ks[((R) + 8) % 9] + (R) + 1; \
|
X7 += ks[((R) + 8) % 9] + (R) + 1;
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
#else /* looping version */
|
#else /* looping version */
|
||||||
#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
#define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
||||||
Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum) \
|
Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, rNum)
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rNum, Xptr);
|
|
||||||
|
|
||||||
#define I512(R) \
|
#define I512(R) \
|
||||||
X0 += ks[r + (R) + 0]; /* inject the key schedule value */ \
|
X0 += ks[r + (R) + 0]; /* inject the key schedule value */ \
|
||||||
|
@ -384,8 +160,7 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
X6 += ks[r + (R) + 6] + ts[r + (R) + 1]; \
|
X6 += ks[r + (R) + 6] + ts[r + (R) + 1]; \
|
||||||
X7 += ks[r + (R) + 7] + r + (R); \
|
X7 += ks[r + (R) + 7] + r + (R); \
|
||||||
ks[r + (R)+8] = ks[r + (R) - 1]; /* rotate key schedule */\
|
ks[r + (R)+8] = ks[r + (R) - 1]; /* rotate key schedule */\
|
||||||
ts[r + (R)+2] = ts[r + (R) - 1]; \
|
ts[r + (R)+2] = ts[r + (R) - 1];
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
|
|
||||||
/* loop through it */
|
/* loop through it */
|
||||||
for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512)
|
for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512)
|
||||||
|
@ -401,9 +176,9 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_5, 8 * (R) + 6); \
|
R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_5, 8 * (R) + 6); \
|
||||||
R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_6, 8 * (R) + 7); \
|
R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_6, 8 * (R) + 7); \
|
||||||
R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_7, 8 * (R) + 8); \
|
R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_7, 8 * (R) + 8); \
|
||||||
I512(2*(R) + 1); /* and key injection */
|
I512(2*(R) + 1); /* and key injection */
|
||||||
|
|
||||||
R512_8_rounds(0);
|
R512_8_rounds(0);
|
||||||
|
|
||||||
#define R512_Unroll_R(NN) \
|
#define R512_Unroll_R(NN) \
|
||||||
((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL / 8 > (NN)) || \
|
((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL / 8 > (NN)) || \
|
||||||
|
@ -467,326 +242,10 @@ Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
||||||
ctx->X[5] = X5 ^ w[5];
|
ctx->X[5] = X5 ^ w[5];
|
||||||
ctx->X[6] = X6 ^ w[6];
|
ctx->X[6] = X6 ^ w[6];
|
||||||
ctx->X[7] = X7 ^ w[7];
|
ctx->X[7] = X7 ^ w[7];
|
||||||
Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
|
|
||||||
|
|
||||||
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
|
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
|
||||||
} while (--blkCnt);
|
} while (--blkCnt);
|
||||||
|
|
||||||
ctx->h.T[0] = ts[0];
|
ctx->h.T[0] = ts[0];
|
||||||
ctx->h.T[1] = ts[1];
|
ctx->h.T[1] = ts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
|
|
||||||
size_t
|
|
||||||
Skein_512_Process_Block_CodeSize(void)
|
|
||||||
{
|
|
||||||
return ((uint8_t *)Skein_512_Process_Block_CodeSize) -
|
|
||||||
((uint8_t *)Skein_512_Process_Block);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint_t
|
|
||||||
Skein_512_Unroll_Cnt(void)
|
|
||||||
{
|
|
||||||
return (SKEIN_UNROLL_512);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Skein1024 */
|
|
||||||
#if !(SKEIN_USE_ASM & 1024)
|
|
||||||
void
|
|
||||||
Skein1024_Process_Block(Skein1024_Ctxt_t *ctx, const uint8_t *blkPtr,
|
|
||||||
size_t blkCnt, size_t byteCntAdd)
|
|
||||||
{
|
|
||||||
/* do it in C, always looping (unrolled is bigger AND slower!) */
|
|
||||||
enum {
|
|
||||||
WCNT = SKEIN1024_STATE_WORDS
|
|
||||||
};
|
|
||||||
#undef RCNT
|
|
||||||
#define RCNT (SKEIN1024_ROUNDS_TOTAL/8)
|
|
||||||
|
|
||||||
#ifdef SKEIN_LOOP /* configure how much to unroll the loop */
|
|
||||||
#define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10)
|
|
||||||
#else
|
|
||||||
#define SKEIN_UNROLL_1024 (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (SKEIN_UNROLL_1024 != 0)
|
|
||||||
#if (RCNT % SKEIN_UNROLL_1024)
|
|
||||||
#error "Invalid SKEIN_UNROLL_1024" /* sanity check on unroll count */
|
|
||||||
#endif
|
|
||||||
size_t r;
|
|
||||||
/* key schedule words : chaining vars + tweak + "rotation" */
|
|
||||||
uint64_t kw[WCNT + 4 + RCNT * 2];
|
|
||||||
#else
|
|
||||||
uint64_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* local copy of vars, for speed */
|
|
||||||
uint64_t X00, X01, X02, X03, X04, X05, X06, X07, X08, X09, X10, X11,
|
|
||||||
X12, X13, X14, X15;
|
|
||||||
uint64_t w[WCNT]; /* local copy of input block */
|
|
||||||
#ifdef SKEIN_DEBUG
|
|
||||||
/* use for debugging (help compiler put Xn in registers) */
|
|
||||||
const uint64_t *Xptr[16];
|
|
||||||
Xptr[0] = &X00;
|
|
||||||
Xptr[1] = &X01;
|
|
||||||
Xptr[2] = &X02;
|
|
||||||
Xptr[3] = &X03;
|
|
||||||
Xptr[4] = &X04;
|
|
||||||
Xptr[5] = &X05;
|
|
||||||
Xptr[6] = &X06;
|
|
||||||
Xptr[7] = &X07;
|
|
||||||
Xptr[8] = &X08;
|
|
||||||
Xptr[9] = &X09;
|
|
||||||
Xptr[10] = &X10;
|
|
||||||
Xptr[11] = &X11;
|
|
||||||
Xptr[12] = &X12;
|
|
||||||
Xptr[13] = &X13;
|
|
||||||
Xptr[14] = &X14;
|
|
||||||
Xptr[15] = &X15;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
|
|
||||||
ts[0] = ctx->h.T[0];
|
|
||||||
ts[1] = ctx->h.T[1];
|
|
||||||
do {
|
|
||||||
/*
|
|
||||||
* this implementation only supports 2**64 input bytes
|
|
||||||
* (no carry out here)
|
|
||||||
*/
|
|
||||||
ts[0] += byteCntAdd; /* update processed length */
|
|
||||||
|
|
||||||
/* precompute the key schedule for this block */
|
|
||||||
ks[0] = ctx->X[0];
|
|
||||||
ks[1] = ctx->X[1];
|
|
||||||
ks[2] = ctx->X[2];
|
|
||||||
ks[3] = ctx->X[3];
|
|
||||||
ks[4] = ctx->X[4];
|
|
||||||
ks[5] = ctx->X[5];
|
|
||||||
ks[6] = ctx->X[6];
|
|
||||||
ks[7] = ctx->X[7];
|
|
||||||
ks[8] = ctx->X[8];
|
|
||||||
ks[9] = ctx->X[9];
|
|
||||||
ks[10] = ctx->X[10];
|
|
||||||
ks[11] = ctx->X[11];
|
|
||||||
ks[12] = ctx->X[12];
|
|
||||||
ks[13] = ctx->X[13];
|
|
||||||
ks[14] = ctx->X[14];
|
|
||||||
ks[15] = ctx->X[15];
|
|
||||||
ks[16] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^
|
|
||||||
ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^
|
|
||||||
ks[8] ^ ks[9] ^ ks[10] ^ ks[11] ^
|
|
||||||
ks[12] ^ ks[13] ^ ks[14] ^ ks[15] ^ SKEIN_KS_PARITY;
|
|
||||||
|
|
||||||
ts[2] = ts[0] ^ ts[1];
|
|
||||||
|
|
||||||
/* get input block in little-endian format */
|
|
||||||
Skein_Get64_LSB_First(w, blkPtr, WCNT);
|
|
||||||
DebugSaveTweak(ctx);
|
|
||||||
Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts);
|
|
||||||
|
|
||||||
X00 = w[0] + ks[0]; /* do the first full key injection */
|
|
||||||
X01 = w[1] + ks[1];
|
|
||||||
X02 = w[2] + ks[2];
|
|
||||||
X03 = w[3] + ks[3];
|
|
||||||
X04 = w[4] + ks[4];
|
|
||||||
X05 = w[5] + ks[5];
|
|
||||||
X06 = w[6] + ks[6];
|
|
||||||
X07 = w[7] + ks[7];
|
|
||||||
X08 = w[8] + ks[8];
|
|
||||||
X09 = w[9] + ks[9];
|
|
||||||
X10 = w[10] + ks[10];
|
|
||||||
X11 = w[11] + ks[11];
|
|
||||||
X12 = w[12] + ks[12];
|
|
||||||
X13 = w[13] + ks[13] + ts[0];
|
|
||||||
X14 = w[14] + ks[14] + ts[1];
|
|
||||||
X15 = w[15] + ks[15];
|
|
||||||
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
|
|
||||||
Xptr);
|
|
||||||
|
|
||||||
#define Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \
|
|
||||||
pD, pE, pF, ROT, rNum) \
|
|
||||||
X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0;\
|
|
||||||
X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2;\
|
|
||||||
X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4;\
|
|
||||||
X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6;\
|
|
||||||
X##p8 += X##p9; X##p9 = RotL_64(X##p9, ROT##_4); X##p9 ^= X##p8;\
|
|
||||||
X##pA += X##pB; X##pB = RotL_64(X##pB, ROT##_5); X##pB ^= X##pA;\
|
|
||||||
X##pC += X##pD; X##pD = RotL_64(X##pD, ROT##_6); X##pD ^= X##pC;\
|
|
||||||
X##pE += X##pF; X##pF = RotL_64(X##pF, ROT##_7); X##pF ^= X##pE;
|
|
||||||
|
|
||||||
#if SKEIN_UNROLL_1024 == 0
|
|
||||||
#define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, \
|
|
||||||
pE, pF, ROT, rn) \
|
|
||||||
Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \
|
|
||||||
pD, pE, pF, ROT, rn) \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rn, Xptr);
|
|
||||||
|
|
||||||
#define I1024(R) \
|
|
||||||
X00 += ks[((R) + 1) % 17]; /* inject the key schedule value */\
|
|
||||||
X01 += ks[((R) + 2) % 17]; \
|
|
||||||
X02 += ks[((R) + 3) % 17]; \
|
|
||||||
X03 += ks[((R) + 4) % 17]; \
|
|
||||||
X04 += ks[((R) + 5) % 17]; \
|
|
||||||
X05 += ks[((R) + 6) % 17]; \
|
|
||||||
X06 += ks[((R) + 7) % 17]; \
|
|
||||||
X07 += ks[((R) + 8) % 17]; \
|
|
||||||
X08 += ks[((R) + 9) % 17]; \
|
|
||||||
X09 += ks[((R) + 10) % 17]; \
|
|
||||||
X10 += ks[((R) + 11) % 17]; \
|
|
||||||
X11 += ks[((R) + 12) % 17]; \
|
|
||||||
X12 += ks[((R) + 13) % 17]; \
|
|
||||||
X13 += ks[((R) + 14) % 17] + ts[((R) + 1) % 3]; \
|
|
||||||
X14 += ks[((R) + 15) % 17] + ts[((R) + 2) % 3]; \
|
|
||||||
X15 += ks[((R) + 16) % 17] + (R) +1; \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
#else /* looping version */
|
|
||||||
#define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, \
|
|
||||||
pE, pF, ROT, rn) \
|
|
||||||
Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, \
|
|
||||||
pD, pE, pF, ROT, rn) \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rn, Xptr);
|
|
||||||
|
|
||||||
#define I1024(R) \
|
|
||||||
X00 += ks[r + (R) + 0]; /* inject the key schedule value */ \
|
|
||||||
X01 += ks[r + (R) + 1]; \
|
|
||||||
X02 += ks[r + (R) + 2]; \
|
|
||||||
X03 += ks[r + (R) + 3]; \
|
|
||||||
X04 += ks[r + (R) + 4]; \
|
|
||||||
X05 += ks[r + (R) + 5]; \
|
|
||||||
X06 += ks[r + (R) + 6]; \
|
|
||||||
X07 += ks[r + (R) + 7]; \
|
|
||||||
X08 += ks[r + (R) + 8]; \
|
|
||||||
X09 += ks[r + (R) + 9]; \
|
|
||||||
X10 += ks[r + (R) + 10]; \
|
|
||||||
X11 += ks[r + (R) + 11]; \
|
|
||||||
X12 += ks[r + (R) + 12]; \
|
|
||||||
X13 += ks[r + (R) + 13] + ts[r + (R) + 0]; \
|
|
||||||
X14 += ks[r + (R) + 14] + ts[r + (R) + 1]; \
|
|
||||||
X15 += ks[r + (R) + 15] + r + (R); \
|
|
||||||
ks[r + (R) + 16] = ks[r + (R) - 1]; /* rotate key schedule */\
|
|
||||||
ts[r + (R) + 2] = ts[r + (R) - 1]; \
|
|
||||||
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, Xptr);
|
|
||||||
|
|
||||||
/* loop through it */
|
|
||||||
for (r = 1; r <= 2 * RCNT; r += 2 * SKEIN_UNROLL_1024)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#define R1024_8_rounds(R) /* do 8 full rounds */ \
|
|
||||||
R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, \
|
|
||||||
14, 15, R1024_0, 8 * (R) + 1); \
|
|
||||||
R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, \
|
|
||||||
08, 01, R1024_1, 8 * (R) + 2); \
|
|
||||||
R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, \
|
|
||||||
10, 09, R1024_2, 8 * (R) + 3); \
|
|
||||||
R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, \
|
|
||||||
12, 07, R1024_3, 8 * (R) + 4); \
|
|
||||||
I1024(2 * (R)); \
|
|
||||||
R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, \
|
|
||||||
14, 15, R1024_4, 8 * (R) + 5); \
|
|
||||||
R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, \
|
|
||||||
08, 01, R1024_5, 8 * (R) + 6); \
|
|
||||||
R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, \
|
|
||||||
10, 09, R1024_6, 8 * (R) + 7); \
|
|
||||||
R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, \
|
|
||||||
12, 07, R1024_7, 8 * (R) + 8); \
|
|
||||||
I1024(2 * (R) + 1);
|
|
||||||
|
|
||||||
R1024_8_rounds(0);
|
|
||||||
|
|
||||||
#define R1024_Unroll_R(NN) \
|
|
||||||
((SKEIN_UNROLL_1024 == 0 && SKEIN1024_ROUNDS_TOTAL/8 > (NN)) || \
|
|
||||||
(SKEIN_UNROLL_1024 > (NN)))
|
|
||||||
|
|
||||||
#if R1024_Unroll_R(1)
|
|
||||||
R1024_8_rounds(1);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(2)
|
|
||||||
R1024_8_rounds(2);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(3)
|
|
||||||
R1024_8_rounds(3);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(4)
|
|
||||||
R1024_8_rounds(4);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(5)
|
|
||||||
R1024_8_rounds(5);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(6)
|
|
||||||
R1024_8_rounds(6);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(7)
|
|
||||||
R1024_8_rounds(7);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(8)
|
|
||||||
R1024_8_rounds(8);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(9)
|
|
||||||
R1024_8_rounds(9);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(10)
|
|
||||||
R1024_8_rounds(10);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(11)
|
|
||||||
R1024_8_rounds(11);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(12)
|
|
||||||
R1024_8_rounds(12);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(13)
|
|
||||||
R1024_8_rounds(13);
|
|
||||||
#endif
|
|
||||||
#if R1024_Unroll_R(14)
|
|
||||||
R1024_8_rounds(14);
|
|
||||||
#endif
|
|
||||||
#if (SKEIN_UNROLL_1024 > 14)
|
|
||||||
#error "need more unrolling in Skein_1024_Process_Block"
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* do the final "feedforward" xor, update context chaining vars
|
|
||||||
*/
|
|
||||||
|
|
||||||
ctx->X[0] = X00 ^ w[0];
|
|
||||||
ctx->X[1] = X01 ^ w[1];
|
|
||||||
ctx->X[2] = X02 ^ w[2];
|
|
||||||
ctx->X[3] = X03 ^ w[3];
|
|
||||||
ctx->X[4] = X04 ^ w[4];
|
|
||||||
ctx->X[5] = X05 ^ w[5];
|
|
||||||
ctx->X[6] = X06 ^ w[6];
|
|
||||||
ctx->X[7] = X07 ^ w[7];
|
|
||||||
ctx->X[8] = X08 ^ w[8];
|
|
||||||
ctx->X[9] = X09 ^ w[9];
|
|
||||||
ctx->X[10] = X10 ^ w[10];
|
|
||||||
ctx->X[11] = X11 ^ w[11];
|
|
||||||
ctx->X[12] = X12 ^ w[12];
|
|
||||||
ctx->X[13] = X13 ^ w[13];
|
|
||||||
ctx->X[14] = X14 ^ w[14];
|
|
||||||
ctx->X[15] = X15 ^ w[15];
|
|
||||||
|
|
||||||
Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
|
|
||||||
|
|
||||||
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
|
|
||||||
blkPtr += SKEIN1024_BLOCK_BYTES;
|
|
||||||
} while (--blkCnt);
|
|
||||||
ctx->h.T[0] = ts[0];
|
|
||||||
ctx->h.T[1] = ts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
|
|
||||||
size_t
|
|
||||||
Skein1024_Process_Block_CodeSize(void)
|
|
||||||
{
|
|
||||||
return ((uint8_t *)Skein1024_Process_Block_CodeSize) -
|
|
||||||
((uint8_t *)Skein1024_Process_Block);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint_t
|
|
||||||
Skein1024_Unroll_Cnt(void)
|
|
||||||
{
|
|
||||||
return (SKEIN_UNROLL_1024);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,41 +1,78 @@
|
||||||
/*
|
/*
|
||||||
* Internal definitions for Skein hashing.
|
* CDDL HEADER START
|
||||||
* Source code author: Doug Whiting, 2008.
|
|
||||||
* This algorithm and source code is released to the public domain.
|
|
||||||
*
|
*
|
||||||
* The following compile-time switches may be defined to control some
|
* The contents of this file are subject to the terms of the
|
||||||
* tradeoffs between speed, code size, error checking, and security.
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* The "default" note explains what happens when the switch is not defined.
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
* SKEIN_DEBUG -- make callouts from inside Skein code
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
* to examine/display intermediate values.
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
* [default: no callouts (no overhead)]
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
*
|
*
|
||||||
* SKEIN_ERR_CHECK -- how error checking is handled inside Skein
|
* CDDL HEADER END
|
||||||
* code. If not defined, most error checking
|
*/
|
||||||
* is disabled (for performance). Otherwise,
|
|
||||||
* the switch value is interpreted as:
|
/*
|
||||||
* 0: use assert() to flag errors
|
* Implementation of the Skein 512-bit hash function, based
|
||||||
* 1: return SKEIN_FAIL to flag errors
|
* on the public domain implementation by Doug Whiting.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008,2013 Doug Whiting
|
||||||
|
* Copyright (c) 2023 Tino Reichardt <milky-zfs@mcmilk.de>
|
||||||
*/
|
*/
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
|
|
||||||
#ifndef _SKEIN_IMPL_H_
|
#ifndef _SKEIN_IMPL_H_
|
||||||
#define _SKEIN_IMPL_H_
|
#define _SKEIN_IMPL_H_
|
||||||
|
|
||||||
#include <sys/skein.h>
|
|
||||||
#include <sys/string.h>
|
#include <sys/string.h>
|
||||||
#include "skein_impl.h"
|
#include <sys/skein.h>
|
||||||
#include "skein_port.h"
|
|
||||||
|
|
||||||
/*
|
#include "skein_impl.h"
|
||||||
* "Internal" Skein definitions
|
|
||||||
* -- not needed for sequential hashing API, but will be
|
#if defined(_ZFS_BIG_ENDIAN)
|
||||||
* helpful for other uses of Skein (e.g., tree hash mode).
|
#define SKEIN_NEED_SWAP (1)
|
||||||
* -- included here so that they can be shared between
|
#define Skein_Swap64(w64) (__builtin_bswap64(w64))
|
||||||
* reference and optimized code.
|
#else
|
||||||
*/
|
#define SKEIN_NEED_SWAP (0)
|
||||||
|
#define Skein_Swap64(w64) (w64)
|
||||||
|
#define Skein_Put64_LSB_First(dst, src, bCnt) memcpy(dst, src, bCnt)
|
||||||
|
#define Skein_Get64_LSB_First(dst, src, wCnt) memcpy(dst, src, 8 * (wCnt))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Skein_Put64_LSB_First
|
||||||
|
/* this is fully portable for all endian, but slow */
|
||||||
|
static inline void
|
||||||
|
Skein_Put64_LSB_First(uint8_t *dst, const uint64_t *src, size_t bCnt)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < bCnt; n++)
|
||||||
|
dst[n] = (uint8_t)(src[n >> 3] >> (8 * (n & 7)));
|
||||||
|
}
|
||||||
|
#endif /* ifndef Skein_Put64_LSB_First */
|
||||||
|
|
||||||
|
#ifndef Skein_Get64_LSB_First
|
||||||
|
/* this is fully portable for all endian, but slow */
|
||||||
|
static inline void
|
||||||
|
Skein_Get64_LSB_First(uint64_t *dst, const uint8_t *src, size_t wCnt)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < 8 * wCnt; n += 8)
|
||||||
|
dst[n / 8] = (((uint64_t)src[n])) +
|
||||||
|
(((uint64_t)src[n + 1]) << 8) +
|
||||||
|
(((uint64_t)src[n + 2]) << 16) +
|
||||||
|
(((uint64_t)src[n + 3]) << 24) +
|
||||||
|
(((uint64_t)src[n + 4]) << 32) +
|
||||||
|
(((uint64_t)src[n + 5]) << 40) +
|
||||||
|
(((uint64_t)src[n + 6]) << 48) +
|
||||||
|
(((uint64_t)src[n + 7]) << 56);
|
||||||
|
}
|
||||||
|
#endif /* ifndef Skein_Get64_LSB_First */
|
||||||
|
|
||||||
/* tweak word T[1]: bit field starting positions */
|
/* tweak word T[1]: bit field starting positions */
|
||||||
/* offset 64 because it's the second word */
|
/* offset 64 because it's the second word */
|
||||||
|
@ -65,7 +102,7 @@
|
||||||
#define SKEIN_BLK_TYPE_KEY (0) /* key, for MAC and KDF */
|
#define SKEIN_BLK_TYPE_KEY (0) /* key, for MAC and KDF */
|
||||||
#define SKEIN_BLK_TYPE_CFG (4) /* configuration block */
|
#define SKEIN_BLK_TYPE_CFG (4) /* configuration block */
|
||||||
#define SKEIN_BLK_TYPE_PERS (8) /* personalization string */
|
#define SKEIN_BLK_TYPE_PERS (8) /* personalization string */
|
||||||
#define SKEIN_BLK_TYPE_PK (12) /* public key (for signature hashing) */
|
#define SKEIN_BLK_TYPE_PK (12) /* public key (for hashing) */
|
||||||
#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */
|
#define SKEIN_BLK_TYPE_KDF (16) /* key identifier for KDF */
|
||||||
#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */
|
#define SKEIN_BLK_TYPE_NONCE (20) /* nonce for PRNG */
|
||||||
#define SKEIN_BLK_TYPE_MSG (48) /* message processing */
|
#define SKEIN_BLK_TYPE_MSG (48) /* message processing */
|
||||||
|
@ -179,104 +216,27 @@
|
||||||
(hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height); \
|
(hdr).T[1] |= SKEIN_T1_TREE_LEVEL(height); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*
|
|
||||||
* "Internal" Skein definitions for debugging and error checking
|
|
||||||
* Note: in Illumos we always disable debugging features.
|
|
||||||
*/
|
|
||||||
#define Skein_Show_Block(bits, ctx, X, blkPtr, wPtr, ksEvenPtr, ksOddPtr)
|
|
||||||
#define Skein_Show_Round(bits, ctx, r, X)
|
|
||||||
#define Skein_Show_R_Ptr(bits, ctx, r, X_ptr)
|
|
||||||
#define Skein_Show_Final(bits, ctx, cnt, outPtr)
|
|
||||||
#define Skein_Show_Key(bits, ctx, key, keyBytes)
|
|
||||||
|
|
||||||
/* run-time checks (e.g., bad params, uninitialized context)? */
|
|
||||||
#ifndef SKEIN_ERR_CHECK
|
|
||||||
/* default: ignore all Asserts, for performance */
|
|
||||||
#define Skein_Assert(x, retCode)
|
|
||||||
#define Skein_assert(x)
|
|
||||||
#elif defined(SKEIN_ASSERT)
|
|
||||||
#include <sys/debug.h>
|
|
||||||
#define Skein_Assert(x, retCode) ASSERT(x)
|
|
||||||
#define Skein_assert(x) ASSERT(x)
|
|
||||||
#else
|
|
||||||
#include <sys/debug.h>
|
|
||||||
/* caller error */
|
|
||||||
#define Skein_Assert(x, retCode) \
|
|
||||||
do { \
|
|
||||||
if (!(x)) \
|
|
||||||
return (retCode); \
|
|
||||||
} while (0)
|
|
||||||
/* internal error */
|
|
||||||
#define Skein_assert(x) ASSERT(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skein block function constants (shared across Ref and Opt code)
|
* Skein block function constants (shared across Ref and Opt code)
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
/* Skein_256 round rotation constants */
|
|
||||||
R_256_0_0 = 14, R_256_0_1 = 16,
|
|
||||||
R_256_1_0 = 52, R_256_1_1 = 57,
|
|
||||||
R_256_2_0 = 23, R_256_2_1 = 40,
|
|
||||||
R_256_3_0 = 5, R_256_3_1 = 37,
|
|
||||||
R_256_4_0 = 25, R_256_4_1 = 33,
|
|
||||||
R_256_5_0 = 46, R_256_5_1 = 12,
|
|
||||||
R_256_6_0 = 58, R_256_6_1 = 22,
|
|
||||||
R_256_7_0 = 32, R_256_7_1 = 32,
|
|
||||||
|
|
||||||
/* Skein_512 round rotation constants */
|
/* Skein_512 round rotation constants */
|
||||||
R_512_0_0 = 46, R_512_0_1 = 36, R_512_0_2 = 19, R_512_0_3 = 37,
|
R_512_0_0 = 46, R_512_0_1 = 36, R_512_0_2 = 19, R_512_0_3 = 37,
|
||||||
R_512_1_0 = 33, R_512_1_1 = 27, R_512_1_2 = 14, R_512_1_3 = 42,
|
R_512_1_0 = 33, R_512_1_1 = 27, R_512_1_2 = 14, R_512_1_3 = 42,
|
||||||
R_512_2_0 = 17, R_512_2_1 = 49, R_512_2_2 = 36, R_512_2_3 = 39,
|
R_512_2_0 = 17, R_512_2_1 = 49, R_512_2_2 = 36, R_512_2_3 = 39,
|
||||||
R_512_3_0 = 44, R_512_3_1 = 9, R_512_3_2 = 54, R_512_3_3 = 56,
|
R_512_3_0 = 44, R_512_3_1 = 9, R_512_3_2 = 54, R_512_3_3 = 56,
|
||||||
R_512_4_0 = 39, R_512_4_1 = 30, R_512_4_2 = 34, R_512_4_3 = 24,
|
R_512_4_0 = 39, R_512_4_1 = 30, R_512_4_2 = 34, R_512_4_3 = 24,
|
||||||
R_512_5_0 = 13, R_512_5_1 = 50, R_512_5_2 = 10, R_512_5_3 = 17,
|
R_512_5_0 = 13, R_512_5_1 = 50, R_512_5_2 = 10, R_512_5_3 = 17,
|
||||||
R_512_6_0 = 25, R_512_6_1 = 29, R_512_6_2 = 39, R_512_6_3 = 43,
|
R_512_6_0 = 25, R_512_6_1 = 29, R_512_6_2 = 39, R_512_6_3 = 43,
|
||||||
R_512_7_0 = 8, R_512_7_1 = 35, R_512_7_2 = 56, R_512_7_3 = 22,
|
R_512_7_0 = 8, R_512_7_1 = 35, R_512_7_2 = 56, R_512_7_3 = 22,
|
||||||
|
|
||||||
/* Skein1024 round rotation constants */
|
|
||||||
R1024_0_0 = 24, R1024_0_1 = 13, R1024_0_2 = 8, R1024_0_3 =
|
|
||||||
47, R1024_0_4 = 8, R1024_0_5 = 17, R1024_0_6 = 22, R1024_0_7 = 37,
|
|
||||||
R1024_1_0 = 38, R1024_1_1 = 19, R1024_1_2 = 10, R1024_1_3 =
|
|
||||||
55, R1024_1_4 = 49, R1024_1_5 = 18, R1024_1_6 = 23, R1024_1_7 = 52,
|
|
||||||
R1024_2_0 = 33, R1024_2_1 = 4, R1024_2_2 = 51, R1024_2_3 =
|
|
||||||
13, R1024_2_4 = 34, R1024_2_5 = 41, R1024_2_6 = 59, R1024_2_7 = 17,
|
|
||||||
R1024_3_0 = 5, R1024_3_1 = 20, R1024_3_2 = 48, R1024_3_3 =
|
|
||||||
41, R1024_3_4 = 47, R1024_3_5 = 28, R1024_3_6 = 16, R1024_3_7 = 25,
|
|
||||||
R1024_4_0 = 41, R1024_4_1 = 9, R1024_4_2 = 37, R1024_4_3 =
|
|
||||||
31, R1024_4_4 = 12, R1024_4_5 = 47, R1024_4_6 = 44, R1024_4_7 = 30,
|
|
||||||
R1024_5_0 = 16, R1024_5_1 = 34, R1024_5_2 = 56, R1024_5_3 =
|
|
||||||
51, R1024_5_4 = 4, R1024_5_5 = 53, R1024_5_6 = 42, R1024_5_7 = 41,
|
|
||||||
R1024_6_0 = 31, R1024_6_1 = 44, R1024_6_2 = 47, R1024_6_3 =
|
|
||||||
46, R1024_6_4 = 19, R1024_6_5 = 42, R1024_6_6 = 44, R1024_6_7 = 25,
|
|
||||||
R1024_7_0 = 9, R1024_7_1 = 48, R1024_7_2 = 35, R1024_7_3 =
|
|
||||||
52, R1024_7_4 = 23, R1024_7_5 = 31, R1024_7_6 = 37, R1024_7_7 = 20
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* number of rounds for the different block sizes */
|
/* number of rounds for the different block sizes */
|
||||||
#define SKEIN_256_ROUNDS_TOTAL (72)
|
|
||||||
#define SKEIN_512_ROUNDS_TOTAL (72)
|
#define SKEIN_512_ROUNDS_TOTAL (72)
|
||||||
#define SKEIN1024_ROUNDS_TOTAL (80)
|
|
||||||
|
|
||||||
|
|
||||||
extern const uint64_t SKEIN_256_IV_128[];
|
|
||||||
extern const uint64_t SKEIN_256_IV_160[];
|
|
||||||
extern const uint64_t SKEIN_256_IV_224[];
|
|
||||||
extern const uint64_t SKEIN_256_IV_256[];
|
|
||||||
extern const uint64_t SKEIN_512_IV_224[];
|
|
||||||
extern const uint64_t SKEIN_512_IV_256[];
|
|
||||||
extern const uint64_t SKEIN_512_IV_384[];
|
|
||||||
extern const uint64_t SKEIN_512_IV_512[];
|
|
||||||
extern const uint64_t SKEIN1024_IV_384[];
|
|
||||||
extern const uint64_t SKEIN1024_IV_512[];
|
|
||||||
extern const uint64_t SKEIN1024_IV_1024[];
|
|
||||||
|
|
||||||
/* Functions to process blkCnt (nonzero) full block(s) of data. */
|
/* Functions to process blkCnt (nonzero) full block(s) of data. */
|
||||||
void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr,
|
extern void
|
||||||
size_t blkCnt, size_t byteCntAdd);
|
Skein_512_Process_Block(SKEIN_CTX *ctx, const uint8_t *blkPtr,
|
||||||
void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
|
|
||||||
size_t blkCnt, size_t byteCntAdd);
|
|
||||||
void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx, const uint8_t *blkPtr,
|
|
||||||
size_t blkCnt, size_t byteCntAdd);
|
size_t blkCnt, size_t byteCntAdd);
|
||||||
|
|
||||||
#endif /* _SKEIN_IMPL_H_ */
|
#endif /* _SKEIN_IMPL_H_ */
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* Pre-computed Skein IVs
|
|
||||||
*
|
|
||||||
* NOTE: these values are not "magic" constants, but
|
|
||||||
* are generated using the Threefish block function.
|
|
||||||
* They are pre-computed here only for speed; i.e., to
|
|
||||||
* avoid the need for a Threefish call during Init().
|
|
||||||
*
|
|
||||||
* The IV for any fixed hash length may be pre-computed.
|
|
||||||
* Only the most common values are included here.
|
|
||||||
*/
|
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
/*
|
|
||||||
* Illumos implementation note: these constants are for Skein v1.3 as per:
|
|
||||||
* http://www.skein-hash.info/sites/default/files/skein1.3.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/skein.h> /* get Skein macros and types */
|
|
||||||
#include "skein_impl.h" /* get internal definitions */
|
|
||||||
|
|
||||||
#define MK_64 SKEIN_MK_64
|
|
||||||
|
|
||||||
/* blkSize = 256 bits. hashSize = 128 bits */
|
|
||||||
const uint64_t SKEIN_256_IV_128[] = {
|
|
||||||
MK_64(0xE1111906, 0x964D7260),
|
|
||||||
MK_64(0x883DAAA7, 0x7C8D811C),
|
|
||||||
MK_64(0x10080DF4, 0x91960F7A),
|
|
||||||
MK_64(0xCCF7DDE5, 0xB45BC1C2)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 256 bits. hashSize = 160 bits */
|
|
||||||
const uint64_t SKEIN_256_IV_160[] = {
|
|
||||||
MK_64(0x14202314, 0x72825E98),
|
|
||||||
MK_64(0x2AC4E9A2, 0x5A77E590),
|
|
||||||
MK_64(0xD47A5856, 0x8838D63E),
|
|
||||||
MK_64(0x2DD2E496, 0x8586AB7D)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 256 bits. hashSize = 224 bits */
|
|
||||||
const uint64_t SKEIN_256_IV_224[] = {
|
|
||||||
MK_64(0xC6098A8C, 0x9AE5EA0B),
|
|
||||||
MK_64(0x876D5686, 0x08C5191C),
|
|
||||||
MK_64(0x99CB88D7, 0xD7F53884),
|
|
||||||
MK_64(0x384BDDB1, 0xAEDDB5DE)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 256 bits. hashSize = 256 bits */
|
|
||||||
const uint64_t SKEIN_256_IV_256[] = {
|
|
||||||
MK_64(0xFC9DA860, 0xD048B449),
|
|
||||||
MK_64(0x2FCA6647, 0x9FA7D833),
|
|
||||||
MK_64(0xB33BC389, 0x6656840F),
|
|
||||||
MK_64(0x6A54E920, 0xFDE8DA69)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 512 bits. hashSize = 224 bits */
|
|
||||||
const uint64_t SKEIN_512_IV_224[] = {
|
|
||||||
MK_64(0xCCD06162, 0x48677224),
|
|
||||||
MK_64(0xCBA65CF3, 0xA92339EF),
|
|
||||||
MK_64(0x8CCD69D6, 0x52FF4B64),
|
|
||||||
MK_64(0x398AED7B, 0x3AB890B4),
|
|
||||||
MK_64(0x0F59D1B1, 0x457D2BD0),
|
|
||||||
MK_64(0x6776FE65, 0x75D4EB3D),
|
|
||||||
MK_64(0x99FBC70E, 0x997413E9),
|
|
||||||
MK_64(0x9E2CFCCF, 0xE1C41EF7)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 512 bits. hashSize = 256 bits */
|
|
||||||
const uint64_t SKEIN_512_IV_256[] = {
|
|
||||||
MK_64(0xCCD044A1, 0x2FDB3E13),
|
|
||||||
MK_64(0xE8359030, 0x1A79A9EB),
|
|
||||||
MK_64(0x55AEA061, 0x4F816E6F),
|
|
||||||
MK_64(0x2A2767A4, 0xAE9B94DB),
|
|
||||||
MK_64(0xEC06025E, 0x74DD7683),
|
|
||||||
MK_64(0xE7A436CD, 0xC4746251),
|
|
||||||
MK_64(0xC36FBAF9, 0x393AD185),
|
|
||||||
MK_64(0x3EEDBA18, 0x33EDFC13)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 512 bits. hashSize = 384 bits */
|
|
||||||
const uint64_t SKEIN_512_IV_384[] = {
|
|
||||||
MK_64(0xA3F6C6BF, 0x3A75EF5F),
|
|
||||||
MK_64(0xB0FEF9CC, 0xFD84FAA4),
|
|
||||||
MK_64(0x9D77DD66, 0x3D770CFE),
|
|
||||||
MK_64(0xD798CBF3, 0xB468FDDA),
|
|
||||||
MK_64(0x1BC4A666, 0x8A0E4465),
|
|
||||||
MK_64(0x7ED7D434, 0xE5807407),
|
|
||||||
MK_64(0x548FC1AC, 0xD4EC44D6),
|
|
||||||
MK_64(0x266E1754, 0x6AA18FF8)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 512 bits. hashSize = 512 bits */
|
|
||||||
const uint64_t SKEIN_512_IV_512[] = {
|
|
||||||
MK_64(0x4903ADFF, 0x749C51CE),
|
|
||||||
MK_64(0x0D95DE39, 0x9746DF03),
|
|
||||||
MK_64(0x8FD19341, 0x27C79BCE),
|
|
||||||
MK_64(0x9A255629, 0xFF352CB1),
|
|
||||||
MK_64(0x5DB62599, 0xDF6CA7B0),
|
|
||||||
MK_64(0xEABE394C, 0xA9D5C3F4),
|
|
||||||
MK_64(0x991112C7, 0x1A75B523),
|
|
||||||
MK_64(0xAE18A40B, 0x660FCC33)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 1024 bits. hashSize = 384 bits */
|
|
||||||
const uint64_t SKEIN1024_IV_384[] = {
|
|
||||||
MK_64(0x5102B6B8, 0xC1894A35),
|
|
||||||
MK_64(0xFEEBC9E3, 0xFE8AF11A),
|
|
||||||
MK_64(0x0C807F06, 0xE32BED71),
|
|
||||||
MK_64(0x60C13A52, 0xB41A91F6),
|
|
||||||
MK_64(0x9716D35D, 0xD4917C38),
|
|
||||||
MK_64(0xE780DF12, 0x6FD31D3A),
|
|
||||||
MK_64(0x797846B6, 0xC898303A),
|
|
||||||
MK_64(0xB172C2A8, 0xB3572A3B),
|
|
||||||
MK_64(0xC9BC8203, 0xA6104A6C),
|
|
||||||
MK_64(0x65909338, 0xD75624F4),
|
|
||||||
MK_64(0x94BCC568, 0x4B3F81A0),
|
|
||||||
MK_64(0x3EBBF51E, 0x10ECFD46),
|
|
||||||
MK_64(0x2DF50F0B, 0xEEB08542),
|
|
||||||
MK_64(0x3B5A6530, 0x0DBC6516),
|
|
||||||
MK_64(0x484B9CD2, 0x167BBCE1),
|
|
||||||
MK_64(0x2D136947, 0xD4CBAFEA)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 1024 bits. hashSize = 512 bits */
|
|
||||||
const uint64_t SKEIN1024_IV_512[] = {
|
|
||||||
MK_64(0xCAEC0E5D, 0x7C1B1B18),
|
|
||||||
MK_64(0xA01B0E04, 0x5F03E802),
|
|
||||||
MK_64(0x33840451, 0xED912885),
|
|
||||||
MK_64(0x374AFB04, 0xEAEC2E1C),
|
|
||||||
MK_64(0xDF25A0E2, 0x813581F7),
|
|
||||||
MK_64(0xE4004093, 0x8B12F9D2),
|
|
||||||
MK_64(0xA662D539, 0xC2ED39B6),
|
|
||||||
MK_64(0xFA8B85CF, 0x45D8C75A),
|
|
||||||
MK_64(0x8316ED8E, 0x29EDE796),
|
|
||||||
MK_64(0x053289C0, 0x2E9F91B8),
|
|
||||||
MK_64(0xC3F8EF1D, 0x6D518B73),
|
|
||||||
MK_64(0xBDCEC3C4, 0xD5EF332E),
|
|
||||||
MK_64(0x549A7E52, 0x22974487),
|
|
||||||
MK_64(0x67070872, 0x5B749816),
|
|
||||||
MK_64(0xB9CD28FB, 0xF0581BD1),
|
|
||||||
MK_64(0x0E2940B8, 0x15804974)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* blkSize = 1024 bits. hashSize = 1024 bits */
|
|
||||||
const uint64_t SKEIN1024_IV_1024[] = {
|
|
||||||
MK_64(0xD593DA07, 0x41E72355),
|
|
||||||
MK_64(0x15B5E511, 0xAC73E00C),
|
|
||||||
MK_64(0x5180E5AE, 0xBAF2C4F0),
|
|
||||||
MK_64(0x03BD41D3, 0xFCBCAFAF),
|
|
||||||
MK_64(0x1CAEC6FD, 0x1983A898),
|
|
||||||
MK_64(0x6E510B8B, 0xCDD0589F),
|
|
||||||
MK_64(0x77E2BDFD, 0xC6394ADA),
|
|
||||||
MK_64(0xC11E1DB5, 0x24DCB0A3),
|
|
||||||
MK_64(0xD6D14AF9, 0xC6329AB5),
|
|
||||||
MK_64(0x6A9B0BFC, 0x6EB67E0D),
|
|
||||||
MK_64(0x9243C60D, 0xCCFF1332),
|
|
||||||
MK_64(0x1A1F1DDE, 0x743F02D4),
|
|
||||||
MK_64(0x0996753C, 0x10ED0BB8),
|
|
||||||
MK_64(0x6572DD22, 0xF2B4969A),
|
|
||||||
MK_64(0x61FD3062, 0xD00A579A),
|
|
||||||
MK_64(0x1DE0536E, 0x8682E539)
|
|
||||||
};
|
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
* Platform-specific definitions for Skein hash function.
|
|
||||||
*
|
|
||||||
* Source code author: Doug Whiting, 2008.
|
|
||||||
*
|
|
||||||
* This algorithm and source code is released to the public domain.
|
|
||||||
*
|
|
||||||
* Many thanks to Brian Gladman for his portable header files.
|
|
||||||
*
|
|
||||||
* To port Skein to an "unsupported" platform, change the definitions
|
|
||||||
* in this file appropriately.
|
|
||||||
*/
|
|
||||||
/* Copyright 2013 Doug Whiting. This code is released to the public domain. */
|
|
||||||
|
|
||||||
#ifndef _SKEIN_PORT_H_
|
|
||||||
#define _SKEIN_PORT_H_
|
|
||||||
|
|
||||||
#include <sys/types.h> /* get integer type definitions */
|
|
||||||
|
|
||||||
#ifndef RotL_64
|
|
||||||
#define RotL_64(x, N) (((x) << (N)) | ((x) >> (64 - (N))))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skein is "natively" little-endian (unlike SHA-xxx), for optimal
|
|
||||||
* performance on x86 CPUs. The Skein code requires the following
|
|
||||||
* definitions for dealing with endianness:
|
|
||||||
*
|
|
||||||
* SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian
|
|
||||||
* Skein_Put64_LSB_First
|
|
||||||
* Skein_Get64_LSB_First
|
|
||||||
* Skein_Swap64
|
|
||||||
*
|
|
||||||
* If SKEIN_NEED_SWAP is defined at compile time, it is used here
|
|
||||||
* along with the portable versions of Put64/Get64/Swap64, which
|
|
||||||
* are slow in general.
|
|
||||||
*
|
|
||||||
* Otherwise, an "auto-detect" of endianness is attempted below.
|
|
||||||
* If the default handling doesn't work well, the user may insert
|
|
||||||
* platform-specific code instead (e.g., for big-endian CPUs).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */
|
|
||||||
|
|
||||||
#include <sys/isa_defs.h> /* get endianness selection */
|
|
||||||
|
|
||||||
#if defined(_ZFS_BIG_ENDIAN)
|
|
||||||
/* here for big-endian CPUs */
|
|
||||||
#define SKEIN_NEED_SWAP (1)
|
|
||||||
#else
|
|
||||||
/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
|
|
||||||
#define SKEIN_NEED_SWAP (0)
|
|
||||||
#define Skein_Put64_LSB_First(dst08, src64, bCnt) memcpy(dst08, src64, bCnt)
|
|
||||||
#define Skein_Get64_LSB_First(dst64, src08, wCnt) \
|
|
||||||
memcpy(dst64, src08, 8 * (wCnt))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ifndef SKEIN_NEED_SWAP */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide any definitions still needed.
|
|
||||||
*/
|
|
||||||
#ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */
|
|
||||||
#if SKEIN_NEED_SWAP
|
|
||||||
#define Skein_Swap64(w64) \
|
|
||||||
(((((uint64_t)(w64)) & 0xFF) << 56) | \
|
|
||||||
(((((uint64_t)(w64)) >> 8) & 0xFF) << 48) | \
|
|
||||||
(((((uint64_t)(w64)) >> 16) & 0xFF) << 40) | \
|
|
||||||
(((((uint64_t)(w64)) >> 24) & 0xFF) << 32) | \
|
|
||||||
(((((uint64_t)(w64)) >> 32) & 0xFF) << 24) | \
|
|
||||||
(((((uint64_t)(w64)) >> 40) & 0xFF) << 16) | \
|
|
||||||
(((((uint64_t)(w64)) >> 48) & 0xFF) << 8) | \
|
|
||||||
(((((uint64_t)(w64)) >> 56) & 0xFF)))
|
|
||||||
#else
|
|
||||||
#define Skein_Swap64(w64) (w64)
|
|
||||||
#endif
|
|
||||||
#endif /* ifndef Skein_Swap64 */
|
|
||||||
|
|
||||||
#ifndef Skein_Put64_LSB_First
|
|
||||||
static inline void
|
|
||||||
Skein_Put64_LSB_First(uint8_t *dst, const uint64_t *src, size_t bCnt)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* this version is fully portable (big-endian or little-endian),
|
|
||||||
* but slow
|
|
||||||
*/
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
for (n = 0; n < bCnt; n++)
|
|
||||||
dst[n] = (uint8_t)(src[n >> 3] >> (8 * (n & 7)));
|
|
||||||
}
|
|
||||||
#endif /* ifndef Skein_Put64_LSB_First */
|
|
||||||
|
|
||||||
#ifndef Skein_Get64_LSB_First
|
|
||||||
static inline void
|
|
||||||
Skein_Get64_LSB_First(uint64_t *dst, const uint8_t *src, size_t wCnt)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* this version is fully portable (big-endian or little-endian),
|
|
||||||
* but slow
|
|
||||||
*/
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
for (n = 0; n < 8 * wCnt; n += 8)
|
|
||||||
dst[n / 8] = (((uint64_t)src[n])) +
|
|
||||||
(((uint64_t)src[n + 1]) << 8) +
|
|
||||||
(((uint64_t)src[n + 2]) << 16) +
|
|
||||||
(((uint64_t)src[n + 3]) << 24) +
|
|
||||||
(((uint64_t)src[n + 4]) << 32) +
|
|
||||||
(((uint64_t)src[n + 5]) << 40) +
|
|
||||||
(((uint64_t)src[n + 6]) << 48) +
|
|
||||||
(((uint64_t)src[n + 7]) << 56);
|
|
||||||
}
|
|
||||||
#endif /* ifndef Skein_Get64_LSB_First */
|
|
||||||
|
|
||||||
#endif /* _SKEIN_PORT_H_ */
|
|
|
@ -18,22 +18,22 @@
|
||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2013 Saso Kiselkov. All rights reserved.
|
* Copyright (c) 2013 Saso Kiselkov. All rights reserved.
|
||||||
* Copyright (c) 2016 by Delphix. All rights reserved.
|
* Copyright (c) 2016 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
#include <sys/zio.h>
|
|
||||||
#include <sys/zio_checksum.h>
|
#include <sys/zio_checksum.h>
|
||||||
#include <sys/skein.h>
|
#include <sys/skein.h>
|
||||||
|
|
||||||
#include <sys/abd.h>
|
#include <sys/abd.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
skein_incremental(void *buf, size_t size, void *arg)
|
skein_incremental(void *buf, size_t size, void *arg)
|
||||||
{
|
{
|
||||||
Skein_512_Ctxt_t *ctx = arg;
|
SKEIN_CTX *ctx = arg;
|
||||||
(void) Skein_512_Update(ctx, buf, size);
|
Skein_512_Update(ctx, buf, size);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -45,12 +45,12 @@ void
|
||||||
abd_checksum_skein_native(abd_t *abd, uint64_t size,
|
abd_checksum_skein_native(abd_t *abd, uint64_t size,
|
||||||
const void *ctx_template, zio_cksum_t *zcp)
|
const void *ctx_template, zio_cksum_t *zcp)
|
||||||
{
|
{
|
||||||
Skein_512_Ctxt_t ctx;
|
SKEIN_CTX ctx;
|
||||||
|
|
||||||
ASSERT(ctx_template != NULL);
|
ASSERT(ctx_template != NULL);
|
||||||
memcpy(&ctx, ctx_template, sizeof (ctx));
|
memcpy(&ctx, ctx_template, sizeof (ctx));
|
||||||
(void) abd_iterate_func(abd, 0, size, skein_incremental, &ctx);
|
(void) abd_iterate_func(abd, 0, size, skein_incremental, &ctx);
|
||||||
(void) Skein_512_Final(&ctx, (uint8_t *)zcp);
|
Skein_512_Final(&ctx, (uint8_t *)zcp);
|
||||||
memset(&ctx, 0, sizeof (ctx));
|
memset(&ctx, 0, sizeof (ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +79,9 @@ abd_checksum_skein_byteswap(abd_t *abd, uint64_t size,
|
||||||
void *
|
void *
|
||||||
abd_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt)
|
abd_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt)
|
||||||
{
|
{
|
||||||
Skein_512_Ctxt_t *ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
|
SKEIN_CTX *ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
|
||||||
|
|
||||||
(void) Skein_512_InitExt(ctx, sizeof (zio_cksum_t) * 8, 0,
|
Skein_512_InitExt(ctx, sizeof (zio_cksum_t) * 8, 0,
|
||||||
salt->zcs_bytes, sizeof (salt->zcs_bytes));
|
salt->zcs_bytes, sizeof (salt->zcs_bytes));
|
||||||
return (ctx);
|
return (ctx);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ abd_checksum_skein_tmpl_init(const zio_cksum_salt_t *salt)
|
||||||
void
|
void
|
||||||
abd_checksum_skein_tmpl_free(void *ctx_template)
|
abd_checksum_skein_tmpl_free(void *ctx_template)
|
||||||
{
|
{
|
||||||
Skein_512_Ctxt_t *ctx = ctx_template;
|
SKEIN_CTX *ctx = ctx_template;
|
||||||
|
|
||||||
memset(ctx, 0, sizeof (*ctx));
|
memset(ctx, 0, sizeof (*ctx));
|
||||||
kmem_free(ctx, sizeof (*ctx));
|
kmem_free(ctx, sizeof (*ctx));
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skein test suite using values from the Skein V1.3 specification found at:
|
* Skein test suite using values from the Skein V1.3 specification found at:
|
||||||
* http://www.skein-hash.info/sites/default/files/skein1.3.pdf
|
* https://www.schneier.com/wp-content/uploads/2015/01/skein.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -48,13 +48,6 @@ static const uint8_t test_msg0[] = {
|
||||||
0xFF
|
0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t test_msg1[] = {
|
|
||||||
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
|
|
||||||
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
|
|
||||||
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
|
|
||||||
0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t test_msg2[] = {
|
static const uint8_t test_msg2[] = {
|
||||||
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
|
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
|
||||||
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
|
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
|
||||||
|
@ -85,69 +78,9 @@ static const uint8_t test_msg3[] = {
|
||||||
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
|
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t test_msg4[] = {
|
|
||||||
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
|
|
||||||
0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
|
|
||||||
0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
|
|
||||||
0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
|
|
||||||
0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
|
|
||||||
0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
|
|
||||||
0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
|
|
||||||
0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
|
|
||||||
0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
|
|
||||||
0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
|
|
||||||
0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
|
|
||||||
0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
|
|
||||||
0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
|
|
||||||
0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
|
|
||||||
0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
|
|
||||||
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
|
|
||||||
0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78,
|
|
||||||
0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
|
|
||||||
0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68,
|
|
||||||
0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
|
|
||||||
0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58,
|
|
||||||
0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
|
|
||||||
0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
|
|
||||||
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
|
|
||||||
0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
|
|
||||||
0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
|
|
||||||
0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28,
|
|
||||||
0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
|
|
||||||
0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
|
|
||||||
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
|
|
||||||
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
|
|
||||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test digests from the Skein spec, Appendix C.
|
* Test digests from the Skein spec, Appendix C.
|
||||||
*/
|
*/
|
||||||
static const uint8_t skein_256_test_digests[][32] = {
|
|
||||||
{
|
|
||||||
/* for test_msg0 */
|
|
||||||
0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50,
|
|
||||||
0xA7, 0xA2, 0x44, 0xC4, 0x44, 0xE2, 0x5C, 0x23,
|
|
||||||
0xDA, 0x30, 0xC1, 0x0F, 0xC9, 0xA1, 0xF2, 0x70,
|
|
||||||
0xA6, 0x63, 0x7F, 0x1F, 0x34, 0xE6, 0x7E, 0xD2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* for test_msg1 */
|
|
||||||
0x8D, 0x0F, 0xA4, 0xEF, 0x77, 0x7F, 0xD7, 0x59,
|
|
||||||
0xDF, 0xD4, 0x04, 0x4E, 0x6F, 0x6A, 0x5A, 0xC3,
|
|
||||||
0xC7, 0x74, 0xAE, 0xC9, 0x43, 0xDC, 0xFC, 0x07,
|
|
||||||
0x92, 0x7B, 0x72, 0x3B, 0x5D, 0xBF, 0x40, 0x8B
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* for test_msg2 */
|
|
||||||
0xDF, 0x28, 0xE9, 0x16, 0x63, 0x0D, 0x0B, 0x44,
|
|
||||||
0xC4, 0xA8, 0x49, 0xDC, 0x9A, 0x02, 0xF0, 0x7A,
|
|
||||||
0x07, 0xCB, 0x30, 0xF7, 0x32, 0x31, 0x82, 0x56,
|
|
||||||
0xB1, 0x5D, 0x86, 0x5A, 0xC4, 0xAE, 0x16, 0x2F
|
|
||||||
}
|
|
||||||
/* no test digests for test_msg3 and test_msg4 */
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t skein_512_test_digests[][64] = {
|
static const uint8_t skein_512_test_digests[][64] = {
|
||||||
{
|
{
|
||||||
/* for test_msg0 */
|
/* for test_msg0 */
|
||||||
|
@ -189,74 +122,6 @@ static const uint8_t skein_512_test_digests[][64] = {
|
||||||
/* no test digests for test_msg4 */
|
/* no test digests for test_msg4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t skein_1024_test_digests[][128] = {
|
|
||||||
{
|
|
||||||
/* for test_msg0 */
|
|
||||||
0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24,
|
|
||||||
0x07, 0xCD, 0xD8, 0x78, 0x7F, 0xDA, 0x9E, 0x35,
|
|
||||||
0x70, 0x3D, 0xE8, 0x62, 0xA4, 0xFB, 0xC1, 0x19,
|
|
||||||
0xCF, 0xF8, 0x59, 0x0A, 0xFE, 0x79, 0x25, 0x0B,
|
|
||||||
0xCC, 0xC8, 0xB3, 0xFA, 0xF1, 0xBD, 0x24, 0x22,
|
|
||||||
0xAB, 0x5C, 0x0D, 0x26, 0x3F, 0xB2, 0xF8, 0xAF,
|
|
||||||
0xB3, 0xF7, 0x96, 0xF0, 0x48, 0x00, 0x03, 0x81,
|
|
||||||
0x53, 0x1B, 0x6F, 0x00, 0xD8, 0x51, 0x61, 0xBC,
|
|
||||||
0x0F, 0xFF, 0x4B, 0xEF, 0x24, 0x86, 0xB1, 0xEB,
|
|
||||||
0xCD, 0x37, 0x73, 0xFA, 0xBF, 0x50, 0xAD, 0x4A,
|
|
||||||
0xD5, 0x63, 0x9A, 0xF9, 0x04, 0x0E, 0x3F, 0x29,
|
|
||||||
0xC6, 0xC9, 0x31, 0x30, 0x1B, 0xF7, 0x98, 0x32,
|
|
||||||
0xE9, 0xDA, 0x09, 0x85, 0x7E, 0x83, 0x1E, 0x82,
|
|
||||||
0xEF, 0x8B, 0x46, 0x91, 0xC2, 0x35, 0x65, 0x65,
|
|
||||||
0x15, 0xD4, 0x37, 0xD2, 0xBD, 0xA3, 0x3B, 0xCE,
|
|
||||||
0xC0, 0x01, 0xC6, 0x7F, 0xFD, 0xE1, 0x5B, 0xA8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* no test vector for test_msg1 */
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* no test vector for test_msg2 */
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* for test_msg3 */
|
|
||||||
0x1F, 0x3E, 0x02, 0xC4, 0x6F, 0xB8, 0x0A, 0x3F,
|
|
||||||
0xCD, 0x2D, 0xFB, 0xBC, 0x7C, 0x17, 0x38, 0x00,
|
|
||||||
0xB4, 0x0C, 0x60, 0xC2, 0x35, 0x4A, 0xF5, 0x51,
|
|
||||||
0x18, 0x9E, 0xBF, 0x43, 0x3C, 0x3D, 0x85, 0xF9,
|
|
||||||
0xFF, 0x18, 0x03, 0xE6, 0xD9, 0x20, 0x49, 0x31,
|
|
||||||
0x79, 0xED, 0x7A, 0xE7, 0xFC, 0xE6, 0x9C, 0x35,
|
|
||||||
0x81, 0xA5, 0xA2, 0xF8, 0x2D, 0x3E, 0x0C, 0x7A,
|
|
||||||
0x29, 0x55, 0x74, 0xD0, 0xCD, 0x7D, 0x21, 0x7C,
|
|
||||||
0x48, 0x4D, 0x2F, 0x63, 0x13, 0xD5, 0x9A, 0x77,
|
|
||||||
0x18, 0xEA, 0xD0, 0x7D, 0x07, 0x29, 0xC2, 0x48,
|
|
||||||
0x51, 0xD7, 0xE7, 0xD2, 0x49, 0x1B, 0x90, 0x2D,
|
|
||||||
0x48, 0x91, 0x94, 0xE6, 0xB7, 0xD3, 0x69, 0xDB,
|
|
||||||
0x0A, 0xB7, 0xAA, 0x10, 0x6F, 0x0E, 0xE0, 0xA3,
|
|
||||||
0x9A, 0x42, 0xEF, 0xC5, 0x4F, 0x18, 0xD9, 0x37,
|
|
||||||
0x76, 0x08, 0x09, 0x85, 0xF9, 0x07, 0x57, 0x4F,
|
|
||||||
0x99, 0x5E, 0xC6, 0xA3, 0x71, 0x53, 0xA5, 0x78
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/* for test_msg4 */
|
|
||||||
0x84, 0x2A, 0x53, 0xC9, 0x9C, 0x12, 0xB0, 0xCF,
|
|
||||||
0x80, 0xCF, 0x69, 0x49, 0x1B, 0xE5, 0xE2, 0xF7,
|
|
||||||
0x51, 0x5D, 0xE8, 0x73, 0x3B, 0x6E, 0xA9, 0x42,
|
|
||||||
0x2D, 0xFD, 0x67, 0x66, 0x65, 0xB5, 0xFA, 0x42,
|
|
||||||
0xFF, 0xB3, 0xA9, 0xC4, 0x8C, 0x21, 0x77, 0x77,
|
|
||||||
0x95, 0x08, 0x48, 0xCE, 0xCD, 0xB4, 0x8F, 0x64,
|
|
||||||
0x0F, 0x81, 0xFB, 0x92, 0xBE, 0xF6, 0xF8, 0x8F,
|
|
||||||
0x7A, 0x85, 0xC1, 0xF7, 0xCD, 0x14, 0x46, 0xC9,
|
|
||||||
0x16, 0x1C, 0x0A, 0xFE, 0x8F, 0x25, 0xAE, 0x44,
|
|
||||||
0x4F, 0x40, 0xD3, 0x68, 0x00, 0x81, 0xC3, 0x5A,
|
|
||||||
0xA4, 0x3F, 0x64, 0x0F, 0xD5, 0xFA, 0x3C, 0x3C,
|
|
||||||
0x03, 0x0B, 0xCC, 0x06, 0xAB, 0xAC, 0x01, 0xD0,
|
|
||||||
0x98, 0xBC, 0xC9, 0x84, 0xEB, 0xD8, 0x32, 0x27,
|
|
||||||
0x12, 0x92, 0x1E, 0x00, 0xB1, 0xBA, 0x07, 0xD6,
|
|
||||||
0xD0, 0x1F, 0x26, 0x90, 0x70, 0x50, 0x25, 0x5E,
|
|
||||||
0xF2, 0xC8, 0xE2, 0x4F, 0x71, 0x6C, 0x52, 0xA5
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -268,11 +133,11 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
#define SKEIN_ALGO_TEST(_m, mode, diglen, testdigest) \
|
#define SKEIN_ALGO_TEST(_m, mode, diglen, testdigest) \
|
||||||
do { \
|
do { \
|
||||||
Skein ## mode ## _Ctxt_t ctx; \
|
SKEIN_CTX ctx; \
|
||||||
uint8_t digest[diglen / 8]; \
|
uint8_t digest[diglen / 8]; \
|
||||||
(void) Skein ## mode ## _Init(&ctx, diglen); \
|
Skein ## mode ## _Init(&ctx, diglen); \
|
||||||
(void) Skein ## mode ## _Update(&ctx, _m, sizeof (_m)); \
|
Skein ## mode ## _Update(&ctx, _m, sizeof (_m)); \
|
||||||
(void) Skein ## mode ## _Final(&ctx, digest); \
|
Skein ## mode ## _Final(&ctx, digest); \
|
||||||
(void) printf("Skein" #mode "/" #diglen \
|
(void) printf("Skein" #mode "/" #diglen \
|
||||||
"\tMessage: " #_m "\tResult: "); \
|
"\tMessage: " #_m "\tResult: "); \
|
||||||
if (memcmp(digest, testdigest, diglen / 8) == 0) { \
|
if (memcmp(digest, testdigest, diglen / 8) == 0) { \
|
||||||
|
@ -285,7 +150,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
#define SKEIN_PERF_TEST(mode, diglen) \
|
#define SKEIN_PERF_TEST(mode, diglen) \
|
||||||
do { \
|
do { \
|
||||||
Skein ## mode ## _Ctxt_t ctx; \
|
SKEIN_CTX ctx; \
|
||||||
uint8_t digest[diglen / 8]; \
|
uint8_t digest[diglen / 8]; \
|
||||||
uint8_t block[131072]; \
|
uint8_t block[131072]; \
|
||||||
uint64_t delta; \
|
uint64_t delta; \
|
||||||
|
@ -294,12 +159,12 @@ main(int argc, char *argv[])
|
||||||
struct timeval start, end; \
|
struct timeval start, end; \
|
||||||
memset(block, 0, sizeof (block)); \
|
memset(block, 0, sizeof (block)); \
|
||||||
(void) gettimeofday(&start, NULL); \
|
(void) gettimeofday(&start, NULL); \
|
||||||
(void) Skein ## mode ## _Init(&ctx, diglen); \
|
Skein ## mode ## _Init(&ctx, diglen); \
|
||||||
for (i = 0; i < 8192; i++) { \
|
for (i = 0; i < 8192; i++) { \
|
||||||
(void) Skein ## mode ## _Update(&ctx, block, \
|
Skein ## mode ## _Update(&ctx, block, \
|
||||||
sizeof (block)); \
|
sizeof (block)); \
|
||||||
} \
|
} \
|
||||||
(void) Skein ## mode ## _Final(&ctx, digest); \
|
Skein ## mode ## _Final(&ctx, digest); \
|
||||||
(void) gettimeofday(&end, NULL); \
|
(void) gettimeofday(&end, NULL); \
|
||||||
delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
|
delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
|
||||||
(start.tv_sec * 1000000llu + start.tv_usec); \
|
(start.tv_sec * 1000000llu + start.tv_usec); \
|
||||||
|
@ -312,23 +177,15 @@ main(int argc, char *argv[])
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
(void) printf("Running algorithm correctness tests:\n");
|
(void) printf("Running algorithm correctness tests:\n");
|
||||||
SKEIN_ALGO_TEST(test_msg0, _256, 256, skein_256_test_digests[0]);
|
|
||||||
SKEIN_ALGO_TEST(test_msg1, _256, 256, skein_256_test_digests[1]);
|
|
||||||
SKEIN_ALGO_TEST(test_msg2, _256, 256, skein_256_test_digests[2]);
|
|
||||||
SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]);
|
SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]);
|
||||||
SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]);
|
SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]);
|
||||||
SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]);
|
SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]);
|
||||||
SKEIN_ALGO_TEST(test_msg0, 1024, 1024, skein_1024_test_digests[0]);
|
|
||||||
SKEIN_ALGO_TEST(test_msg3, 1024, 1024, skein_1024_test_digests[3]);
|
|
||||||
SKEIN_ALGO_TEST(test_msg4, 1024, 1024, skein_1024_test_digests[4]);
|
|
||||||
if (failed)
|
if (failed)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
(void) printf("Running performance tests (hashing 1024 MiB of "
|
(void) printf("Running performance tests (hashing 1024 MiB of "
|
||||||
"data):\n");
|
"data):\n");
|
||||||
SKEIN_PERF_TEST(_256, 256);
|
|
||||||
SKEIN_PERF_TEST(_512, 512);
|
SKEIN_PERF_TEST(_512, 512);
|
||||||
SKEIN_PERF_TEST(1024, 1024);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue