Jet ed25519 point scalar multiplication.

This adds a jet for +scalarmult:ed:crypto. While previous jets could
just call math from the ed25519 library, scalarmult wasn't provided
by that library. This patch also translates an implementation of that
function from DEDIS' BSDed ed25519 golang library.
This commit is contained in:
Elliot Glaysher 2019-06-13 11:24:43 -07:00
parent 683de2ed52
commit e42ad8ca9d
6 changed files with 271 additions and 4 deletions

View File

@ -156,6 +156,7 @@
u3_noun u3wee_veri(u3_noun);
u3_noun u3wee_shar(u3_noun);
u3_noun u3wee_point_add(u3_noun);
u3_noun u3wee_scalarmult(u3_noun);
u3_noun u3wee_double_scalarmult(u3_noun);
u3_noun u3wee_scalarmult_base(u3_noun);

66
jets/e/ed_scalarmult.c Normal file
View File

@ -0,0 +1,66 @@
/* gen164/5/ed_scalarmult.c
**
*/
#include "all.h"
#include <ed25519.h>
#include "ge_additions.h"
/* functions
*/
u3_noun
u3qc_scalarmult(u3_atom a,
u3_atom b)
{
c3_y met_w;
met_w = u3r_met(3, a);
if (met_w > 32) {
return u3m_bail(c3__exit);
}
c3_y a_y[32];
memset(a_y, 0, 32);
u3r_bytes(0, met_w, a_y, a);
met_w = u3r_met(3, b);
if (met_w > 32) {
return u3m_bail(c3__exit);
}
c3_y b_y[32];
memset(b_y, 0, 32);
u3r_bytes(0, met_w, b_y, b);
ge_p3 B;
if (ge_frombytes_negate_vartime(&B, b_y) != 0) {
return u3m_bail(c3__exit);
}
// Undo the negation from above. See add_scalar.c in the ed25519 distro.
fe_neg(B.X, B.X);
fe_neg(B.T, B.T);
ge_p3 result;
ge_scalarmult(&result, a_y, &B);
c3_y output_y[32];
ge_p3_tobytes(output_y, &result);
return u3i_bytes(32, output_y);
}
u3_noun
u3wee_scalarmult(u3_noun cor)
{
u3_noun a, b;
if ( (c3n == u3r_mean(cor, u3x_sam_2, &a,
u3x_sam_3, &b, 0)) ||
(c3n == u3ud(a)) ||
(c3n == u3ud(b)) )
{
return u3m_bail(c3__exit);
} else {
return u3qc_scalarmult(a, b);
}
}

169
jets/e/ge_additions.c Normal file
View File

@ -0,0 +1,169 @@
// Group Element Additions
//
// Urbit uses the ge.h code from the ed25519 library, which was ported from the
// ref10 SUPERCOP public domain implementation. That implementation doesn't
// contain several functions needed for ring signatures.
//
// This file is does. The providence of this code starts with Adam Langley
// taking the SUPERCOP C implementation and producing an ed25519 implementation
// for in golang (https://godoc.org/golang.org/x/crypto/ed25519). (If you look
// at the go code, you'll see the comments are the same as the comments in the
// C implementation.)
//
// From there, the DEDIS group from ETH Zurich took that implementation and
// added the additional methods to make a generalized ECC point library. While
// their project as a whole is MPL, they deliberately left their ed25519
// implementation under the Go BSD-3 license:
// (https://github.com/dedis/kyber/blob/master/group/edwards25519/LICENSE)
//
// This file is a fairly straight translation from Go to C of DEDIS' additions,
// so this falls under the same license.
//
// ------
//
// Copyright (c) 2009 The Go Authors. 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.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER OR CONTRIBUTORS 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 "ge_additions.h"
#include <fe.h>
static unsigned char equal(signed char b, signed char c) {
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
}
static unsigned char negative(signed char b) {
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
}
void ge_cached_0(ge_cached* c) {
fe_1(c->YplusX);
fe_1(c->YminusX);
fe_1(c->Z);
fe_0(c->T2d);
}
void ge_cached_cmov(ge_cached* r, const ge_cached* u, int32_t b)
{
fe_cmov(r->YplusX, u->YplusX, b);
fe_cmov(r->YminusX, u->YminusX, b);
fe_cmov(r->Z, u->Z, b);
fe_cmov(r->T2d, u->T2d, b);
}
void ge_cached_neg(ge_cached* r, const ge_cached* t)
{
fe_copy(r->YplusX, t->YminusX);
fe_copy(r->YminusX, t->YplusX);
fe_copy(r->Z, t->Z);
fe_neg(r->T2d, t->T2d);
}
void select_cached(ge_cached* c, const ge_cached Ai[8], int32_t b)
{
int32_t is_negative = negative(b);
int32_t b_abs = b - (((-is_negative) & b) << 1);
ge_cached_0(c);
for (int32_t i = 0; i < 8; ++i) {
ge_cached_cmov(c, &Ai[i], equal(b_abs, i+1));
}
ge_cached minusC;
ge_cached_neg(&minusC, c);
ge_cached_cmov(c, &minusC, is_negative);
}
//
void ge_scalarmult(ge_p3* h, const unsigned char* a, const ge_p3* A)
{
signed char e[64];
int i;
ge_p1p1 t;
ge_p3 u;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
signed char carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
// compute cached array of multiples of A from 1A through 8A
ge_cached Ai[8];
ge_p3_to_cached(&Ai[0], A);
for (i = 0; i < 7; ++i) {
ge_add(&t, A, &Ai[i]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[i+1], &u);
}
// special case for exponent nybble i == 63
ge_p3_0(&u);
ge_cached c;
select_cached(&c, Ai, e[63]);
ge_add(&t, &u, &c);
ge_p2 r;
for (i = 62; i >= 0; i--) {
// t <<= 4
ge_p1p1_to_p2(&r, &t);
ge_p2_dbl(&t, &r);
ge_p1p1_to_p2(&r, &t);
ge_p2_dbl(&t, &r);
ge_p1p1_to_p2(&r, &t);
ge_p2_dbl(&t, &r);
ge_p1p1_to_p2(&r, &t);
ge_p2_dbl(&t, &r);
// Add next nyble
ge_p1p1_to_p3(&u, &t);
select_cached(&c, Ai, e[i]);
ge_add(&t, &u, &c);
}
ge_p1p1_to_p3(h, &t);
}

