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
|
#include <errno.h>
#include <string.h>
#include "crypto_auth_hmacsha512.h"
#include "crypto_kdf.h"
#include "crypto_kdf_hkdf_sha512.h"
#include "randombytes.h"
#include "utils.h"
int
crypto_kdf_hkdf_sha512_extract_init(crypto_kdf_hkdf_sha512_state *state,
const unsigned char *salt, size_t salt_len)
{
return crypto_auth_hmacsha512_init(&state->st, salt, salt_len);
}
int
crypto_kdf_hkdf_sha512_extract_update(crypto_kdf_hkdf_sha512_state *state,
const unsigned char *ikm, size_t ikm_len)
{
return crypto_auth_hmacsha512_update(&state->st, ikm, ikm_len);
}
int
crypto_kdf_hkdf_sha512_extract_final(crypto_kdf_hkdf_sha512_state *state,
unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
{
crypto_auth_hmacsha512_final(&state->st, prk);
sodium_memzero(state, sizeof *state);
return 0;
}
int
crypto_kdf_hkdf_sha512_extract(
unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES],
const unsigned char *salt, size_t salt_len, const unsigned char *ikm,
size_t ikm_len)
{
crypto_kdf_hkdf_sha512_state state;
crypto_kdf_hkdf_sha512_extract_init(&state, salt, salt_len);
crypto_kdf_hkdf_sha512_extract_update(&state, ikm, ikm_len);
return crypto_kdf_hkdf_sha512_extract_final(&state, prk);
}
void
crypto_kdf_hkdf_sha512_keygen(unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
{
randombytes_buf(prk, crypto_kdf_hkdf_sha512_KEYBYTES);
}
int
crypto_kdf_hkdf_sha512_expand(unsigned char *out, size_t out_len,
const char *ctx, size_t ctx_len,
const unsigned char prk[crypto_kdf_hkdf_sha512_KEYBYTES])
{
crypto_auth_hmacsha512_state st;
unsigned char tmp[crypto_auth_hmacsha512_BYTES];
size_t i;
size_t left;
unsigned char counter = 1U;
if (out_len > crypto_kdf_hkdf_sha512_BYTES_MAX) {
errno = EINVAL;
return -1;
}
for (i = (size_t) 0U; i + crypto_auth_hmacsha512_BYTES <= out_len;
i += crypto_auth_hmacsha512_BYTES) {
crypto_auth_hmacsha512_init(&st, prk, crypto_kdf_hkdf_sha512_KEYBYTES);
if (i != (size_t) 0U) {
crypto_auth_hmacsha512_update(&st,
&out[i - crypto_auth_hmacsha512_BYTES],
crypto_auth_hmacsha512_BYTES);
}
crypto_auth_hmacsha512_update(&st,
(const unsigned char *) ctx, ctx_len);
crypto_auth_hmacsha512_update(&st, &counter, (size_t) 1U);
crypto_auth_hmacsha512_final(&st, &out[i]);
counter++;
}
if ((left = out_len & (crypto_auth_hmacsha512_BYTES - 1U)) != (size_t) 0U) {
crypto_auth_hmacsha512_init(&st, prk, crypto_kdf_hkdf_sha512_KEYBYTES);
if (i != (size_t) 0U) {
crypto_auth_hmacsha512_update(&st,
&out[i - crypto_auth_hmacsha512_BYTES],
crypto_auth_hmacsha512_BYTES);
}
crypto_auth_hmacsha512_update(&st,
(const unsigned char *) ctx, ctx_len);
crypto_auth_hmacsha512_update(&st, &counter, (size_t) 1U);
crypto_auth_hmacsha512_final(&st, tmp);
memcpy(&out[i], tmp, left);
sodium_memzero(tmp, sizeof tmp);
}
sodium_memzero(&st, sizeof st);
return 0;
}
size_t
crypto_kdf_hkdf_sha512_keybytes(void)
{
return crypto_kdf_hkdf_sha512_KEYBYTES;
}
size_t
crypto_kdf_hkdf_sha512_bytes_min(void)
{
return crypto_kdf_hkdf_sha512_BYTES_MIN;
}
size_t
crypto_kdf_hkdf_sha512_bytes_max(void)
{
return crypto_kdf_hkdf_sha512_BYTES_MAX;
}
size_t crypto_kdf_hkdf_sha512_statebytes(void)
{
return sizeof(crypto_kdf_hkdf_sha512_state);
}
|