our own copy of libsodium
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

133 lines
4.9 KiB

#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "core_h2c.h"
#include "crypto_hash_sha256.h"
#include "crypto_hash_sha512.h"
#include "private/common.h"
#define HASH_BYTES crypto_hash_sha256_BYTES
#define HASH_BLOCKBYTES 64U
static int
core_h2c_string_to_hash_sha256(unsigned char *h, const size_t h_len, const char *ctx,
const unsigned char *msg, size_t msg_len)
{
crypto_hash_sha256_state st;
const unsigned char empty_block[HASH_BLOCKBYTES] = { 0 };
unsigned char u0[HASH_BYTES];
unsigned char ux[HASH_BYTES] = { 0 };
unsigned char t[3] = { 0U, (unsigned char) h_len, 0U};
unsigned char ctx_len_u8;
size_t ctx_len = ctx != NULL ? strlen(ctx) : 0U;
size_t i, j;
assert(h_len <= 0xff);
if (ctx_len > (size_t) 0xff) {
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st,
(const unsigned char *) "H2C-OVERSIZE-DST-",
sizeof "H2C-OVERSIZE-DST-" - 1U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_final(&st, u0);
ctx = (const char *) u0;
ctx_len = HASH_BYTES;
COMPILER_ASSERT(HASH_BYTES <= (size_t) 0xff);
}
ctx_len_u8 = (unsigned char) ctx_len;
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st, empty_block, sizeof empty_block);
crypto_hash_sha256_update(&st, msg, msg_len);
crypto_hash_sha256_update(&st, t, 3U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, u0);
for (i = 0U; i < h_len; i += HASH_BYTES) {
for (j = 0U; j < HASH_BYTES; j++) {
ux[j] ^= u0[j];
}
t[2]++;
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st, ux, HASH_BYTES);
crypto_hash_sha256_update(&st, &t[2], 1U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, ux);
memcpy(&h[i], ux, h_len - i >= (sizeof ux) ? (sizeof ux) : h_len - i);
}
return 0;
}
#undef HASH_BYTES
#undef HASH_BLOCKBYTES
#define HASH_BYTES crypto_hash_sha512_BYTES
#define HASH_BLOCKBYTES 128U
static int
core_h2c_string_to_hash_sha512(unsigned char *h, const size_t h_len, const char *ctx,
const unsigned char *msg, size_t msg_len)
{
crypto_hash_sha512_state st;
const unsigned char empty_block[HASH_BLOCKBYTES] = { 0 };
unsigned char u0[HASH_BYTES];
unsigned char ux[HASH_BYTES] = { 0 };
unsigned char t[3] = { 0U, (unsigned char) h_len, 0U};
unsigned char ctx_len_u8;
size_t ctx_len = ctx != NULL ? strlen(ctx) : 0U;
size_t i, j;
assert(h_len <= 0xff);
if (ctx_len > (size_t) 0xff) {
crypto_hash_sha512_init(&st);
crypto_hash_sha512_update(&st,
(const unsigned char *) "H2C-OVERSIZE-DST-",
sizeof "H2C-OVERSIZE-DST-" - 1U);
crypto_hash_sha512_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha512_final(&st, u0);
ctx = (const char *) u0;
ctx_len = HASH_BYTES;
COMPILER_ASSERT(HASH_BYTES <= (size_t) 0xff);
}
ctx_len_u8 = (unsigned char) ctx_len;
crypto_hash_sha512_init(&st);
crypto_hash_sha512_update(&st, empty_block, sizeof empty_block);
crypto_hash_sha512_update(&st, msg, msg_len);
crypto_hash_sha512_update(&st, t, 3U);
crypto_hash_sha512_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha512_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha512_final(&st, u0);
for (i = 0U; i < h_len; i += HASH_BYTES) {
for (j = 0U; j < HASH_BYTES; j++) {
ux[j] ^= u0[j];
}
t[2]++;
crypto_hash_sha512_init(&st);
crypto_hash_sha512_update(&st, ux, HASH_BYTES);
crypto_hash_sha512_update(&st, &t[2], 1U);
crypto_hash_sha512_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha512_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha512_final(&st, ux);
memcpy(&h[i], ux, h_len - i >= (sizeof ux) ? (sizeof ux) : h_len - i);
}
return 0;
}
int
core_h2c_string_to_hash(unsigned char *h, const size_t h_len, const char *ctx,
const unsigned char *msg, size_t msg_len, int hash_alg)
{
switch (hash_alg) {
case CORE_H2C_SHA256:
return core_h2c_string_to_hash_sha256(h, h_len, ctx, msg, msg_len);
case CORE_H2C_SHA512:
return core_h2c_string_to_hash_sha512(h, h_len, ctx, msg, msg_len);
default:
errno = EINVAL;
return -1;
}
}