8
jets/e/ge_additions.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef GE_ADDITIONS_H
#define GE_ADDITIONS_H
#include <ge.h>
void ge_scalarmult(ge_p3* h, const unsigned char* a, const ge_p3* A);
#endif

View File

@ -178,19 +178,23 @@ static c3_c* _141_hex_coed__ed_shar_ha[] = {
static u3j_harm _141_hex_coed__ed_add_a[] =
{{".2", u3wee_point_add}, {}};
static u3j_harm _141_hex_coed__ed_scalarmult_a[] =
{{".2", u3wee_scalarmult}, {}};
static u3j_harm _141_hex_coed__ed_scalarmult_base_a[] =
{{".2", u3wee_scalarmult_base}, {}};
static u3j_harm _141_hex_coed__ed_double_scalarmult_a[] =
{{".2", u3wee_double_scalarmult}, {}};
static u3j_harm _141_hex_coed__ed_scalarmult_a[] =
{{".2", u3wee_scalarmult_base}, {}};
static u3j_core _141_hex_coed__ed_d[] =
{ { "sign", 7, _141_hex_coed__ed_sign_a, 0, _141_hex_coed__ed_sign_ha },
{ "puck", 7, _141_hex_coed__ed_puck_a, 0, _141_hex_coed__ed_puck_ha },
{ "veri", 7, _141_hex_coed__ed_veri_a, 0, _141_hex_coed__ed_veri_ha },
{ "shar", 7, _141_hex_coed__ed_shar_a, 0, _141_hex_coed__ed_shar_ha },
{ "add", 7, _141_hex_coed__ed_add_a, 0, 0 },
{ "scalarmult-base", 7, _141_hex_coed__ed_scalarmult_a, 0, 0 },
{ "scalarmult", 7, _141_hex_coed__ed_scalarmult_a, 0, 0 },
{ "scalarmult-base", 7, _141_hex_coed__ed_scalarmult_base_a, 0, 0 },
{ "double-scalarmult", 7, _141_hex_coed__ed_double_scalarmult_a, 0, 0 },
{}
};

View File

@ -138,6 +138,7 @@ jets_e_ed_src = [
'jets/e/ed_veri.c',
'jets/e/ed_shar.c',
'jets/e/ed_point_add.c',
'jets/e/ed_scalarmult.c',
'jets/e/ed_scalarmult_base.c',
'jets/e/ed_double_scalarmult.c'
]
@ -333,9 +334,27 @@ murmur3_dep = dependency('murmur3', version: '>=0.1.0', fallback: ['murmur3', 'm
secp256k1_dep = dependency('libsecp256k1', version: '>=0.1.0', fallback: ['secp256k1', 'secp256k1_dep'])
softfloat3_dep = dependency('softfloat3', version: '>=3.0.0', fallback: ['softfloat3', 'softfloat3_dep'])
# Our ge additions must be in their own library because they cannot be compiled
# with '-funsigned-char' since they rely on signed characters.
ge_additions_src = [
'jets/e/ge_additions.c',
]
ge_additions_include = include_directories('jets/e/')
ge_additions_lib = static_library('ge-additions',
sources: ge_additions_src,
include_directories: ge_additions_include,
c_args: ['-Wall'],
dependencies: ed25519_dep,
install: false)
gd_additions_dep = declare_dependency(link_with : ge_additions_lib)
deps = [argon2_dep,
curl_dep,
ed25519_dep,
gd_additions_dep,
gmp_dep,
libent_dep,
libh2o_dep,