summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-03-21 22:17:51 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2018-03-30 05:18:49 +0200
commitef8ddb80781934f44cc27f5f5e8625f7fff0b033 (patch)
treee424eb5c29895c568d635e0676692326d61e1cbc
parentInitial commit (diff)
downloadcurve25519-precomp-fuzzer-ef8ddb80781934f44cc27f5f5e8625f7fff0b033.tar.xz
curve25519-precomp-fuzzer-ef8ddb80781934f44cc27f5f5e8625f7fff0b033.zip
Add gmp tests
-rw-r--r--gmp/Makefile12
-rw-r--r--gmp/gmp_fp25519_a24.c78
-rw-r--r--gmp/gmp_fp25519_add.c80
-rw-r--r--gmp/gmp_fp25519_fred.c68
-rw-r--r--gmp/gmp_fp25519_inv.c74
-rw-r--r--gmp/gmp_fp25519_mul.c69
-rw-r--r--gmp/gmp_fp25519_mul2.c78
-rw-r--r--gmp/gmp_fp25519_red.c76
-rw-r--r--gmp/gmp_fp25519_red2.c92
-rw-r--r--gmp/gmp_fp25519_sqr.c65
-rw-r--r--gmp/gmp_fp25519_sqr2.c72
-rw-r--r--gmp/gmp_fp25519_sub.c79
-rwxr-xr-xgmp/run.sh13
-rw-r--r--gmp/shim.h147
14 files changed, 1003 insertions, 0 deletions
diff --git a/gmp/Makefile b/gmp/Makefile
new file mode 100644
index 0000000..4cc9d55
--- /dev/null
+++ b/gmp/Makefile
@@ -0,0 +1,12 @@
+CFLAGS ?= -O3 -march=native -fomit-frame-pointer
+
+TARGETS := $(basename $(wildcard *.c))
+
+all: $(TARGETS)
+
+%: %.c
+ clang -o $@ $(CFLAGS) -I../bogus-include -fsanitize=fuzzer -lgmp $<
+clean:
+ rm -f $(basename $(TARGETS)) *.log
+
+.PHONY: clean all
diff --git a/gmp/gmp_fp25519_a24.c b/gmp/gmp_fp25519_a24.c
new file mode 100644
index 0000000..75e4d7d
--- /dev/null
+++ b/gmp/gmp_fp25519_a24.c
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0<= c=a24*a < 2^256 and that c be congruent to a24*a mod p
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=32
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 32) return 0;
+ const uint64_t a24 = 121666;
+ EltFp25519_1w_x64 a, get_c, want_c;
+
+ mpz_t gmp_a, gmp_c, gmp_low, gmp_high, two_to_256;
+ mpz_init(gmp_a);
+ mpz_init(gmp_c);
+ mpz_init(gmp_low);
+ mpz_init(gmp_high);
+
+ // two_to_256 = 2^256
+ mpz_init_set_ui(two_to_256, 1);
+ mpz_mul_2exp(two_to_256, two_to_256, 256);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ memcpy(a, Data + 0, 32);
+
+ mul_a24_EltFp25519_1w_x64(get_c, a);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_mul_ui(gmp_c, gmp_a, a24);
+
+ while (mpz_cmp(gmp_c, two_to_256) >= 0) {
+ mpz_mod_2exp(gmp_low, gmp_c, 256);
+ mpz_div_2exp(gmp_high, gmp_c, 256);
+ mpz_mul_ui(gmp_high, gmp_high, 38);
+ mpz_add(gmp_c, gmp_low, gmp_high);
+ }
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c);
+
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_c);
+ mpz_clear(gmp_low);
+ mpz_clear(gmp_high);
+ mpz_clear(two_to_256);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_add.c b/gmp/gmp_fp25519_add.c
new file mode 100644
index 0000000..7c2751c
--- /dev/null
+++ b/gmp/gmp_fp25519_add.c
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c=a+b < 2^256 and that c be congruent to a+b mod p
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 32) return 0;
+
+ EltFp25519_1w_x64 a, b, get_c, want_c;
+
+ mpz_t gmp_a, gmp_b, gmp_c, two_prime, two_to_256;
+ mpz_init(gmp_a);
+ mpz_init(gmp_b);
+ mpz_init(gmp_c);
+
+ // two_prime = 2^256-38
+ mpz_init_set_ui(two_prime, 1);
+ mpz_mul_2exp(two_prime, two_prime, 256);
+ mpz_sub_ui(two_prime, two_prime, 38);
+
+ // two_to_256 = 2^256
+ mpz_init_set_ui(two_to_256, 1);
+ mpz_mul_2exp(two_to_256, two_to_256, 256);
+
+ memcpy(a, Data + 0, 32);
+ memcpy(b, Data + 32, 32);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ add_EltFp25519_1w_x64(get_c, a, b);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_import(gmp_b, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 32);
+
+ mpz_add(gmp_c, gmp_a, gmp_b);
+ while (mpz_cmp(gmp_c, two_to_256) >= 0) {
+ mpz_sub(gmp_c, gmp_c, two_prime);
+ }
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c);
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_b);
+ mpz_clear(gmp_c);
+ mpz_clear(two_prime);
+ mpz_clear(two_to_256);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_fred.c b/gmp/gmp_fp25519_fred.c
new file mode 100644
index 0000000..cba671b
--- /dev/null
+++ b/gmp/gmp_fp25519_fred.c
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c=a mod p < 2^255-19 for a number 0 <= a < 2^256
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=32
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 32) return 0;
+ EltFp25519_1w_x64 a, get_c, want_c;
+
+ mpz_t gmp_a, gmp_c, prime;
+ mpz_init(gmp_a);
+ mpz_init(gmp_c);
+
+ // prime = p-2 = 2^255-19
+ mpz_init_set_ui(prime, 1);
+ mpz_mul_2exp(prime, prime, 255);
+ mpz_sub_ui(prime, prime, 19);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ memcpy(a, Data + 0, 32);
+
+ copy_EltFp25519_1w_x64(get_c, a);
+ fred_EltFp25519_1w_x64(get_c);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_mod(gmp_c, gmp_a, prime);
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c);
+
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_c);
+ mpz_clear(prime);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_inv.c b/gmp/gmp_fp25519_inv.c
new file mode 100644
index 0000000..bf7c2f5
--- /dev/null
+++ b/gmp/gmp_fp25519_inv.c
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= a < 2^256 and that c be congruent to a^-1 mod p
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=32
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 32) return 0;
+
+ EltFp25519_1w_x64 a, get_c, want_c;
+
+ mpz_t gmp_a, gmp_c, prime, prime_minus_two;
+ mpz_init(gmp_a);
+ mpz_init(gmp_c);
+
+ // two_prime = 2^255-19
+ mpz_init_set_ui(prime, 1);
+ mpz_mul_2exp(prime, prime, 255);
+ mpz_sub_ui(prime, prime, 19);
+
+ // expo = p-2 = 2^255-19-2 = 2^255-21
+ mpz_init_set_ui(prime_minus_two, 1);
+ mpz_mul_2exp(prime_minus_two, prime_minus_two, 255);
+ mpz_sub_ui(prime_minus_two, prime_minus_two, 21);
+
+ memcpy(a, Data + 0, 32);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ inv_EltFp25519_1w_x64(get_c, a);
+ fred_EltFp25519_1w_x64(get_c);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_powm(gmp_c, gmp_a, prime_minus_two, prime);
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c);
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_c);
+ mpz_clear(prime);
+ mpz_clear(prime_minus_two);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_mul.c b/gmp/gmp_fp25519_mul.c
new file mode 100644
index 0000000..ebdd5bc
--- /dev/null
+++ b/gmp/gmp_fp25519_mul.c
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c=a*b < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 32) return 0;
+
+ EltFp25519_1w_x64 a, b;
+ EltFp25519_1w_Buffer_x64 get_c, want_c;
+
+ mpz_t gmp_a, gmp_b, gmp_c;
+ mpz_init(gmp_a);
+ mpz_init(gmp_b);
+ mpz_init(gmp_c);
+
+ memcpy(a, Data + 0, 32);
+ memcpy(b, Data + 32, 32);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+ setzero_EltFp25519_1w_x64(get_c + NUM_WORDS_ELTFP25519_X64);
+ setzero_EltFp25519_1w_x64(want_c + NUM_WORDS_ELTFP25519_X64);
+
+ mul_256x256_integer_x64(get_c, a, b);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_import(gmp_b, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 32);
+
+ mpz_mul(gmp_c, gmp_a, gmp_b);
+ mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c);
+ assert(memcmp(get_c, want_c, 2 * SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_b);
+ mpz_clear(gmp_c);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_mul2.c b/gmp/gmp_fp25519_mul2.c
new file mode 100644
index 0000000..3fd0308
--- /dev/null
+++ b/gmp/gmp_fp25519_mul2.c
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c0=a0*b0 < 2^512 and 0 <= c1=a1*b1 < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=128
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 2 * 32) return 0;
+
+ EltFp25519_2w_x64 a, b;
+ EltFp25519_2w_Buffer_x64 get_c, want_c;
+
+ mpz_t gmp_a0, gmp_b0, gmp_c0, gmp_a1, gmp_b1, gmp_c1;
+ mpz_init(gmp_a0);
+ mpz_init(gmp_a1);
+ mpz_init(gmp_b0);
+ mpz_init(gmp_b1);
+ mpz_init(gmp_c0);
+ mpz_init(gmp_c1);
+
+ memcpy(a, Data + 0, 64);
+ memcpy(b, Data + 64, 64);
+
+ memset(get_c, 0, sizeof(get_c));
+ memset(want_c, 0, sizeof(want_c));
+
+ mul2_256x256_integer_x64(get_c, a, b);
+
+ mpz_import(gmp_a0, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_import(gmp_a1, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 32);
+ mpz_import(gmp_b0, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 64);
+ mpz_import(gmp_b1, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 96);
+
+ mpz_mul(gmp_c0, gmp_a0, gmp_b0);
+ mpz_mul(gmp_c1, gmp_a1, gmp_b1);
+ mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c0);
+ mpz_export(want_c + 2 * NUM_WORDS_ELTFP25519_X64, NULL, -1,
+ 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c1);
+ assert(memcmp(get_c, want_c, sizeof(get_c)) == 0);
+
+ mpz_clear(gmp_a0);
+ mpz_clear(gmp_a1);
+ mpz_clear(gmp_b0);
+ mpz_clear(gmp_b1);
+ mpz_clear(gmp_c0);
+ mpz_clear(gmp_c1);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_red.c b/gmp/gmp_fp25519_red.c
new file mode 100644
index 0000000..5f8d226
--- /dev/null
+++ b/gmp/gmp_fp25519_red.c
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c < 2^256 be congruent (mod p) to 0<= a < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 32) return 0;
+ EltFp25519_1w_x64 get_c, want_c;
+ EltFp25519_1w_Buffer_x64 a;
+
+ mpz_t gmp_a, gmp_low, gmp_high, two_to_256;
+ mpz_init(gmp_a);
+ mpz_init(gmp_low);
+ mpz_init(gmp_high);
+
+ // two_to_256 = 2^256
+ mpz_init_set_ui(two_to_256, 1);
+ mpz_mul_2exp(two_to_256, two_to_256, 256);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ memcpy(a, Data + 0, 64);
+
+ red_EltFp25519_1w_x64(get_c, a);
+
+ mpz_import(gmp_a, 2 * SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0,
+ Data + 0);
+
+ while (mpz_cmp(gmp_a, two_to_256) >= 0) {
+ mpz_mod_2exp(gmp_low, gmp_a, 256);
+ mpz_div_2exp(gmp_high, gmp_a, 256);
+ mpz_mul_ui(gmp_high, gmp_high, 38);
+ mpz_add(gmp_a, gmp_low, gmp_high);
+ }
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_a);
+
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_low);
+ mpz_clear(gmp_high);
+ mpz_clear(two_to_256);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_red2.c b/gmp/gmp_fp25519_red2.c
new file mode 100644
index 0000000..ed29a30
--- /dev/null
+++ b/gmp/gmp_fp25519_red2.c
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c < 2^256 be congruent (mod p) to 0<= a < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 2 * 32) return 0;
+
+ EltFp25519_2w_x64 get_c, want_c;
+ EltFp25519_2w_Buffer_x64 a;
+
+ mpz_t gmp_a0, gmp_a1, gmp_low, gmp_high, two_to_256;
+ mpz_init(gmp_a0);
+ mpz_init(gmp_a1);
+ mpz_init(gmp_low);
+ mpz_init(gmp_high);
+
+ // two_to_256 = 2^256
+ mpz_init_set_ui(two_to_256, 1);
+ mpz_mul_2exp(two_to_256, two_to_256, 256);
+
+ setzero_EltFp25519_1w_x64(get_c + 0);
+ setzero_EltFp25519_1w_x64(get_c + NUM_WORDS_ELTFP25519_X64);
+ setzero_EltFp25519_1w_x64(want_c + 0);
+ setzero_EltFp25519_1w_x64(want_c + NUM_WORDS_ELTFP25519_X64);
+
+ memcpy(a, Data + 0, 128);
+
+ red_EltFp25519_2w_x64(get_c, a);
+
+ mpz_import(gmp_a0, 2 * SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0,
+ Data + 0);
+ mpz_import(gmp_a1, 2 * SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0,
+ Data + 64);
+
+ while (mpz_cmp(gmp_a0, two_to_256) >= 0) {
+ mpz_mod_2exp(gmp_low, gmp_a0, 256);
+ mpz_div_2exp(gmp_high, gmp_a0, 256);
+ mpz_mul_ui(gmp_high, gmp_high, 38);
+ mpz_add(gmp_a0, gmp_low, gmp_high);
+ }
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_a0);
+
+ while (mpz_cmp(gmp_a1, two_to_256) >= 0) {
+ mpz_mod_2exp(gmp_low, gmp_a1, 256);
+ mpz_div_2exp(gmp_high, gmp_a1, 256);
+ mpz_mul_ui(gmp_high, gmp_high, 38);
+ mpz_add(gmp_a1, gmp_low, gmp_high);
+ }
+ mpz_export(want_c + NUM_WORDS_ELTFP25519_X64, NULL, -1, SIZE_BYTES_FP25519, 0,
+ 0, gmp_a1);
+
+ assert(memcmp(get_c, want_c, sizeof(get_c)) == 0);
+
+ mpz_clear(gmp_a0);
+ mpz_clear(gmp_a1);
+ mpz_clear(gmp_low);
+ mpz_clear(gmp_high);
+ mpz_clear(two_to_256);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_sqr.c b/gmp/gmp_fp25519_sqr.c
new file mode 100644
index 0000000..3f85c84
--- /dev/null
+++ b/gmp/gmp_fp25519_sqr.c
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c=a*a < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=32
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 32) return 0;
+
+ EltFp25519_1w_x64 a;
+ EltFp25519_1w_Buffer_x64 get_c, want_c;
+
+ mpz_t gmp_a, gmp_c;
+ mpz_init(gmp_a);
+ mpz_init(gmp_c);
+
+ memcpy(a, Data + 0, 32);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+ setzero_EltFp25519_1w_x64(get_c + NUM_WORDS_ELTFP25519_X64);
+ setzero_EltFp25519_1w_x64(want_c + NUM_WORDS_ELTFP25519_X64);
+
+ sqr_256x256_integer_x64(get_c, a);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+
+ mpz_mul(gmp_c, gmp_a, gmp_a);
+ mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c);
+ assert(memcmp(get_c, want_c, 2 * SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_c);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_sqr2.c b/gmp/gmp_fp25519_sqr2.c
new file mode 100644
index 0000000..132567a
--- /dev/null
+++ b/gmp/gmp_fp25519_sqr2.c
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c0=a0*a0 < 2^512 and 0 <= c1=a1*a1 < 2^512
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 32) return 0;
+
+ EltFp25519_2w_x64 a;
+ EltFp25519_2w_Buffer_x64 get_c, want_c;
+
+ mpz_t gmp_a0, gmp_c0, gmp_a1, gmp_c1;
+ mpz_init(gmp_a0);
+ mpz_init(gmp_a1);
+ mpz_init(gmp_c0);
+ mpz_init(gmp_c1);
+
+ memcpy(a, Data + 0, 64);
+
+ memset(get_c, 0, sizeof(get_c));
+ memset(want_c, 0, sizeof(want_c));
+
+ sqr2_256x256_integer_x64(get_c, a);
+
+ mpz_import(gmp_a0, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_import(gmp_a1, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 32);
+
+ mpz_mul(gmp_c0, gmp_a0, gmp_a0);
+ mpz_mul(gmp_c1, gmp_a1, gmp_a1);
+
+ mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c0);
+ mpz_export(want_c + 2 * NUM_WORDS_ELTFP25519_X64, NULL, -1,
+ 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c1);
+ assert(memcmp(get_c, want_c, sizeof(get_c)) == 0);
+
+ mpz_clear(gmp_a0);
+ mpz_clear(gmp_a1);
+ mpz_clear(gmp_c0);
+ mpz_clear(gmp_c1);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/gmp_fp25519_sub.c b/gmp/gmp_fp25519_sub.c
new file mode 100644
index 0000000..962e541
--- /dev/null
+++ b/gmp/gmp_fp25519_sub.c
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>. All Rights Reserved.
+ * Institute of Computing.
+ * University of Campinas, Brazil.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, version 2 or greater.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <assert.h>
+#include "shim.h"
+#include <gmp.h>
+#include <string.h>
+
+/**
+ * Verifies that 0 <= c=a-b < 2^256 and that c be congruent to a-b mod p
+ * @param Data Random binary data.
+ * @param Size Non-trivial input size is set -max_len=64
+ * @return Always return 0 in case of success.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 2 * 32) return 0;
+
+ EltFp25519_1w_x64 a, b, get_c, want_c;
+
+ mpz_t gmp_a, gmp_b, gmp_c, two_prime, zero;
+ mpz_init(gmp_a);
+ mpz_init(gmp_b);
+ mpz_init(gmp_c);
+
+ // two_prime = 2^256-38
+ mpz_init_set_ui(two_prime, 1);
+ mpz_mul_2exp(two_prime, two_prime, 256);
+ mpz_sub_ui(two_prime, two_prime, 38);
+
+ // zero = 0
+ mpz_init_set_ui(zero, 0);
+
+ memcpy(a, Data + 0, 32);
+ memcpy(b, Data + 32, 32);
+
+ setzero_EltFp25519_1w_x64(get_c);
+ setzero_EltFp25519_1w_x64(want_c);
+
+ sub_EltFp25519_1w_x64(get_c, a, b);
+
+ mpz_import(gmp_a, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 0);
+ mpz_import(gmp_b, SIZE_BYTES_FP25519, -1, sizeof(Data[0]), 0, 0, Data + 32);
+
+ mpz_sub(gmp_c, gmp_a, gmp_b);
+ while (mpz_cmp(gmp_c, zero) < 0) {
+ mpz_add(gmp_c, gmp_c, two_prime);
+ }
+ mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c);
+ assert(memcmp(get_c, want_c, SIZE_BYTES_FP25519) == 0);
+
+ mpz_clear(gmp_a);
+ mpz_clear(gmp_b);
+ mpz_clear(gmp_c);
+ mpz_clear(two_prime);
+ mpz_clear(zero);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gmp/run.sh b/gmp/run.sh
new file mode 100755
index 0000000..c89d313
--- /dev/null
+++ b/gmp/run.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+mkdir -p gmp_fp25519_fred.logs && cd gmp_fp25519_fred.logs; ../gmp_fp25519_fred -max_len=32 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_sqr2.logs && cd gmp_fp25519_sqr2.logs; ../gmp_fp25519_sqr2 -max_len=64 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_inv.logs && cd gmp_fp25519_inv.logs; ../gmp_fp25519_inv -max_len=32 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_red2.logs && cd gmp_fp25519_red2.logs; ../gmp_fp25519_red2 -max_len=128 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_mul2.logs && cd gmp_fp25519_mul2.logs; ../gmp_fp25519_mul2 -max_len=128 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_sqr.logs && cd gmp_fp25519_sqr.logs; ../gmp_fp25519_sqr -max_len=32 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_red.logs && cd gmp_fp25519_red.logs; ../gmp_fp25519_red -max_len=64 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_add.logs && cd gmp_fp25519_add.logs; ../gmp_fp25519_add -max_len=64 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_a24.logs && cd gmp_fp25519_a24.logs; ../gmp_fp25519_a24 -max_len=32 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_sub.logs && cd gmp_fp25519_sub.logs; ../gmp_fp25519_sub -max_len=64 -workers=5 -jobs=5 & cd ..
+mkdir -p gmp_fp25519_mul.logs && cd gmp_fp25519_mul.logs; ../gmp_fp25519_mul -max_len=64 -workers=5 -jobs=5 & cd ..
+wait
diff --git a/gmp/shim.h b/gmp/shim.h
new file mode 100644
index 0000000..9ce3775
--- /dev/null
+++ b/gmp/shim.h
@@ -0,0 +1,147 @@
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <linux/types.h>
+typedef __u64 u64;
+typedef __u32 u32;
+typedef __u8 u8;
+typedef __s64 s64;
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define le64_to_cpup(a) __builtin_bswap64(*(a))
+#define le32_to_cpup(a) __builtin_bswap32(*(a))
+#define cpu_to_le64(a) __builtin_bswap64(a)
+#else
+#define le64_to_cpup(a) (*(a))
+#define le32_to_cpup(a) (*(a))
+#define cpu_to_le64(a) (a)
+#endif
+#ifndef __always_inline
+#define __always_inline __inline __attribute__((__always_inline__))
+#endif
+#ifndef noinline
+#define noinline __attribute__((noinline))
+#endif
+#ifndef __aligned
+#define __aligned(x) __attribute__((aligned(x)))
+#endif
+#ifndef __force
+#define __force
+#endif
+#ifndef memzero_explicit
+#define memzero_explicit(a, b)
+#endif
+#ifndef __ro_after_init
+#define __ro_after_init
+#endif
+#ifndef __init
+#define __init
+#endif
+#define boot_cpu_has(a) true
+
+enum curve25519_lengths {
+ CURVE25519_POINT_SIZE = 32,
+};
+
+static inline void normalize_secret(u8 secret[CURVE25519_POINT_SIZE])
+{
+ secret[0] &= 248;
+ secret[31] &= 127;
+ secret[31] |= 64;
+}
+
+#include "../WireGuard/src/crypto/curve25519-x86_64.h"
+
+typedef u8 uint8_t;
+typedef u64 uint64_t;
+#define NUM_WORDS_ELTFP25519_X64 4
+#define SIZE_BYTES_FP25519 32
+typedef __aligned(32) uint64_t EltFp25519_1w_x64[NUM_WORDS_ELTFP25519_X64];
+typedef __aligned(32) uint64_t EltFp25519_1w_Buffer_x64[2 * NUM_WORDS_ELTFP25519_X64];
+typedef __aligned(32) uint64_t EltFp25519_2w_x64[2 * NUM_WORDS_ELTFP25519_X64];
+typedef __aligned(32) uint64_t EltFp25519_2w_Buffer_x64[4 * NUM_WORDS_ELTFP25519_X64];
+#define setzero_EltFp25519_1w_x64(a) setzero_eltfp25519_1w(a)
+#define copy_EltFp25519_1w_x64(a, b) copy_eltfp25519_1w(a, b)
+
+static inline void mul2_256x256_integer_x64(uint64_t *const c, uint64_t *const a,
+ uint64_t *const b)
+{
+ EltFp25519_2w_Buffer_x64 other = { 0 };
+ mul2_256x256_integer_adx(other, a, b);
+ mul2_256x256_integer_bmi2(c, a, b);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+
+static inline void sqr2_256x256_integer_x64(uint64_t *const c, uint64_t *const a)
+{
+ EltFp25519_2w_Buffer_x64 other = { 0 };
+ sqr2_256x256_integer_adx(other, a);
+ sqr2_256x256_integer_bmi2(c, a);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void red_EltFp25519_2w_x64(uint64_t *const c, uint64_t *const a)
+{
+ EltFp25519_2w_x64 other = { 0 };
+ red_eltfp25519_2w_adx(other, a);
+ red_eltfp25519_2w_bmi2(c, a);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void mul_256x256_integer_x64(uint64_t *const c, uint64_t *const a,
+ uint64_t *const b)
+{
+ EltFp25519_1w_Buffer_x64 other = { 0 };
+ mul_256x256_integer_adx(other, a, b);
+ mul_256x256_integer_bmi2(c, a, b);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void sqr_256x256_integer_x64(uint64_t *const c, uint64_t *const a)
+{
+ EltFp25519_1w_Buffer_x64 other = { 0 };
+ sqr_256x256_integer_adx(other, a);
+ sqr_256x256_integer_bmi2(c, a);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void red_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a)
+{
+ EltFp25519_1w_x64 other = { 0 };
+ red_eltfp25519_1w_adx(other, a);
+ red_eltfp25519_1w_bmi2(c, a);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void add_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a,
+ uint64_t *const b)
+{
+ EltFp25519_1w_x64 other = { 0 };
+ add_eltfp25519_1w_adx(other, a, b);
+ add_eltfp25519_1w_bmi2(c, a, b);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void sub_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a,
+ uint64_t *const b)
+{
+ sub_eltfp25519_1w(c, a, b);
+}
+
+static inline void mul_a24_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a)
+{
+ mul_a24_eltfp25519_1w(c, a);
+}
+
+static inline void inv_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a)
+{
+ EltFp25519_1w_x64 other = { 0 };
+ inv_eltfp25519_1w_adx(other, a);
+ inv_eltfp25519_1w_bmi2(c, a);
+ assert(!memcmp(other, c, sizeof(other)));
+}
+
+static inline void fred_EltFp25519_1w_x64(uint64_t *const c)
+{
+ fred_eltfp25519_1w(c);
+}