]> source.dussan.org Git - rspamd.git/commitdiff
Add ed25519 reference implementation
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 29 Jan 2016 14:47:52 +0000 (14:47 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 29 Jan 2016 14:47:52 +0000 (14:47 +0000)
src/libcryptobox/CMakeLists.txt
src/libcryptobox/curve25519/fe.h
src/libcryptobox/ed25519/ed25519.c [new file with mode: 0644]
src/libcryptobox/ed25519/ed25519.h [new file with mode: 0644]
src/libcryptobox/ed25519/ref.c [new file with mode: 0644]

index 18736dc065a62c79b08abd1fd6ba8b745606a0df..874e945673cba295d259005968bab6db16c14aed 100644 (file)
@@ -13,6 +13,9 @@ SET(BLAKE2SRC ${CMAKE_CURRENT_SOURCE_DIR}/blake2/blake2.c
 SET(CURVESRC ${CMAKE_CURRENT_SOURCE_DIR}/curve25519/ref.c
                ${CMAKE_CURRENT_SOURCE_DIR}/curve25519/curve25519.c)
 
+SET(EDSRC ${CMAKE_CURRENT_SOURCE_DIR}/ed25519/ref.c
+               ${CMAKE_CURRENT_SOURCE_DIR}/ed25519/ed25519.c)
+
 SET(ASM_CODE "
        .macro TEST1 op
        \\op %eax, %eax
@@ -85,4 +88,4 @@ INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}")
 SET(LIBCRYPTOBOXSRC ${CMAKE_CURRENT_SOURCE_DIR}/cryptobox.c)
 
 SET(RSPAMD_CRYPTOBOX ${LIBCRYPTOBOXSRC} ${CHACHASRC} ${POLYSRC} ${SIPHASHSRC}
-       ${CURVESRC} ${BLAKE2SRC} PARENT_SCOPE)
+       ${CURVESRC} ${BLAKE2SRC} ${EDSRC} PARENT_SCOPE)
index 1c458965909004ac683d89fa45874fb75574a8ab..d5d8b93fd1ea1d6b9146ead806c48da9e2e61482 100644 (file)
@@ -114,6 +114,7 @@ void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *);
 void ge_scalarmult_base(ge_p3 *,const unsigned char *);
 void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *);
 void ge_scalarmult_vartime(ge_p3 *,const unsigned char *,const ge_p3 *);
