mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 15:27:32 +09:00
Update NSS to 3.35-RTM
This commit is contained in:
parent
23de11e5cd
commit
608f9fca02
388 changed files with 39075 additions and 20752 deletions
430
security/nss/lib/freebl/blake2b.c
Normal file
430
security/nss/lib/freebl/blake2b.c
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
/*
|
||||
* 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/. */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "secerr.h"
|
||||
#include "blapi.h"
|
||||
#include "blake2b.h"
|
||||
#include "crypto_primitives.h"
|
||||
|
||||
/**
|
||||
* This contains the BLAKE2b initialization vectors.
|
||||
*/
|
||||
static const uint64_t iv[8] = {
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL,
|
||||
0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
/**
|
||||
* This contains the table of permutations for blake2b compression function.
|
||||
*/
|
||||
static const uint8_t sigma[12][16] = {
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
#define ROUND(i) \
|
||||
G(v[0], v[4], v[8], v[12], m[sigma[i][0]], m[sigma[i][1]]); \
|
||||
G(v[1], v[5], v[9], v[13], m[sigma[i][2]], m[sigma[i][3]]); \
|
||||
G(v[2], v[6], v[10], v[14], m[sigma[i][4]], m[sigma[i][5]]); \
|
||||
G(v[3], v[7], v[11], v[15], m[sigma[i][6]], m[sigma[i][7]]); \
|
||||
G(v[0], v[5], v[10], v[15], m[sigma[i][8]], m[sigma[i][9]]); \
|
||||
G(v[1], v[6], v[11], v[12], m[sigma[i][10]], m[sigma[i][11]]); \
|
||||
G(v[2], v[7], v[8], v[13], m[sigma[i][12]], m[sigma[i][13]]); \
|
||||
G(v[3], v[4], v[9], v[14], m[sigma[i][14]], m[sigma[i][15]])
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
PORT_Memcpy(v, ctx->h, 8 * 8);
|
||||
PORT_Memcpy(v + 8, iv, 8 * 8);
|
||||
|
||||
v[12] ^= ctx->t[0];
|
||||
v[13] ^= ctx->t[1];
|
||||
v[14] ^= ctx->f;
|
||||
|
||||
ROUND(0);
|
||||
ROUND(1);
|
||||
ROUND(2);
|
||||
ROUND(3);
|
||||
ROUND(4);
|
||||
ROUND(5);
|
||||
ROUND(6);
|
||||
ROUND(7);
|
||||
ROUND(8);
|
||||
ROUND(9);
|
||||
ROUND(10);
|
||||
ROUND(11);
|
||||
|
||||
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)
|
||||
{
|
||||
PORT_Assert(ctx != NULL);
|
||||
if (!ctx) {
|
||||
goto failure;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Mix key size(keylen) and desired hash length(outlen) into h0 */
|
||||
uint64_t param = outlen ^ (keylen << 8) ^ (1 << 16) ^ (1 << 24);
|
||||
PORT_Memcpy(ctx->h, iv, 8 * 8);
|
||||
ctx->h[0] ^= param;
|
||||
ctx->outlen = outlen;
|
||||
|
||||
/* This updates the context for only the keyed version */
|
||||
if (keylen > 0 && keylen <= BLAKE2B_KEY_SIZE && key) {
|
||||
uint8_t block[BLAKE2B_BLOCK_LENGTH] = { 0 };
|
||||
PORT_Memcpy(block, key, keylen);
|
||||
BLAKE2B_Update(ctx, block, BLAKE2B_BLOCK_LENGTH);
|
||||
PORT_Memset(block, 0, BLAKE2B_BLOCK_LENGTH);
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
failure:
|
||||
PORT_Memset(&ctx, 0, sizeof(ctx));
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_Begin(BLAKE2BContext* ctx)
|
||||
{
|
||||
return blake2b_Begin(ctx, BLAKE2B512_LENGTH, NULL, 0);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_MAC_Begin(BLAKE2BContext* ctx, const PRUint8* key, const size_t keylen)
|
||||
{
|
||||
PORT_Assert(key != NULL);
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
return blake2b_Begin(ctx, BLAKE2B512_LENGTH, (const uint8_t*)key, keylen);
|
||||
}
|
||||
|
||||
static void
|
||||
blake2b_IncrementCompress(BLAKE2BContext* ctx, size_t blockLength,
|
||||
const unsigned char* input)
|
||||
{
|
||||
blake2b_IncrementCounter(ctx, blockLength);
|
||||
blake2b_Compress(ctx, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates blake2b ctx and can be used for both keyed and unkeyed
|
||||
* version.
|
||||
*/
|
||||
SECStatus
|
||||
BLAKE2B_Update(BLAKE2BContext* ctx, const unsigned char* in,
|
||||
unsigned int inlen)
|
||||
{
|
||||
size_t left = ctx->buflen;
|
||||
size_t fill = BLAKE2B_BLOCK_LENGTH - left;
|
||||
|
||||
/* Nothing to do if there's nothing. */
|
||||
if (inlen == 0) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PORT_Assert(ctx != NULL);
|
||||
PORT_Assert(in != NULL);
|
||||
PORT_Assert(left <= BLAKE2B_BLOCK_LENGTH);
|
||||
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;
|
||||
}
|
||||
|
||||
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, unsigned char* out,
|
||||
unsigned int* digestLen, size_t maxDigestLen)
|
||||
{
|
||||
size_t i;
|
||||
unsigned int outlen = PR_MIN(BLAKE2B512_LENGTH, maxDigestLen);
|
||||
|
||||
/* Argument checks */
|
||||
if (!ctx || !out) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (digestLen) {
|
||||
*digestLen = outlen;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
blake2b_HashBuf(uint8_t* output, const uint8_t* input, uint8_t outlen,
|
||||
size_t inlen, const uint8_t* key, size_t keylen)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
BLAKE2BContext ctx = { { 0 } };
|
||||
|
||||
if (inlen != 0) {
|
||||
PORT_Assert(input != NULL);
|
||||
if (input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
PORT_Assert(output != NULL);
|
||||
if (output == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (blake2b_Begin(&ctx, outlen, key, keylen) != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (BLAKE2B_Update(&ctx, input, inlen) != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (BLAKE2B_End(&ctx, output, NULL, outlen) != SECSuccess) {
|
||||
goto done;
|
||||
}
|
||||
rv = SECSuccess;
|
||||
|
||||
done:
|
||||
PORT_Memset(&ctx, 0, sizeof ctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_Hash(unsigned char* dest, const char* src)
|
||||
{
|
||||
return blake2b_HashBuf(dest, (const unsigned char*)src, BLAKE2B512_LENGTH,
|
||||
PORT_Strlen(src), NULL, 0);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_HashBuf(unsigned char* output, const unsigned char* input, PRUint32 inlen)
|
||||
{
|
||||
return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, NULL, 0);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_MAC_HashBuf(unsigned char* output, const unsigned char* input,
|
||||
unsigned int inlen, const unsigned char* key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
PORT_Assert(key != NULL);
|
||||
if (!key && keylen <= BLAKE2B_KEY_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, key, keylen);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
BLAKE2B_FlattenSize(BLAKE2BContext* ctx)
|
||||
{
|
||||
return sizeof(BLAKE2BContext);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
BLAKE2B_Flatten(BLAKE2BContext* ctx, unsigned char* space)
|
||||
{
|
||||
PORT_Assert(space != NULL);
|
||||
if (!space) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memcpy(space, ctx, sizeof(BLAKE2BContext));
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
BLAKE2BContext*
|
||||
BLAKE2B_Resurrect(unsigned char* space, void* arg)
|
||||
{
|
||||
PORT_Assert(space != NULL);
|
||||
if (!space) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
BLAKE2BContext* ctx = BLAKE2B_NewContext();
|
||||
if (ctx == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PORT_Memcpy(ctx, space, sizeof(BLAKE2BContext));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void
|
||||
BLAKE2B_Clone(BLAKE2BContext* dest, BLAKE2BContext* src)
|
||||
{
|
||||
PORT_Assert(dest != NULL);
|
||||
PORT_Assert(src != NULL);
|
||||
if (!dest || !src) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return;
|
||||
}
|
||||
PORT_Memcpy(dest, src, sizeof(BLAKE2BContext));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue