@pinkparrot/qsafe-mayo-wasm 0.0.3
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.
- package/.gitmodules +3 -0
- package/.vscode/launch.json +12 -0
- package/LICENSE +201 -0
- package/bridge/mayo1_bridge.c +26 -0
- package/bridge/mayo2_bridge.c +26 -0
- package/bridge/randombytes_inject.c +44 -0
- package/build_mayo1.ps1 +36 -0
- package/build_mayo2.ps1 +36 -0
- package/dist/mayo.browser.min.js +216 -0
- package/dist/mayo1.js +0 -0
- package/dist/mayo2.js +0 -0
- package/dist/mayo_api.js +139 -0
- package/dist/package.json +1 -0
- package/gitignore +2 -0
- package/index.mjs +1 -0
- package/mayo-c/.astylerc +16 -0
- package/mayo-c/.cmake/flags.cmake +45 -0
- package/mayo-c/.cmake/sanitizers.cmake +81 -0
- package/mayo-c/.cmake/target.cmake +71 -0
- package/mayo-c/.github/workflows/ci_clang.yml +61 -0
- package/mayo-c/.github/workflows/ci_gcc.yml +60 -0
- package/mayo-c/.github/workflows/cmake.yml +160 -0
- package/mayo-c/.github/workflows/macos_m1.yml +68 -0
- package/mayo-c/CMakeLists.txt +35 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.rsp +902 -0
- package/mayo-c/LICENSE +202 -0
- package/mayo-c/META/MAYO-1_META.yml +52 -0
- package/mayo-c/META/MAYO-2_META.yml +52 -0
- package/mayo-c/META/MAYO-3_META.yml +52 -0
- package/mayo-c/META/MAYO-5_META.yml +52 -0
- package/mayo-c/NOTICE +13 -0
- package/mayo-c/README.md +183 -0
- package/mayo-c/apps/CMakeLists.txt +31 -0
- package/mayo-c/apps/PQCgenKAT_sign.c +281 -0
- package/mayo-c/apps/example.c +151 -0
- package/mayo-c/apps/example_nistapi.c +124 -0
- package/mayo-c/include/mayo.h +442 -0
- package/mayo-c/include/mem.h +25 -0
- package/mayo-c/include/randombytes.h +31 -0
- package/mayo-c/scripts/contstants.py +141 -0
- package/mayo-c/scripts/find_irred_poly.sage +39 -0
- package/mayo-c/src/AVX2/arithmetic_common.h +159 -0
- package/mayo-c/src/AVX2/echelon_form.h +91 -0
- package/mayo-c/src/AVX2/echelon_form_loop.h +58 -0
- package/mayo-c/src/AVX2/shuffle_arithmetic.h +442 -0
- package/mayo-c/src/CMakeLists.txt +98 -0
- package/mayo-c/src/arithmetic.c +128 -0
- package/mayo-c/src/arithmetic.h +124 -0
- package/mayo-c/src/common/aes128ctr.c +293 -0
- package/mayo-c/src/common/aes_c.c +741 -0
- package/mayo-c/src/common/aes_ctr.h +32 -0
- package/mayo-c/src/common/aes_neon.c +201 -0
- package/mayo-c/src/common/debug_bench_tools.h +69 -0
- package/mayo-c/src/common/fips202.c +1093 -0
- package/mayo-c/src/common/fips202.h +12 -0
- package/mayo-c/src/common/mem.c +19 -0
- package/mayo-c/src/common/randombytes_ctrdrbg.c +141 -0
- package/mayo-c/src/common/randombytes_system.c +399 -0
- package/mayo-c/src/generic/arithmetic_dynamic.h +68 -0
- package/mayo-c/src/generic/arithmetic_fixed.h +84 -0
- package/mayo-c/src/generic/echelon_form.h +152 -0
- package/mayo-c/src/generic/ef_inner_loop.h +56 -0
- package/mayo-c/src/generic/generic_arithmetic.h +294 -0
- package/mayo-c/src/mayo.c +675 -0
- package/mayo-c/src/mayo_1/api.c +46 -0
- package/mayo-c/src/mayo_1/api.h +43 -0
- package/mayo-c/src/mayo_2/api.c +46 -0
- package/mayo-c/src/mayo_2/api.h +43 -0
- package/mayo-c/src/mayo_3/api.c +46 -0
- package/mayo-c/src/mayo_3/api.h +43 -0
- package/mayo-c/src/mayo_5/api.c +46 -0
- package/mayo-c/src/mayo_5/api.h +43 -0
- package/mayo-c/src/neon/arithmetic_common.h +132 -0
- package/mayo-c/src/neon/echelon_form.h +55 -0
- package/mayo-c/src/neon/echelon_form_loop.h +58 -0
- package/mayo-c/src/neon/shuffle_arithmetic.h +462 -0
- package/mayo-c/src/params.c +42 -0
- package/mayo-c/src/simple_arithmetic.h +138 -0
- package/mayo-c/test/CMakeLists.txt +51 -0
- package/mayo-c/test/bench.c +166 -0
- package/mayo-c/test/m1cycles.c +155 -0
- package/mayo-c/test/m1cycles.h +13 -0
- package/mayo-c/test/test_kat.c +271 -0
- package/mayo-c/test/test_mayo.c +139 -0
- package/mayo-c/test/test_sample_solution.c +75 -0
- package/mayo-c/test/test_various.c +680 -0
- package/package.json +39 -0
- package/publish.bat +22 -0
- package/readme.md +80 -0
- package/test/test.mjs +42 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
#ifndef FIPS202_H
|
|
4
|
+
#define FIPS202_H
|
|
5
|
+
|
|
6
|
+
#include <stddef.h>
|
|
7
|
+
|
|
8
|
+
int shake128(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen);
|
|
9
|
+
int shake256(unsigned char *output, size_t outputByteLen, const unsigned char *input, size_t inputByteLen);
|
|
10
|
+
|
|
11
|
+
#endif
|
|
12
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
#include <string.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
|
|
7
|
+
void mayo_secure_free(void *mem, size_t size) {
|
|
8
|
+
if (mem) {
|
|
9
|
+
typedef void *(*memset_t)(void *, int, size_t);
|
|
10
|
+
static volatile memset_t memset_func = memset;
|
|
11
|
+
memset_func(mem, 0, size);
|
|
12
|
+
free(mem);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
void mayo_secure_clear(void *mem, size_t size) {
|
|
16
|
+
typedef void *(*memset_t)(void *, int, size_t);
|
|
17
|
+
static volatile memset_t memset_func = memset;
|
|
18
|
+
memset_func(mem, 0, size);
|
|
19
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0 and Unknown
|
|
2
|
+
//
|
|
3
|
+
/*
|
|
4
|
+
NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software.
|
|
5
|
+
|
|
6
|
+
NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
|
|
7
|
+
|
|
8
|
+
You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include <string.h>
|
|
12
|
+
|
|
13
|
+
#include <aes_ctr.h>
|
|
14
|
+
|
|
15
|
+
#ifdef ENABLE_CT_TESTING
|
|
16
|
+
#include <valgrind/memcheck.h>
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
#define RNG_SUCCESS 0
|
|
20
|
+
#define RNG_BAD_MAXLEN -1
|
|
21
|
+
#define RNG_BAD_OUTBUF -2
|
|
22
|
+
#define RNG_BAD_REQ_LEN -3
|
|
23
|
+
|
|
24
|
+
static __inline void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) {
|
|
25
|
+
AES_ECB_encrypt(ctr, key, buffer);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
typedef struct {
|
|
29
|
+
unsigned char buffer[16];
|
|
30
|
+
int buffer_pos;
|
|
31
|
+
unsigned long length_remaining;
|
|
32
|
+
unsigned char key[32];
|
|
33
|
+
unsigned char ctr[16];
|
|
34
|
+
} AES_XOF_struct;
|
|
35
|
+
|
|
36
|
+
typedef struct {
|
|
37
|
+
unsigned char Key[32];
|
|
38
|
+
unsigned char V[16];
|
|
39
|
+
int reseed_counter;
|
|
40
|
+
} AES256_CTR_DRBG_struct;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
void
|
|
44
|
+
AES256_CTR_DRBG_Update(unsigned char *provided_data,
|
|
45
|
+
unsigned char *Key,
|
|
46
|
+
unsigned char *V);
|
|
47
|
+
|
|
48
|
+
AES256_CTR_DRBG_struct DRBG_ctx;
|
|
49
|
+
|
|
50
|
+
static void
|
|
51
|
+
randombytes_init_nist(unsigned char *entropy_input,
|
|
52
|
+
unsigned char *personalization_string,
|
|
53
|
+
int security_strength) {
|
|
54
|
+
unsigned char seed_material[48];
|
|
55
|
+
|
|
56
|
+
(void)security_strength; // Unused parameter
|
|
57
|
+
memcpy(seed_material, entropy_input, 48);
|
|
58
|
+
if (personalization_string)
|
|
59
|
+
for (int i = 0; i < 48; i++) {
|
|
60
|
+
seed_material[i] ^= personalization_string[i];
|
|
61
|
+
}
|
|
62
|
+
memset(DRBG_ctx.Key, 0x00, 32);
|
|
63
|
+
memset(DRBG_ctx.V, 0x00, 16);
|
|
64
|
+
AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
|
|
65
|
+
DRBG_ctx.reseed_counter = 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static int
|
|
69
|
+
randombytes_nist(unsigned char *x, size_t xlen) {
|
|
70
|
+
unsigned char block[16];
|
|
71
|
+
size_t i = 0;
|
|
72
|
+
|
|
73
|
+
while ( xlen > 0 ) {
|
|
74
|
+
//increment V
|
|
75
|
+
for (int j = 15; j >= 0; j--) {
|
|
76
|
+
if ( DRBG_ctx.V[j] == 0xff ) {
|
|
77
|
+
DRBG_ctx.V[j] = 0x00;
|
|
78
|
+
} else {
|
|
79
|
+
DRBG_ctx.V[j]++;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
|
|
84
|
+
if ( xlen > 15 ) {
|
|
85
|
+
memcpy(x + i, block, 16);
|
|
86
|
+
i += 16;
|
|
87
|
+
xlen -= 16;
|
|
88
|
+
} else {
|
|
89
|
+
memcpy(x + i, block, xlen);
|
|
90
|
+
i += xlen;
|
|
91
|
+
xlen = 0;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
|
|
95
|
+
DRBG_ctx.reseed_counter++;
|
|
96
|
+
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
void
|
|
101
|
+
AES256_CTR_DRBG_Update(unsigned char *provided_data,
|
|
102
|
+
unsigned char *Key,
|
|
103
|
+
unsigned char *V) {
|
|
104
|
+
unsigned char temp[48];
|
|
105
|
+
|
|
106
|
+
for (int i = 0; i < 3; i++) {
|
|
107
|
+
//increment V
|
|
108
|
+
for (int j = 15; j >= 0; j--) {
|
|
109
|
+
if ( V[j] == 0xff ) {
|
|
110
|
+
V[j] = 0x00;
|
|
111
|
+
} else {
|
|
112
|
+
V[j]++;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
AES256_ECB(Key, V, temp + 16 * i);
|
|
118
|
+
}
|
|
119
|
+
if ( provided_data != NULL )
|
|
120
|
+
for (int i = 0; i < 48; i++) {
|
|
121
|
+
temp[i] ^= provided_data[i];
|
|
122
|
+
}
|
|
123
|
+
memcpy(Key, temp, 32);
|
|
124
|
+
memcpy(V, temp + 32, 16);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
int randombytes(unsigned char *random_array, size_t nbytes) {
|
|
128
|
+
int ret = randombytes_nist(random_array, nbytes);
|
|
129
|
+
#ifdef ENABLE_CT_TESTING
|
|
130
|
+
VALGRIND_MAKE_MEM_UNDEFINED(random_array, ret);
|
|
131
|
+
#endif
|
|
132
|
+
return ret;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void
|
|
136
|
+
randombytes_init(unsigned char *entropy_input,
|
|
137
|
+
unsigned char *personalization_string,
|
|
138
|
+
int security_strength) {
|
|
139
|
+
return randombytes_init_nist(entropy_input, personalization_string, security_strength);
|
|
140
|
+
}
|
|
141
|
+
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The MIT License
|
|
5
|
+
Copyright (c) 2017 Daan Sprenkels <hello@dsprenkels.com>
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
+
THE SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
#ifdef ENABLE_CT_TESTING
|
|
24
|
+
#include <valgrind/memcheck.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
// In the case that are compiling on linux, we need to define _GNU_SOURCE
|
|
28
|
+
// *before* randombytes.h is included. Otherwise SYS_getrandom will not be
|
|
29
|
+
// declared.
|
|
30
|
+
#if defined(__linux__) || defined(__GNU__)
|
|
31
|
+
# define _GNU_SOURCE
|
|
32
|
+
#endif /* defined(__linux__) || defined(__GNU__) */
|
|
33
|
+
|
|
34
|
+
#include <randombytes.h>
|
|
35
|
+
|
|
36
|
+
#if defined(_WIN32)
|
|
37
|
+
/* Windows */
|
|
38
|
+
# include <windows.h>
|
|
39
|
+
# include <wincrypt.h> /* CryptAcquireContext, CryptGenRandom */
|
|
40
|
+
#endif /* defined(_WIN32) */
|
|
41
|
+
|
|
42
|
+
/* wasi */
|
|
43
|
+
#if defined(__wasi__)
|
|
44
|
+
#include <stdlib.h>
|
|
45
|
+
#endif
|
|
46
|
+
|
|
47
|
+
/* kFreeBSD */
|
|
48
|
+
#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
|
|
49
|
+
# define GNU_KFREEBSD
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
#if defined(__linux__) || defined(__GNU__) || defined(GNU_KFREEBSD)
|
|
53
|
+
/* Linux */
|
|
54
|
+
// We would need to include <linux/random.h>, but not every target has access
|
|
55
|
+
// to the linux headers. We only need RNDGETENTCNT, so we instead inline it.
|
|
56
|
+
// RNDGETENTCNT is originally defined in `include/uapi/linux/random.h` in the
|
|
57
|
+
// linux repo.
|
|
58
|
+
# define RNDGETENTCNT 0x80045200
|
|
59
|
+
|
|
60
|
+
# include <assert.h>
|
|
61
|
+
# include <errno.h>
|
|
62
|
+
# include <fcntl.h>
|
|
63
|
+
# include <poll.h>
|
|
64
|
+
# include <stdint.h>
|
|
65
|
+
# include <stdio.h>
|
|
66
|
+
# include <sys/ioctl.h>
|
|
67
|
+
# if (defined(__linux__) || defined(__GNU__)) && defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC_MINOR__ > 24))
|
|
68
|
+
# define USE_GLIBC
|
|
69
|
+
# include <sys/random.h>
|
|
70
|
+
# endif /* (defined(__linux__) || defined(__GNU__)) && defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC_MINOR__ > 24)) */
|
|
71
|
+
# include <sys/stat.h>
|
|
72
|
+
# include <sys/syscall.h>
|
|
73
|
+
# include <sys/types.h>
|
|
74
|
+
# include <unistd.h>
|
|
75
|
+
|
|
76
|
+
// We need SSIZE_MAX as the maximum read len from /dev/urandom
|
|
77
|
+
# if !defined(SSIZE_MAX)
|
|
78
|
+
# define SSIZE_MAX (SIZE_MAX / 2 - 1)
|
|
79
|
+
# endif /* defined(SSIZE_MAX) */
|
|
80
|
+
|
|
81
|
+
#endif /* defined(__linux__) || defined(__GNU__) || defined(GNU_KFREEBSD) */
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
|
85
|
+
/* Dragonfly, FreeBSD, NetBSD, OpenBSD (has arc4random) */
|
|
86
|
+
# include <sys/param.h>
|
|
87
|
+
# if defined(BSD)
|
|
88
|
+
# include <stdlib.h>
|
|
89
|
+
# endif
|
|
90
|
+
/* GNU/Hurd defines BSD in sys/param.h which causes problems later */
|
|
91
|
+
# if defined(__GNU__)
|
|
92
|
+
# undef BSD
|
|
93
|
+
# endif
|
|
94
|
+
#endif
|
|
95
|
+
|
|
96
|
+
#if defined(__EMSCRIPTEN__)
|
|
97
|
+
# include <assert.h>
|
|
98
|
+
# include <emscripten.h>
|
|
99
|
+
# include <errno.h>
|
|
100
|
+
# include <stdbool.h>
|
|
101
|
+
#endif /* defined(__EMSCRIPTEN__) */
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
#if defined(_WIN32)
|
|
105
|
+
static int randombytes_win32_randombytes(void* buf, size_t n)
|
|
106
|
+
{
|
|
107
|
+
HCRYPTPROV ctx;
|
|
108
|
+
BOOL tmp;
|
|
109
|
+
DWORD to_read = 0;
|
|
110
|
+
const size_t MAX_DWORD = 0xFFFFFFFF;
|
|
111
|
+
|
|
112
|
+
tmp = CryptAcquireContext(&ctx, NULL, NULL, PROV_RSA_FULL,
|
|
113
|
+
CRYPT_VERIFYCONTEXT);
|
|
114
|
+
if (tmp == FALSE) return -1;
|
|
115
|
+
|
|
116
|
+
while (n > 0) {
|
|
117
|
+
to_read = (DWORD)(n < MAX_DWORD ? n : MAX_DWORD);
|
|
118
|
+
tmp = CryptGenRandom(ctx, to_read, (BYTE*) buf);
|
|
119
|
+
if (tmp == FALSE) return -1;
|
|
120
|
+
buf = ((char*)buf) + to_read;
|
|
121
|
+
n -= to_read;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
tmp = CryptReleaseContext(ctx, 0);
|
|
125
|
+
if (tmp == FALSE) return -1;
|
|
126
|
+
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
#endif /* defined(_WIN32) */
|
|
130
|
+
|
|
131
|
+
#if defined(__wasi__)
|
|
132
|
+
static int randombytes_wasi_randombytes(void *buf, size_t n) {
|
|
133
|
+
arc4random_buf(buf, n);
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
#endif /* defined(__wasi__) */
|
|
137
|
+
|
|
138
|
+
#if (defined(__linux__) || defined(__GNU__)) && (defined(USE_GLIBC) || defined(SYS_getrandom))
|
|
139
|
+
# if defined(USE_GLIBC)
|
|
140
|
+
// getrandom is declared in glibc.
|
|
141
|
+
# elif defined(SYS_getrandom)
|
|
142
|
+
static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
|
|
143
|
+
return syscall(SYS_getrandom, buf, buflen, flags);
|
|
144
|
+
}
|
|
145
|
+
# endif
|
|
146
|
+
|
|
147
|
+
static int randombytes_linux_randombytes_getrandom(void *buf, size_t n)
|
|
148
|
+
{
|
|
149
|
+
/* I have thought about using a separate PRF, seeded by getrandom, but
|
|
150
|
+
* it turns out that the performance of getrandom is good enough
|
|
151
|
+
* (250 MB/s on my laptop).
|
|
152
|
+
*/
|
|
153
|
+
size_t offset = 0, chunk;
|
|
154
|
+
int ret;
|
|
155
|
+
while (n > 0) {
|
|
156
|
+
/* getrandom does not allow chunks larger than 33554431 */
|
|
157
|
+
chunk = n <= 33554431 ? n : 33554431;
|
|
158
|
+
do {
|
|
159
|
+
ret = getrandom((char *)buf + offset, chunk, 0);
|
|
160
|
+
} while (ret == -1 && errno == EINTR);
|
|
161
|
+
if (ret < 0) return ret;
|
|
162
|
+
offset += ret;
|
|
163
|
+
n -= ret;
|
|
164
|
+
}
|
|
165
|
+
assert(n == 0);
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
#endif /* (defined(__linux__) || defined(__GNU__)) && (defined(USE_GLIBC) || defined(SYS_getrandom)) */
|
|
169
|
+
|
|
170
|
+
#if (defined(__linux__) || defined(GNU_KFREEBSD)) && !defined(SYS_getrandom)
|
|
171
|
+
|
|
172
|
+
# if defined(__linux__)
|
|
173
|
+
static int randombytes_linux_read_entropy_ioctl(int device, int *entropy)
|
|
174
|
+
{
|
|
175
|
+
return ioctl(device, RNDGETENTCNT, entropy);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
static int randombytes_linux_read_entropy_proc(FILE *stream, int *entropy)
|
|
179
|
+
{
|
|
180
|
+
int retcode;
|
|
181
|
+
do {
|
|
182
|
+
rewind(stream);
|
|
183
|
+
retcode = fscanf(stream, "%d", entropy);
|
|
184
|
+
} while (retcode != 1 && errno == EINTR);
|
|
185
|
+
if (retcode != 1) {
|
|
186
|
+
return -1;
|
|
187
|
+
}
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static int randombytes_linux_wait_for_entropy(int device)
|
|
192
|
+
{
|
|
193
|
+
/* We will block on /dev/random, because any increase in the OS' entropy
|
|
194
|
+
* level will unblock the request. I use poll here (as does libsodium),
|
|
195
|
+
* because we don't *actually* want to read from the device. */
|
|
196
|
+
enum { IOCTL, PROC } strategy = IOCTL;
|
|
197
|
+
const int bits = 128;
|
|
198
|
+
struct pollfd pfd;
|
|
199
|
+
int fd;
|
|
200
|
+
FILE *proc_file;
|
|
201
|
+
int retcode, retcode_error = 0; // Used as return codes throughout this function
|
|
202
|
+
int entropy = 0;
|
|
203
|
+
|
|
204
|
+
/* If the device has enough entropy already, we will want to return early */
|
|
205
|
+
retcode = randombytes_linux_read_entropy_ioctl(device, &entropy);
|
|
206
|
+
// printf("errno: %d (%s)\n", errno, strerror(errno));
|
|
207
|
+
if (retcode != 0 && (errno == ENOTTY || errno == ENOSYS)) {
|
|
208
|
+
// The ioctl call on /dev/urandom has failed due to a
|
|
209
|
+
// - ENOTTY (unsupported action), or
|
|
210
|
+
// - ENOSYS (invalid ioctl; this happens on MIPS, see #22).
|
|
211
|
+
//
|
|
212
|
+
// We will fall back to reading from
|
|
213
|
+
// `/proc/sys/kernel/random/entropy_avail`. This less ideal,
|
|
214
|
+
// because it allocates a file descriptor, and it may not work
|
|
215
|
+
// in a chroot. But at this point it seems we have no better
|
|
216
|
+
// options left.
|
|
217
|
+
strategy = PROC;
|
|
218
|
+
// Open the entropy count file
|
|
219
|
+
proc_file = fopen("/proc/sys/kernel/random/entropy_avail", "r");
|
|
220
|
+
if (proc_file == NULL) {
|
|
221
|
+
return -1;
|
|
222
|
+
}
|
|
223
|
+
} else if (retcode != 0) {
|
|
224
|
+
// Unrecoverable ioctl error
|
|
225
|
+
return -1;
|
|
226
|
+
}
|
|
227
|
+
if (entropy >= bits) {
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
do {
|
|
232
|
+
fd = open("/dev/random", O_RDONLY);
|
|
233
|
+
} while (fd == -1 && errno == EINTR); /* EAGAIN will not occur */
|
|
234
|
+
if (fd == -1) {
|
|
235
|
+
/* Unrecoverable IO error */
|
|
236
|
+
return -1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
pfd.fd = fd;
|
|
240
|
+
pfd.events = POLLIN;
|
|
241
|
+
for (;;) {
|
|
242
|
+
retcode = poll(&pfd, 1, -1);
|
|
243
|
+
if (retcode == -1 && (errno == EINTR || errno == EAGAIN)) {
|
|
244
|
+
continue;
|
|
245
|
+
} else if (retcode == 1) {
|
|
246
|
+
if (strategy == IOCTL) {
|
|
247
|
+
retcode = randombytes_linux_read_entropy_ioctl(device, &entropy);
|
|
248
|
+
} else if (strategy == PROC) {
|
|
249
|
+
retcode = randombytes_linux_read_entropy_proc(proc_file, &entropy);
|
|
250
|
+
} else {
|
|
251
|
+
return -1; // Unreachable
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (retcode != 0) {
|
|
255
|
+
// Unrecoverable I/O error
|
|
256
|
+
retcode_error = retcode;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
if (entropy >= bits) {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
// Unreachable: poll() should only return -1 or 1
|
|
264
|
+
retcode_error = -1;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
do {
|
|
269
|
+
retcode = close(fd);
|
|
270
|
+
} while (retcode == -1 && errno == EINTR);
|
|
271
|
+
if (strategy == PROC) {
|
|
272
|
+
do {
|
|
273
|
+
retcode = fclose(proc_file);
|
|
274
|
+
} while (retcode == -1 && errno == EINTR);
|
|
275
|
+
}
|
|
276
|
+
if (retcode_error != 0) {
|
|
277
|
+
return retcode_error;
|
|
278
|
+
}
|
|
279
|
+
return retcode;
|
|
280
|
+
}
|
|
281
|
+
# endif /* defined(__linux__) */
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
static int randombytes_linux_randombytes_urandom(void *buf, size_t n)
|
|
285
|
+
{
|
|
286
|
+
int fd;
|
|
287
|
+
size_t offset = 0, count;
|
|
288
|
+
ssize_t tmp;
|
|
289
|
+
do {
|
|
290
|
+
fd = open("/dev/urandom", O_RDONLY);
|
|
291
|
+
} while (fd == -1 && errno == EINTR);
|
|
292
|
+
if (fd == -1) return -1;
|
|
293
|
+
# if defined(__linux__)
|
|
294
|
+
if (randombytes_linux_wait_for_entropy(fd) == -1) return -1;
|
|
295
|
+
# endif
|
|
296
|
+
|
|
297
|
+
while (n > 0) {
|
|
298
|
+
count = n <= SSIZE_MAX ? n : SSIZE_MAX;
|
|
299
|
+
tmp = read(fd, (char *)buf + offset, count);
|
|
300
|
+
if (tmp == -1 && (errno == EAGAIN || errno == EINTR)) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (tmp == -1) return -1; /* Unrecoverable IO error */
|
|
304
|
+
offset += tmp;
|
|
305
|
+
n -= tmp;
|
|
306
|
+
}
|
|
307
|
+
close(fd);
|
|
308
|
+
assert(n == 0);
|
|
309
|
+
return 0;
|
|
310
|
+
}
|
|
311
|
+
#endif /* defined(__linux__) && !defined(SYS_getrandom) */
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
#if defined(BSD)
|
|
315
|
+
static int randombytes_bsd_randombytes(void *buf, size_t n)
|
|
316
|
+
{
|
|
317
|
+
arc4random_buf(buf, n);
|
|
318
|
+
return 0;
|
|
319
|
+
}
|
|
320
|
+
#endif /* defined(BSD) */
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
#if defined(__EMSCRIPTEN__)
|
|
324
|
+
static int randombytes_js_randombytes_nodejs(void *buf, size_t n) {
|
|
325
|
+
const int ret = EM_ASM_INT({
|
|
326
|
+
var crypto;
|
|
327
|
+
try {
|
|
328
|
+
crypto = require('crypto');
|
|
329
|
+
} catch (error) {
|
|
330
|
+
return -2;
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
writeArrayToMemory(crypto.randomBytes($1), $0);
|
|
334
|
+
return 0;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
return -1;
|
|
337
|
+
}
|
|
338
|
+
}, buf, n);
|
|
339
|
+
switch (ret) {
|
|
340
|
+
case 0:
|
|
341
|
+
return 0;
|
|
342
|
+
case -1:
|
|
343
|
+
errno = EINVAL;
|
|
344
|
+
return -1;
|
|
345
|
+
case -2:
|
|
346
|
+
errno = ENOSYS;
|
|
347
|
+
return -1;
|
|
348
|
+
}
|
|
349
|
+
assert(false); // Unreachable
|
|
350
|
+
}
|
|
351
|
+
#endif /* defined(__EMSCRIPTEN__) */
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
static int randombytes_select(void *buf, size_t n)
|
|
355
|
+
{
|
|
356
|
+
#if defined(__EMSCRIPTEN__)
|
|
357
|
+
return randombytes_js_randombytes_nodejs(buf, n);
|
|
358
|
+
#elif defined(__linux__) || defined(__GNU__) || defined(GNU_KFREEBSD)
|
|
359
|
+
# if defined(USE_GLIBC)
|
|
360
|
+
/* Use getrandom system call */
|
|
361
|
+
return randombytes_linux_randombytes_getrandom(buf, n);
|
|
362
|
+
# elif defined(SYS_getrandom)
|
|
363
|
+
/* Use getrandom system call */
|
|
364
|
+
return randombytes_linux_randombytes_getrandom(buf, n);
|
|
365
|
+
# else
|
|
366
|
+
/* When we have enough entropy, we can read from /dev/urandom */
|
|
367
|
+
return randombytes_linux_randombytes_urandom(buf, n);
|
|
368
|
+
# endif
|
|
369
|
+
#elif defined(BSD)
|
|
370
|
+
/* Use arc4random system call */
|
|
371
|
+
return randombytes_bsd_randombytes(buf, n);
|
|
372
|
+
#elif defined(_WIN32)
|
|
373
|
+
/* Use windows API */
|
|
374
|
+
return randombytes_win32_randombytes(buf, n);
|
|
375
|
+
#elif defined(__wasi__)
|
|
376
|
+
/* Use WASI */
|
|
377
|
+
return randombytes_wasi_randombytes(buf, n);
|
|
378
|
+
#else
|
|
379
|
+
# error "randombytes(...) is not supported on this platform"
|
|
380
|
+
#endif
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
int randombytes(unsigned char *x, size_t xlen) {
|
|
384
|
+
|
|
385
|
+
int ret = randombytes_select(x, (size_t) xlen);
|
|
386
|
+
#ifdef ENABLE_CT_TESTING
|
|
387
|
+
VALGRIND_MAKE_MEM_UNDEFINED(x, xlen);
|
|
388
|
+
#endif
|
|
389
|
+
return ret;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
void randombytes_init(unsigned char *entropy_input,
|
|
393
|
+
unsigned char *personalization_string,
|
|
394
|
+
int security_strength) {
|
|
395
|
+
(void) entropy_input;
|
|
396
|
+
(void) personalization_string;
|
|
397
|
+
(void) security_strength;
|
|
398
|
+
}
|
|
399
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
#ifndef ARITHMETIC_DYNAMIC_H
|
|
4
|
+
#define ARITHMETIC_DYNAMIC_H
|
|
5
|
+
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
#include <simple_arithmetic.h>
|
|
8
|
+
|
|
9
|
+
static
|
|
10
|
+
inline void m_vec_copy(int m_vec_limbs, const uint64_t *in, uint64_t *out) {
|
|
11
|
+
for (int i = 0; i < m_vec_limbs; i++) {
|
|
12
|
+
out[i] = in[i];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static
|
|
17
|
+
inline void m_vec_add(int m_vec_limbs, const uint64_t *in, uint64_t *acc) {
|
|
18
|
+
for (int i = 0; i < m_vec_limbs; i++) {
|
|
19
|
+
acc[i] ^= in[i];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static inline
|
|
24
|
+
void m_vec_mul_add(int m_vec_limbs, const uint64_t *in, unsigned char a, uint64_t *acc) {
|
|
25
|
+
for(int i=0; i < m_vec_limbs; i++){
|
|
26
|
+
acc[i] ^= gf16v_mul_u64(in[i], a);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
inline
|
|
31
|
+
static void m_vec_mul_add_x (int m_vec_limbs, const uint64_t *in, uint64_t *acc) {
|
|
32
|
+
uint64_t mask_msb = 0x8888888888888888ULL;
|
|
33
|
+
for(int i=0; i < m_vec_limbs; i++){
|
|
34
|
+
uint64_t t = in[i] & mask_msb;
|
|
35
|
+
acc[i] ^= ((in[i] ^ t) << 1) ^ ((t >> 3) * 3);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
inline
|
|
40
|
+
static void m_vec_mul_add_x_inv (int m_vec_limbs, const uint64_t *in, uint64_t *acc) {
|
|
41
|
+
uint64_t mask_lsb = 0x1111111111111111ULL;
|
|
42
|
+
for(int i=0; i < m_vec_limbs; i++){
|
|
43
|
+
uint64_t t = in[i] & mask_lsb;
|
|
44
|
+
acc[i] ^= ((in[i] ^ t) >> 1) ^ (t * 9);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static
|
|
49
|
+
inline void m_vec_multiply_bins (int m_vec_limbs, uint64_t *bins, uint64_t *out) {
|
|
50
|
+
|
|
51
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 5 * m_vec_limbs, bins + 10 * m_vec_limbs);
|
|
52
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 11 * m_vec_limbs, bins + 12 * m_vec_limbs);
|
|
53
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 10 * m_vec_limbs, bins + 7 * m_vec_limbs);
|
|
54
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 12 * m_vec_limbs, bins + 6 * m_vec_limbs);
|
|
55
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 7 * m_vec_limbs, bins + 14 * m_vec_limbs);
|
|
56
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 6 * m_vec_limbs, bins + 3 * m_vec_limbs);
|
|
57
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 14 * m_vec_limbs, bins + 15 * m_vec_limbs);
|
|
58
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 3 * m_vec_limbs, bins + 8 * m_vec_limbs);
|
|
59
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 15 * m_vec_limbs, bins + 13 * m_vec_limbs);
|
|
60
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 8 * m_vec_limbs, bins + 4 * m_vec_limbs);
|
|
61
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 13 * m_vec_limbs, bins + 9 * m_vec_limbs);
|
|
62
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 4 * m_vec_limbs, bins + 2 * m_vec_limbs);
|
|
63
|
+
m_vec_mul_add_x_inv (m_vec_limbs, bins + 9 * m_vec_limbs, bins + 1 * m_vec_limbs);
|
|
64
|
+
m_vec_mul_add_x (m_vec_limbs, bins + 2 * m_vec_limbs, bins + 1 * m_vec_limbs);
|
|
65
|
+
m_vec_copy (m_vec_limbs, bins + m_vec_limbs, out);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#endif
|