+int verify_32(const unsigned char *x, const unsigned char *y);
 
 /*
 The set of scalars is \Z/l
diff --git a/src/libcryptobox/ed25519/ed25519.c b/src/libcryptobox/ed25519/ed25519.c
new file mode 100644 (file)
index 0000000..776ac4e
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "cryptobox.h"
+#include "ed25519.h"
+#include "platform_config.h"
+
+extern unsigned long cpu_config;
+
+typedef struct ed25519_impl_s {
+       unsigned long cpu_flags;
+       const char *desc;
+
+       void (*keypair) (unsigned char *pk, unsigned char *sk);
+       void (*sign) (unsigned char *sig, unsigned long long *siglen_p,
+                       const unsigned char *m, unsigned long long mlen,
+                       const unsigned char *sk);
+       bool (*verify) (const unsigned char *sig,
+                       const unsigned char *m,
+                       unsigned long long mlen,
+                       const unsigned char *pk);
+} ed25519_impl_t;
+
+#define ED25519_DECLARE(ext) \
+    void ed_keypair_##ext(unsigned char *pk, unsigned char *sk); \
+    void ed_sign_##ext(unsigned char *sig, unsigned long long *siglen_p, \
+        const unsigned char *m, unsigned long long mlen, \
+        const unsigned char *sk); \
+    bool ed_verify_##ext(const unsigned char *sig, \
+        const unsigned char *m, \
+        unsigned long long mlen, \
+        const unsigned char *pk)
+
+#define ED25519_IMPL(cpuflags, desc, ext) \
+    {(cpuflags), desc, ed_keypair_##ext, ed_sign_##ext, ed_verify_##ext}
+
+ED25519_DECLARE(ref);
+#define ED25519_REF ED25519_IMPL(0, "ref", ref)
+
+static const ed25519_impl_t ed25519_list[] = {
+               ED25519_REF,
+};
+
+static const ed25519_impl_t *ed25519_opt = &ed25519_list[0];
+
+const char*
+ed25519_load (void)
+{
+       guint i;
+
+       if (cpu_config != 0) {
+               for (i = 0; i < G_N_ELEMENTS(ed25519_list); i++) {
+                       if (ed25519_list[i].cpu_flags & cpu_config) {
+                               ed25519_opt = &ed25519_list[i];
+                               break;
+                       }
+               }
+       }
+
+
+       return ed25519_opt->desc;
+}
+
+void
+ed25519_keypair (unsigned char *pk, unsigned char *sk)
+{
+       ed25519_opt->keypair (pk, sk);
+}
+
+void
+ed25519_sign (unsigned char *sig, unsigned long long *siglen_p,
+               const unsigned char *m, unsigned long long mlen,
+               const unsigned char *sk)
+{
+       ed25519_opt->sign (sig, siglen_p, m, mlen, sk);
+}
+
+bool
+ed25519_verify (const unsigned char *sig,
+               const unsigned char *m,
+               unsigned long long mlen,
+               const unsigned char *pk)
+{
+       return ed25519_opt->verify (sig, m, mlen, pk);
+}
diff --git a/src/libcryptobox/ed25519/ed25519.h b/src/libcryptobox/ed25519/ed25519.h
new file mode 100644 (file)
index 0000000..3481478
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_LIBCRYPTOBOX_ED25519_ED25519_H_
+#define SRC_LIBCRYPTOBOX_ED25519_ED25519_H_
+
+#include "config.h"
+#include <stdbool.h>
+
+const char* ed25519_load (void);
+void ed25519_keypair (unsigned char *pk, unsigned char *sk);
+void ed25519_sign (unsigned char *sig, unsigned long long *siglen_p,
+               const unsigned char *m, unsigned long long mlen,
+               const unsigned char *sk);
+bool ed25519_verify (const unsigned char *sig,
+               const unsigned char *m,
+               unsigned long long mlen,
+               const unsigned char *pk);
+
+#endif /* SRC_LIBCRYPTOBOX_ED25519_ED25519_H_ */
diff --git a/src/libcryptobox/ed25519/ref.c b/src/libcryptobox/ed25519/ref.c
new file mode 100644 (file)
index 0000000..a1053c6
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2013-2016
+ * Frank Denis <j at pureftpd dot org>
+ * Vsevolod Stakhov
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+#include "ed25519.h"
+#include "cryptobox.h"
+#include "../curve25519/fe.h"
+#include "ottery.h"
+#include <openssl/evp.h> /* SHA512 */
+
+static int
+ed_seed_keypair_ref (unsigned char *pk, unsigned char *sk,
+               const unsigned char *seed)
+{
+       ge_p3 A;
+
+       memmove (sk, seed, 32);
+       sk[0] &= 248;
+       sk[31] &= 63;
+       sk[31] |= 64;
+
+       ge_scalarmult_base (&A, sk);
+       ge_p3_tobytes (pk, &A);
+
+       memmove (sk, seed, 32);
+       memmove (sk + 32, pk, 32);
+
+       return 0;
+}
+
+int
+ed_keypair_ref (unsigned char *pk, unsigned char *sk)
+{
+       unsigned char seed[rspamd_cryptobox_HASHBYTES];
+       int ret;
+
+       ottery_rand_bytes (seed, sizeof (seed));
+       rspamd_cryptobox_hash (seed, seed, sizeof (seed), NULL, 0);
+       ret = ed_seed_keypair_ref (pk, sk, seed);
+       rspamd_explicit_memzero (seed, sizeof (seed));
+
+       return ret;
+}
+
+int
+ed_verify_ref(const unsigned char *sig, const unsigned char *m,
+               unsigned long long mlen, const unsigned char *pk)
+{
+       EVP_MD_CTX sha_ctx;
+       unsigned char h[64];
+       unsigned char rcheck[32];
+       unsigned int i;
+       unsigned char d = 0;
+       ge_p3 A;
+       ge_p2 R;
+
+       if (sig[63] & 224) {
+               return -1;
+       }
+       if (ge_frombytes_negate_vartime (&A, pk) != 0) {
+               return -1;
+       }
+       for (i = 0; i < 32; ++i) {
+               d |= pk[i];
+       }
+       if (d == 0) {
+               return -1;
+       }
+
+       g_assert (EVP_DigestInit (&sha_ctx, EVP_sha512()) == 1);
+       EVP_DigestUpdate (&sha_ctx, sig, 32);
+       EVP_DigestUpdate (&sha_ctx, pk, 32);
+       EVP_DigestUpdate (&sha_ctx, m, mlen);
+       EVP_DigestFinal (&sha_ctx, h, NULL);
+       sc_reduce (h);
+
+       ge_double_scalarmult_vartime (&R, h, &A, sig + 32);
+       ge_tobytes (rcheck, &R);
+
+       return verify_32 (rcheck, sig) | (-(rcheck == sig));
+}
+
+void
+ed_sign_ref(unsigned char *sig, unsigned long long *siglen_p,
+               const unsigned char *m, unsigned long long mlen,
+               const unsigned char *sk)
+{
+       EVP_MD_CTX sha_ctx;
+       unsigned char az[64];
+       unsigned char nonce[64];
+       unsigned char hram[64];
+       ge_p3 R;
+
+       g_assert (EVP_DigestInit (&sha_ctx, EVP_sha512()) == 1);
+       EVP_DigestUpdate (&sha_ctx, sk, 32);
+       EVP_DigestFinal (&sha_ctx, az, NULL);
+       az[0] &= 248;
+       az[31] &= 63;
+       az[31] |= 64;
+
+       g_assert (EVP_DigestInit (&sha_ctx, EVP_sha512()) == 1);
+       EVP_DigestUpdate (&sha_ctx, az + 32, 32);
+       EVP_DigestUpdate (&sha_ctx, m, mlen);
+       EVP_DigestFinal (&sha_ctx, nonce, NULL);
+
+       memmove (sig + 32, sk + 32, 32);
+
+       sc_reduce (nonce);
+       ge_scalarmult_base (&R, nonce);
+       ge_p3_tobytes (sig, &R);
+
+       g_assert (EVP_DigestInit (&sha_ctx, EVP_sha512()) == 1);
+       EVP_DigestUpdate (&sha_ctx, sig, 64);
+       EVP_DigestUpdate (&sha_ctx, m, mlen);
+       EVP_DigestFinal (&sha_ctx, hram, NULL);
+
+       sc_reduce (hram);
+       sc_muladd (sig + 32, hram, az, nonce);
+
+       rspamd_explicit_memzero (az, sizeof (az));
+
+       if (siglen_p != NULL) {
+               *siglen_p = 64U;
+       }
+}