/* * blake2b.c - definitions for the blake2b hash function * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * This function increments the blake2b ctx counter.
*/ void
blake2b_IncrementCounter(BLAKE2BContext* ctx, const uint64_t inc)
{
ctx->t[0] += inc;
ctx->t[1] += ctx->t[0] < inc;
}
/** * This macro implements the blake2b mixing function which mixes two 8-byte * words from the message into the hash.
*/ #define G(a, b, c, d, x, y) \
a += b + x; \
d = ROTR64(d ^ a, 32); \
c += d; \
b = ROTR64(b ^ c, 24); \
a += b + y; \
d = ROTR64(d ^ a, 16); \
c += d; \
b = ROTR64(b ^ c, 63)
/** * The blake2b compression function which takes a full 128-byte chunk of the * input message and mixes it into the ongoing ctx array, i.e., permute the * ctx while xoring in the block of data.
*/ void
blake2b_Compress(BLAKE2BContext* ctx, const uint8_t* block)
{
size_t i;
uint64_t v[16], m[16];
PORT_Memcpy(m, block, BLAKE2B_BLOCK_LENGTH); #if !defined(IS_LITTLE_ENDIAN) for (i = 0; i < 16; ++i) {
m[i] = FREEBL_HTONLL(m[i]);
} #endif
for (i = 0; i < 8; i++) {
ctx->h[i] ^= v[i] ^ v[i + 8];
}
}
/** * This function can be used for both keyed and unkeyed version.
*/
BLAKE2BContext*
BLAKE2B_NewContext()
{ return PORT_ZNew(BLAKE2BContext);
}
/** * Zero and free the context and can be used for both keyed and unkeyed version.
*/ void
BLAKE2B_DestroyContext(BLAKE2BContext* ctx, PRBool freeit)
{
PORT_Memset(ctx, 0, sizeof(*ctx)); if (freeit) {
PORT_Free(ctx);
}
}
/** * This function initializes blake2b ctx and can be used for both keyed and * unkeyed version. It also checks ctx and sets error states.
*/ static SECStatus
blake2b_Begin(BLAKE2BContext* ctx, uint8_t outlen, const uint8_t* key,
size_t keylen)
{ if (!ctx) { goto failure_noclean;
} if (outlen == 0 || outlen > BLAKE2B512_LENGTH) { goto failure;
} if (key && keylen > BLAKE2B_KEY_SIZE) { goto failure;
} /* Note: key can be null if it's unkeyed. */ if ((key == NULL && keylen > 0) || keylen > BLAKE2B_KEY_SIZE ||
(key != NULL && keylen == 0)) { goto failure;
}
/** * This function updates blake2b ctx and can be used for both keyed and unkeyed * version.
*/
SECStatus
BLAKE2B_Update(BLAKE2BContext* ctx, constunsignedchar* in, unsignedint inlen)
{ /* Nothing to do if there's nothing. */ if (inlen == 0) { return SECSuccess;
}
if (!ctx || !in) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
/* Is this a reused context? */ if (ctx->f) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
size_t left = ctx->buflen;
PORT_Assert(left <= BLAKE2B_BLOCK_LENGTH);
size_t fill = BLAKE2B_BLOCK_LENGTH - left;
if (inlen > fill) { if (ctx->buflen) { /* There's some remaining data in ctx->buf that we have to prepend
* to in. */
PORT_Memcpy(ctx->buf + left, in, fill);
ctx->buflen = 0;
blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, ctx->buf);
in += fill;
inlen -= fill;
} while (inlen > BLAKE2B_BLOCK_LENGTH) {
blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, in);
in += BLAKE2B_BLOCK_LENGTH;
inlen -= BLAKE2B_BLOCK_LENGTH;
}
}
/* Store the remaining data from in in ctx->buf to process later. * Note that ctx->buflen can be BLAKE2B_BLOCK_LENGTH. We can't process that * here because we have to update ctx->f before compressing the last block.
*/
PORT_Assert(inlen <= BLAKE2B_BLOCK_LENGTH);
PORT_Memcpy(ctx->buf + ctx->buflen, in, inlen);
ctx->buflen += inlen;
return SECSuccess;
}
/** * This function finalizes ctx, pads final block and stores hash. * It can be used for both keyed and unkeyed version.
*/
SECStatus
BLAKE2B_End(BLAKE2BContext* ctx, unsignedchar* out, unsignedint* digestLen, size_t maxDigestLen)
{
size_t i; unsignedint outlen = PR_MIN(BLAKE2B512_LENGTH, maxDigestLen);
/* Sanity check against outlen in context. */ if (ctx->outlen < outlen) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
/* Is this a reused context? */ if (ctx->f != 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
/* Process the remaining data from ctx->buf (padded with 0). */
blake2b_IncrementCounter(ctx, ctx->buflen); /* BLAKE2B_BLOCK_LENGTH - ctx->buflen can be 0. */
PORT_Memset(ctx->buf + ctx->buflen, 0, BLAKE2B_BLOCK_LENGTH - ctx->buflen);
ctx->f = UINT64_MAX;
blake2b_Compress(ctx, ctx->buf);
/* Write out the blake2b context(ctx). */ for (i = 0; i < outlen; ++i) {
out[i] = ctx->h[i / 8] >> ((i % 8) * 8);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.