licentivo-sdk 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/NOTICE +17 -0
- data/README.md +80 -0
- data/build_native.rb +48 -0
- data/examples/app.rb +56 -0
- data/examples/quickstart.rb +32 -0
- data/examples/vectors.rb +10 -0
- data/ext/licentivo_native/extconf.rb +27 -0
- data/lib/licentivo.rb +231 -0
- data/native/feature_tasks.h +72 -0
- data/native/licentivo.c +370 -0
- data/native/licentivo.h +64 -0
- data/native/vendor/Monocypher-LICENCE.md +173 -0
- data/native/vendor/cJSON-LICENSE +20 -0
- data/native/vendor/cJSON.c +3191 -0
- data/native/vendor/cJSON.h +306 -0
- data/native/vendor/monocypher-ed25519.c +500 -0
- data/native/vendor/monocypher-ed25519.h +140 -0
- data/native/vendor/monocypher.c +2956 -0
- data/native/vendor/monocypher.h +321 -0
- metadata +71 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
// Monocypher version __git__
|
|
2
|
+
//
|
|
3
|
+
// This file is dual-licensed. Choose whichever licence you want from
|
|
4
|
+
// the two licences listed below.
|
|
5
|
+
//
|
|
6
|
+
// The first licence is a regular 2-clause BSD licence. The second licence
|
|
7
|
+
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
|
8
|
+
// to the public domain. The BSD licence serves as a fallback option.
|
|
9
|
+
//
|
|
10
|
+
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
|
11
|
+
//
|
|
12
|
+
// ------------------------------------------------------------------------
|
|
13
|
+
//
|
|
14
|
+
// Copyright (c) 2017-2019, Loup Vaillant
|
|
15
|
+
// All rights reserved.
|
|
16
|
+
//
|
|
17
|
+
//
|
|
18
|
+
// Redistribution and use in source and binary forms, with or without
|
|
19
|
+
// modification, are permitted provided that the following conditions are
|
|
20
|
+
// met:
|
|
21
|
+
//
|
|
22
|
+
// 1. Redistributions of source code must retain the above copyright
|
|
23
|
+
// notice, this list of conditions and the following disclaimer.
|
|
24
|
+
//
|
|
25
|
+
// 2. Redistributions in binary form must reproduce the above copyright
|
|
26
|
+
// notice, this list of conditions and the following disclaimer in the
|
|
27
|
+
// documentation and/or other materials provided with the
|
|
28
|
+
// distribution.
|
|
29
|
+
//
|
|
30
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
31
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
32
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
33
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
34
|
+
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
35
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
36
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
37
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
38
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
39
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
40
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
41
|
+
//
|
|
42
|
+
// ------------------------------------------------------------------------
|
|
43
|
+
//
|
|
44
|
+
// Written in 2017-2019 by Loup Vaillant
|
|
45
|
+
//
|
|
46
|
+
// To the extent possible under law, the author(s) have dedicated all copyright
|
|
47
|
+
// and related neighboring rights to this software to the public domain
|
|
48
|
+
// worldwide. This software is distributed without any warranty.
|
|
49
|
+
//
|
|
50
|
+
// You should have received a copy of the CC0 Public Domain Dedication along
|
|
51
|
+
// with this software. If not, see
|
|
52
|
+
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
|
53
|
+
|
|
54
|
+
#include "monocypher-ed25519.h"
|
|
55
|
+
|
|
56
|
+
#ifdef MONOCYPHER_CPP_NAMESPACE
|
|
57
|
+
namespace MONOCYPHER_CPP_NAMESPACE {
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
/////////////////
|
|
61
|
+
/// Utilities ///
|
|
62
|
+
/////////////////
|
|
63
|
+
#define FOR(i, min, max) for (size_t i = min; i < max; i++)
|
|
64
|
+
#define COPY(dst, src, size) FOR(_i_, 0, size) (dst)[_i_] = (src)[_i_]
|
|
65
|
+
#define ZERO(buf, size) FOR(_i_, 0, size) (buf)[_i_] = 0
|
|
66
|
+
#define WIPE_CTX(ctx) crypto_wipe(ctx , sizeof(*(ctx)))
|
|
67
|
+
#define WIPE_BUFFER(buffer) crypto_wipe(buffer, sizeof(buffer))
|
|
68
|
+
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
|
|
69
|
+
typedef uint8_t u8;
|
|
70
|
+
typedef uint64_t u64;
|
|
71
|
+
|
|
72
|
+
// Returns the smallest positive integer y such that
|
|
73
|
+
// (x + y) % pow_2 == 0
|
|
74
|
+
// Basically, it's how many bytes we need to add to "align" x.
|
|
75
|
+
// Only works when pow_2 is a power of 2.
|
|
76
|
+
// Note: we use ~x+1 instead of -x to avoid compiler warnings
|
|
77
|
+
static size_t align(size_t x, size_t pow_2)
|
|
78
|
+
{
|
|
79
|
+
return (~x + 1) & (pow_2 - 1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static u64 load64_be(const u8 s[8])
|
|
83
|
+
{
|
|
84
|
+
return((u64)s[0] << 56)
|
|
85
|
+
| ((u64)s[1] << 48)
|
|
86
|
+
| ((u64)s[2] << 40)
|
|
87
|
+
| ((u64)s[3] << 32)
|
|
88
|
+
| ((u64)s[4] << 24)
|
|
89
|
+
| ((u64)s[5] << 16)
|
|
90
|
+
| ((u64)s[6] << 8)
|
|
91
|
+
| (u64)s[7];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static void store64_be(u8 out[8], u64 in)
|
|
95
|
+
{
|
|
96
|
+
out[0] = (in >> 56) & 0xff;
|
|
97
|
+
out[1] = (in >> 48) & 0xff;
|
|
98
|
+
out[2] = (in >> 40) & 0xff;
|
|
99
|
+
out[3] = (in >> 32) & 0xff;
|
|
100
|
+
out[4] = (in >> 24) & 0xff;
|
|
101
|
+
out[5] = (in >> 16) & 0xff;
|
|
102
|
+
out[6] = (in >> 8) & 0xff;
|
|
103
|
+
out[7] = in & 0xff;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static void load64_be_buf (u64 *dst, const u8 *src, size_t size) {
|
|
107
|
+
FOR(i, 0, size) { dst[i] = load64_be(src + i*8); }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
///////////////
|
|
111
|
+
/// SHA 512 ///
|
|
112
|
+
///////////////
|
|
113
|
+
static u64 rot(u64 x, int c ) { return (x >> c) | (x << (64 - c)); }
|
|
114
|
+
static u64 ch (u64 x, u64 y, u64 z) { return (x & y) ^ (~x & z); }
|
|
115
|
+
static u64 maj(u64 x, u64 y, u64 z) { return (x & y) ^ ( x & z) ^ (y & z); }
|
|
116
|
+
static u64 big_sigma0(u64 x) { return rot(x, 28) ^ rot(x, 34) ^ rot(x, 39); }
|
|
117
|
+
static u64 big_sigma1(u64 x) { return rot(x, 14) ^ rot(x, 18) ^ rot(x, 41); }
|
|
118
|
+
static u64 lit_sigma0(u64 x) { return rot(x, 1) ^ rot(x, 8) ^ (x >> 7); }
|
|
119
|
+
static u64 lit_sigma1(u64 x) { return rot(x, 19) ^ rot(x, 61) ^ (x >> 6); }
|
|
120
|
+
|
|
121
|
+
static const u64 K[80] = {
|
|
122
|
+
0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc,
|
|
123
|
+
0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118,
|
|
124
|
+
0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2,
|
|
125
|
+
0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694,
|
|
126
|
+
0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65,
|
|
127
|
+
0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5,
|
|
128
|
+
0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4,
|
|
129
|
+
0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70,
|
|
130
|
+
0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df,
|
|
131
|
+
0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b,
|
|
132
|
+
0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30,
|
|
133
|
+
0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8,
|
|
134
|
+
0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8,
|
|
135
|
+
0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3,
|
|
136
|
+
0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec,
|
|
137
|
+
0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b,
|
|
138
|
+
0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178,
|
|
139
|
+
0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b,
|
|
140
|
+
0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c,
|
|
141
|
+
0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
static void sha512_compress(crypto_sha512_ctx *ctx)
|
|
145
|
+
{
|
|
146
|
+
u64 a = ctx->hash[0]; u64 b = ctx->hash[1];
|
|
147
|
+
u64 c = ctx->hash[2]; u64 d = ctx->hash[3];
|
|
148
|
+
u64 e = ctx->hash[4]; u64 f = ctx->hash[5];
|
|
149
|
+
u64 g = ctx->hash[6]; u64 h = ctx->hash[7];
|
|
150
|
+
|
|
151
|
+
FOR (j, 0, 16) {
|
|
152
|
+
u64 in = K[j] + ctx->input[j];
|
|
153
|
+
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
|
154
|
+
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
|
155
|
+
h = g; g = f; f = e; e = d + t1;
|
|
156
|
+
d = c; c = b; b = a; a = t1 + t2;
|
|
157
|
+
}
|
|
158
|
+
size_t i16 = 0;
|
|
159
|
+
FOR(i, 1, 5) {
|
|
160
|
+
i16 += 16;
|
|
161
|
+
FOR (j, 0, 16) {
|
|
162
|
+
ctx->input[j] += lit_sigma1(ctx->input[(j- 2) & 15]);
|
|
163
|
+
ctx->input[j] += lit_sigma0(ctx->input[(j-15) & 15]);
|
|
164
|
+
ctx->input[j] += ctx->input[(j- 7) & 15];
|
|
165
|
+
u64 in = K[i16 + j] + ctx->input[j];
|
|
166
|
+
u64 t1 = big_sigma1(e) + ch (e, f, g) + h + in;
|
|
167
|
+
u64 t2 = big_sigma0(a) + maj(a, b, c);
|
|
168
|
+
h = g; g = f; f = e; e = d + t1;
|
|
169
|
+
d = c; c = b; b = a; a = t1 + t2;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
ctx->hash[0] += a; ctx->hash[1] += b;
|
|
174
|
+
ctx->hash[2] += c; ctx->hash[3] += d;
|
|
175
|
+
ctx->hash[4] += e; ctx->hash[5] += f;
|
|
176
|
+
ctx->hash[6] += g; ctx->hash[7] += h;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Write 1 input byte
|
|
180
|
+
static void sha512_set_input(crypto_sha512_ctx *ctx, u8 input)
|
|
181
|
+
{
|
|
182
|
+
size_t word = ctx->input_idx >> 3;
|
|
183
|
+
size_t byte = ctx->input_idx & 7;
|
|
184
|
+
ctx->input[word] |= (u64)input << (8 * (7 - byte));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Increment a 128-bit "word".
|
|
188
|
+
static void sha512_incr(u64 x[2], u64 y)
|
|
189
|
+
{
|
|
190
|
+
x[1] += y;
|
|
191
|
+
if (x[1] < y) {
|
|
192
|
+
x[0]++;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
void crypto_sha512_init(crypto_sha512_ctx *ctx)
|
|
197
|
+
{
|
|
198
|
+
ctx->hash[0] = 0x6a09e667f3bcc908;
|
|
199
|
+
ctx->hash[1] = 0xbb67ae8584caa73b;
|
|
200
|
+
ctx->hash[2] = 0x3c6ef372fe94f82b;
|
|
201
|
+
ctx->hash[3] = 0xa54ff53a5f1d36f1;
|
|
202
|
+
ctx->hash[4] = 0x510e527fade682d1;
|
|
203
|
+
ctx->hash[5] = 0x9b05688c2b3e6c1f;
|
|
204
|
+
ctx->hash[6] = 0x1f83d9abfb41bd6b;
|
|
205
|
+
ctx->hash[7] = 0x5be0cd19137e2179;
|
|
206
|
+
ctx->input_size[0] = 0;
|
|
207
|
+
ctx->input_size[1] = 0;
|
|
208
|
+
ctx->input_idx = 0;
|
|
209
|
+
ZERO(ctx->input, 16);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
|
213
|
+
const u8 *message, size_t message_size)
|
|
214
|
+
{
|
|
215
|
+
// Avoid undefined NULL pointer increments with empty messages
|
|
216
|
+
if (message_size == 0) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Align ourselves with word boundaries
|
|
221
|
+
if ((ctx->input_idx & 7) != 0) {
|
|
222
|
+
size_t nb_bytes = MIN(align(ctx->input_idx, 8), message_size);
|
|
223
|
+
FOR (i, 0, nb_bytes) {
|
|
224
|
+
sha512_set_input(ctx, message[i]);
|
|
225
|
+
ctx->input_idx++;
|
|
226
|
+
}
|
|
227
|
+
message += nb_bytes;
|
|
228
|
+
message_size -= nb_bytes;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Align ourselves with block boundaries
|
|
232
|
+
if ((ctx->input_idx & 127) != 0) {
|
|
233
|
+
size_t nb_words = MIN(align(ctx->input_idx, 128), message_size) >> 3;
|
|
234
|
+
load64_be_buf(ctx->input + (ctx->input_idx >> 3), message, nb_words);
|
|
235
|
+
ctx->input_idx += nb_words << 3;
|
|
236
|
+
message += nb_words << 3;
|
|
237
|
+
message_size -= nb_words << 3;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Compress block if needed
|
|
241
|
+
if (ctx->input_idx == 128) {
|
|
242
|
+
sha512_incr(ctx->input_size, 1024); // size is in bits
|
|
243
|
+
sha512_compress(ctx);
|
|
244
|
+
ctx->input_idx = 0;
|
|
245
|
+
ZERO(ctx->input, 16);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Process the message block by block
|
|
249
|
+
FOR (i, 0, message_size >> 7) { // number of blocks
|
|
250
|
+
load64_be_buf(ctx->input, message, 16);
|
|
251
|
+
sha512_incr(ctx->input_size, 1024); // size is in bits
|
|
252
|
+
sha512_compress(ctx);
|
|
253
|
+
ctx->input_idx = 0;
|
|
254
|
+
ZERO(ctx->input, 16);
|
|
255
|
+
message += 128;
|
|
256
|
+
}
|
|
257
|
+
message_size &= 127;
|
|
258
|
+
|
|
259
|
+
if (message_size != 0) {
|
|
260
|
+
// Remaining words
|
|
261
|
+
size_t nb_words = message_size >> 3;
|
|
262
|
+
load64_be_buf(ctx->input, message, nb_words);
|
|
263
|
+
ctx->input_idx += nb_words << 3;
|
|
264
|
+
message += nb_words << 3;
|
|
265
|
+
message_size -= nb_words << 3;
|
|
266
|
+
|
|
267
|
+
// Remaining bytes
|
|
268
|
+
FOR (i, 0, message_size) {
|
|
269
|
+
sha512_set_input(ctx, message[i]);
|
|
270
|
+
ctx->input_idx++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
void crypto_sha512_final(crypto_sha512_ctx *ctx, u8 hash[64])
|
|
276
|
+
{
|
|
277
|
+
// Add padding bit
|
|
278
|
+
if (ctx->input_idx == 0) {
|
|
279
|
+
ZERO(ctx->input, 16);
|
|
280
|
+
}
|
|
281
|
+
sha512_set_input(ctx, 128);
|
|
282
|
+
|
|
283
|
+
// Update size
|
|
284
|
+
sha512_incr(ctx->input_size, ctx->input_idx * 8);
|
|
285
|
+
|
|
286
|
+
// Compress penultimate block (if any)
|
|
287
|
+
if (ctx->input_idx > 111) {
|
|
288
|
+
sha512_compress(ctx);
|
|
289
|
+
ZERO(ctx->input, 14);
|
|
290
|
+
}
|
|
291
|
+
// Compress last block
|
|
292
|
+
ctx->input[14] = ctx->input_size[0];
|
|
293
|
+
ctx->input[15] = ctx->input_size[1];
|
|
294
|
+
sha512_compress(ctx);
|
|
295
|
+
|
|
296
|
+
// Copy hash to output (big endian)
|
|
297
|
+
FOR (i, 0, 8) {
|
|
298
|
+
store64_be(hash + i*8, ctx->hash[i]);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
WIPE_CTX(ctx);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
void crypto_sha512(u8 hash[64], const u8 *message, size_t message_size)
|
|
305
|
+
{
|
|
306
|
+
crypto_sha512_ctx ctx;
|
|
307
|
+
crypto_sha512_init (&ctx);
|
|
308
|
+
crypto_sha512_update(&ctx, message, message_size);
|
|
309
|
+
crypto_sha512_final (&ctx, hash);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
////////////////////
|
|
313
|
+
/// HMAC SHA 512 ///
|
|
314
|
+
////////////////////
|
|
315
|
+
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
|
316
|
+
const u8 *key, size_t key_size)
|
|
317
|
+
{
|
|
318
|
+
// hash key if it is too long
|
|
319
|
+
if (key_size > 128) {
|
|
320
|
+
crypto_sha512(ctx->key, key, key_size);
|
|
321
|
+
key = ctx->key;
|
|
322
|
+
key_size = 64;
|
|
323
|
+
}
|
|
324
|
+
// Compute inner key: padded key XOR 0x36
|
|
325
|
+
FOR (i, 0, key_size) { ctx->key[i] = key[i] ^ 0x36; }
|
|
326
|
+
FOR (i, key_size, 128) { ctx->key[i] = 0x36; }
|
|
327
|
+
// Start computing inner hash
|
|
328
|
+
crypto_sha512_init (&ctx->ctx);
|
|
329
|
+
crypto_sha512_update(&ctx->ctx, ctx->key, 128);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
|
333
|
+
const u8 *message, size_t message_size)
|
|
334
|
+
{
|
|
335
|
+
crypto_sha512_update(&ctx->ctx, message, message_size);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, u8 hmac[64])
|
|
339
|
+
{
|
|
340
|
+
// Finish computing inner hash
|
|
341
|
+
crypto_sha512_final(&ctx->ctx, hmac);
|
|
342
|
+
// Compute outer key: padded key XOR 0x5c
|
|
343
|
+
FOR (i, 0, 128) {
|
|
344
|
+
ctx->key[i] ^= 0x36 ^ 0x5c;
|
|
345
|
+
}
|
|
346
|
+
// Compute outer hash
|
|
347
|
+
crypto_sha512_init (&ctx->ctx);
|
|
348
|
+
crypto_sha512_update(&ctx->ctx, ctx->key , 128);
|
|
349
|
+
crypto_sha512_update(&ctx->ctx, hmac, 64);
|
|
350
|
+
crypto_sha512_final (&ctx->ctx, hmac); // outer hash
|
|
351
|
+
WIPE_CTX(ctx);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
void crypto_sha512_hmac(u8 hmac[64], const u8 *key, size_t key_size,
|
|
355
|
+
const u8 *message, size_t message_size)
|
|
356
|
+
{
|
|
357
|
+
crypto_sha512_hmac_ctx ctx;
|
|
358
|
+
crypto_sha512_hmac_init (&ctx, key, key_size);
|
|
359
|
+
crypto_sha512_hmac_update(&ctx, message, message_size);
|
|
360
|
+
crypto_sha512_hmac_final (&ctx, hmac);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
////////////////////
|
|
364
|
+
/// HKDF SHA 512 ///
|
|
365
|
+
////////////////////
|
|
366
|
+
void crypto_sha512_hkdf_expand(u8 *okm, size_t okm_size,
|
|
367
|
+
const u8 *prk, size_t prk_size,
|
|
368
|
+
const u8 *info, size_t info_size)
|
|
369
|
+
{
|
|
370
|
+
int not_first = 0;
|
|
371
|
+
u8 ctr = 1;
|
|
372
|
+
u8 blk[64];
|
|
373
|
+
|
|
374
|
+
while (okm_size > 0) {
|
|
375
|
+
size_t out_size = MIN(okm_size, sizeof(blk));
|
|
376
|
+
|
|
377
|
+
crypto_sha512_hmac_ctx ctx;
|
|
378
|
+
crypto_sha512_hmac_init(&ctx, prk , prk_size);
|
|
379
|
+
if (not_first) {
|
|
380
|
+
// For some reason HKDF uses some kind of CBC mode.
|
|
381
|
+
// For some reason CTR mode alone wasn't enough.
|
|
382
|
+
// Like what, they didn't trust HMAC in 2010? Really??
|
|
383
|
+
crypto_sha512_hmac_update(&ctx, blk , sizeof(blk));
|
|
384
|
+
}
|
|
385
|
+
crypto_sha512_hmac_update(&ctx, info, info_size);
|
|
386
|
+
crypto_sha512_hmac_update(&ctx, &ctr, 1);
|
|
387
|
+
crypto_sha512_hmac_final(&ctx, blk);
|
|
388
|
+
|
|
389
|
+
COPY(okm, blk, out_size);
|
|
390
|
+
|
|
391
|
+
not_first = 1;
|
|
392
|
+
okm += out_size;
|
|
393
|
+
okm_size -= out_size;
|
|
394
|
+
ctr++;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
void crypto_sha512_hkdf(u8 *okm , size_t okm_size,
|
|
399
|
+
const u8 *ikm , size_t ikm_size,
|
|
400
|
+
const u8 *salt, size_t salt_size,
|
|
401
|
+
const u8 *info, size_t info_size)
|
|
402
|
+
{
|
|
403
|
+
// Extract
|
|
404
|
+
u8 prk[64];
|
|
405
|
+
crypto_sha512_hmac(prk, salt, salt_size, ikm, ikm_size);
|
|
406
|
+
|
|
407
|
+
// Expand
|
|
408
|
+
crypto_sha512_hkdf_expand(okm, okm_size, prk, sizeof(prk), info, info_size);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
///////////////
|
|
412
|
+
/// Ed25519 ///
|
|
413
|
+
///////////////
|
|
414
|
+
void crypto_ed25519_key_pair(u8 secret_key[64], u8 public_key[32], u8 seed[32])
|
|
415
|
+
{
|
|
416
|
+
u8 a[64];
|
|
417
|
+
COPY(a, seed, 32); // a[ 0..31] = seed
|
|
418
|
+
crypto_wipe(seed, 32);
|
|
419
|
+
COPY(secret_key, a, 32); // secret key = seed
|
|
420
|
+
crypto_sha512(a, a, 32); // a[ 0..31] = scalar
|
|
421
|
+
crypto_eddsa_trim_scalar(a, a); // a[ 0..31] = trimmed scalar
|
|
422
|
+
crypto_eddsa_scalarbase(public_key, a); // public key = [trimmed scalar]B
|
|
423
|
+
COPY(secret_key + 32, public_key, 32); // secret key includes public half
|
|
424
|
+
WIPE_BUFFER(a);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
static void hash_reduce(u8 h[32],
|
|
428
|
+
const u8 *a, size_t a_size,
|
|
429
|
+
const u8 *b, size_t b_size,
|
|
430
|
+
const u8 *c, size_t c_size,
|
|
431
|
+
const u8 *d, size_t d_size)
|
|
432
|
+
{
|
|
433
|
+
u8 hash[64];
|
|
434
|
+
crypto_sha512_ctx ctx;
|
|
435
|
+
crypto_sha512_init (&ctx);
|
|
436
|
+
crypto_sha512_update(&ctx, a, a_size);
|
|
437
|
+
crypto_sha512_update(&ctx, b, b_size);
|
|
438
|
+
crypto_sha512_update(&ctx, c, c_size);
|
|
439
|
+
crypto_sha512_update(&ctx, d, d_size);
|
|
440
|
+
crypto_sha512_final (&ctx, hash);
|
|
441
|
+
crypto_eddsa_reduce(h, hash);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
static void ed25519_dom_sign(u8 signature [64], const u8 secret_key[32],
|
|
445
|
+
const u8 *dom, size_t dom_size,
|
|
446
|
+
const u8 *message, size_t message_size)
|
|
447
|
+
{
|
|
448
|
+
u8 a[64]; // secret scalar and prefix
|
|
449
|
+
u8 r[32]; // secret deterministic "random" nonce
|
|
450
|
+
u8 h[32]; // publically verifiable hash of the message (not wiped)
|
|
451
|
+
u8 R[32]; // first half of the signature (allows overlapping inputs)
|
|
452
|
+
const u8 *pk = secret_key + 32;
|
|
453
|
+
|
|
454
|
+
crypto_sha512(a, secret_key, 32);
|
|
455
|
+
crypto_eddsa_trim_scalar(a, a);
|
|
456
|
+
hash_reduce(r, dom, dom_size, a + 32, 32, message, message_size, 0, 0);
|
|
457
|
+
crypto_eddsa_scalarbase(R, r);
|
|
458
|
+
hash_reduce(h, dom, dom_size, R, 32, pk, 32, message, message_size);
|
|
459
|
+
COPY(signature, R, 32);
|
|
460
|
+
crypto_eddsa_mul_add(signature + 32, h, a, r);
|
|
461
|
+
|
|
462
|
+
WIPE_BUFFER(a);
|
|
463
|
+
WIPE_BUFFER(r);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
void crypto_ed25519_sign(u8 signature [64], const u8 secret_key[64],
|
|
467
|
+
const u8 *message, size_t message_size)
|
|
468
|
+
{
|
|
469
|
+
ed25519_dom_sign(signature, secret_key, 0, 0, message, message_size);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
int crypto_ed25519_check(const u8 signature[64], const u8 public_key[32],
|
|
473
|
+
const u8 *msg, size_t msg_size)
|
|
474
|
+
{
|
|
475
|
+
u8 h_ram[32];
|
|
476
|
+
hash_reduce(h_ram, signature, 32, public_key, 32, msg, msg_size, 0, 0);
|
|
477
|
+
return crypto_eddsa_check_equation(signature, public_key, h_ram);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
static const u8 domain[34] = "SigEd25519 no Ed25519 collisions\1";
|
|
481
|
+
|
|
482
|
+
void crypto_ed25519_ph_sign(uint8_t signature[64], const uint8_t secret_key[64],
|
|
483
|
+
const uint8_t message_hash[64])
|
|
484
|
+
{
|
|
485
|
+
ed25519_dom_sign(signature, secret_key, domain, sizeof(domain),
|
|
486
|
+
message_hash, 64);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32],
|
|
490
|
+
const uint8_t msg_hash[64])
|
|
491
|
+
{
|
|
492
|
+
u8 h_ram[32];
|
|
493
|
+
hash_reduce(h_ram, domain, sizeof(domain), sig, 32, pk, 32, msg_hash, 64);
|
|
494
|
+
return crypto_eddsa_check_equation(sig, pk, h_ram);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
#ifdef MONOCYPHER_CPP_NAMESPACE
|
|
499
|
+
}
|
|
500
|
+
#endif
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Monocypher version __git__
|
|
2
|
+
//
|
|
3
|
+
// This file is dual-licensed. Choose whichever licence you want from
|
|
4
|
+
// the two licences listed below.
|
|
5
|
+
//
|
|
6
|
+
// The first licence is a regular 2-clause BSD licence. The second licence
|
|
7
|
+
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
|
8
|
+
// to the public domain. The BSD licence serves as a fallback option.
|
|
9
|
+
//
|
|
10
|
+
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
|
11
|
+
//
|
|
12
|
+
// ------------------------------------------------------------------------
|
|
13
|
+
//
|
|
14
|
+
// Copyright (c) 2017-2019, Loup Vaillant
|
|
15
|
+
// All rights reserved.
|
|
16
|
+
//
|
|
17
|
+
//
|
|
18
|
+
// Redistribution and use in source and binary forms, with or without
|
|
19
|
+
// modification, are permitted provided that the following conditions are
|
|
20
|
+
// met:
|
|
21
|
+
//
|
|
22
|
+
// 1. Redistributions of source code must retain the above copyright
|
|
23
|
+
// notice, this list of conditions and the following disclaimer.
|
|
24
|
+
//
|
|
25
|
+
// 2. Redistributions in binary form must reproduce the above copyright
|
|
26
|
+
// notice, this list of conditions and the following disclaimer in the
|
|
27
|
+
// documentation and/or other materials provided with the
|
|
28
|
+
// distribution.
|
|
29
|
+
//
|
|
30
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
31
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
32
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
33
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
34
|
+
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
35
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
36
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
37
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
38
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
39
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
40
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
41
|
+
//
|
|
42
|
+
// ------------------------------------------------------------------------
|
|
43
|
+
//
|
|
44
|
+
// Written in 2017-2019 by Loup Vaillant
|
|
45
|
+
//
|
|
46
|
+
// To the extent possible under law, the author(s) have dedicated all copyright
|
|
47
|
+
// and related neighboring rights to this software to the public domain
|
|
48
|
+
// worldwide. This software is distributed without any warranty.
|
|
49
|
+
//
|
|
50
|
+
// You should have received a copy of the CC0 Public Domain Dedication along
|
|
51
|
+
// with this software. If not, see
|
|
52
|
+
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
|
53
|
+
|
|
54
|
+
#ifndef ED25519_H
|
|
55
|
+
#define ED25519_H
|
|
56
|
+
|
|
57
|
+
#include "monocypher.h"
|
|
58
|
+
|
|
59
|
+
#ifdef MONOCYPHER_CPP_NAMESPACE
|
|
60
|
+
namespace MONOCYPHER_CPP_NAMESPACE {
|
|
61
|
+
#elif defined(__cplusplus)
|
|
62
|
+
extern "C" {
|
|
63
|
+
#endif
|
|
64
|
+
|
|
65
|
+
////////////////////////
|
|
66
|
+
/// Type definitions ///
|
|
67
|
+
////////////////////////
|
|
68
|
+
|
|
69
|
+
// Do not rely on the size or content on any of those types,
|
|
70
|
+
// they may change without notice.
|
|
71
|
+
typedef struct {
|
|
72
|
+
uint64_t hash[8];
|
|
73
|
+
uint64_t input[16];
|
|
74
|
+
uint64_t input_size[2];
|
|
75
|
+
size_t input_idx;
|
|
76
|
+
} crypto_sha512_ctx;
|
|
77
|
+
|
|
78
|
+
typedef struct {
|
|
79
|
+
uint8_t key[128];
|
|
80
|
+
crypto_sha512_ctx ctx;
|
|
81
|
+
} crypto_sha512_hmac_ctx;
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// SHA 512
|
|
85
|
+
// -------
|
|
86
|
+
void crypto_sha512_init (crypto_sha512_ctx *ctx);
|
|
87
|
+
void crypto_sha512_update(crypto_sha512_ctx *ctx,
|
|
88
|
+
const uint8_t *message, size_t message_size);
|
|
89
|
+
void crypto_sha512_final (crypto_sha512_ctx *ctx, uint8_t hash[64]);
|
|
90
|
+
void crypto_sha512(uint8_t hash[64],
|
|
91
|
+
const uint8_t *message, size_t message_size);
|
|
92
|
+
|
|
93
|
+
// SHA 512 HMAC
|
|
94
|
+
// ------------
|
|
95
|
+
void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx,
|
|
96
|
+
const uint8_t *key, size_t key_size);
|
|
97
|
+
void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
|
|
98
|
+
const uint8_t *message, size_t message_size);
|
|
99
|
+
void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
|
|
100
|
+
void crypto_sha512_hmac(uint8_t hmac[64],
|
|
101
|
+
const uint8_t *key , size_t key_size,
|
|
102
|
+
const uint8_t *message, size_t message_size);
|
|
103
|
+
|
|
104
|
+
// SHA 512 HKDF
|
|
105
|
+
// ------------
|
|
106
|
+
void crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
|
|
107
|
+
const uint8_t *prk, size_t prk_size,
|
|
108
|
+
const uint8_t *info, size_t info_size);
|
|
109
|
+
void crypto_sha512_hkdf(uint8_t *okm , size_t okm_size,
|
|
110
|
+
const uint8_t *ikm , size_t ikm_size,
|
|
111
|
+
const uint8_t *salt, size_t salt_size,
|
|
112
|
+
const uint8_t *info, size_t info_size);
|
|
113
|
+
|
|
114
|
+
// Ed25519
|
|
115
|
+
// -------
|
|
116
|
+
// Signatures (EdDSA with curve25519 + SHA-512)
|
|
117
|
+
// --------------------------------------------
|
|
118
|
+
void crypto_ed25519_key_pair(uint8_t secret_key[64],
|
|
119
|
+
uint8_t public_key[32],
|
|
120
|
+
uint8_t seed[32]);
|
|
121
|
+
void crypto_ed25519_sign(uint8_t signature [64],
|
|
122
|
+
const uint8_t secret_key[64],
|
|
123
|
+
const uint8_t *message, size_t message_size);
|
|
124
|
+
int crypto_ed25519_check(const uint8_t signature [64],
|
|
125
|
+
const uint8_t public_key[32],
|
|
126
|
+
const uint8_t *message, size_t message_size);
|
|
127
|
+
|
|
128
|
+
// Pre-hash variants
|
|
129
|
+
void crypto_ed25519_ph_sign(uint8_t signature [64],
|
|
130
|
+
const uint8_t secret_key [64],
|
|
131
|
+
const uint8_t message_hash[64]);
|
|
132
|
+
int crypto_ed25519_ph_check(const uint8_t signature [64],
|
|
133
|
+
const uint8_t public_key [32],
|
|
134
|
+
const uint8_t message_hash[64]);
|
|
135
|
+
|
|
136
|
+
#ifdef __cplusplus
|
|
137
|
+
}
|
|
138
|
+
#endif
|
|
139
|
+
|
|
140
|
+
#endif // ED25519_H
|