1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
#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;
}
}
|