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
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;
|
|
}
|
|
}
|
|
|