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.
@@ -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