1 // Monocypher version 4.0.2
3 // This file is dual-licensed. Choose whichever licence you want from
4 // the two licences listed below.
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.
10 // SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
12 // ------------------------------------------------------------------------
14 // Copyright (c) 2017-2019, Loup Vaillant
15 // All rights reserved.
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
22 // 1. Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
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
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.
42 // ------------------------------------------------------------------------
44 // Written in 2017-2019 by Loup Vaillant
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.
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/>
54 #include "monocypher-ed25519.h"
56 #ifdef MONOCYPHER_CPP_NAMESPACE
57 namespace MONOCYPHER_CPP_NAMESPACE
{
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 MC_MIN(a, b) ((a) <= (b) ? (a) : (b))
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
)
79 return (~x
+ 1) & (pow_2
- 1);
82 static u64
load64_be(const u8 s
[8])
84 return((u64
)s
[0] << 56)
94 static void store64_be(u8 out
[8], u64 in
)
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;
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); }
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); }
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
144 static void sha512_compress(crypto_sha512_ctx
*ctx
)
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];
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
;
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
;
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
;
179 // Write 1 input byte
180 static void sha512_set_input(crypto_sha512_ctx
*ctx
, u8 input
)
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
));
187 // Increment a 128-bit "word".
188 static void sha512_incr(u64 x
[2], u64 y
)
196 void crypto_sha512_init(crypto_sha512_ctx
*ctx
)
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;
209 ZERO(ctx
->input
, 16);
212 void crypto_sha512_update(crypto_sha512_ctx
*ctx
,
213 const u8
*message
, size_t message_size
)
215 // Avoid undefined NULL pointer increments with empty messages
216 if (message_size
== 0) {
220 // Align ourselves with word boundaries
221 if ((ctx
->input_idx
& 7) != 0) {
222 size_t nb_bytes
= MC_MIN(align(ctx
->input_idx
, 8), message_size
);
223 FOR (i
, 0, nb_bytes
) {
224 sha512_set_input(ctx
, message
[i
]);
228 message_size
-= nb_bytes
;
231 // Align ourselves with block boundaries
232 if ((ctx
->input_idx
& 127) != 0) {
233 size_t nb_words
= MC_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;
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
);
245 ZERO(ctx
->input
, 16);
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
);
254 ZERO(ctx
->input
, 16);
259 if (message_size
!= 0) {
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;
268 FOR (i
, 0, message_size
) {
269 sha512_set_input(ctx
, message
[i
]);
275 void crypto_sha512_final(crypto_sha512_ctx
*ctx
, u8 hash
[64])
278 if (ctx
->input_idx
== 0) {
279 ZERO(ctx
->input
, 16);
281 sha512_set_input(ctx
, 128);
284 sha512_incr(ctx
->input_size
, ctx
->input_idx
* 8);
286 // Compress penultimate block (if any)
287 if (ctx
->input_idx
> 111) {
288 sha512_compress(ctx
);
289 ZERO(ctx
->input
, 14);
291 // Compress last block
292 ctx
->input
[14] = ctx
->input_size
[0];
293 ctx
->input
[15] = ctx
->input_size
[1];
294 sha512_compress(ctx
);
296 // Copy hash to output (big endian)
298 store64_be(hash
+ i
*8, ctx
->hash
[i
]);
304 void crypto_sha512(u8 hash
[64], const u8
*message
, size_t message_size
)
306 crypto_sha512_ctx ctx
;
307 crypto_sha512_init (&ctx
);
308 crypto_sha512_update(&ctx
, message
, message_size
);
309 crypto_sha512_final (&ctx
, hash
);
315 void crypto_sha512_hmac_init(crypto_sha512_hmac_ctx
*ctx
,
316 const u8
*key
, size_t key_size
)
318 // hash key if it is too long
319 if (key_size
> 128) {
320 crypto_sha512(ctx
->key
, key
, key_size
);
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);
332 void crypto_sha512_hmac_update(crypto_sha512_hmac_ctx
*ctx
,
333 const u8
*message
, size_t message_size
)
335 crypto_sha512_update(&ctx
->ctx
, message
, message_size
);
338 void crypto_sha512_hmac_final(crypto_sha512_hmac_ctx
*ctx
, u8 hmac
[64])
340 // Finish computing inner hash
341 crypto_sha512_final(&ctx
->ctx
, hmac
);
342 // Compute outer key: padded key XOR 0x5c
344 ctx
->key
[i
] ^= 0x36 ^ 0x5c;
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
354 void crypto_sha512_hmac(u8 hmac
[64], const u8
*key
, size_t key_size
,
355 const u8
*message
, size_t message_size
)
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
);
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
)
374 while (okm_size
> 0) {
375 size_t out_size
= MC_MIN(okm_size
, sizeof(blk
));
377 crypto_sha512_hmac_ctx ctx
;
378 crypto_sha512_hmac_init(&ctx
, prk
, prk_size
);
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
));
385 crypto_sha512_hmac_update(&ctx
, info
, info_size
);
386 crypto_sha512_hmac_update(&ctx
, &ctr
, 1);
387 crypto_sha512_hmac_final(&ctx
, blk
);
389 COPY(okm
, blk
, out_size
);
393 okm_size
-= out_size
;
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
)
405 crypto_sha512_hmac(prk
, salt
, salt_size
, ikm
, ikm_size
);
408 crypto_sha512_hkdf_expand(okm
, okm_size
, prk
, sizeof(prk
), info
, info_size
);
414 void crypto_ed25519_key_pair(u8 secret_key
[64], u8 public_key
[32], u8 seed
[32])
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
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
)
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
);
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
)
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;
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
);
466 void crypto_ed25519_sign(u8 signature
[64], const u8 secret_key
[64],
467 const u8
*message
, size_t message_size
)
469 ed25519_dom_sign(signature
, secret_key
, 0, 0, message
, message_size
);
472 int crypto_ed25519_check(const u8 signature
[64], const u8 public_key
[32],
473 const u8
*msg
, size_t msg_size
)
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
);
480 static const u8 domain
[34] = "SigEd25519 no Ed25519 collisions\1";
482 void crypto_ed25519_ph_sign(uint8_t signature
[64], const uint8_t secret_key
[64],
483 const uint8_t message_hash
[64])
485 ed25519_dom_sign(signature
, secret_key
, domain
, sizeof(domain
),
489 int crypto_ed25519_ph_check(const uint8_t sig
[64], const uint8_t pk
[32],
490 const uint8_t msg_hash
[64])
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
);
498 #ifdef MONOCYPHER_CPP_NAMESPACE