Import: ocaml-secp256k1 in vendors
This commit is contained in:
parent
19843b96b0
commit
9adee55234
@ -469,6 +469,10 @@ opam:46:tezos-node:
|
||||
variables:
|
||||
package: tezos-node
|
||||
|
||||
opam:46:secp256k1-internal:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: secp256k1-internal
|
||||
|
||||
##END_OPAM##
|
||||
|
||||
|
3
vendors/ocaml-secp256k1-internal/.gitignore
vendored
Normal file
3
vendors/ocaml-secp256k1-internal/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
_build
|
||||
*.install
|
||||
**/.merlin
|
5
vendors/ocaml-secp256k1-internal/Makefile
vendored
Normal file
5
vendors/ocaml-secp256k1-internal/Makefile
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
all:
|
||||
jbuilder build @install @runtest
|
||||
|
||||
clean:
|
||||
rm -rf _build
|
3
vendors/ocaml-secp256k1-internal/config/config.ml
vendored
Normal file
3
vendors/ocaml-secp256k1-internal/config/config.ml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
external ml_get_hw_identifier : unit -> string = "ml_get_hw_identifier"
|
||||
|
||||
let hw_identifier = ml_get_hw_identifier
|
1
vendors/ocaml-secp256k1-internal/config/config.mli
vendored
Normal file
1
vendors/ocaml-secp256k1-internal/config/config.mli
vendored
Normal file
@ -0,0 +1 @@
|
||||
val hw_identifier : unit -> string
|
15
vendors/ocaml-secp256k1-internal/config/config_stubs.c
vendored
Normal file
15
vendors/ocaml-secp256k1-internal/config/config_stubs.c
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/memory.h>
|
||||
#include <caml/alloc.h>
|
||||
|
||||
CAMLprim value ml_get_hw_identifier(value unit) {
|
||||
CAMLparam1(unit);
|
||||
CAMLlocal1(res);
|
||||
|
||||
struct utsname buf;
|
||||
uname(&buf);
|
||||
res = caml_copy_string(buf.machine);
|
||||
CAMLreturn(res);
|
||||
}
|
38
vendors/ocaml-secp256k1-internal/config/discover.ml
vendored
Normal file
38
vendors/ocaml-secp256k1-internal/config/discover.ml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
let output_defines ppf symbols =
|
||||
let pp_sep ppf () = Format.pp_print_char ppf ' ' in
|
||||
let pp_symbol ppf sym =
|
||||
match sym with
|
||||
| None -> ()
|
||||
| Some (sym, None) -> Format.fprintf ppf "-D%s" sym
|
||||
| Some (sym, Some def) -> Format.fprintf ppf "-D%s=%s" sym def in
|
||||
let pp = Format.pp_print_list ~pp_sep pp_symbol in
|
||||
Format.fprintf ppf "(%a)%!" pp symbols
|
||||
|
||||
let hw = Config.hw_identifier ()
|
||||
let sixtyfour = Sys.word_size = 64
|
||||
|
||||
let symbols = [
|
||||
(if sixtyfour then Some ("HAVE___INT128", None) else None) ;
|
||||
(if hw = "x86_64" then Some ("USE_ASM_X86_64", None) else None) ;
|
||||
Some ((if sixtyfour then "USE_SCALAR_4X64" else "USE_SCALAR_8X32"), None) ;
|
||||
Some ((if sixtyfour then "USE_FIELD_5X52" else "USE_FIELD_10X26"), None) ;
|
||||
Some ("USE_NUM_GMP", None) ;
|
||||
Some ("USE_SCALAR_INV_NUM", None) ;
|
||||
Some ("USE_FIELD_INV_NUM", None) ;
|
||||
Some ("SECP256K1_INLINE", Some "inline") ;
|
||||
Some ("SECP256K1_RESTRICT", Some "restrict") ;
|
||||
|
||||
Some ("SECP256K1_TAG_PUBKEY_EVEN", Some "0x02") ;
|
||||
Some ("SECP256K1_TAG_PUBKEY_ODD", Some "0x03") ;
|
||||
Some ("SECP256K1_TAG_PUBKEY_UNCOMPRESSED", Some "0x04") ;
|
||||
Some ("SECP256K1_TAG_PUBKEY_HYBRID_EVEN", Some "0x06") ;
|
||||
Some ("SECP256K1_TAG_PUBKEY_HYBRID_ODD", Some "0x07") ;
|
||||
|
||||
Some ("ENABLE_MODULE_RECOVERY", None) ;
|
||||
]
|
||||
|
||||
let () =
|
||||
let oc = open_out "c_flags.sexp" in
|
||||
let ppf = Format.formatter_of_out_channel oc in
|
||||
output_defines ppf symbols ;
|
||||
close_out oc
|
11
vendors/ocaml-secp256k1-internal/config/jbuild
vendored
Normal file
11
vendors/ocaml-secp256k1-internal/config/jbuild
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(library
|
||||
((name config)
|
||||
(modules config)
|
||||
(c_names (config_stubs))))
|
||||
|
||||
(executable
|
||||
((name discover)
|
||||
(modules discover)
|
||||
(libraries (config))))
|
19
vendors/ocaml-secp256k1-internal/secp256k1-internal.opam
vendored
Normal file
19
vendors/ocaml-secp256k1-internal/secp256k1-internal.opam
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
opam-version: "1.2"
|
||||
name: "secp256k1-internal"
|
||||
version: "0.1"
|
||||
authors: "Vincent Bernardoff <vb@luminar.eu.org>"
|
||||
maintainer: "Vincent Bernardoff <vb@luminar.eu.org>"
|
||||
homepage: "https://github.com/vbmithr/ocaml-secp256k1-internal"
|
||||
bug-reports: "https://github.com/vbmithr/ocaml-secp256k1-internal/issues"
|
||||
dev-repo: "git://github.com/vbmithr/ocaml-secp256k1-internal"
|
||||
|
||||
available: [
|
||||
ocaml-version >= "4.03.0"
|
||||
]
|
||||
|
||||
build: [ "jbuilder" "build" "-j" jobs "-p" name "@install" ]
|
||||
depends: [
|
||||
"conf-gmp" {build}
|
||||
"jbuilder" {build & >= "1.0+beta19.1"}
|
||||
"cstruct" {>= "3.2.1"}
|
||||
]
|
33
vendors/ocaml-secp256k1-internal/src/basic-config.h
vendored
Normal file
33
vendors/ocaml-secp256k1-internal/src/basic-config.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_BASIC_CONFIG_H
|
||||
#define SECP256K1_BASIC_CONFIG_H
|
||||
|
||||
#ifdef USE_BASIC_CONFIG
|
||||
|
||||
#undef USE_ASM_X86_64
|
||||
#undef USE_ENDOMORPHISM
|
||||
#undef USE_FIELD_10X26
|
||||
#undef USE_FIELD_5X52
|
||||
#undef USE_FIELD_INV_BUILTIN
|
||||
#undef USE_FIELD_INV_NUM
|
||||
#undef USE_NUM_GMP
|
||||
#undef USE_NUM_NONE
|
||||
#undef USE_SCALAR_4X64
|
||||
#undef USE_SCALAR_8X32
|
||||
#undef USE_SCALAR_INV_BUILTIN
|
||||
#undef USE_SCALAR_INV_NUM
|
||||
|
||||
#define USE_NUM_NONE 1
|
||||
#define USE_FIELD_INV_BUILTIN 1
|
||||
#define USE_SCALAR_INV_BUILTIN 1
|
||||
#define USE_FIELD_10X26 1
|
||||
#define USE_SCALAR_8X32 1
|
||||
|
||||
#endif /* USE_BASIC_CONFIG */
|
||||
|
||||
#endif /* SECP256K1_BASIC_CONFIG_H */
|
82
vendors/ocaml-secp256k1-internal/src/bench.h
vendored
Normal file
82
vendors/ocaml-secp256k1-internal/src/bench.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_BENCH_H
|
||||
#define SECP256K1_BENCH_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sys/time.h"
|
||||
|
||||
static double gettimedouble(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_usec * 0.000001 + tv.tv_sec;
|
||||
}
|
||||
|
||||
void print_number(double x) {
|
||||
double y = x;
|
||||
int c = 0;
|
||||
if (y < 0.0) {
|
||||
y = -y;
|
||||
}
|
||||
while (y > 0 && y < 100.0) {
|
||||
y *= 10.0;
|
||||
c++;
|
||||
}
|
||||
printf("%.*f", c, x);
|
||||
}
|
||||
|
||||
void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
|
||||
int i;
|
||||
double min = HUGE_VAL;
|
||||
double sum = 0.0;
|
||||
double max = 0.0;
|
||||
for (i = 0; i < count; i++) {
|
||||
double begin, total;
|
||||
if (setup != NULL) {
|
||||
setup(data);
|
||||
}
|
||||
begin = gettimedouble();
|
||||
benchmark(data);
|
||||
total = gettimedouble() - begin;
|
||||
if (teardown != NULL) {
|
||||
teardown(data);
|
||||
}
|
||||
if (total < min) {
|
||||
min = total;
|
||||
}
|
||||
if (total > max) {
|
||||
max = total;
|
||||
}
|
||||
sum += total;
|
||||
}
|
||||
printf("%s: min ", name);
|
||||
print_number(min * 1000000.0 / iter);
|
||||
printf("us / avg ");
|
||||
print_number((sum / count) * 1000000.0 / iter);
|
||||
printf("us / max ");
|
||||
print_number(max * 1000000.0 / iter);
|
||||
printf("us\n");
|
||||
}
|
||||
|
||||
int have_flag(int argc, char** argv, char *flag) {
|
||||
char** argm = argv + argc;
|
||||
argv++;
|
||||
if (argv == argm) {
|
||||
return 1;
|
||||
}
|
||||
while (argv != NULL && argv != argm) {
|
||||
if (strcmp(*argv, flag) == 0) {
|
||||
return 1;
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_BENCH_H */
|
54
vendors/ocaml-secp256k1-internal/src/ecdh.h
vendored
Normal file
54
vendors/ocaml-secp256k1-internal/src/ecdh.h
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_MODULE_ECDH_MAIN_H
|
||||
#define SECP256K1_MODULE_ECDH_MAIN_H
|
||||
|
||||
#include "secp256k1_ecdh.h"
|
||||
#include "ecmult_const_impl.h"
|
||||
|
||||
int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) {
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
secp256k1_gej res;
|
||||
secp256k1_ge pt;
|
||||
secp256k1_scalar s;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(result != NULL);
|
||||
ARG_CHECK(point != NULL);
|
||||
ARG_CHECK(scalar != NULL);
|
||||
|
||||
secp256k1_pubkey_load(ctx, &pt, point);
|
||||
secp256k1_scalar_set_b32(&s, scalar, &overflow);
|
||||
if (overflow || secp256k1_scalar_is_zero(&s)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
unsigned char x[32];
|
||||
unsigned char y[1];
|
||||
secp256k1_sha256 sha;
|
||||
|
||||
secp256k1_ecmult_const(&res, &pt, &s);
|
||||
secp256k1_ge_set_gej(&pt, &res);
|
||||
/* Compute a hash of the point in compressed form
|
||||
* Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not
|
||||
* expect its output to be secret and has a timing sidechannel. */
|
||||
secp256k1_fe_normalize(&pt.x);
|
||||
secp256k1_fe_normalize(&pt.y);
|
||||
secp256k1_fe_get_b32(x, &pt.x);
|
||||
y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y);
|
||||
|
||||
secp256k1_sha256_initialize(&sha);
|
||||
secp256k1_sha256_write(&sha, y, sizeof(y));
|
||||
secp256k1_sha256_write(&sha, x, sizeof(x));
|
||||
secp256k1_sha256_finalize(&sha, result);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
secp256k1_scalar_clear(&s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_MODULE_ECDH_MAIN_H */
|
21
vendors/ocaml-secp256k1-internal/src/ecdsa.h
vendored
Normal file
21
vendors/ocaml-secp256k1-internal/src/ecdsa.h
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECDSA_H
|
||||
#define SECP256K1_ECDSA_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
|
||||
|
||||
#endif /* SECP256K1_ECDSA_H */
|
313
vendors/ocaml-secp256k1-internal/src/ecdsa_impl.h
vendored
Normal file
313
vendors/ocaml-secp256k1-internal/src/ecdsa_impl.h
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#ifndef SECP256K1_ECDSA_IMPL_H
|
||||
#define SECP256K1_ECDSA_IMPL_H
|
||||
|
||||
#include "scalar.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "ecdsa.h"
|
||||
|
||||
/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
|
||||
* sage: for t in xrange(1023, -1, -1):
|
||||
* .. p = 2**256 - 2**32 - t
|
||||
* .. if p.is_prime():
|
||||
* .. print '%x'%p
|
||||
* .. break
|
||||
* 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
|
||||
* sage: a = 0
|
||||
* sage: b = 7
|
||||
* sage: F = FiniteField (p)
|
||||
* sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
|
||||
* 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
|
||||
*/
|
||||
static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
|
||||
0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL
|
||||
);
|
||||
|
||||
/** Difference between field and order, values 'p' and 'n' values defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
||||
* sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||
* sage: a = 0
|
||||
* sage: b = 7
|
||||
* sage: F = FiniteField (p)
|
||||
* sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
|
||||
* '14551231950b75fc4402da1722fc9baee'
|
||||
*/
|
||||
static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
|
||||
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
|
||||
);
|
||||
|
||||
static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) {
|
||||
int lenleft, b1;
|
||||
size_t ret = 0;
|
||||
if (*sigp >= sigend) {
|
||||
return -1;
|
||||
}
|
||||
b1 = *((*sigp)++);
|
||||
if (b1 == 0xFF) {
|
||||
/* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */
|
||||
return -1;
|
||||
}
|
||||
if ((b1 & 0x80) == 0) {
|
||||
/* X.690-0207 8.1.3.4 short form length octets */
|
||||
return b1;
|
||||
}
|
||||
if (b1 == 0x80) {
|
||||
/* Indefinite length is not allowed in DER. */
|
||||
return -1;
|
||||
}
|
||||
/* X.690-207 8.1.3.5 long form length octets */
|
||||
lenleft = b1 & 0x7F;
|
||||
if (lenleft > sigend - *sigp) {
|
||||
return -1;
|
||||
}
|
||||
if (**sigp == 0) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
return -1;
|
||||
}
|
||||
if ((size_t)lenleft > sizeof(size_t)) {
|
||||
/* The resulting length would exceed the range of a size_t, so
|
||||
* certainly longer than the passed array size.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
while (lenleft > 0) {
|
||||
ret = (ret << 8) | **sigp;
|
||||
if (ret + lenleft > (size_t)(sigend - *sigp)) {
|
||||
/* Result exceeds the length of the passed array. */
|
||||
return -1;
|
||||
}
|
||||
(*sigp)++;
|
||||
lenleft--;
|
||||
}
|
||||
if (ret < 128) {
|
||||
/* Not the shortest possible length encoding. */
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) {
|
||||
int overflow = 0;
|
||||
unsigned char ra[32] = {0};
|
||||
int rlen;
|
||||
|
||||
if (*sig == sigend || **sig != 0x02) {
|
||||
/* Not a primitive integer (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
(*sig)++;
|
||||
rlen = secp256k1_der_read_len(sig, sigend);
|
||||
if (rlen <= 0 || (*sig) + rlen > sigend) {
|
||||
/* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) {
|
||||
/* Excessive 0x00 padding. */
|
||||
return 0;
|
||||
}
|
||||
if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) {
|
||||
/* Excessive 0xFF padding. */
|
||||
return 0;
|
||||
}
|
||||
if ((**sig & 0x80) == 0x80) {
|
||||
/* Negative. */
|
||||
overflow = 1;
|
||||
}
|
||||
while (rlen > 0 && **sig == 0) {
|
||||
/* Skip leading zero bytes */
|
||||
rlen--;
|
||||
(*sig)++;
|
||||
}
|
||||
if (rlen > 32) {
|
||||
overflow = 1;
|
||||
}
|
||||
if (!overflow) {
|
||||
memcpy(ra + 32 - rlen, *sig, rlen);
|
||||
secp256k1_scalar_set_b32(r, ra, &overflow);
|
||||
}
|
||||
if (overflow) {
|
||||
secp256k1_scalar_set_int(r, 0);
|
||||
}
|
||||
(*sig) += rlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) {
|
||||
const unsigned char *sigend = sig + size;
|
||||
int rlen;
|
||||
if (sig == sigend || *(sig++) != 0x30) {
|
||||
/* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */
|
||||
return 0;
|
||||
}
|
||||
rlen = secp256k1_der_read_len(&sig, sigend);
|
||||
if (rlen < 0 || sig + rlen > sigend) {
|
||||
/* Tuple exceeds bounds */
|
||||
return 0;
|
||||
}
|
||||
if (sig + rlen != sigend) {
|
||||
/* Garbage after tuple. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!secp256k1_der_parse_integer(rr, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
if (!secp256k1_der_parse_integer(rs, &sig, sigend)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig != sigend) {
|
||||
/* Trailing garbage inside tuple. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) {
|
||||
unsigned char r[33] = {0}, s[33] = {0};
|
||||
unsigned char *rp = r, *sp = s;
|
||||
size_t lenR = 33, lenS = 33;
|
||||
secp256k1_scalar_get_b32(&r[1], ar);
|
||||
secp256k1_scalar_get_b32(&s[1], as);
|
||||
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
|
||||
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
|
||||
if (*size < 6+lenS+lenR) {
|
||||
*size = 6 + lenS + lenR;
|
||||
return 0;
|
||||
}
|
||||
*size = 6 + lenS + lenR;
|
||||
sig[0] = 0x30;
|
||||
sig[1] = 4 + lenS + lenR;
|
||||
sig[2] = 0x02;
|
||||
sig[3] = lenR;
|
||||
memcpy(sig+4, rp, lenR);
|
||||
sig[4+lenR] = 0x02;
|
||||
sig[5+lenR] = lenS;
|
||||
memcpy(sig+lenR+6, sp, lenS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar sn, u1, u2;
|
||||
#if !defined(EXHAUSTIVE_TEST_ORDER)
|
||||
secp256k1_fe xr;
|
||||
#endif
|
||||
secp256k1_gej pubkeyj;
|
||||
secp256k1_gej pr;
|
||||
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_inverse_var(&sn, sigs);
|
||||
secp256k1_scalar_mul(&u1, &sn, message);
|
||||
secp256k1_scalar_mul(&u2, &sn, sigr);
|
||||
secp256k1_gej_set_ge(&pubkeyj, pubkey);
|
||||
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
|
||||
if (secp256k1_gej_is_infinity(&pr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
{
|
||||
secp256k1_scalar computed_r;
|
||||
secp256k1_ge pr_ge;
|
||||
secp256k1_ge_set_gej(&pr_ge, &pr);
|
||||
secp256k1_fe_normalize(&pr_ge.x);
|
||||
|
||||
secp256k1_fe_get_b32(c, &pr_ge.x);
|
||||
secp256k1_scalar_set_b32(&computed_r, c, NULL);
|
||||
return secp256k1_scalar_eq(sigr, &computed_r);
|
||||
}
|
||||
#else
|
||||
secp256k1_scalar_get_b32(c, sigr);
|
||||
secp256k1_fe_set_b32(&xr, c);
|
||||
|
||||
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
||||
* in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p),
|
||||
* compute the remainder modulo n, and compare it to xr. However:
|
||||
*
|
||||
* xr == X(pr) mod n
|
||||
* <=> exists h. (xr + h * n < p && xr + h * n == X(pr))
|
||||
* [Since 2 * n > p, h can only be 0 or 1]
|
||||
* <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr))
|
||||
* [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p]
|
||||
* <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p)
|
||||
* [Multiplying both sides of the equations by pr.z^2 mod p]
|
||||
* <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x)
|
||||
*
|
||||
* Thus, we can avoid the inversion, but we have to check both cases separately.
|
||||
* secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test.
|
||||
*/
|
||||
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
|
||||
/* xr * pr.z^2 mod p == pr.x, so the signature is valid. */
|
||||
return 1;
|
||||
}
|
||||
if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
/* xr + n >= p, so we can skip testing the second case. */
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe);
|
||||
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
|
||||
/* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
|
||||
unsigned char b[32];
|
||||
secp256k1_gej rp;
|
||||
secp256k1_ge r;
|
||||
secp256k1_scalar n;
|
||||
int overflow = 0;
|
||||
|
||||
secp256k1_ecmult_gen(ctx, &rp, nonce);
|
||||
secp256k1_ge_set_gej(&r, &rp);
|
||||
secp256k1_fe_normalize(&r.x);
|
||||
secp256k1_fe_normalize(&r.y);
|
||||
secp256k1_fe_get_b32(b, &r.x);
|
||||
secp256k1_scalar_set_b32(sigr, b, &overflow);
|
||||
/* These two conditions should be checked before calling */
|
||||
VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr));
|
||||
VERIFY_CHECK(overflow == 0);
|
||||
|
||||
if (recid) {
|
||||
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
|
||||
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
|
||||
*/
|
||||
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
}
|
||||
secp256k1_scalar_mul(&n, sigr, seckey);
|
||||
secp256k1_scalar_add(&n, &n, message);
|
||||
secp256k1_scalar_inverse(sigs, nonce);
|
||||
secp256k1_scalar_mul(sigs, sigs, &n);
|
||||
secp256k1_scalar_clear(&n);
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
if (secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_scalar_is_high(sigs)) {
|
||||
secp256k1_scalar_negate(sigs, sigs);
|
||||
if (recid) {
|
||||
*recid ^= 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECDSA_IMPL_H */
|
25
vendors/ocaml-secp256k1-internal/src/eckey.h
vendored
Normal file
25
vendors/ocaml-secp256k1-internal/src/eckey.h
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECKEY_H
|
||||
#define SECP256K1_ECKEY_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecmult_gen.h"
|
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size);
|
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
|
||||
|
||||
#endif /* SECP256K1_ECKEY_H */
|
100
vendors/ocaml-secp256k1-internal/src/eckey_impl.h
vendored
Normal file
100
vendors/ocaml-secp256k1-internal/src/eckey_impl.h
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECKEY_IMPL_H
|
||||
#define SECP256K1_ECKEY_IMPL_H
|
||||
|
||||
#include "eckey.h"
|
||||
|
||||
#include "scalar.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
|
||||
if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
|
||||
secp256k1_fe x;
|
||||
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
|
||||
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
|
||||
secp256k1_fe x, y;
|
||||
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_ge_set_xy(elem, &x, &y);
|
||||
if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) &&
|
||||
secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
|
||||
return 0;
|
||||
}
|
||||
return secp256k1_ge_is_valid_var(elem);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) {
|
||||
if (secp256k1_ge_is_infinity(elem)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_normalize_var(&elem->x);
|
||||
secp256k1_fe_normalize_var(&elem->y);
|
||||
secp256k1_fe_get_b32(&pub[1], &elem->x);
|
||||
if (compressed) {
|
||||
*size = 33;
|
||||
pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
|
||||
} else {
|
||||
*size = 65;
|
||||
pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED;
|
||||
secp256k1_fe_get_b32(&pub[33], &elem->y);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar_add(key, key, tweak);
|
||||
if (secp256k1_scalar_is_zero(key)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_gej pt;
|
||||
secp256k1_scalar one;
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak);
|
||||
|
||||
if (secp256k1_gej_is_infinity(&pt)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_ge_set_gej(key, &pt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) {
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_mul(key, key, tweak);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) {
|
||||
secp256k1_scalar zero;
|
||||
secp256k1_gej pt;
|
||||
if (secp256k1_scalar_is_zero(tweak)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_int(&zero, 0);
|
||||
secp256k1_gej_set_ge(&pt, key);
|
||||
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero);
|
||||
secp256k1_ge_set_gej(key, &pt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECKEY_IMPL_H */
|
47
vendors/ocaml-secp256k1-internal/src/ecmult.h
vendored
Normal file
47
vendors/ocaml-secp256k1-internal/src/ecmult.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_H
|
||||
#define SECP256K1_ECMULT_H
|
||||
|
||||
#include "num.h"
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
#include "scratch.h"
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*P + b*G: */
|
||||
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */
|
||||
#endif
|
||||
} secp256k1_ecmult_context;
|
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb);
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
|
||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb);
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
|
||||
|
||||
/** Double multiply: R = na*A + ng*G */
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
|
||||
|
||||
typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
|
||||
|
||||
/**
|
||||
* Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai.
|
||||
* Chooses the right algorithm for a given number of points and scratch space
|
||||
* size. Resets and overwrites the given scratch space. If the points do not
|
||||
* fit in the scratch space the algorithm is repeatedly run with batches of
|
||||
* points.
|
||||
* Returns: 1 on success (including when inp_g_sc is NULL and n is 0)
|
||||
* 0 if there is not enough scratch space for a single point or
|
||||
* callback returns 0
|
||||
*/
|
||||
static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_H */
|
15
vendors/ocaml-secp256k1-internal/src/ecmult_const.h
vendored
Normal file
15
vendors/ocaml-secp256k1-internal/src/ecmult_const.h
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_CONST_H
|
||||
#define SECP256K1_ECMULT_CONST_H
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_CONST_H */
|
233
vendors/ocaml-secp256k1-internal/src/ecmult_const_impl.h
vendored
Normal file
233
vendors/ocaml-secp256k1-internal/src/ecmult_const_impl.h
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_CONST_IMPL_H
|
||||
#define SECP256K1_ECMULT_CONST_IMPL_H
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_const.h"
|
||||
#include "ecmult_impl.h"
|
||||
|
||||
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */
|
||||
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
|
||||
int m; \
|
||||
int abs_n = (n) * (((n) > 0) * 2 - 1); \
|
||||
int idx_n = abs_n / 2; \
|
||||
secp256k1_fe neg_y; \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
|
||||
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
|
||||
/* This loop is used to avoid secret data in array indices. See
|
||||
* the comment in ecmult_gen_impl.h for rationale. */ \
|
||||
secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \
|
||||
secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \
|
||||
} \
|
||||
(r)->infinity = 0; \
|
||||
secp256k1_fe_negate(&neg_y, &(r)->y, 1); \
|
||||
secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/** Convert a number to WNAF notation.
|
||||
* The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val.
|
||||
* It has the following guarantees:
|
||||
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w)
|
||||
* - each wnaf[i] is nonzero
|
||||
* - the number of words set is always WNAF_SIZE(w) + 1
|
||||
*
|
||||
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar
|
||||
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.)
|
||||
* CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003
|
||||
*
|
||||
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
|
||||
*/
|
||||
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
|
||||
int global_sign;
|
||||
int skew = 0;
|
||||
int word = 0;
|
||||
|
||||
/* 1 2 3 */
|
||||
int u_last;
|
||||
int u;
|
||||
|
||||
int flip;
|
||||
int bit;
|
||||
secp256k1_scalar neg_s;
|
||||
int not_neg_one;
|
||||
/* Note that we cannot handle even numbers by negating them to be odd, as is
|
||||
* done in other implementations, since if our scalars were specified to have
|
||||
* width < 256 for performance reasons, their negations would have width 256
|
||||
* and we'd lose any performance benefit. Instead, we use a technique from
|
||||
* Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
|
||||
* or 2 (for odd) to the number we are encoding, returning a skew value indicating
|
||||
* this, and having the caller compensate after doing the multiplication. */
|
||||
|
||||
/* Negative numbers will be negated to keep their bit representation below the maximum width */
|
||||
flip = secp256k1_scalar_is_high(&s);
|
||||
/* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
|
||||
bit = flip ^ !secp256k1_scalar_is_even(&s);
|
||||
/* We check for negative one, since adding 2 to it will cause an overflow */
|
||||
secp256k1_scalar_negate(&neg_s, &s);
|
||||
not_neg_one = !secp256k1_scalar_is_one(&neg_s);
|
||||
secp256k1_scalar_cadd_bit(&s, bit, not_neg_one);
|
||||
/* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
|
||||
* that we added two to it and flipped it. In fact for -1 these operations are
|
||||
* identical. We only flipped, but since skewing is required (in the sense that
|
||||
* the skew must be 1 or 2, never zero) and flipping is not, we need to change
|
||||
* our flags to claim that we only skewed. */
|
||||
global_sign = secp256k1_scalar_cond_negate(&s, flip);
|
||||
global_sign *= not_neg_one * 2 - 1;
|
||||
skew = 1 << bit;
|
||||
|
||||
/* 4 */
|
||||
u_last = secp256k1_scalar_shr_int(&s, w);
|
||||
while (word * w < WNAF_BITS) {
|
||||
int sign;
|
||||
int even;
|
||||
|
||||
/* 4.1 4.4 */
|
||||
u = secp256k1_scalar_shr_int(&s, w);
|
||||
/* 4.2 */
|
||||
even = ((u & 1) == 0);
|
||||
sign = 2 * (u_last > 0) - 1;
|
||||
u += sign * even;
|
||||
u_last -= sign * even * (1 << w);
|
||||
|
||||
/* 4.3, adapted for global sign change */
|
||||
wnaf[word++] = u_last * global_sign;
|
||||
|
||||
u_last = u;
|
||||
}
|
||||
wnaf[word] = u * global_sign;
|
||||
|
||||
VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
|
||||
VERIFY_CHECK(word == WNAF_SIZE(w));
|
||||
return skew;
|
||||
}
|
||||
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
|
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
secp256k1_ge tmpa;
|
||||
secp256k1_fe Z;
|
||||
|
||||
int skew_1;
|
||||
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
|
||||
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)];
|
||||
int skew_lam;
|
||||
secp256k1_scalar q_1, q_lam;
|
||||
#endif
|
||||
|
||||
int i;
|
||||
secp256k1_scalar sc = *scalar;
|
||||
|
||||
/* build wnaf representation for q. */
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
|
||||
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc);
|
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1);
|
||||
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1);
|
||||
#else
|
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1);
|
||||
#endif
|
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored
|
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
|
||||
* that the Z coordinate was 1, use affine addition formulae, and correct
|
||||
* the Z coordinate of the result once at the end.
|
||||
*/
|
||||
secp256k1_gej_set_ge(r, a);
|
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r);
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_fe_normalize_weak(&pre_a[i].y);
|
||||
}
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
|
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* first loop iteration (separated out so we can directly set r, rather
|
||||
* than having it start at infinity, get doubled several times, then have
|
||||
* its new value added to it) */
|
||||
i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
|
||||
secp256k1_gej_set_ge(r, &tmpa);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)];
|
||||
VERIFY_CHECK(i != 0);
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#endif
|
||||
/* remaining loop iterations */
|
||||
for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) {
|
||||
int n;
|
||||
int j;
|
||||
for (j = 0; j < WINDOW_A - 1; ++j) {
|
||||
secp256k1_gej_double_nonzero(r, r, NULL);
|
||||
}
|
||||
|
||||
n = wnaf_1[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
n = wnaf_lam[i];
|
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
|
||||
VERIFY_CHECK(n != 0);
|
||||
secp256k1_gej_add_ge(r, r, &tmpa);
|
||||
#endif
|
||||
}
|
||||
|
||||
secp256k1_fe_mul(&r->z, &r->z, &Z);
|
||||
|
||||
{
|
||||
/* Correct for wNAF skew */
|
||||
secp256k1_ge correction = *a;
|
||||
secp256k1_ge_storage correction_1_stor;
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage correction_lam_stor;
|
||||
#endif
|
||||
secp256k1_ge_storage a2_stor;
|
||||
secp256k1_gej tmpj;
|
||||
secp256k1_gej_set_ge(&tmpj, &correction);
|
||||
secp256k1_gej_double_var(&tmpj, &tmpj, NULL);
|
||||
secp256k1_ge_set_gej(&correction, &tmpj);
|
||||
secp256k1_ge_to_storage(&correction_1_stor, a);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_to_storage(&correction_lam_stor, a);
|
||||
#endif
|
||||
secp256k1_ge_to_storage(&a2_stor, &correction);
|
||||
|
||||
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
|
||||
secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
|
||||
#endif
|
||||
|
||||
/* Apply the correction */
|
||||
secp256k1_ge_from_storage(&correction, &correction_1_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
secp256k1_ge_from_storage(&correction, &correction_lam_stor);
|
||||
secp256k1_ge_neg(&correction, &correction);
|
||||
secp256k1_ge_mul_lambda(&correction, &correction);
|
||||
secp256k1_gej_add_ge(r, r, &correction);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECMULT_CONST_IMPL_H */
|
43
vendors/ocaml-secp256k1-internal/src/ecmult_gen.h
vendored
Normal file
43
vendors/ocaml-secp256k1-internal/src/ecmult_gen.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_GEN_H
|
||||
#define SECP256K1_ECMULT_GEN_H
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
|
||||
typedef struct {
|
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism:
|
||||
* * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63.
|
||||
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where:
|
||||
* * U_i = U * 2^i (for i=0..62)
|
||||
* * U_i = U * (1-2^63) (for i=63)
|
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0.
|
||||
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is
|
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
|
||||
* None of the resulting prec group elements have a known scalar, and neither do any of
|
||||
* the intermediate sums while computing a*G.
|
||||
*/
|
||||
secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */
|
||||
secp256k1_scalar blind;
|
||||
secp256k1_gej initial;
|
||||
} secp256k1_ecmult_gen_context;
|
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb);
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
||||
const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb);
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
||||
|
||||
/** Multiply with the generator: R = a*G */
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a);
|
||||
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32);
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_H */
|
210
vendors/ocaml-secp256k1-internal/src/ecmult_gen_impl.h
vendored
Normal file
210
vendors/ocaml-secp256k1-internal/src/ecmult_gen_impl.h
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_ECMULT_GEN_IMPL_H
|
||||
#define SECP256K1_ECMULT_GEN_IMPL_H
|
||||
|
||||
#include "scalar.h"
|
||||
#include "group.h"
|
||||
#include "ecmult_gen.h"
|
||||
#include "hash_impl.h"
|
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
#include "ecmult_static_context.h"
|
||||
#endif
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) {
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
secp256k1_ge prec[1024];
|
||||
secp256k1_gej gj;
|
||||
secp256k1_gej nums_gej;
|
||||
int i, j;
|
||||
#endif
|
||||
|
||||
if (ctx->prec != NULL) {
|
||||
return;
|
||||
}
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec));
|
||||
|
||||
/* get the generator */
|
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
|
||||
{
|
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown";
|
||||
secp256k1_fe nums_x;
|
||||
secp256k1_ge nums_ge;
|
||||
int r;
|
||||
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r);
|
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
|
||||
/* Add G to make the bits in x uniformly distributed. */
|
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL);
|
||||
}
|
||||
|
||||
/* compute prec. */
|
||||
{
|
||||
secp256k1_gej precj[1024]; /* Jacobian versions of prec. */
|
||||
secp256k1_gej gbase;
|
||||
secp256k1_gej numsbase;
|
||||
gbase = gj; /* 16^j * G */
|
||||
numsbase = nums_gej; /* 2^j * nums. */
|
||||
for (j = 0; j < 64; j++) {
|
||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
|
||||
precj[j*16] = numsbase;
|
||||
for (i = 1; i < 16; i++) {
|
||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL);
|
||||
}
|
||||
/* Multiply gbase by 16. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL);
|
||||
}
|
||||
/* Multiply numbase by 2. */
|
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL);
|
||||
if (j == 62) {
|
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
|
||||
secp256k1_gej_neg(&numsbase, &numsbase);
|
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
|
||||
}
|
||||
}
|
||||
secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb);
|
||||
}
|
||||
for (j = 0; j < 64; j++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)cb;
|
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context;
|
||||
#endif
|
||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||
}
|
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) {
|
||||
return ctx->prec != NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
||||
const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) {
|
||||
if (src->prec == NULL) {
|
||||
dst->prec = NULL;
|
||||
} else {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec));
|
||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
||||
#else
|
||||
(void)cb;
|
||||
dst->prec = src->prec;
|
||||
#endif
|
||||
dst->initial = src->initial;
|
||||
dst->blind = src->blind;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||
free(ctx->prec);
|
||||
#endif
|
||||
secp256k1_scalar_clear(&ctx->blind);
|
||||
secp256k1_gej_clear(&ctx->initial);
|
||||
ctx->prec = NULL;
|
||||
}
|
||||
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) {
|
||||
secp256k1_ge add;
|
||||
secp256k1_ge_storage adds;
|
||||
secp256k1_scalar gnb;
|
||||
int bits;
|
||||
int i, j;
|
||||
memset(&adds, 0, sizeof(adds));
|
||||
*r = ctx->initial;
|
||||
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */
|
||||
secp256k1_scalar_add(&gnb, gn, &ctx->blind);
|
||||
add.infinity = 0;
|
||||
for (j = 0; j < 64; j++) {
|
||||
bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4);
|
||||
for (i = 0; i < 16; i++) {
|
||||
/** This uses a conditional move to avoid any secret data in array indexes.
|
||||
* _Any_ use of secret indexes has been demonstrated to result in timing
|
||||
* sidechannels, even when the cache-line access patterns are uniform.
|
||||
* See also:
|
||||
* "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe
|
||||
* (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and
|
||||
* "Cache Attacks and Countermeasures: the Case of AES", RSA 2006,
|
||||
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
|
||||
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
|
||||
*/
|
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
|
||||
}
|
||||
secp256k1_ge_from_storage(&add, &adds);
|
||||
secp256k1_gej_add_ge(r, r, &add);
|
||||
}
|
||||
bits = 0;
|
||||
secp256k1_ge_clear(&add);
|
||||
secp256k1_scalar_clear(&gnb);
|
||||
}
|
||||
|
||||
/* Setup blinding values for secp256k1_ecmult_gen. */
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) {
|
||||
secp256k1_scalar b;
|
||||
secp256k1_gej gb;
|
||||
secp256k1_fe s;
|
||||
unsigned char nonce32[32];
|
||||
secp256k1_rfc6979_hmac_sha256 rng;
|
||||
int retry;
|
||||
unsigned char keydata[64] = {0};
|
||||
if (seed32 == NULL) {
|
||||
/* When seed is NULL, reset the initial point and blinding value. */
|
||||
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g);
|
||||
secp256k1_gej_neg(&ctx->initial, &ctx->initial);
|
||||
secp256k1_scalar_set_int(&ctx->blind, 1);
|
||||
}
|
||||
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */
|
||||
secp256k1_scalar_get_b32(nonce32, &ctx->blind);
|
||||
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
|
||||
* and guards against weak or adversarial seeds. This is a simpler and safer interface than
|
||||
* asking the caller for blinding values directly and expecting them to retry on failure.
|
||||
*/
|
||||
memcpy(keydata, nonce32, 32);
|
||||
if (seed32 != NULL) {
|
||||
memcpy(keydata + 32, seed32, 32);
|
||||
}
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32);
|
||||
memset(keydata, 0, sizeof(keydata));
|
||||
/* Retry for out of range results to achieve uniformity. */
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
retry = !secp256k1_fe_set_b32(&s, nonce32);
|
||||
retry |= secp256k1_fe_is_zero(&s);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
|
||||
/* Randomize the projection to defend against multiplier sidechannels. */
|
||||
secp256k1_gej_rescale(&ctx->initial, &s);
|
||||
secp256k1_fe_clear(&s);
|
||||
do {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
|
||||
secp256k1_scalar_set_b32(&b, nonce32, &retry);
|
||||
/* A blinding value of 0 works, but would undermine the projection hardening. */
|
||||
retry |= secp256k1_scalar_is_zero(&b);
|
||||
} while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */
|
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
|
||||
memset(nonce32, 0, 32);
|
||||
secp256k1_ecmult_gen(ctx, &gb, &b);
|
||||
secp256k1_scalar_negate(&b, &b);
|
||||
ctx->blind = b;
|
||||
ctx->initial = gb;
|
||||
secp256k1_scalar_clear(&b);
|
||||
secp256k1_gej_clear(&gb);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_ECMULT_GEN_IMPL_H */
|
1011
vendors/ocaml-secp256k1-internal/src/ecmult_impl.h
vendored
Normal file
1011
vendors/ocaml-secp256k1-internal/src/ecmult_impl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1160
vendors/ocaml-secp256k1-internal/src/ecmult_static_context.h
vendored
Normal file
1160
vendors/ocaml-secp256k1-internal/src/ecmult_static_context.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
469
vendors/ocaml-secp256k1-internal/src/external.ml
vendored
Normal file
469
vendors/ocaml-secp256k1-internal/src/external.ml
vendored
Normal file
@ -0,0 +1,469 @@
|
||||
open StdLabels
|
||||
|
||||
module BA = struct
|
||||
include Bigarray.Array1
|
||||
|
||||
let length = size_in_bytes
|
||||
|
||||
let rec compare_rec a b i len_a len_b =
|
||||
if i=len_a && i=len_b then 0
|
||||
else if i=len_a then -1
|
||||
else if i=len_b then 1
|
||||
else
|
||||
match Char.compare (get a i) (get b i) with
|
||||
| 0 -> compare_rec a b (i+1) len_a len_b
|
||||
| n -> n
|
||||
|
||||
let compare a b =
|
||||
compare_rec a b 0 (length a) (length b)
|
||||
|
||||
let equal a b = compare a b = 0
|
||||
|
||||
let create len =
|
||||
Bigarray.(create char c_layout len)
|
||||
end
|
||||
|
||||
type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
||||
|
||||
module Context = struct
|
||||
type flag =
|
||||
| Verify
|
||||
| Sign
|
||||
|
||||
type t
|
||||
|
||||
external flags : buffer -> int = "context_flags"
|
||||
external create : int -> t = "context_create"
|
||||
external clone : t -> t = "context_clone"
|
||||
external randomize : t -> buffer -> bool = "context_randomize" [@@noalloc]
|
||||
external get_16 : buffer -> int -> int = "%caml_bigstring_get16" [@@noalloc]
|
||||
|
||||
let flags =
|
||||
let buf = BA.create (3 * 2) in
|
||||
let _ = flags buf in
|
||||
buf
|
||||
|
||||
let int_of_flag = function
|
||||
| Verify -> get_16 flags 2
|
||||
| Sign -> get_16 flags 4
|
||||
|
||||
let create a =
|
||||
List.fold_left a ~init:(get_16 flags 0) ~f:(fun a f -> a lor (int_of_flag f)) |>
|
||||
create
|
||||
|
||||
let randomize ctx buf =
|
||||
if BA.length buf <> 32 then
|
||||
invalid_arg "Context.randomize: input must be 32 bytes long" ;
|
||||
randomize ctx buf
|
||||
end
|
||||
|
||||
module Key = struct
|
||||
type secret
|
||||
type public
|
||||
type _ t =
|
||||
| Sk : buffer -> secret t
|
||||
| Pk : buffer -> public t
|
||||
|
||||
let to_buffer : type a. a t -> buffer = function
|
||||
| Sk k -> k
|
||||
| Pk k -> k
|
||||
|
||||
let secret_bytes = 32
|
||||
let public_bytes = 64
|
||||
|
||||
let length : type a. a t -> int = function
|
||||
| Sk _ -> 32
|
||||
| Pk _ -> 64
|
||||
|
||||
let equal : type a. a t -> a t -> bool = fun a b ->
|
||||
match a, b with
|
||||
| Sk a, Sk b -> BA.equal a b
|
||||
| Pk a, Pk b -> BA.equal a b
|
||||
|
||||
let copy : type a. a t -> a t = function
|
||||
| Sk k ->
|
||||
let k' = BA.create secret_bytes in
|
||||
BA.blit k k' ;
|
||||
Sk k'
|
||||
| Pk k ->
|
||||
let k' = BA.create public_bytes in
|
||||
BA.blit k k' ;
|
||||
Pk k'
|
||||
|
||||
external sk_negate_inplace : Context.t -> buffer -> unit =
|
||||
"ec_privkey_negate" [@@noalloc]
|
||||
external sk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_privkey_tweak_add" [@@noalloc]
|
||||
external sk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_privkey_tweak_mul" [@@noalloc]
|
||||
external pk_negate_inplace : Context.t -> buffer -> unit =
|
||||
"ec_pubkey_negate" [@@noalloc]
|
||||
external pk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_pubkey_tweak_add" [@@noalloc]
|
||||
external pk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_pubkey_tweak_mul" [@@noalloc]
|
||||
external pk_combine : Context.t -> buffer -> buffer list -> bool =
|
||||
"ec_pubkey_combine" [@@noalloc]
|
||||
|
||||
let negate_inplace :
|
||||
type a. Context.t -> a t -> unit = fun ctx -> function
|
||||
| Sk k -> sk_negate_inplace ctx k
|
||||
| Pk k -> pk_negate_inplace ctx k
|
||||
|
||||
let negate ctx k =
|
||||
let k' = copy k in
|
||||
negate_inplace ctx k' ;
|
||||
k'
|
||||
|
||||
let op_tweak :
|
||||
type a. string -> (Context.t -> buffer -> buffer -> bool) ->
|
||||
Context.t -> a t -> ?pos:int -> buffer -> buffer =
|
||||
fun name f ctx k ?(pos=0) buf ->
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - 32 then
|
||||
invalid_arg (Printf.sprintf "Key.%s: pos < 0 or pos > buflen - 32" name) ;
|
||||
let buf = BA.sub buf pos 32 in
|
||||
let k' = copy k |> to_buffer in
|
||||
if not (f ctx k' buf) then
|
||||
failwith (Printf.sprintf "Key.%s: operation failed" name) ;
|
||||
k'
|
||||
|
||||
let add_tweak :
|
||||
type a. Context.t -> a t -> ?pos:int -> buffer -> a t =
|
||||
fun ctx k ?pos buf ->
|
||||
match k with
|
||||
| Sk _ -> Sk (op_tweak "add_tweak" sk_add_tweak_inplace ctx k ?pos buf)
|
||||
| Pk _ -> Pk (op_tweak "add_tweak" pk_add_tweak_inplace ctx k ?pos buf)
|
||||
|
||||
let mul_tweak :
|
||||
type a. Context.t -> a t -> ?pos:int -> buffer -> a t =
|
||||
fun ctx k ?pos buf ->
|
||||
match k with
|
||||
| Sk _ -> Sk (op_tweak "mul_tweak" sk_mul_tweak_inplace ctx k ?pos buf)
|
||||
| Pk _ -> Pk (op_tweak "mul_tweak" pk_mul_tweak_inplace ctx k ?pos buf)
|
||||
|
||||
external pk_parse : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_pubkey_parse" [@@noalloc]
|
||||
external pk_serialize : Context.t -> buffer -> buffer -> int =
|
||||
"ec_pubkey_serialize" [@@noalloc]
|
||||
external pk_create : Context.t -> buffer -> buffer -> bool =
|
||||
"ec_pubkey_create" [@@noalloc]
|
||||
|
||||
let neuterize :
|
||||
type a. Context.t -> a t -> public t option = fun ctx -> function
|
||||
| Pk pk -> Some (Pk pk)
|
||||
| Sk sk ->
|
||||
let pk = BA.create public_bytes in
|
||||
if pk_create ctx pk sk then Some (Pk pk) else None
|
||||
|
||||
let neuterize_exn ctx k =
|
||||
match neuterize ctx k with
|
||||
| None -> invalid_arg "Key.neuterize_exn: invalid secret key"
|
||||
| Some pk -> pk
|
||||
|
||||
let list_map_filter_opt ~f l =
|
||||
List.fold_left ~init:[] ~f:begin fun a e ->
|
||||
match f e with
|
||||
| None -> a
|
||||
| Some r -> r :: a
|
||||
end l
|
||||
|
||||
let combine ctx pks =
|
||||
let nb_pks = List.length pks in
|
||||
if nb_pks = 0 || nb_pks > 1024 then None
|
||||
else
|
||||
let pk = BA.create public_bytes in
|
||||
let pks = list_map_filter_opt ~f:begin fun k ->
|
||||
match neuterize ctx k with
|
||||
| None -> None
|
||||
| Some (Pk k) -> Some k
|
||||
end pks in
|
||||
if pk_combine ctx pk pks then Some (Pk pk)
|
||||
else None
|
||||
|
||||
let combine_exn ctx pks =
|
||||
match combine ctx pks with
|
||||
| None -> invalid_arg "Key.combine_exn: sum of pks is invalid"
|
||||
| Some pk -> pk
|
||||
|
||||
external verify_sk : Context.t -> buffer -> bool =
|
||||
"ec_seckey_verify" [@@noalloc]
|
||||
|
||||
let read_sk_exn ctx ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - secret_bytes then
|
||||
invalid_arg "Key.read_sk: pos < 0 or pos + 32 > buflen" ;
|
||||
let buf = BA.sub buf pos secret_bytes in
|
||||
match verify_sk ctx buf with
|
||||
| true ->
|
||||
let t = BA.create secret_bytes in
|
||||
BA.blit buf t ;
|
||||
Sk buf
|
||||
| false -> invalid_arg "Key.read_sk_exn: secret key is invalid"
|
||||
|
||||
let read_sk ctx ?pos buf =
|
||||
try Ok (read_sk_exn ctx ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let read_pk_exn ctx ?(pos=0) inbuf =
|
||||
let pklen = BA.length inbuf in
|
||||
if pos < 0 || pos > pklen - 33 then
|
||||
invalid_arg "Key.read_pk: pos < 0 or pos > buflen - 33" ;
|
||||
let inbuf = BA.(sub inbuf pos (length inbuf)) in
|
||||
if BA.(length inbuf < 33) then
|
||||
invalid_arg "Key.read_pk: input must be at least 33 bytes long" ;
|
||||
let outbuf = BA.create public_bytes in
|
||||
if (pk_parse ctx outbuf inbuf) then Pk outbuf
|
||||
else invalid_arg "Key.read_pk_exn: public key is invalid"
|
||||
|
||||
let read_pk ctx ?pos buf =
|
||||
try Ok (read_pk_exn ctx ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let write :
|
||||
type a. ?compress:bool -> Context.t -> ?pos:int -> buffer -> a t -> int =
|
||||
fun ?(compress=true) ctx ?(pos=0) buf -> function
|
||||
| Sk sk ->
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - secret_bytes then
|
||||
invalid_arg "Key.write (secret): pos < 0 or pos + 32 > buflen" ;
|
||||
let buf = BA.sub buf pos secret_bytes in
|
||||
BA.blit sk buf ;
|
||||
secret_bytes
|
||||
| Pk pk ->
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0
|
||||
|| (compress && pos > buflen - 33)
|
||||
|| (not compress && pos > buflen - 65) then
|
||||
invalid_arg (Printf.sprintf "Key.write (public): pos=%d, buflen=%d" pos buflen) ;
|
||||
let len = if compress then 33 else 65 in
|
||||
let buf = BA.sub buf pos len in
|
||||
pk_serialize ctx buf pk
|
||||
|
||||
let to_bytes :
|
||||
type a. ?compress:bool -> Context.t -> a t -> buffer =
|
||||
fun ?(compress=true) ctx -> function
|
||||
| Sk _ as sk ->
|
||||
let buf = BA.create secret_bytes in
|
||||
let _ = write ~compress ctx buf sk in
|
||||
buf
|
||||
| Pk _ as pk ->
|
||||
let buf =
|
||||
BA.create (1 + (if compress then secret_bytes else public_bytes)) in
|
||||
let _ = write ~compress ctx buf pk in
|
||||
buf
|
||||
end
|
||||
|
||||
module Sign = struct
|
||||
type plain
|
||||
type recoverable
|
||||
type _ t =
|
||||
| P : buffer -> plain t
|
||||
| R : buffer -> recoverable t
|
||||
|
||||
let plain_bytes = 64
|
||||
let recoverable_bytes = 65
|
||||
let msg_bytes = 32
|
||||
|
||||
type msg = buffer
|
||||
|
||||
let msg_of_bytes ?(pos=0) buf =
|
||||
try Some (BA.sub buf pos msg_bytes) with _ -> None
|
||||
let msg_of_bytes_exn ?pos buf =
|
||||
match msg_of_bytes ?pos buf with
|
||||
| None -> invalid_arg "msg_of_bytes_exn"
|
||||
| Some msg -> msg
|
||||
let write_msg_exn ?(pos=0) buf msg =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - msg_bytes then
|
||||
invalid_arg "Sign.read_exn: pos < 0 or pos > buflen - 64" ;
|
||||
BA.blit (BA.sub msg 0 msg_bytes) (BA.sub buf pos msg_bytes) ;
|
||||
msg_bytes
|
||||
|
||||
let write_msg ?pos buf msg =
|
||||
try Ok (write_msg_exn ?pos buf msg) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let msg_to_bytes msg = msg
|
||||
|
||||
let equal : type a. a t -> a t -> bool = fun a b ->
|
||||
match a, b with
|
||||
| P a, P b -> BA.equal a b
|
||||
| R a, R b -> BA.equal a b
|
||||
|
||||
external parse_compact : Context.t -> buffer -> buffer -> bool =
|
||||
"ecdsa_signature_parse_compact" [@@noalloc]
|
||||
external parse_der : Context.t -> buffer -> buffer -> bool =
|
||||
"ecdsa_signature_parse_der" [@@noalloc]
|
||||
external serialize_compact : Context.t -> buffer -> buffer -> unit =
|
||||
"ecdsa_signature_serialize_compact" [@@noalloc]
|
||||
external serialize_der : Context.t -> buffer -> buffer -> int =
|
||||
"ecdsa_signature_serialize_der" [@@noalloc]
|
||||
external parse_recoverable : Context.t -> buffer -> buffer -> int -> bool =
|
||||
"ecdsa_recoverable_signature_parse_compact" [@@noalloc]
|
||||
external serialize_recoverable : Context.t -> buffer -> buffer -> int =
|
||||
"ecdsa_recoverable_signature_serialize_compact" [@@noalloc]
|
||||
|
||||
let read_exn ctx ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - plain_bytes then
|
||||
invalid_arg "Sign.read_exn: pos < 0 or pos > buflen - 64" ;
|
||||
let signature = BA.create plain_bytes in
|
||||
if parse_compact ctx signature (BA.sub buf pos plain_bytes) then
|
||||
P signature
|
||||
else invalid_arg "Sign.read_exn: signature could not be parsed"
|
||||
|
||||
let read ctx ?pos buf =
|
||||
try Ok (read_exn ctx ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let read_der_exn ctx ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - plain_bytes then
|
||||
invalid_arg "Sign.read_der: pos < 0 or pos > buflen - 72" ;
|
||||
let signature = BA.create plain_bytes in
|
||||
if parse_der ctx signature BA.(sub buf pos (length buf)) then
|
||||
P signature
|
||||
else invalid_arg "Sign.read_der_exn: signature could not be parsed"
|
||||
|
||||
let read_der ctx ?pos buf =
|
||||
try Ok (read_der_exn ctx ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let read_recoverable_exn ctx ~recid ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - plain_bytes then
|
||||
invalid_arg "Sign.read_recoverable_exn: pos < 0 or pos > buflen - 64" ;
|
||||
let signature = BA.create recoverable_bytes in
|
||||
if parse_recoverable ctx signature (BA.sub buf pos plain_bytes) recid then (R signature)
|
||||
else invalid_arg "Sign.read_recoverable_exn: signature could not be parsed"
|
||||
|
||||
let read_recoverable ctx ~recid ?pos buf =
|
||||
try Ok (read_recoverable_exn ctx ~recid ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let write_exn :
|
||||
type a. ?der:bool -> Context.t -> ?pos:int -> buffer -> a t -> int =
|
||||
fun ?(der=false) ctx ?(pos=0) buf -> function
|
||||
| P signature ->
|
||||
let buf = BA.(sub buf pos (length buf)) in
|
||||
if der then serialize_der ctx buf signature
|
||||
else (serialize_compact ctx buf signature ; plain_bytes)
|
||||
| R signature ->
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - plain_bytes then
|
||||
invalid_arg "write: pos < 0 or pos > buflen - 64" ;
|
||||
ignore (serialize_recoverable ctx (BA.sub buf pos plain_bytes) signature) ;
|
||||
plain_bytes
|
||||
|
||||
let write ?der ctx ?pos buf signature =
|
||||
try Ok (write_exn ?der ctx ?pos buf signature) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let to_bytes ?der ctx signature =
|
||||
let buf = BA.create 72 in
|
||||
let nb_written = write_exn ?der ctx buf signature in
|
||||
BA.sub buf 0 nb_written
|
||||
|
||||
let to_bytes_recid ctx (R signature) =
|
||||
let buf = BA.create plain_bytes in
|
||||
let recid = serialize_recoverable ctx buf signature in
|
||||
buf, recid
|
||||
|
||||
external sign : Context.t -> buffer -> buffer -> buffer -> bool =
|
||||
"ecdsa_sign" [@@noalloc]
|
||||
external verify : Context.t -> buffer -> buffer -> buffer -> bool =
|
||||
"ecdsa_verify" [@@noalloc]
|
||||
|
||||
let write_sign_exn ctx ~sk ~msg ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - plain_bytes then
|
||||
invalid_arg "Sign.write_sign: outpos < 0 or outpos > outbuf - 64" ;
|
||||
if sign ctx (BA.sub buf pos plain_bytes) (Key.to_buffer sk) msg then plain_bytes
|
||||
else invalid_arg
|
||||
"Sign.write_sign: the nonce generation function failed, or the private key was invalid"
|
||||
|
||||
let write_sign ctx ~sk ~msg ?pos buf =
|
||||
try Ok (write_sign_exn ctx ~sk ~msg ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let sign ctx ~sk ~msg =
|
||||
let signature = BA.create plain_bytes in
|
||||
match write_sign ctx ~sk ~msg signature with
|
||||
| Error msg -> Error msg
|
||||
| Ok _nb_written -> Ok (P signature)
|
||||
|
||||
let sign_exn ctx ~sk ~msg =
|
||||
match sign ctx ~sk ~msg with
|
||||
| Error msg -> invalid_arg msg
|
||||
| Ok signature -> signature
|
||||
|
||||
external sign_recoverable : Context.t -> buffer -> buffer -> buffer -> bool =
|
||||
"ecdsa_sign_recoverable" [@@noalloc]
|
||||
|
||||
let write_sign_recoverable_exn ctx ~sk ~msg ?(pos=0) buf =
|
||||
let buflen = BA.length buf in
|
||||
if pos < 0 || pos > buflen - recoverable_bytes then
|
||||
invalid_arg "Sign.write_sign_recoverable_exn: \
|
||||
outpos < 0 or outpos > outbuflen - 65" ;
|
||||
if sign_recoverable ctx
|
||||
(BA.sub buf pos recoverable_bytes)
|
||||
(Key.to_buffer sk) msg then recoverable_bytes
|
||||
else invalid_arg
|
||||
"Sign.write_sign_recoverable_exn: \
|
||||
the nonce generation function failed, or the private key was invalid"
|
||||
|
||||
let write_sign_recoverable ctx ~sk ~msg ?pos buf =
|
||||
try Ok (write_sign_recoverable_exn ctx ~sk ~msg ?pos buf) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
let sign_recoverable ctx ~sk msg =
|
||||
let signature = BA.create recoverable_bytes in
|
||||
match write_sign_recoverable ctx ~sk ~msg signature with
|
||||
| Error error -> Error error
|
||||
| Ok _nb_written -> Ok (R signature)
|
||||
|
||||
let sign_recoverable_exn ctx ~sk msg =
|
||||
match sign_recoverable ctx ~sk msg with
|
||||
| Error msg -> invalid_arg msg
|
||||
| Ok signature -> signature
|
||||
|
||||
external to_plain : Context.t -> buffer -> buffer -> unit =
|
||||
"ecdsa_recoverable_signature_convert" [@@noalloc]
|
||||
|
||||
let to_plain ctx (R recoverable) =
|
||||
let plain = BA.create plain_bytes in
|
||||
to_plain ctx plain recoverable ;
|
||||
P plain
|
||||
|
||||
let verify_plain_exn ctx ~pk ?(pos=0) msg signature =
|
||||
let msglen = BA.length msg in
|
||||
if pos < 0 || pos > msglen - 32 then
|
||||
invalid_arg "Sign.verify: msg must be at least 32 bytes long" ;
|
||||
verify ctx (Key.to_buffer pk) (BA.sub msg pos 32) signature
|
||||
|
||||
let verify_exn :
|
||||
type a. Context.t -> pk:Key.public Key.t -> msg:msg -> signature:a t -> bool =
|
||||
fun ctx ~pk ~msg ~signature -> match signature with
|
||||
| P signature -> verify_plain_exn ctx ~pk msg signature
|
||||
| R _ as r ->
|
||||
let P signature = to_plain ctx r in
|
||||
verify_plain_exn ctx ~pk msg signature
|
||||
|
||||
let verify ctx ~pk ~msg ~signature =
|
||||
try Ok (verify_exn ctx ~pk ~msg ~signature) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
|
||||
external recover : Context.t -> buffer -> buffer -> buffer -> bool =
|
||||
"ecdsa_recover" [@@noalloc]
|
||||
|
||||
let recover_exn ctx ~signature:(R signature) ~msg =
|
||||
let pk = BA.create Key.public_bytes in
|
||||
if recover ctx pk signature msg then Key.Pk pk
|
||||
else
|
||||
invalid_arg "Sign.recover: pk could not be recovered"
|
||||
|
||||
let recover ctx ~signature ~msg =
|
||||
try Ok (recover_exn ctx ~signature ~msg) with
|
||||
| Invalid_argument msg -> Error msg
|
||||
end
|
146
vendors/ocaml-secp256k1-internal/src/external.mli
vendored
Normal file
146
vendors/ocaml-secp256k1-internal/src/external.mli
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
||||
|
||||
module Context : sig
|
||||
type flag =
|
||||
| Verify
|
||||
| Sign
|
||||
(** which parts of the context to initialize. *)
|
||||
|
||||
type t
|
||||
(** Opaque data structure that holds context information
|
||||
(precomputed tables etc.).
|
||||
|
||||
Do not create a new context object for each operation, as
|
||||
construction is far slower than all other API calls (~100 times
|
||||
slower than an ECDSA verification).
|
||||
|
||||
A constructed context can safely be used from multiple threads
|
||||
simultaneously, but API call that take a non-const pointer to a
|
||||
context need exclusive access to it. In particular this is the
|
||||
case for secp256k1_context_destroy and
|
||||
secp256k1_context_randomize.
|
||||
|
||||
Regarding randomization, either do it once at creation time (in
|
||||
which case you do not need any locking for the other calls), or
|
||||
use a read-write lock. *)
|
||||
|
||||
val create : flag list -> t
|
||||
(** Create a secp256k1 context object. *)
|
||||
|
||||
val clone : t -> t
|
||||
(** Copies a secp256k1 context object. *)
|
||||
|
||||
val randomize : t -> buffer -> bool
|
||||
(** While secp256k1 code is written to be constant-time no matter
|
||||
what secret values are, it's possible that a future compiler may
|
||||
output code which isn't, and also that the CPU may not emit the
|
||||
same radio frequencies or draw the same amount power for all
|
||||
values.
|
||||
|
||||
This function provides a seed which is combined into the
|
||||
blinding value: that blinding value is added before each
|
||||
multiplication (and removed afterwards) so that it does not
|
||||
affect function results, but shields against attacks which rely
|
||||
on any input-dependent behaviour.
|
||||
|
||||
You should call this after secp256k1_context_create or
|
||||
secp256k1_context_clone, and may call this repeatedly
|
||||
afterwards. *)
|
||||
|
||||
end
|
||||
|
||||
module Key : sig
|
||||
type secret
|
||||
type public
|
||||
type _ t = private
|
||||
| Sk : buffer -> secret t
|
||||
| Pk : buffer -> public t
|
||||
|
||||
val to_buffer : _ t -> buffer
|
||||
val length : _ t -> int
|
||||
val equal : 'a t -> 'a t -> bool
|
||||
val copy : 'a t -> 'a t
|
||||
|
||||
(** {2 Aritmetic operations } *)
|
||||
|
||||
val negate : Context.t -> 'a t -> 'a t
|
||||
val add_tweak : Context.t -> 'a t -> ?pos:int -> buffer -> 'a t
|
||||
val mul_tweak : Context.t -> 'a t -> ?pos:int -> buffer -> 'a t
|
||||
val neuterize : Context.t -> _ t -> public t option
|
||||
val neuterize_exn : Context.t -> _ t -> public t
|
||||
val combine : Context.t -> _ t list -> public t option
|
||||
val combine_exn : Context.t -> _ t list -> public t
|
||||
|
||||
(** {2 Input/Output} *)
|
||||
|
||||
val read_sk : Context.t -> ?pos:int -> buffer -> (secret t, string) result
|
||||
val read_sk_exn : Context.t -> ?pos:int -> buffer -> secret t
|
||||
val read_pk : Context.t -> ?pos:int -> buffer -> (public t, string) result
|
||||
val read_pk_exn : Context.t -> ?pos:int -> buffer -> public t
|
||||
val write : ?compress:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int
|
||||
val to_bytes : ?compress:bool -> Context.t -> _ t -> buffer
|
||||
end
|
||||
|
||||
module Sign : sig
|
||||
|
||||
(** {2 Message} *)
|
||||
|
||||
type msg
|
||||
|
||||
val msg_of_bytes : ?pos:int -> buffer -> msg option
|
||||
val msg_of_bytes_exn : ?pos:int -> buffer -> msg
|
||||
val write_msg_exn : ?pos:int -> buffer -> msg -> int
|
||||
val write_msg : ?pos:int -> buffer -> msg -> (int, string) result
|
||||
val msg_to_bytes : msg -> buffer
|
||||
|
||||
(** {2 Signature} *)
|
||||
|
||||
type plain
|
||||
type recoverable
|
||||
type _ t = private
|
||||
| P : buffer -> plain t
|
||||
| R : buffer -> recoverable t
|
||||
|
||||
val equal : 'a t -> 'a t -> bool
|
||||
val to_plain : Context.t -> recoverable t -> plain t
|
||||
|
||||
(** {3 Input/Output} *)
|
||||
|
||||
val read : Context.t -> ?pos:int -> buffer -> (plain t, string) result
|
||||
val read_exn : Context.t -> ?pos:int -> buffer -> plain t
|
||||
val read_der : Context.t -> ?pos:int -> buffer -> (plain t, string) result
|
||||
val read_der_exn : Context.t -> ?pos:int -> buffer -> plain t
|
||||
val read_recoverable : Context.t -> recid:int -> ?pos:int -> buffer -> (recoverable t, string) result
|
||||
val read_recoverable_exn : Context.t -> recid:int -> ?pos:int -> buffer -> recoverable t
|
||||
|
||||
val write_exn : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int
|
||||
val write : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> (int, string) result
|
||||
val to_bytes : ?der:bool -> Context.t -> _ t -> buffer
|
||||
val to_bytes_recid : Context.t -> recoverable t -> buffer * int
|
||||
|
||||
(** {3 Sign} *)
|
||||
|
||||
(** {4 Creation} *)
|
||||
|
||||
val sign : Context.t -> sk:Key.secret Key.t -> msg:msg -> (plain t, string) result
|
||||
val sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> plain t
|
||||
val sign_recoverable : Context.t -> sk:Key.secret Key.t -> msg -> (recoverable t, string) result
|
||||
val sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> msg -> recoverable t
|
||||
|
||||
(** {4 Direct write in buffers} *)
|
||||
|
||||
val write_sign : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> (int, string) result
|
||||
val write_sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> int
|
||||
val write_sign_recoverable : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> (int, string) result
|
||||
val write_sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> int
|
||||
|
||||
(** {4 Verification} *)
|
||||
|
||||
val verify_exn : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> bool
|
||||
val verify : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> (bool, string) result
|
||||
|
||||
(** {4 Recovery} *)
|
||||
|
||||
val recover_exn : Context.t -> signature:recoverable t -> msg:msg -> Key.public Key.t
|
||||
val recover : Context.t -> signature:recoverable t -> msg:msg -> (Key.public Key.t, string) result
|
||||
end
|
132
vendors/ocaml-secp256k1-internal/src/field.h
vendored
Normal file
132
vendors/ocaml-secp256k1-internal/src/field.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_H
|
||||
#define SECP256K1_FIELD_H
|
||||
|
||||
/** Field element module.
|
||||
*
|
||||
* Field elements can be represented in several ways, but code accessing
|
||||
* it (and implementations) need to take certain properties into account:
|
||||
* - Each field element can be normalized or not.
|
||||
* - Each field element has a magnitude, which represents how far away
|
||||
* its representation is away from normalization. Normalized elements
|
||||
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||||
* normality.
|
||||
*/
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_FIELD_10X26)
|
||||
#include "field_10x26.h"
|
||||
#elif defined(USE_FIELD_5X52)
|
||||
#include "field_5x52.h"
|
||||
#else
|
||||
#error "Please select field implementation"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/** Normalize a field element. */
|
||||
static void secp256k1_fe_normalize(secp256k1_fe *r);
|
||||
|
||||
/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */
|
||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
|
||||
|
||||
/** Normalize a field element, without constant-time guarantee. */
|
||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
|
||||
|
||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
|
||||
* implementation may optionally normalize the input, but this should not be relied upon. */
|
||||
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r);
|
||||
|
||||
/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field
|
||||
* implementation may optionally normalize the input, but this should not be relied upon. */
|
||||
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r);
|
||||
|
||||
/** Set a field element equal to a small integer. Resulting field element is normalized. */
|
||||
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
|
||||
|
||||
/** Sets a field element equal to zero, initializing all fields. */
|
||||
static void secp256k1_fe_clear(secp256k1_fe *a);
|
||||
|
||||
/** Verify whether a field element is zero. Requires the input to be normalized. */
|
||||
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
|
||||
|
||||
/** Check the "oddness" of a field element. Requires the input to be normalized. */
|
||||
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
|
||||
|
||||
/** Compare two field elements. Requires magnitude-1 inputs. */
|
||||
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Same as secp256k1_fe_equal, but may be variable time. */
|
||||
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Compare two field elements. Requires both inputs to be normalized */
|
||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
|
||||
|
||||
/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
|
||||
|
||||
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
|
||||
* as an argument. The magnitude of the output is one higher. */
|
||||
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
|
||||
|
||||
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
|
||||
* small integer. */
|
||||
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
|
||||
|
||||
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
|
||||
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
|
||||
|
||||
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
|
||||
* The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** If a has a square root, it is computed in r and 1 is returned. If a does not
|
||||
* have a square root, the root of its negation is computed and 0 is returned.
|
||||
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
|
||||
* guaranteed to be normalized). The result in r will always be a square
|
||||
* itself. */
|
||||
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Checks whether a field element is a quadratic residue. */
|
||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a);
|
||||
|
||||
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
|
||||
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
|
||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
|
||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
|
||||
|
||||
/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be
|
||||
* at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and
|
||||
* outputs must not overlap in memory. */
|
||||
static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len);
|
||||
|
||||
/** Convert a field element to the storage type. */
|
||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
|
||||
|
||||
/** Convert a field element back from the storage type. */
|
||||
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
|
||||
|
||||
#endif /* SECP256K1_FIELD_H */
|
48
vendors/ocaml-secp256k1-internal/src/field_10x26.h
vendored
Normal file
48
vendors/ocaml-secp256k1-internal/src/field_10x26.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_REPR_H
|
||||
#define SECP256K1_FIELD_REPR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
/* X = sum(i=0..9, elem[i]*2^26) mod n */
|
||||
uint32_t n[10];
|
||||
#ifdef VERIFY
|
||||
int magnitude;
|
||||
int normalized;
|
||||
#endif
|
||||
} secp256k1_fe;
|
||||
|
||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) & 0x3FFFFFFUL, \
|
||||
(((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \
|
||||
(((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \
|
||||
(((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \
|
||||
(((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \
|
||||
(((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \
|
||||
(((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \
|
||||
(((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \
|
||||
(((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \
|
||||
(((uint32_t)d7) >> 10) \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
||||
#else
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t n[8];
|
||||
} secp256k1_fe_storage;
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
|
||||
#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0]
|
||||
|
||||
#endif /* SECP256K1_FIELD_REPR_H */
|
1161
vendors/ocaml-secp256k1-internal/src/field_10x26_impl.h
vendored
Normal file
1161
vendors/ocaml-secp256k1-internal/src/field_10x26_impl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
vendors/ocaml-secp256k1-internal/src/field_5x52.h
vendored
Normal file
47
vendors/ocaml-secp256k1-internal/src/field_5x52.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_REPR_H
|
||||
#define SECP256K1_FIELD_REPR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
/* X = sum(i=0..4, elem[i]*2^52) mod n */
|
||||
uint64_t n[5];
|
||||
#ifdef VERIFY
|
||||
int magnitude;
|
||||
int normalized;
|
||||
#endif
|
||||
} secp256k1_fe;
|
||||
|
||||
/* Unpacks a constant into a overlapping multi-limbed FE element. */
|
||||
#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \
|
||||
(d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \
|
||||
((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \
|
||||
((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \
|
||||
((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \
|
||||
((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \
|
||||
}
|
||||
|
||||
#ifdef VERIFY
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
|
||||
#else
|
||||
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint64_t n[4];
|
||||
} secp256k1_fe_storage;
|
||||
|
||||
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \
|
||||
(d0) | (((uint64_t)(d1)) << 32), \
|
||||
(d2) | (((uint64_t)(d3)) << 32), \
|
||||
(d4) | (((uint64_t)(d5)) << 32), \
|
||||
(d6) | (((uint64_t)(d7)) << 32) \
|
||||
}}
|
||||
|
||||
#endif /* SECP256K1_FIELD_REPR_H */
|
502
vendors/ocaml-secp256k1-internal/src/field_5x52_asm_impl.h
vendored
Normal file
502
vendors/ocaml-secp256k1-internal/src/field_5x52_asm_impl.h
vendored
Normal file
@ -0,0 +1,502 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* Changelog:
|
||||
* - March 2013, Diederik Huys: original version
|
||||
* - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm
|
||||
* - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly
|
||||
*/
|
||||
|
||||
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||
#define SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
||||
/**
|
||||
* Registers: rdx:rax = multiplication accumulator
|
||||
* r9:r8 = c
|
||||
* r15:rcx = d
|
||||
* r10-r14 = a0-a4
|
||||
* rbx = b
|
||||
* rdi = r
|
||||
* rsi = a / t?
|
||||
*/
|
||||
uint64_t tmp1, tmp2, tmp3;
|
||||
__asm__ __volatile__(
|
||||
"movq 0(%%rsi),%%r10\n"
|
||||
"movq 8(%%rsi),%%r11\n"
|
||||
"movq 16(%%rsi),%%r12\n"
|
||||
"movq 24(%%rsi),%%r13\n"
|
||||
"movq 32(%%rsi),%%r14\n"
|
||||
|
||||
/* d += a3 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"movq %%rax,%%rcx\n"
|
||||
"movq %%rdx,%%r15\n"
|
||||
/* d += a2 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d = a0 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c = a4 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += (c & M) * R */
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* t3 (tmp1) = d & M */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
"movq %%rsi,%q1\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* d += a4 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a0 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += c * R */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* t4 = d & M (%%rsi) */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* tx = t4 >> 48 (tmp3) */
|
||||
"movq %%rsi,%%rax\n"
|
||||
"shrq $48,%%rax\n"
|
||||
"movq %%rax,%q3\n"
|
||||
/* t4 &= (M >> 4) (tmp2) */
|
||||
"movq $0xffffffffffff,%%rax\n"
|
||||
"andq %%rax,%%rsi\n"
|
||||
"movq %%rsi,%q2\n"
|
||||
/* c = a0 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += a4 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a1 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* u0 = d & M (%%rsi) */
|
||||
"movq %%rcx,%%rsi\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* u0 = (u0 << 4) | tx (%%rsi) */
|
||||
"shlq $4,%%rsi\n"
|
||||
"movq %q3,%%rax\n"
|
||||
"orq %%rax,%%rsi\n"
|
||||
/* c += u0 * (R >> 4) */
|
||||
"movq $0x1000003d1,%%rax\n"
|
||||
"mulq %%rsi\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[0] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,0(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a1 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a0 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a4 * b2 */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a2 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
"xorq %%r15,%%r15\n"
|
||||
/* r[1] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,8(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a2 * b0 */
|
||||
"movq 0(%%rbx),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a1 * b1 */
|
||||
"movq 8(%%rbx),%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* c += a0 * b2 (last use of %%r10 = a0) */
|
||||
"movq 16(%%rbx),%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */
|
||||
"movq %q2,%%rsi\n"
|
||||
"movq %q1,%%r10\n"
|
||||
/* d += a4 * b3 */
|
||||
"movq 24(%%rbx),%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* d += a3 * b4 */
|
||||
"movq 32(%%rbx),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rcx\n"
|
||||
"adcq %%rdx,%%r15\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 (%%rcx only) */
|
||||
"shrdq $52,%%r15,%%rcx\n"
|
||||
/* r[2] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,16(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += t3 */
|
||||
"addq %%r10,%%r8\n"
|
||||
/* c += d * R */
|
||||
"movq %%rcx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[3] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0xfffffffffffff,%%rdx\n"
|
||||
"andq %%rdx,%%rax\n"
|
||||
"movq %%rax,24(%%rdi)\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* c += t4 (%%r8 only) */
|
||||
"addq %%rsi,%%r8\n"
|
||||
/* r[4] = c */
|
||||
"movq %%r8,32(%%rdi)\n"
|
||||
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
|
||||
: "b"(b), "D"(r)
|
||||
: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
|
||||
/**
|
||||
* Registers: rdx:rax = multiplication accumulator
|
||||
* r9:r8 = c
|
||||
* rcx:rbx = d
|
||||
* r10-r14 = a0-a4
|
||||
* r15 = M (0xfffffffffffff)
|
||||
* rdi = r
|
||||
* rsi = a / t?
|
||||
*/
|
||||
uint64_t tmp1, tmp2, tmp3;
|
||||
__asm__ __volatile__(
|
||||
"movq 0(%%rsi),%%r10\n"
|
||||
"movq 8(%%rsi),%%r11\n"
|
||||
"movq 16(%%rsi),%%r12\n"
|
||||
"movq 24(%%rsi),%%r13\n"
|
||||
"movq 32(%%rsi),%%r14\n"
|
||||
"movq $0xfffffffffffff,%%r15\n"
|
||||
|
||||
/* d = (a0*2) * a3 */
|
||||
"leaq (%%r10,%%r10,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"movq %%rax,%%rbx\n"
|
||||
"movq %%rdx,%%rcx\n"
|
||||
/* d += (a1*2) * a2 */
|
||||
"leaq (%%r11,%%r11,1),%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c = a4 * a4 */
|
||||
"movq %%r14,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += (c & M) * R */
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* t3 (tmp1) = d & M */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
"movq %%rsi,%q1\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* a4 *= 2 */
|
||||
"addq %%r14,%%r14\n"
|
||||
/* d += a0 * a4 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d+= (a1*2) * a3 */
|
||||
"leaq (%%r11,%%r11,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += a2 * a2 */
|
||||
"movq %%r12,%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += c * R */
|
||||
"movq %%r8,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* t4 = d & M (%%rsi) */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* tx = t4 >> 48 (tmp3) */
|
||||
"movq %%rsi,%%rax\n"
|
||||
"shrq $48,%%rax\n"
|
||||
"movq %%rax,%q3\n"
|
||||
/* t4 &= (M >> 4) (tmp2) */
|
||||
"movq $0xffffffffffff,%%rax\n"
|
||||
"andq %%rax,%%rsi\n"
|
||||
"movq %%rsi,%q2\n"
|
||||
/* c = a0 * a0 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"movq %%rax,%%r8\n"
|
||||
"movq %%rdx,%%r9\n"
|
||||
/* d += a1 * a4 */
|
||||
"movq %%r11,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += (a2*2) * a3 */
|
||||
"leaq (%%r12,%%r12,1),%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* u0 = d & M (%%rsi) */
|
||||
"movq %%rbx,%%rsi\n"
|
||||
"andq %%r15,%%rsi\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* u0 = (u0 << 4) | tx (%%rsi) */
|
||||
"shlq $4,%%rsi\n"
|
||||
"movq %q3,%%rax\n"
|
||||
"orq %%rax,%%rsi\n"
|
||||
/* c += u0 * (R >> 4) */
|
||||
"movq $0x1000003d1,%%rax\n"
|
||||
"mulq %%rsi\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[0] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,0(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* a0 *= 2 */
|
||||
"addq %%r10,%%r10\n"
|
||||
/* c += a0 * a1 */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a2 * a4 */
|
||||
"movq %%r12,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* d += a3 * a3 */
|
||||
"movq %%r13,%%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
"xorq %%rcx,%%rcx\n"
|
||||
/* r[1] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,8(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += a0 * a2 (last use of %%r10) */
|
||||
"movq %%r10,%%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */
|
||||
"movq %q2,%%rsi\n"
|
||||
"movq %q1,%%r10\n"
|
||||
/* c += a1 * a1 */
|
||||
"movq %%r11,%%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d += a3 * a4 */
|
||||
"movq %%r13,%%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax,%%rbx\n"
|
||||
"adcq %%rdx,%%rcx\n"
|
||||
/* c += (d & M) * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* d >>= 52 (%%rbx only) */
|
||||
"shrdq $52,%%rcx,%%rbx\n"
|
||||
/* r[2] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,16(%%rdi)\n"
|
||||
/* c >>= 52 */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
"xorq %%r9,%%r9\n"
|
||||
/* c += t3 */
|
||||
"addq %%r10,%%r8\n"
|
||||
/* c += d * R */
|
||||
"movq %%rbx,%%rax\n"
|
||||
"movq $0x1000003d10,%%rdx\n"
|
||||
"mulq %%rdx\n"
|
||||
"addq %%rax,%%r8\n"
|
||||
"adcq %%rdx,%%r9\n"
|
||||
/* r[3] = c & M */
|
||||
"movq %%r8,%%rax\n"
|
||||
"andq %%r15,%%rax\n"
|
||||
"movq %%rax,24(%%rdi)\n"
|
||||
/* c >>= 52 (%%r8 only) */
|
||||
"shrdq $52,%%r9,%%r8\n"
|
||||
/* c += t4 (%%r8 only) */
|
||||
"addq %%rsi,%%r8\n"
|
||||
/* r[4] = c */
|
||||
"movq %%r8,32(%%rdi)\n"
|
||||
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
|
||||
: "D"(r)
|
||||
: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */
|
496
vendors/ocaml-secp256k1-internal/src/field_5x52_impl.h
vendored
Normal file
496
vendors/ocaml-secp256k1-internal/src/field_5x52_impl.h
vendored
Normal file
@ -0,0 +1,496 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_REPR_IMPL_H
|
||||
#define SECP256K1_FIELD_REPR_IMPL_H
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
|
||||
#if defined(USE_ASM_X86_64)
|
||||
#include "field_5x52_asm_impl.h"
|
||||
#else
|
||||
#include "field_5x52_int128_impl.h"
|
||||
#endif
|
||||
|
||||
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
||||
* represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular,
|
||||
* each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
|
||||
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
|
||||
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their
|
||||
* output.
|
||||
*/
|
||||
|
||||
#ifdef VERIFY
|
||||
static void secp256k1_fe_verify(const secp256k1_fe *a) {
|
||||
const uint64_t *d = a->n;
|
||||
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
|
||||
/* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
|
||||
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
|
||||
r &= (a->magnitude >= 0);
|
||||
r &= (a->magnitude <= 2048);
|
||||
if (a->normalized) {
|
||||
r &= (a->magnitude <= 1);
|
||||
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
|
||||
r &= (d[0] < 0xFFFFEFFFFFC2FULL);
|
||||
}
|
||||
}
|
||||
VERIFY_CHECK(r == 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void secp256k1_fe_normalize(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t m;
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
/* At most a single final reduction is needed; check if the value is >= the field characteristic */
|
||||
x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL)
|
||||
& (t0 >= 0xFFFFEFFFFFC2FULL));
|
||||
|
||||
/* Apply the final reduction (for constant-time behaviour, we do it always) */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* If t4 didn't carry to bit 48 already, then it should have after any final reduction */
|
||||
VERIFY_CHECK(t4 >> 48 == x);
|
||||
|
||||
/* Mask off the possible multiple of 2^256 from the final reduction */
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t m;
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
/* At most a single final reduction is needed; check if the value is >= the field characteristic */
|
||||
x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL)
|
||||
& (t0 >= 0xFFFFEFFFFFC2FULL));
|
||||
|
||||
if (x) {
|
||||
t0 += 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL;
|
||||
|
||||
/* If t4 didn't carry to bit 48 already, then it should have after any final reduction */
|
||||
VERIFY_CHECK(t4 >> 48 == x);
|
||||
|
||||
/* Mask off the possible multiple of 2^256 from the final reduction */
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
}
|
||||
|
||||
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) {
|
||||
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
|
||||
|
||||
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
||||
uint64_t z0, z1;
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
|
||||
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||
}
|
||||
|
||||
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) {
|
||||
uint64_t t0, t1, t2, t3, t4;
|
||||
uint64_t z0, z1;
|
||||
uint64_t x;
|
||||
|
||||
t0 = r->n[0];
|
||||
t4 = r->n[4];
|
||||
|
||||
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
|
||||
x = t4 >> 48;
|
||||
|
||||
/* The first pass ensures the magnitude is 1, ... */
|
||||
t0 += x * 0x1000003D1ULL;
|
||||
|
||||
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
|
||||
z0 = t0 & 0xFFFFFFFFFFFFFULL;
|
||||
z1 = z0 ^ 0x1000003D0ULL;
|
||||
|
||||
/* Fast return path should catch the majority of cases */
|
||||
if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
t1 = r->n[1];
|
||||
t2 = r->n[2];
|
||||
t3 = r->n[3];
|
||||
|
||||
t4 &= 0x0FFFFFFFFFFFFULL;
|
||||
|
||||
t1 += (t0 >> 52);
|
||||
t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1;
|
||||
t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2;
|
||||
t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3;
|
||||
z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL;
|
||||
|
||||
/* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */
|
||||
VERIFY_CHECK(t4 >> 49 == 0);
|
||||
|
||||
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
|
||||
r->n[0] = a;
|
||||
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
|
||||
const uint64_t *t = a->n;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
return a->n[0] & 1;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
|
||||
int i;
|
||||
#ifdef VERIFY
|
||||
a->magnitude = 0;
|
||||
a->normalized = 1;
|
||||
#endif
|
||||
for (i=0; i<5; i++) {
|
||||
a->n[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
int i;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
VERIFY_CHECK(b->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
secp256k1_fe_verify(b);
|
||||
#endif
|
||||
for (i = 4; i >= 0; i--) {
|
||||
if (a->n[i] > b->n[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (a->n[i] < b->n[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
|
||||
r->n[0] = (uint64_t)a[31]
|
||||
| ((uint64_t)a[30] << 8)
|
||||
| ((uint64_t)a[29] << 16)
|
||||
| ((uint64_t)a[28] << 24)
|
||||
| ((uint64_t)a[27] << 32)
|
||||
| ((uint64_t)a[26] << 40)
|
||||
| ((uint64_t)(a[25] & 0xF) << 48);
|
||||
r->n[1] = (uint64_t)((a[25] >> 4) & 0xF)
|
||||
| ((uint64_t)a[24] << 4)
|
||||
| ((uint64_t)a[23] << 12)
|
||||
| ((uint64_t)a[22] << 20)
|
||||
| ((uint64_t)a[21] << 28)
|
||||
| ((uint64_t)a[20] << 36)
|
||||
| ((uint64_t)a[19] << 44);
|
||||
r->n[2] = (uint64_t)a[18]
|
||||
| ((uint64_t)a[17] << 8)
|
||||
| ((uint64_t)a[16] << 16)
|
||||
| ((uint64_t)a[15] << 24)
|
||||
| ((uint64_t)a[14] << 32)
|
||||
| ((uint64_t)a[13] << 40)
|
||||
| ((uint64_t)(a[12] & 0xF) << 48);
|
||||
r->n[3] = (uint64_t)((a[12] >> 4) & 0xF)
|
||||
| ((uint64_t)a[11] << 4)
|
||||
| ((uint64_t)a[10] << 12)
|
||||
| ((uint64_t)a[9] << 20)
|
||||
| ((uint64_t)a[8] << 28)
|
||||
| ((uint64_t)a[7] << 36)
|
||||
| ((uint64_t)a[6] << 44);
|
||||
r->n[4] = (uint64_t)a[5]
|
||||
| ((uint64_t)a[4] << 8)
|
||||
| ((uint64_t)a[3] << 16)
|
||||
| ((uint64_t)a[2] << 24)
|
||||
| ((uint64_t)a[1] << 32)
|
||||
| ((uint64_t)a[0] << 40);
|
||||
if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
|
||||
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
r[0] = (a->n[4] >> 40) & 0xFF;
|
||||
r[1] = (a->n[4] >> 32) & 0xFF;
|
||||
r[2] = (a->n[4] >> 24) & 0xFF;
|
||||
r[3] = (a->n[4] >> 16) & 0xFF;
|
||||
r[4] = (a->n[4] >> 8) & 0xFF;
|
||||
r[5] = a->n[4] & 0xFF;
|
||||
r[6] = (a->n[3] >> 44) & 0xFF;
|
||||
r[7] = (a->n[3] >> 36) & 0xFF;
|
||||
r[8] = (a->n[3] >> 28) & 0xFF;
|
||||
r[9] = (a->n[3] >> 20) & 0xFF;
|
||||
r[10] = (a->n[3] >> 12) & 0xFF;
|
||||
r[11] = (a->n[3] >> 4) & 0xFF;
|
||||
r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4);
|
||||
r[13] = (a->n[2] >> 40) & 0xFF;
|
||||
r[14] = (a->n[2] >> 32) & 0xFF;
|
||||
r[15] = (a->n[2] >> 24) & 0xFF;
|
||||
r[16] = (a->n[2] >> 16) & 0xFF;
|
||||
r[17] = (a->n[2] >> 8) & 0xFF;
|
||||
r[18] = a->n[2] & 0xFF;
|
||||
r[19] = (a->n[1] >> 44) & 0xFF;
|
||||
r[20] = (a->n[1] >> 36) & 0xFF;
|
||||
r[21] = (a->n[1] >> 28) & 0xFF;
|
||||
r[22] = (a->n[1] >> 20) & 0xFF;
|
||||
r[23] = (a->n[1] >> 12) & 0xFF;
|
||||
r[24] = (a->n[1] >> 4) & 0xFF;
|
||||
r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4);
|
||||
r[26] = (a->n[0] >> 40) & 0xFF;
|
||||
r[27] = (a->n[0] >> 32) & 0xFF;
|
||||
r[28] = (a->n[0] >> 24) & 0xFF;
|
||||
r[29] = (a->n[0] >> 16) & 0xFF;
|
||||
r[30] = (a->n[0] >> 8) & 0xFF;
|
||||
r[31] = a->n[0] & 0xFF;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= m);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
|
||||
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
|
||||
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2];
|
||||
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3];
|
||||
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
|
||||
#ifdef VERIFY
|
||||
r->magnitude = m + 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
|
||||
r->n[0] *= a;
|
||||
r->n[1] *= a;
|
||||
r->n[2] *= a;
|
||||
r->n[3] *= a;
|
||||
r->n[4] *= a;
|
||||
#ifdef VERIFY
|
||||
r->magnitude *= a;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
r->n[0] += a->n[0];
|
||||
r->n[1] += a->n[1];
|
||||
r->n[2] += a->n[2];
|
||||
r->n[3] += a->n[3];
|
||||
r->n[4] += a->n[4];
|
||||
#ifdef VERIFY
|
||||
r->magnitude += a->magnitude;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= 8);
|
||||
VERIFY_CHECK(b->magnitude <= 8);
|
||||
secp256k1_fe_verify(a);
|
||||
secp256k1_fe_verify(b);
|
||||
VERIFY_CHECK(r != b);
|
||||
#endif
|
||||
secp256k1_fe_mul_inner(r->n, a->n, b->n);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->magnitude <= 8);
|
||||
secp256k1_fe_verify(a);
|
||||
#endif
|
||||
secp256k1_fe_sqr_inner(r->n, a->n);
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 0;
|
||||
secp256k1_fe_verify(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
|
||||
uint64_t mask0, mask1;
|
||||
mask0 = flag + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
|
||||
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
|
||||
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1);
|
||||
#ifdef VERIFY
|
||||
if (a->magnitude > r->magnitude) {
|
||||
r->magnitude = a->magnitude;
|
||||
}
|
||||
r->normalized &= a->normalized;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
|
||||
uint64_t mask0, mask1;
|
||||
mask0 = flag + ~((uint64_t)0);
|
||||
mask1 = ~mask0;
|
||||
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
|
||||
r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1);
|
||||
r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1);
|
||||
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(a->normalized);
|
||||
#endif
|
||||
r->n[0] = a->n[0] | a->n[1] << 52;
|
||||
r->n[1] = a->n[1] >> 12 | a->n[2] << 40;
|
||||
r->n[2] = a->n[2] >> 24 | a->n[3] << 28;
|
||||
r->n[3] = a->n[3] >> 36 | a->n[4] << 16;
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
|
||||
r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL;
|
||||
r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL);
|
||||
r->n[4] = a->n[3] >> 16;
|
||||
#ifdef VERIFY
|
||||
r->magnitude = 1;
|
||||
r->normalized = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_FIELD_REPR_IMPL_H */
|
277
vendors/ocaml-secp256k1-internal/src/field_5x52_int128_impl.h
vendored
Normal file
277
vendors/ocaml-secp256k1-internal/src/field_5x52_int128_impl.h
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||
#define SECP256K1_FIELD_INNER5X52_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef VERIFY
|
||||
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
|
||||
#else
|
||||
#define VERIFY_BITS(x, n) do { } while(0)
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
|
||||
uint128_t c, d;
|
||||
uint64_t t3, t4, tx, u0;
|
||||
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
|
||||
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
|
||||
|
||||
VERIFY_BITS(a[0], 56);
|
||||
VERIFY_BITS(a[1], 56);
|
||||
VERIFY_BITS(a[2], 56);
|
||||
VERIFY_BITS(a[3], 56);
|
||||
VERIFY_BITS(a[4], 52);
|
||||
VERIFY_BITS(b[0], 56);
|
||||
VERIFY_BITS(b[1], 56);
|
||||
VERIFY_BITS(b[2], 56);
|
||||
VERIFY_BITS(b[3], 56);
|
||||
VERIFY_BITS(b[4], 52);
|
||||
VERIFY_CHECK(r != b);
|
||||
|
||||
/* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
|
||||
* px is a shorthand for sum(a[i]*b[x-i], i=0..x).
|
||||
* Note that [x 0 0 0 0 0] = [x*R].
|
||||
*/
|
||||
|
||||
d = (uint128_t)a0 * b[3]
|
||||
+ (uint128_t)a1 * b[2]
|
||||
+ (uint128_t)a2 * b[1]
|
||||
+ (uint128_t)a3 * b[0];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 0] = [p3 0 0 0] */
|
||||
c = (uint128_t)a4 * b[4];
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
d += (uint128_t)a0 * b[4]
|
||||
+ (uint128_t)a1 * b[3]
|
||||
+ (uint128_t)a2 * b[2]
|
||||
+ (uint128_t)a3 * b[1]
|
||||
+ (uint128_t)a4 * b[0];
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t4, 52);
|
||||
VERIFY_BITS(d, 64);
|
||||
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
tx = (t4 >> 48); t4 &= (M >> 4);
|
||||
VERIFY_BITS(tx, 4);
|
||||
VERIFY_BITS(t4, 48);
|
||||
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
|
||||
c = (uint128_t)a0 * b[0];
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
|
||||
d += (uint128_t)a1 * b[4]
|
||||
+ (uint128_t)a2 * b[3]
|
||||
+ (uint128_t)a3 * b[2]
|
||||
+ (uint128_t)a4 * b[1];
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = d & M; d >>= 52;
|
||||
VERIFY_BITS(u0, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = (u0 << 4) | tx;
|
||||
VERIFY_BITS(u0, 56);
|
||||
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
c += (uint128_t)u0 * (R >> 4);
|
||||
VERIFY_BITS(c, 115);
|
||||
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
r[0] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[0], 52);
|
||||
VERIFY_BITS(c, 61);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
|
||||
c += (uint128_t)a0 * b[1]
|
||||
+ (uint128_t)a1 * b[0];
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
|
||||
d += (uint128_t)a2 * b[4]
|
||||
+ (uint128_t)a3 * b[3]
|
||||
+ (uint128_t)a4 * b[2];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
r[1] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[1], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
|
||||
c += (uint128_t)a0 * b[2]
|
||||
+ (uint128_t)a1 * b[1]
|
||||
+ (uint128_t)a2 * b[0];
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
|
||||
d += (uint128_t)a3 * b[4]
|
||||
+ (uint128_t)a4 * b[3];
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += d * R + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[3], 52);
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += t4;
|
||||
VERIFY_BITS(c, 49);
|
||||
/* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[4] = c;
|
||||
VERIFY_BITS(r[4], 49);
|
||||
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
|
||||
uint128_t c, d;
|
||||
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
|
||||
int64_t t3, t4, tx, u0;
|
||||
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
|
||||
|
||||
VERIFY_BITS(a[0], 56);
|
||||
VERIFY_BITS(a[1], 56);
|
||||
VERIFY_BITS(a[2], 56);
|
||||
VERIFY_BITS(a[3], 56);
|
||||
VERIFY_BITS(a[4], 52);
|
||||
|
||||
/** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n.
|
||||
* px is a shorthand for sum(a[i]*a[x-i], i=0..x).
|
||||
* Note that [x 0 0 0 0 0] = [x*R].
|
||||
*/
|
||||
|
||||
d = (uint128_t)(a0*2) * a3
|
||||
+ (uint128_t)(a1*2) * a2;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 0] = [p3 0 0 0] */
|
||||
c = (uint128_t)a4 * a4;
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
d += (c & M) * R; c >>= 52;
|
||||
VERIFY_BITS(d, 115);
|
||||
VERIFY_BITS(c, 60);
|
||||
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
t3 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t3, 52);
|
||||
VERIFY_BITS(d, 63);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
|
||||
|
||||
a4 *= 2;
|
||||
d += (uint128_t)a0 * a4
|
||||
+ (uint128_t)(a1*2) * a3
|
||||
+ (uint128_t)a2 * a2;
|
||||
VERIFY_BITS(d, 115);
|
||||
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
d += c * R;
|
||||
VERIFY_BITS(d, 116);
|
||||
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
t4 = d & M; d >>= 52;
|
||||
VERIFY_BITS(t4, 52);
|
||||
VERIFY_BITS(d, 64);
|
||||
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
tx = (t4 >> 48); t4 &= (M >> 4);
|
||||
VERIFY_BITS(tx, 4);
|
||||
VERIFY_BITS(t4, 48);
|
||||
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
|
||||
|
||||
c = (uint128_t)a0 * a0;
|
||||
VERIFY_BITS(c, 112);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
|
||||
d += (uint128_t)a1 * a4
|
||||
+ (uint128_t)(a2*2) * a3;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = d & M; d >>= 52;
|
||||
VERIFY_BITS(u0, 52);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
/* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
u0 = (u0 << 4) | tx;
|
||||
VERIFY_BITS(u0, 56);
|
||||
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
c += (uint128_t)u0 * (R >> 4);
|
||||
VERIFY_BITS(c, 113);
|
||||
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
r[0] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[0], 52);
|
||||
VERIFY_BITS(c, 61);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
|
||||
|
||||
a0 *= 2;
|
||||
c += (uint128_t)a0 * a1;
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
|
||||
d += (uint128_t)a2 * a4
|
||||
+ (uint128_t)a3 * a3;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
r[1] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[1], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
|
||||
|
||||
c += (uint128_t)a0 * a2
|
||||
+ (uint128_t)a1 * a1;
|
||||
VERIFY_BITS(c, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
|
||||
d += (uint128_t)a3 * a4;
|
||||
VERIFY_BITS(d, 114);
|
||||
/* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += (d & M) * R; d >>= 52;
|
||||
VERIFY_BITS(c, 115);
|
||||
VERIFY_BITS(d, 62);
|
||||
/* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[2] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[2], 52);
|
||||
VERIFY_BITS(c, 63);
|
||||
/* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
|
||||
c += d * R + t3;
|
||||
VERIFY_BITS(c, 100);
|
||||
/* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[3] = c & M; c >>= 52;
|
||||
VERIFY_BITS(r[3], 52);
|
||||
VERIFY_BITS(c, 48);
|
||||
/* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
c += t4;
|
||||
VERIFY_BITS(c, 49);
|
||||
/* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
r[4] = c;
|
||||
VERIFY_BITS(r[4], 49);
|
||||
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */
|
315
vendors/ocaml-secp256k1-internal/src/field_impl.h
vendored
Normal file
315
vendors/ocaml-secp256k1-internal/src/field_impl.h
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_FIELD_IMPL_H
|
||||
#define SECP256K1_FIELD_IMPL_H
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#if defined(USE_FIELD_10X26)
|
||||
#include "field_10x26_impl.h"
|
||||
#elif defined(USE_FIELD_5X52)
|
||||
#include "field_5x52_impl.h"
|
||||
#else
|
||||
#error "Please select field implementation"
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
secp256k1_fe na;
|
||||
secp256k1_fe_negate(&na, a, 1);
|
||||
secp256k1_fe_add(&na, b);
|
||||
return secp256k1_fe_normalizes_to_zero(&na);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
|
||||
secp256k1_fe na;
|
||||
secp256k1_fe_negate(&na, a, 1);
|
||||
secp256k1_fe_add(&na, b);
|
||||
return secp256k1_fe_normalizes_to_zero_var(&na);
|
||||
}
|
||||
|
||||
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
/** Given that p is congruent to 3 mod 4, we can compute the square root of
|
||||
* a mod p as the (p+1)/4'th power of a.
|
||||
*
|
||||
* As (p+1)/4 is an even number, it will have the same result for a and for
|
||||
* (-a). Only one of these two numbers actually has a square root however,
|
||||
* so we test at the end by squaring and comparing to the input.
|
||||
* Also because (p+1)/4 is an even number, the computed square root is
|
||||
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
|
||||
*/
|
||||
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
||||
int j;
|
||||
|
||||
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
|
||||
* { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
||||
* 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
|
||||
*/
|
||||
|
||||
secp256k1_fe_sqr(&x2, a);
|
||||
secp256k1_fe_mul(&x2, &x2, a);
|
||||
|
||||
secp256k1_fe_sqr(&x3, &x2);
|
||||
secp256k1_fe_mul(&x3, &x3, a);
|
||||
|
||||
x6 = x3;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x6, &x6);
|
||||
}
|
||||
secp256k1_fe_mul(&x6, &x6, &x3);
|
||||
|
||||
x9 = x6;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x9, &x9);
|
||||
}
|
||||
secp256k1_fe_mul(&x9, &x9, &x3);
|
||||
|
||||
x11 = x9;
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&x11, &x11);
|
||||
}
|
||||
secp256k1_fe_mul(&x11, &x11, &x2);
|
||||
|
||||
x22 = x11;
|
||||
for (j=0; j<11; j++) {
|
||||
secp256k1_fe_sqr(&x22, &x22);
|
||||
}
|
||||
secp256k1_fe_mul(&x22, &x22, &x11);
|
||||
|
||||
x44 = x22;
|
||||
for (j=0; j<22; j++) {
|
||||
secp256k1_fe_sqr(&x44, &x44);
|
||||
}
|
||||
secp256k1_fe_mul(&x44, &x44, &x22);
|
||||
|
||||
x88 = x44;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x88, &x88);
|
||||
}
|
||||
secp256k1_fe_mul(&x88, &x88, &x44);
|
||||
|
||||
x176 = x88;
|
||||
for (j=0; j<88; j++) {
|
||||
secp256k1_fe_sqr(&x176, &x176);
|
||||
}
|
||||
secp256k1_fe_mul(&x176, &x176, &x88);
|
||||
|
||||
x220 = x176;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x220, &x220);
|
||||
}
|
||||
secp256k1_fe_mul(&x220, &x220, &x44);
|
||||
|
||||
x223 = x220;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x223, &x223);
|
||||
}
|
||||
secp256k1_fe_mul(&x223, &x223, &x3);
|
||||
|
||||
/* The final result is then assembled using a sliding window over the blocks. */
|
||||
|
||||
t1 = x223;
|
||||
for (j=0; j<23; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x22);
|
||||
for (j=0; j<6; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x2);
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
secp256k1_fe_sqr(r, &t1);
|
||||
|
||||
/* Check that a square root was actually calculated */
|
||||
|
||||
secp256k1_fe_sqr(&t1, r);
|
||||
return secp256k1_fe_equal(&t1, a);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
|
||||
int j;
|
||||
|
||||
/** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
|
||||
* { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
|
||||
* [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
|
||||
*/
|
||||
|
||||
secp256k1_fe_sqr(&x2, a);
|
||||
secp256k1_fe_mul(&x2, &x2, a);
|
||||
|
||||
secp256k1_fe_sqr(&x3, &x2);
|
||||
secp256k1_fe_mul(&x3, &x3, a);
|
||||
|
||||
x6 = x3;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x6, &x6);
|
||||
}
|
||||
secp256k1_fe_mul(&x6, &x6, &x3);
|
||||
|
||||
x9 = x6;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x9, &x9);
|
||||
}
|
||||
secp256k1_fe_mul(&x9, &x9, &x3);
|
||||
|
||||
x11 = x9;
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&x11, &x11);
|
||||
}
|
||||
secp256k1_fe_mul(&x11, &x11, &x2);
|
||||
|
||||
x22 = x11;
|
||||
for (j=0; j<11; j++) {
|
||||
secp256k1_fe_sqr(&x22, &x22);
|
||||
}
|
||||
secp256k1_fe_mul(&x22, &x22, &x11);
|
||||
|
||||
x44 = x22;
|
||||
for (j=0; j<22; j++) {
|
||||
secp256k1_fe_sqr(&x44, &x44);
|
||||
}
|
||||
secp256k1_fe_mul(&x44, &x44, &x22);
|
||||
|
||||
x88 = x44;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x88, &x88);
|
||||
}
|
||||
secp256k1_fe_mul(&x88, &x88, &x44);
|
||||
|
||||
x176 = x88;
|
||||
for (j=0; j<88; j++) {
|
||||
secp256k1_fe_sqr(&x176, &x176);
|
||||
}
|
||||
secp256k1_fe_mul(&x176, &x176, &x88);
|
||||
|
||||
x220 = x176;
|
||||
for (j=0; j<44; j++) {
|
||||
secp256k1_fe_sqr(&x220, &x220);
|
||||
}
|
||||
secp256k1_fe_mul(&x220, &x220, &x44);
|
||||
|
||||
x223 = x220;
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&x223, &x223);
|
||||
}
|
||||
secp256k1_fe_mul(&x223, &x223, &x3);
|
||||
|
||||
/* The final result is then assembled using a sliding window over the blocks. */
|
||||
|
||||
t1 = x223;
|
||||
for (j=0; j<23; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x22);
|
||||
for (j=0; j<5; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, a);
|
||||
for (j=0; j<3; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(&t1, &t1, &x2);
|
||||
for (j=0; j<2; j++) {
|
||||
secp256k1_fe_sqr(&t1, &t1);
|
||||
}
|
||||
secp256k1_fe_mul(r, a, &t1);
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
|
||||
#if defined(USE_FIELD_INV_BUILTIN)
|
||||
secp256k1_fe_inv(r, a);
|
||||
#elif defined(USE_FIELD_INV_NUM)
|
||||
secp256k1_num n, m;
|
||||
static const secp256k1_fe negone = SECP256K1_FE_CONST(
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL,
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL
|
||||
);
|
||||
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
static const unsigned char prime[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
unsigned char b[32];
|
||||
int res;
|
||||
secp256k1_fe c = *a;
|
||||
secp256k1_fe_normalize_var(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_set_bin(&m, prime, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &m);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
res = secp256k1_fe_set_b32(r, b);
|
||||
(void)res;
|
||||
VERIFY_CHECK(res);
|
||||
/* Verify the result is the (unique) valid inverse using non-GMP code. */
|
||||
secp256k1_fe_mul(&c, &c, r);
|
||||
secp256k1_fe_add(&c, &negone);
|
||||
CHECK(secp256k1_fe_normalizes_to_zero_var(&c));
|
||||
#else
|
||||
#error "Please select field inverse implementation"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) {
|
||||
secp256k1_fe u;
|
||||
size_t i;
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
VERIFY_CHECK((r + len <= a) || (a + len <= r));
|
||||
|
||||
r[0] = a[0];
|
||||
|
||||
i = 0;
|
||||
while (++i < len) {
|
||||
secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]);
|
||||
}
|
||||
|
||||
secp256k1_fe_inv_var(&u, &r[--i]);
|
||||
|
||||
while (i > 0) {
|
||||
size_t j = i--;
|
||||
secp256k1_fe_mul(&r[j], &r[i], &u);
|
||||
secp256k1_fe_mul(&u, &u, &a[j]);
|
||||
}
|
||||
|
||||
r[0] = u;
|
||||
}
|
||||
|
||||
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
|
||||
#ifndef USE_NUM_NONE
|
||||
unsigned char b[32];
|
||||
secp256k1_num n;
|
||||
secp256k1_num m;
|
||||
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
|
||||
static const unsigned char prime[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
|
||||
};
|
||||
|
||||
secp256k1_fe c = *a;
|
||||
secp256k1_fe_normalize_var(&c);
|
||||
secp256k1_fe_get_b32(b, &c);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_set_bin(&m, prime, 32);
|
||||
return secp256k1_num_jacobi(&n, &m) >= 0;
|
||||
#else
|
||||
secp256k1_fe r;
|
||||
return secp256k1_fe_sqrt(&r, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_FIELD_IMPL_H */
|
147
vendors/ocaml-secp256k1-internal/src/group.h
vendored
Normal file
147
vendors/ocaml-secp256k1-internal/src/group.h
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_GROUP_H
|
||||
#define SECP256K1_GROUP_H
|
||||
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
|
||||
/** A group element of the secp256k1 curve, in affine coordinates. */
|
||||
typedef struct {
|
||||
secp256k1_fe x;
|
||||
secp256k1_fe y;
|
||||
int infinity; /* whether this represents the point at infinity */
|
||||
} secp256k1_ge;
|
||||
|
||||
#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0}
|
||||
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
|
||||
|
||||
/** A group element of the secp256k1 curve, in jacobian coordinates. */
|
||||
typedef struct {
|
||||
secp256k1_fe x; /* actual X: x/z^2 */
|
||||
secp256k1_fe y; /* actual Y: y/z^3 */
|
||||
secp256k1_fe z;
|
||||
int infinity; /* whether this represents the point at infinity */
|
||||
} secp256k1_gej;
|
||||
|
||||
#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0}
|
||||
#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
|
||||
|
||||
typedef struct {
|
||||
secp256k1_fe_storage x;
|
||||
secp256k1_fe_storage y;
|
||||
} secp256k1_ge_storage;
|
||||
|
||||
#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))}
|
||||
|
||||
#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y)
|
||||
|
||||
/** Set a group element equal to the point with given X and Y coordinates */
|
||||
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y);
|
||||
|
||||
/** Set a group element (affine) equal to the point with the given X coordinate
|
||||
* and a Y coordinate that is a quadratic residue modulo p. The return value
|
||||
* is true iff a coordinate with the given X coordinate exists.
|
||||
*/
|
||||
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x);
|
||||
|
||||
/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness
|
||||
* for Y. Return value indicates whether the result is valid. */
|
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd);
|
||||
|
||||
/** Check whether a group element is the point at infinity. */
|
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge *a);
|
||||
|
||||
/** Check whether a group element is valid (i.e., on the curve). */
|
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a);
|
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a);
|
||||
|
||||
/** Set a group element equal to another which is given in jacobian coordinates */
|
||||
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a);
|
||||
|
||||
/** Set a batch of group elements equal to the inputs given in jacobian coordinates */
|
||||
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb);
|
||||
|
||||
/** Set a batch of group elements equal to the inputs given in jacobian
|
||||
* coordinates (with known z-ratios). zr must contain the known z-ratios such
|
||||
* that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */
|
||||
static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len);
|
||||
|
||||
/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to
|
||||
* the same global z "denominator". zr must contain the known z-ratios such
|
||||
* that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y
|
||||
* coordinates of the result are stored in r, the common z coordinate is
|
||||
* stored in globalz. */
|
||||
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr);
|
||||
|
||||
/** Set a group element (affine) equal to the point at infinity. */
|
||||
static void secp256k1_ge_set_infinity(secp256k1_ge *r);
|
||||
|
||||
/** Set a group element (jacobian) equal to the point at infinity. */
|
||||
static void secp256k1_gej_set_infinity(secp256k1_gej *r);
|
||||
|
||||
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
|
||||
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a);
|
||||
|
||||
/** Compare the X coordinate of a group element (jacobian). */
|
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
|
||||
|
||||
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */
|
||||
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a);
|
||||
|
||||
/** Check whether a group element is the point at infinity. */
|
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej *a);
|
||||
|
||||
/** Check whether a group element's y coordinate is a quadratic residue. */
|
||||
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a);
|
||||
|
||||
/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0).
|
||||
* a may not be zero. Constant time. */
|
||||
static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr);
|
||||
|
||||
/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */
|
||||
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr);
|
||||
|
||||
/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */
|
||||
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr);
|
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */
|
||||
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b);
|
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient
|
||||
than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time
|
||||
guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */
|
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr);
|
||||
|
||||
/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */
|
||||
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */
|
||||
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a);
|
||||
#endif
|
||||
|
||||
/** Clear a secp256k1_gej to prevent leaking sensitive information. */
|
||||
static void secp256k1_gej_clear(secp256k1_gej *r);
|
||||
|
||||
/** Clear a secp256k1_ge to prevent leaking sensitive information. */
|
||||
static void secp256k1_ge_clear(secp256k1_ge *r);
|
||||
|
||||
/** Convert a group element to the storage type. */
|
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a);
|
||||
|
||||
/** Convert a group element back from the storage type. */
|
||||
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a);
|
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
|
||||
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag);
|
||||
|
||||
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
|
||||
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
|
||||
|
||||
#endif /* SECP256K1_GROUP_H */
|
706
vendors/ocaml-secp256k1-internal/src/group_impl.h
vendored
Normal file
706
vendors/ocaml-secp256k1-internal/src/group_impl.h
vendored
Normal file
@ -0,0 +1,706 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_GROUP_IMPL_H
|
||||
#define SECP256K1_GROUP_IMPL_H
|
||||
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
|
||||
/* These points can be generated in sage as follows:
|
||||
*
|
||||
* 0. Setup a worksheet with the following parameters.
|
||||
* b = 4 # whatever CURVE_B will be set to
|
||||
* F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
|
||||
* C = EllipticCurve ([F (0), F (b)])
|
||||
*
|
||||
* 1. Determine all the small orders available to you. (If there are
|
||||
* no satisfactory ones, go back and change b.)
|
||||
* print C.order().factor(limit=1000)
|
||||
*
|
||||
* 2. Choose an order as one of the prime factors listed in the above step.
|
||||
* (You can also multiply some to get a composite order, though the
|
||||
* tests will crash trying to invert scalars during signing.) We take a
|
||||
* random point and scale it to drop its order to the desired value.
|
||||
* There is some probability this won't work; just try again.
|
||||
* order = 199
|
||||
* P = C.random_point()
|
||||
* P = (int(P.order()) / int(order)) * P
|
||||
* assert(P.order() == order)
|
||||
*
|
||||
* 3. Print the values. You'll need to use a vim macro or something to
|
||||
* split the hex output into 4-byte chunks.
|
||||
* print "%x %x" % P.xy()
|
||||
*/
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
# if EXHAUSTIVE_TEST_ORDER == 199
|
||||
const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069,
|
||||
0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18,
|
||||
0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868,
|
||||
0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED
|
||||
);
|
||||
|
||||
const int CURVE_B = 4;
|
||||
# elif EXHAUSTIVE_TEST_ORDER == 13
|
||||
const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0,
|
||||
0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15,
|
||||
0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e,
|
||||
0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac
|
||||
);
|
||||
const int CURVE_B = 2;
|
||||
# else
|
||||
# error No known generator for the specified exhaustive test group order.
|
||||
# endif
|
||||
#else
|
||||
/** Generator for secp256k1, value 'g' defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
|
||||
*/
|
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
|
||||
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
|
||||
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
|
||||
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
|
||||
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
|
||||
);
|
||||
|
||||
const int CURVE_B = 7;
|
||||
#endif
|
||||
|
||||
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
|
||||
secp256k1_fe zi2;
|
||||
secp256k1_fe zi3;
|
||||
secp256k1_fe_sqr(&zi2, zi);
|
||||
secp256k1_fe_mul(&zi3, &zi2, zi);
|
||||
secp256k1_fe_mul(&r->x, &a->x, &zi2);
|
||||
secp256k1_fe_mul(&r->y, &a->y, &zi3);
|
||||
r->infinity = a->infinity;
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
|
||||
r->infinity = 0;
|
||||
r->x = *x;
|
||||
r->y = *y;
|
||||
}
|
||||
|
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
|
||||
return a->infinity;
|
||||
}
|
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
|
||||
*r = *a;
|
||||
secp256k1_fe_normalize_weak(&r->y);
|
||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
|
||||
secp256k1_fe z2, z3;
|
||||
r->infinity = a->infinity;
|
||||
secp256k1_fe_inv(&a->z, &a->z);
|
||||
secp256k1_fe_sqr(&z2, &a->z);
|
||||
secp256k1_fe_mul(&z3, &a->z, &z2);
|
||||
secp256k1_fe_mul(&a->x, &a->x, &z2);
|
||||
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
||||
secp256k1_fe_set_int(&a->z, 1);
|
||||
r->x = a->x;
|
||||
r->y = a->y;
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
|
||||
secp256k1_fe z2, z3;
|
||||
r->infinity = a->infinity;
|
||||
if (a->infinity) {
|
||||
return;
|
||||
}
|
||||
secp256k1_fe_inv_var(&a->z, &a->z);
|
||||
secp256k1_fe_sqr(&z2, &a->z);
|
||||
secp256k1_fe_mul(&z3, &a->z, &z2);
|
||||
secp256k1_fe_mul(&a->x, &a->x, &z2);
|
||||
secp256k1_fe_mul(&a->y, &a->y, &z3);
|
||||
secp256k1_fe_set_int(&a->z, 1);
|
||||
r->x = a->x;
|
||||
r->y = a->y;
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) {
|
||||
secp256k1_fe *az;
|
||||
secp256k1_fe *azi;
|
||||
size_t i;
|
||||
size_t count = 0;
|
||||
az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!a[i].infinity) {
|
||||
az[count++] = a[i].z;
|
||||
}
|
||||
}
|
||||
|
||||
azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count);
|
||||
secp256k1_fe_inv_all_var(azi, az, count);
|
||||
free(az);
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
r[i].infinity = a[i].infinity;
|
||||
if (!a[i].infinity) {
|
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]);
|
||||
}
|
||||
}
|
||||
free(azi);
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) {
|
||||
size_t i = len - 1;
|
||||
secp256k1_fe zi;
|
||||
|
||||
if (len > 0) {
|
||||
/* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */
|
||||
secp256k1_fe_inv(&zi, &a[i].z);
|
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi);
|
||||
|
||||
/* Work out way backwards, using the z-ratios to scale the x/y values. */
|
||||
while (i > 0) {
|
||||
secp256k1_fe_mul(&zi, &zi, &zr[i]);
|
||||
i--;
|
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) {
|
||||
size_t i = len - 1;
|
||||
secp256k1_fe zs;
|
||||
|
||||
if (len > 0) {
|
||||
/* The z of the final point gives us the "global Z" for the table. */
|
||||
r[i].x = a[i].x;
|
||||
r[i].y = a[i].y;
|
||||
*globalz = a[i].z;
|
||||
r[i].infinity = 0;
|
||||
zs = zr[i];
|
||||
|
||||
/* Work our way backwards, using the z-ratios to scale the x/y values. */
|
||||
while (i > 0) {
|
||||
if (i != len - 1) {
|
||||
secp256k1_fe_mul(&zs, &zs, &zr[i]);
|
||||
}
|
||||
i--;
|
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
|
||||
r->infinity = 1;
|
||||
secp256k1_fe_clear(&r->x);
|
||||
secp256k1_fe_clear(&r->y);
|
||||
secp256k1_fe_clear(&r->z);
|
||||
}
|
||||
|
||||
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
|
||||
r->infinity = 1;
|
||||
secp256k1_fe_clear(&r->x);
|
||||
secp256k1_fe_clear(&r->y);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_clear(secp256k1_gej *r) {
|
||||
r->infinity = 0;
|
||||
secp256k1_fe_clear(&r->x);
|
||||
secp256k1_fe_clear(&r->y);
|
||||
secp256k1_fe_clear(&r->z);
|
||||
}
|
||||
|
||||
static void secp256k1_ge_clear(secp256k1_ge *r) {
|
||||
r->infinity = 0;
|
||||
secp256k1_fe_clear(&r->x);
|
||||
secp256k1_fe_clear(&r->y);
|
||||
}
|
||||
|
||||
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
||||
secp256k1_fe x2, x3, c;
|
||||
r->x = *x;
|
||||
secp256k1_fe_sqr(&x2, x);
|
||||
secp256k1_fe_mul(&x3, x, &x2);
|
||||
r->infinity = 0;
|
||||
secp256k1_fe_set_int(&c, CURVE_B);
|
||||
secp256k1_fe_add(&c, &x3);
|
||||
return secp256k1_fe_sqrt(&r->y, &c);
|
||||
}
|
||||
|
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
|
||||
if (!secp256k1_ge_set_xquad(r, x)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_normalize_var(&r->y);
|
||||
if (secp256k1_fe_is_odd(&r->y) != odd) {
|
||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
|
||||
r->infinity = a->infinity;
|
||||
r->x = a->x;
|
||||
r->y = a->y;
|
||||
secp256k1_fe_set_int(&r->z, 1);
|
||||
}
|
||||
|
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
|
||||
secp256k1_fe r, r2;
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
|
||||
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
|
||||
return secp256k1_fe_equal_var(&r, &r2);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
|
||||
r->infinity = a->infinity;
|
||||
r->x = a->x;
|
||||
r->y = a->y;
|
||||
r->z = a->z;
|
||||
secp256k1_fe_normalize_weak(&r->y);
|
||||
secp256k1_fe_negate(&r->y, &r->y, 1);
|
||||
}
|
||||
|
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
|
||||
return a->infinity;
|
||||
}
|
||||
|
||||
static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) {
|
||||
secp256k1_fe y2, x3, z2, z6;
|
||||
if (a->infinity) {
|
||||
return 0;
|
||||
}
|
||||
/** y^2 = x^3 + 7
|
||||
* (Y/Z^3)^2 = (X/Z^2)^3 + 7
|
||||
* Y^2 / Z^6 = X^3 / Z^6 + 7
|
||||
* Y^2 = X^3 + 7*Z^6
|
||||
*/
|
||||
secp256k1_fe_sqr(&y2, &a->y);
|
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
|
||||
secp256k1_fe_sqr(&z2, &a->z);
|
||||
secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
|
||||
secp256k1_fe_mul_int(&z6, CURVE_B);
|
||||
secp256k1_fe_add(&x3, &z6);
|
||||
secp256k1_fe_normalize_weak(&x3);
|
||||
return secp256k1_fe_equal_var(&y2, &x3);
|
||||
}
|
||||
|
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
|
||||
secp256k1_fe y2, x3, c;
|
||||
if (a->infinity) {
|
||||
return 0;
|
||||
}
|
||||
/* y^2 = x^3 + 7 */
|
||||
secp256k1_fe_sqr(&y2, &a->y);
|
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
|
||||
secp256k1_fe_set_int(&c, CURVE_B);
|
||||
secp256k1_fe_add(&x3, &c);
|
||||
secp256k1_fe_normalize_weak(&x3);
|
||||
return secp256k1_fe_equal_var(&y2, &x3);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
|
||||
/* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate.
|
||||
*
|
||||
* Note that there is an implementation described at
|
||||
* https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
* which trades a multiply for a square, but in practice this is actually slower,
|
||||
* mainly because it requires more normalizations.
|
||||
*/
|
||||
secp256k1_fe t1,t2,t3,t4;
|
||||
/** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
|
||||
* Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
|
||||
* y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
|
||||
*
|
||||
* Having said this, if this function receives a point on a sextic twist, e.g. by
|
||||
* a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6,
|
||||
* since -6 does have a cube root mod p. For this point, this function will not set
|
||||
* the infinity flag even though the point doubles to infinity, and the result
|
||||
* point will be gibberish (z = 0 but infinity = 0).
|
||||
*/
|
||||
r->infinity = a->infinity;
|
||||
if (r->infinity) {
|
||||
if (rzr != NULL) {
|
||||
secp256k1_fe_set_int(rzr, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rzr != NULL) {
|
||||
*rzr = a->y;
|
||||
secp256k1_fe_normalize_weak(rzr);
|
||||
secp256k1_fe_mul_int(rzr, 2);
|
||||
}
|
||||
|
||||
secp256k1_fe_mul(&r->z, &a->z, &a->y);
|
||||
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */
|
||||
secp256k1_fe_sqr(&t1, &a->x);
|
||||
secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */
|
||||
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */
|
||||
secp256k1_fe_sqr(&t3, &a->y);
|
||||
secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */
|
||||
secp256k1_fe_sqr(&t4, &t3);
|
||||
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */
|
||||
secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */
|
||||
r->x = t3;
|
||||
secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */
|
||||
secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */
|
||||
secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */
|
||||
secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */
|
||||
secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */
|
||||
secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */
|
||||
secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */
|
||||
secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */
|
||||
secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
|
||||
VERIFY_CHECK(!secp256k1_gej_is_infinity(a));
|
||||
secp256k1_gej_double_var(r, a, rzr);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
|
||||
/* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */
|
||||
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
||||
|
||||
if (a->infinity) {
|
||||
VERIFY_CHECK(rzr == NULL);
|
||||
*r = *b;
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->infinity) {
|
||||
if (rzr != NULL) {
|
||||
secp256k1_fe_set_int(rzr, 1);
|
||||
}
|
||||
*r = *a;
|
||||
return;
|
||||
}
|
||||
|
||||
r->infinity = 0;
|
||||
secp256k1_fe_sqr(&z22, &b->z);
|
||||
secp256k1_fe_sqr(&z12, &a->z);
|
||||
secp256k1_fe_mul(&u1, &a->x, &z22);
|
||||
secp256k1_fe_mul(&u2, &b->x, &z12);
|
||||
secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
|
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
|
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
||||
secp256k1_gej_double_var(r, a, rzr);
|
||||
} else {
|
||||
if (rzr != NULL) {
|
||||
secp256k1_fe_set_int(rzr, 0);
|
||||
}
|
||||
r->infinity = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
secp256k1_fe_sqr(&i2, &i);
|
||||
secp256k1_fe_sqr(&h2, &h);
|
||||
secp256k1_fe_mul(&h3, &h, &h2);
|
||||
secp256k1_fe_mul(&h, &h, &b->z);
|
||||
if (rzr != NULL) {
|
||||
*rzr = h;
|
||||
}
|
||||
secp256k1_fe_mul(&r->z, &a->z, &h);
|
||||
secp256k1_fe_mul(&t, &u1, &h2);
|
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
||||
secp256k1_fe_add(&r->y, &h3);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
|
||||
/* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */
|
||||
secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
||||
if (a->infinity) {
|
||||
VERIFY_CHECK(rzr == NULL);
|
||||
secp256k1_gej_set_ge(r, b);
|
||||
return;
|
||||
}
|
||||
if (b->infinity) {
|
||||
if (rzr != NULL) {
|
||||
secp256k1_fe_set_int(rzr, 1);
|
||||
}
|
||||
*r = *a;
|
||||
return;
|
||||
}
|
||||
r->infinity = 0;
|
||||
|
||||
secp256k1_fe_sqr(&z12, &a->z);
|
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1);
|
||||
secp256k1_fe_mul(&u2, &b->x, &z12);
|
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1);
|
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
|
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
||||
secp256k1_gej_double_var(r, a, rzr);
|
||||
} else {
|
||||
if (rzr != NULL) {
|
||||
secp256k1_fe_set_int(rzr, 0);
|
||||
}
|
||||
r->infinity = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
secp256k1_fe_sqr(&i2, &i);
|
||||
secp256k1_fe_sqr(&h2, &h);
|
||||
secp256k1_fe_mul(&h3, &h, &h2);
|
||||
if (rzr != NULL) {
|
||||
*rzr = h;
|
||||
}
|
||||
secp256k1_fe_mul(&r->z, &a->z, &h);
|
||||
secp256k1_fe_mul(&t, &u1, &h2);
|
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
||||
secp256k1_fe_add(&r->y, &h3);
|
||||
}
|
||||
|
||||
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
|
||||
/* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */
|
||||
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t;
|
||||
|
||||
if (b->infinity) {
|
||||
*r = *a;
|
||||
return;
|
||||
}
|
||||
if (a->infinity) {
|
||||
secp256k1_fe bzinv2, bzinv3;
|
||||
r->infinity = b->infinity;
|
||||
secp256k1_fe_sqr(&bzinv2, bzinv);
|
||||
secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv);
|
||||
secp256k1_fe_mul(&r->x, &b->x, &bzinv2);
|
||||
secp256k1_fe_mul(&r->y, &b->y, &bzinv3);
|
||||
secp256k1_fe_set_int(&r->z, 1);
|
||||
return;
|
||||
}
|
||||
r->infinity = 0;
|
||||
|
||||
/** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to
|
||||
* secp256k1's isomorphism we can multiply the Z coordinates on both sides
|
||||
* by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1).
|
||||
* This means that (rx,ry,rz) can be calculated as
|
||||
* (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz.
|
||||
* The variable az below holds the modified Z coordinate for a, which is used
|
||||
* for the computation of rx and ry, but not for rz.
|
||||
*/
|
||||
secp256k1_fe_mul(&az, &a->z, bzinv);
|
||||
|
||||
secp256k1_fe_sqr(&z12, &az);
|
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1);
|
||||
secp256k1_fe_mul(&u2, &b->x, &z12);
|
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1);
|
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az);
|
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
|
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) {
|
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
|
||||
secp256k1_gej_double_var(r, a, NULL);
|
||||
} else {
|
||||
r->infinity = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
secp256k1_fe_sqr(&i2, &i);
|
||||
secp256k1_fe_sqr(&h2, &h);
|
||||
secp256k1_fe_mul(&h3, &h, &h2);
|
||||
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h);
|
||||
secp256k1_fe_mul(&t, &u1, &h2);
|
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
|
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
|
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
|
||||
secp256k1_fe_add(&r->y, &h3);
|
||||
}
|
||||
|
||||
|
||||
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
|
||||
/* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */
|
||||
static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
|
||||
secp256k1_fe m_alt, rr_alt;
|
||||
int infinity, degenerate;
|
||||
VERIFY_CHECK(!b->infinity);
|
||||
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
|
||||
|
||||
/** In:
|
||||
* Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks.
|
||||
* In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002.
|
||||
* we find as solution for a unified addition/doubling formula:
|
||||
* lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation.
|
||||
* x3 = lambda^2 - (x1 + x2)
|
||||
* 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2).
|
||||
*
|
||||
* Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives:
|
||||
* U1 = X1*Z2^2, U2 = X2*Z1^2
|
||||
* S1 = Y1*Z2^3, S2 = Y2*Z1^3
|
||||
* Z = Z1*Z2
|
||||
* T = U1+U2
|
||||
* M = S1+S2
|
||||
* Q = T*M^2
|
||||
* R = T^2-U1*U2
|
||||
* X3 = 4*(R^2-Q)
|
||||
* Y3 = 4*(R*(3*Q-2*R^2)-M^4)
|
||||
* Z3 = 2*M*Z
|
||||
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.)
|
||||
*
|
||||
* This formula has the benefit of being the same for both addition
|
||||
* of distinct points and doubling. However, it breaks down in the
|
||||
* case that either point is infinity, or that y1 = -y2. We handle
|
||||
* these cases in the following ways:
|
||||
*
|
||||
* - If b is infinity we simply bail by means of a VERIFY_CHECK.
|
||||
*
|
||||
* - If a is infinity, we detect this, and at the end of the
|
||||
* computation replace the result (which will be meaningless,
|
||||
* but we compute to be constant-time) with b.x : b.y : 1.
|
||||
*
|
||||
* - If a = -b, we have y1 = -y2, which is a degenerate case.
|
||||
* But here the answer is infinity, so we simply set the
|
||||
* infinity flag of the result, overriding the computed values
|
||||
* without even needing to cmov.
|
||||
*
|
||||
* - If y1 = -y2 but x1 != x2, which does occur thanks to certain
|
||||
* properties of our curve (specifically, 1 has nontrivial cube
|
||||
* roots in our field, and the curve equation has no x coefficient)
|
||||
* then the answer is not infinity but also not given by the above
|
||||
* equation. In this case, we cmov in place an alternate expression
|
||||
* for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these
|
||||
* expressions for lambda are defined, they are equal, and can be
|
||||
* obtained from each other by multiplication by (y1 + y2)/(y1 + y2)
|
||||
* then substitution of x^3 + 7 for y^2 (using the curve equation).
|
||||
* For all pairs of nonzero points (a, b) at least one is defined,
|
||||
* so this covers everything.
|
||||
*/
|
||||
|
||||
secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
|
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */
|
||||
secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
|
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
|
||||
secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */
|
||||
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
|
||||
t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */
|
||||
m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */
|
||||
secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */
|
||||
secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */
|
||||
secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */
|
||||
secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */
|
||||
/** If lambda = R/M = 0/0 we have a problem (except in the "trivial"
|
||||
* case that Z = z1z2 = 0, and this is special-cased later on). */
|
||||
degenerate = secp256k1_fe_normalizes_to_zero(&m) &
|
||||
secp256k1_fe_normalizes_to_zero(&rr);
|
||||
/* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2.
|
||||
* This means either x1 == beta*x2 or beta*x1 == x2, where beta is
|
||||
* a nontrivial cube root of one. In either case, an alternate
|
||||
* non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2),
|
||||
* so we set R/M equal to this. */
|
||||
rr_alt = s1;
|
||||
secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */
|
||||
secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */
|
||||
|
||||
secp256k1_fe_cmov(&rr_alt, &rr, !degenerate);
|
||||
secp256k1_fe_cmov(&m_alt, &m, !degenerate);
|
||||
/* Now Ralt / Malt = lambda and is guaranteed not to be 0/0.
|
||||
* From here on out Ralt and Malt represent the numerator
|
||||
* and denominator of lambda; R and M represent the explicit
|
||||
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */
|
||||
secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */
|
||||
secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */
|
||||
/* These two lines use the observation that either M == Malt or M == 0,
|
||||
* so M^3 * Malt is either Malt^4 (which is computed by squaring), or
|
||||
* zero (which is "computed" by cmov). So the cost is one squaring
|
||||
* versus two multiplications. */
|
||||
secp256k1_fe_sqr(&n, &n);
|
||||
secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */
|
||||
secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */
|
||||
secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */
|
||||
infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity);
|
||||
secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */
|
||||
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
|
||||
secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */
|
||||
secp256k1_fe_normalize_weak(&t);
|
||||
r->x = t; /* r->x = Ralt^2-Q (1) */
|
||||
secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */
|
||||
secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */
|
||||
secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */
|
||||
secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */
|
||||
secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */
|
||||
secp256k1_fe_normalize_weak(&r->y);
|
||||
secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */
|
||||
secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */
|
||||
|
||||
/** In case a->infinity == 1, replace r with (b->x, b->y, 1). */
|
||||
secp256k1_fe_cmov(&r->x, &b->x, a->infinity);
|
||||
secp256k1_fe_cmov(&r->y, &b->y, a->infinity);
|
||||
secp256k1_fe_cmov(&r->z, &fe_1, a->infinity);
|
||||
r->infinity = infinity;
|
||||
}
|
||||
|
||||
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
|
||||
/* Operations: 4 mul, 1 sqr */
|
||||
secp256k1_fe zz;
|
||||
VERIFY_CHECK(!secp256k1_fe_is_zero(s));
|
||||
secp256k1_fe_sqr(&zz, s);
|
||||
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
|
||||
secp256k1_fe_mul(&r->y, &r->y, &zz);
|
||||
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
|
||||
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
|
||||
}
|
||||
|
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
|
||||
secp256k1_fe x, y;
|
||||
VERIFY_CHECK(!a->infinity);
|
||||
x = a->x;
|
||||
secp256k1_fe_normalize(&x);
|
||||
y = a->y;
|
||||
secp256k1_fe_normalize(&y);
|
||||
secp256k1_fe_to_storage(&r->x, &x);
|
||||
secp256k1_fe_to_storage(&r->y, &y);
|
||||
}
|
||||
|
||||
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) {
|
||||
secp256k1_fe_from_storage(&r->x, &a->x);
|
||||
secp256k1_fe_from_storage(&r->y, &a->y);
|
||||
r->infinity = 0;
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
|
||||
secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
|
||||
secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
|
||||
}
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
|
||||
static const secp256k1_fe beta = SECP256K1_FE_CONST(
|
||||
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
|
||||
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
|
||||
);
|
||||
*r = *a;
|
||||
secp256k1_fe_mul(&r->x, &r->x, &beta);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
|
||||
secp256k1_fe yz;
|
||||
|
||||
if (a->infinity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as
|
||||
* that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z
|
||||
is */
|
||||
secp256k1_fe_mul(&yz, &a->y, &a->z);
|
||||
return secp256k1_fe_is_quad_var(&yz);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_GROUP_IMPL_H */
|
41
vendors/ocaml-secp256k1-internal/src/hash.h
vendored
Normal file
41
vendors/ocaml-secp256k1-internal/src/hash.h
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_HASH_H
|
||||
#define SECP256K1_HASH_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t s[8];
|
||||
uint32_t buf[16]; /* In big endian */
|
||||
size_t bytes;
|
||||
} secp256k1_sha256;
|
||||
|
||||
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
|
||||
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
|
||||
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
|
||||
|
||||
typedef struct {
|
||||
secp256k1_sha256 inner, outer;
|
||||
} secp256k1_hmac_sha256;
|
||||
|
||||
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
|
||||
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
|
||||
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32);
|
||||
|
||||
typedef struct {
|
||||
unsigned char v[32];
|
||||
unsigned char k[32];
|
||||
int retry;
|
||||
} secp256k1_rfc6979_hmac_sha256;
|
||||
|
||||
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
|
||||
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
|
||||
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng);
|
||||
|
||||
#endif /* SECP256K1_HASH_H */
|
282
vendors/ocaml-secp256k1-internal/src/hash_impl.h
vendored
Normal file
282
vendors/ocaml-secp256k1-internal/src/hash_impl.h
vendored
Normal file
@ -0,0 +1,282 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_HASH_IMPL_H
|
||||
#define SECP256K1_HASH_IMPL_H
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
|
||||
#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10))
|
||||
#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7))
|
||||
#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3))
|
||||
#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10))
|
||||
|
||||
#define Round(a,b,c,d,e,f,g,h,k,w) do { \
|
||||
uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \
|
||||
uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \
|
||||
(d) += t1; \
|
||||
(h) = t1 + t2; \
|
||||
} while(0)
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define BE32(x) (x)
|
||||
#else
|
||||
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
|
||||
#endif
|
||||
|
||||
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
|
||||
hash->s[0] = 0x6a09e667ul;
|
||||
hash->s[1] = 0xbb67ae85ul;
|
||||
hash->s[2] = 0x3c6ef372ul;
|
||||
hash->s[3] = 0xa54ff53aul;
|
||||
hash->s[4] = 0x510e527ful;
|
||||
hash->s[5] = 0x9b05688cul;
|
||||
hash->s[6] = 0x1f83d9abul;
|
||||
hash->s[7] = 0x5be0cd19ul;
|
||||
hash->bytes = 0;
|
||||
}
|
||||
|
||||
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
|
||||
static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
|
||||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
|
||||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0]));
|
||||
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1]));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2]));
|
||||
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3]));
|
||||
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4]));
|
||||
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5]));
|
||||
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6]));
|
||||
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7]));
|
||||
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8]));
|
||||
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9]));
|
||||
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10]));
|
||||
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11]));
|
||||
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12]));
|
||||
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13]));
|
||||
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14]));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15]));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
s[0] += a;
|
||||
s[1] += b;
|
||||
s[2] += c;
|
||||
s[3] += d;
|
||||
s[4] += e;
|
||||
s[5] += f;
|
||||
s[6] += g;
|
||||
s[7] += h;
|
||||
}
|
||||
|
||||
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) {
|
||||
size_t bufsize = hash->bytes & 0x3F;
|
||||
hash->bytes += len;
|
||||
while (bufsize + len >= 64) {
|
||||
/* Fill the buffer, and process it. */
|
||||
size_t chunk_len = 64 - bufsize;
|
||||
memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len);
|
||||
data += chunk_len;
|
||||
len -= chunk_len;
|
||||
secp256k1_sha256_transform(hash->s, hash->buf);
|
||||
bufsize = 0;
|
||||
}
|
||||
if (len) {
|
||||
/* Fill the buffer with what remains. */
|
||||
memcpy(((unsigned char*)hash->buf) + bufsize, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) {
|
||||
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint32_t sizedesc[2];
|
||||
uint32_t out[8];
|
||||
int i = 0;
|
||||
sizedesc[0] = BE32(hash->bytes >> 29);
|
||||
sizedesc[1] = BE32(hash->bytes << 3);
|
||||
secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
|
||||
secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8);
|
||||
for (i = 0; i < 8; i++) {
|
||||
out[i] = BE32(hash->s[i]);
|
||||
hash->s[i] = 0;
|
||||
}
|
||||
memcpy(out32, (const unsigned char*)out, 32);
|
||||
}
|
||||
|
||||
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
|
||||
size_t n;
|
||||
unsigned char rkey[64];
|
||||
if (keylen <= sizeof(rkey)) {
|
||||
memcpy(rkey, key, keylen);
|
||||
memset(rkey + keylen, 0, sizeof(rkey) - keylen);
|
||||
} else {
|
||||
secp256k1_sha256 sha256;
|
||||
secp256k1_sha256_initialize(&sha256);
|
||||
secp256k1_sha256_write(&sha256, key, keylen);
|
||||
secp256k1_sha256_finalize(&sha256, rkey);
|
||||
memset(rkey + 32, 0, 32);
|
||||
}
|
||||
|
||||
secp256k1_sha256_initialize(&hash->outer);
|
||||
for (n = 0; n < sizeof(rkey); n++) {
|
||||
rkey[n] ^= 0x5c;
|
||||
}
|
||||
secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey));
|
||||
|
||||
secp256k1_sha256_initialize(&hash->inner);
|
||||
for (n = 0; n < sizeof(rkey); n++) {
|
||||
rkey[n] ^= 0x5c ^ 0x36;
|
||||
}
|
||||
secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey));
|
||||
memset(rkey, 0, sizeof(rkey));
|
||||
}
|
||||
|
||||
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) {
|
||||
secp256k1_sha256_write(&hash->inner, data, size);
|
||||
}
|
||||
|
||||
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) {
|
||||
unsigned char temp[32];
|
||||
secp256k1_sha256_finalize(&hash->inner, temp);
|
||||
secp256k1_sha256_write(&hash->outer, temp, 32);
|
||||
memset(temp, 0, 32);
|
||||
secp256k1_sha256_finalize(&hash->outer, out32);
|
||||
}
|
||||
|
||||
|
||||
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) {
|
||||
secp256k1_hmac_sha256 hmac;
|
||||
static const unsigned char zero[1] = {0x00};
|
||||
static const unsigned char one[1] = {0x01};
|
||||
|
||||
memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */
|
||||
memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */
|
||||
|
||||
/* RFC6979 3.2.d. */
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, zero, 1);
|
||||
secp256k1_hmac_sha256_write(&hmac, key, keylen);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
|
||||
|
||||
/* RFC6979 3.2.f. */
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, one, 1);
|
||||
secp256k1_hmac_sha256_write(&hmac, key, keylen);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
|
||||
rng->retry = 0;
|
||||
}
|
||||
|
||||
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) {
|
||||
/* RFC6979 3.2.h. */
|
||||
static const unsigned char zero[1] = {0x00};
|
||||
if (rng->retry) {
|
||||
secp256k1_hmac_sha256 hmac;
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, zero, 1);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->k);
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
|
||||
}
|
||||
|
||||
while (outlen > 0) {
|
||||
secp256k1_hmac_sha256 hmac;
|
||||
int now = outlen;
|
||||
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
|
||||
secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
|
||||
secp256k1_hmac_sha256_finalize(&hmac, rng->v);
|
||||
if (now > 32) {
|
||||
now = 32;
|
||||
}
|
||||
memcpy(out, rng->v, now);
|
||||
out += now;
|
||||
outlen -= now;
|
||||
}
|
||||
|
||||
rng->retry = 1;
|
||||
}
|
||||
|
||||
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) {
|
||||
memset(rng->k, 0, 32);
|
||||
memset(rng->v, 0, 32);
|
||||
rng->retry = 0;
|
||||
}
|
||||
|
||||
#undef BE32
|
||||
#undef Round
|
||||
#undef sigma1
|
||||
#undef sigma0
|
||||
#undef Sigma1
|
||||
#undef Sigma0
|
||||
#undef Maj
|
||||
#undef Ch
|
||||
|
||||
#endif /* SECP256K1_HASH_IMPL_H */
|
413
vendors/ocaml-secp256k1-internal/src/internal.ml
vendored
Normal file
413
vendors/ocaml-secp256k1-internal/src/internal.ml
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
module Num = struct
|
||||
type t = Cstruct.buffer
|
||||
|
||||
external size :
|
||||
unit -> int = "sizeof_secp256k1_num" [@@noalloc]
|
||||
external copy :
|
||||
t -> t -> unit = "ml_secp256k1_num_copy" [@@noalloc]
|
||||
external get_bin :
|
||||
Cstruct.buffer -> int -> t -> unit = "ml_secp256k1_num_get_bin" [@@noalloc]
|
||||
external set_bin :
|
||||
t -> Cstruct.buffer -> int -> unit = "ml_secp256k1_num_set_bin" [@@noalloc]
|
||||
external mod_inverse :
|
||||
t -> t -> t -> unit = "ml_secp256k1_num_mod_inverse" [@@noalloc]
|
||||
external jacobi :
|
||||
t -> t -> int = "ml_secp256k1_num_jacobi" [@@noalloc]
|
||||
external compare :
|
||||
t -> t -> int = "ml_secp256k1_num_cmp" [@@noalloc]
|
||||
external equal :
|
||||
t -> t -> bool = "ml_secp256k1_num_eq" [@@noalloc]
|
||||
external add :
|
||||
t -> t -> t -> unit = "ml_secp256k1_num_add" [@@noalloc]
|
||||
external sub :
|
||||
t -> t -> t -> unit = "ml_secp256k1_num_sub" [@@noalloc]
|
||||
external mul :
|
||||
t -> t -> t -> unit = "ml_secp256k1_num_mul" [@@noalloc]
|
||||
external modulo :
|
||||
t -> t -> unit = "ml_secp256k1_num_mod" [@@noalloc]
|
||||
external shift :
|
||||
t -> int -> unit = "ml_secp256k1_num_shift" [@@noalloc]
|
||||
external is_zero :
|
||||
t -> bool = "ml_secp256k1_num_is_zero" [@@noalloc]
|
||||
external is_one :
|
||||
t -> bool = "ml_secp256k1_num_is_one" [@@noalloc]
|
||||
external is_neg :
|
||||
t -> bool = "ml_secp256k1_num_is_neg" [@@noalloc]
|
||||
external negate :
|
||||
t -> unit = "ml_secp256k1_num_negate" [@@noalloc]
|
||||
|
||||
let size = size ()
|
||||
|
||||
let get_bin cs =
|
||||
Cstruct.(get_bin (to_bigarray cs) (len cs))
|
||||
let set_bin r cs =
|
||||
Cstruct.(set_bin r (to_bigarray cs) (len cs))
|
||||
|
||||
let of_uint16 i =
|
||||
let t = Cstruct.create size in
|
||||
let cs = Cstruct.create 2 in
|
||||
Cstruct.BE.set_uint16 cs 0 i ;
|
||||
set_bin t.buffer cs ;
|
||||
t.buffer
|
||||
|
||||
let zero () = of_uint16 0
|
||||
let one () = of_uint16 1
|
||||
|
||||
let of_uint32 i =
|
||||
let t = Cstruct.create size in
|
||||
let cs = Cstruct.create 4 in
|
||||
Cstruct.BE.set_uint32 cs 0 i ;
|
||||
set_bin t.buffer cs ;
|
||||
t.buffer
|
||||
|
||||
let of_uint64 i =
|
||||
let t = Cstruct.create size in
|
||||
let cs = Cstruct.create 8 in
|
||||
Cstruct.BE.set_uint64 cs 0 i ;
|
||||
set_bin t.buffer cs ;
|
||||
t.buffer
|
||||
end
|
||||
|
||||
module Scalar = struct
|
||||
type t = Cstruct.buffer
|
||||
|
||||
let size = 32
|
||||
|
||||
external const :
|
||||
t -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> unit =
|
||||
"ml_secp256k1_fe_const_bytecode" "ml_secp256k1_fe_const" [@@noalloc]
|
||||
|
||||
let const ?(d7=0L) ?(d6=0L) ?(d5=0L) ?(d4=0L) ?(d3=0L) ?(d2=0L) ?(d1=0L) ?(d0=0L) () =
|
||||
let buf = Cstruct.create size in
|
||||
const buf.buffer d7 d6 d5 d4 d3 d2 d1 d0 ;
|
||||
buf.buffer
|
||||
|
||||
let zero () = const ()
|
||||
let one () = const ~d0:1L ()
|
||||
let copy t =
|
||||
let ret = Cstruct.create size in
|
||||
Cstruct.(blit (of_bigarray t) 0 ret 0 size) ;
|
||||
ret.buffer
|
||||
|
||||
external clear :
|
||||
t -> unit = "ml_secp256k1_scalar_clear" [@@noalloc]
|
||||
external get_bits :
|
||||
t -> int -> int -> int = "ml_secp256k1_scalar_get_bits" [@@noalloc]
|
||||
external get_bits_var :
|
||||
t -> int -> int -> int = "ml_secp256k1_scalar_get_bits_var" [@@noalloc]
|
||||
external set_b32 :
|
||||
t -> Cstruct.buffer -> bool = "ml_secp256k1_scalar_set_b32" [@@noalloc]
|
||||
external set_int :
|
||||
Cstruct.buffer -> int -> unit = "ml_secp256k1_scalar_set_int" [@@noalloc]
|
||||
external get_b32 :
|
||||
Cstruct.buffer -> t -> unit = "ml_secp256k1_scalar_get_b32" [@@noalloc]
|
||||
external add :
|
||||
t -> t -> t -> bool = "ml_secp256k1_scalar_add" [@@noalloc]
|
||||
external cadd_bit :
|
||||
t -> int -> bool -> unit = "ml_secp256k1_scalar_cadd_bit" [@@noalloc]
|
||||
external mul :
|
||||
t -> t -> t -> unit = "ml_secp256k1_scalar_mul" [@@noalloc]
|
||||
external shr_int :
|
||||
t -> int -> int = "ml_secp256k1_scalar_shr_int" [@@noalloc]
|
||||
external sqr :
|
||||
t -> t -> unit = "ml_secp256k1_scalar_sqr" [@@noalloc]
|
||||
external inverse :
|
||||
t -> t -> unit = "ml_secp256k1_scalar_inverse" [@@noalloc]
|
||||
external inverse_var :
|
||||
t -> t -> unit = "ml_secp256k1_scalar_inverse_var" [@@noalloc]
|
||||
external negate :
|
||||
t -> t -> unit = "ml_secp256k1_scalar_negate" [@@noalloc]
|
||||
external is_zero :
|
||||
t -> bool = "ml_secp256k1_scalar_is_zero" [@@noalloc]
|
||||
external is_one :
|
||||
t -> bool = "ml_secp256k1_scalar_is_one" [@@noalloc]
|
||||
external is_even :
|
||||
t -> bool = "ml_secp256k1_scalar_is_even" [@@noalloc]
|
||||
external is_high :
|
||||
t -> bool = "ml_secp256k1_scalar_is_high" [@@noalloc]
|
||||
external cond_negate :
|
||||
t -> bool -> bool = "ml_secp256k1_scalar_cond_negate" [@@noalloc]
|
||||
external get_num :
|
||||
Num.t -> t -> unit = "ml_secp256k1_scalar_get_num" [@@noalloc]
|
||||
external order_get_num :
|
||||
Num.t -> unit = "ml_secp256k1_scalar_order_get_num" [@@noalloc]
|
||||
external equal :
|
||||
t -> t -> bool = "ml_secp256k1_scalar_eq" [@@noalloc]
|
||||
external mul_shift_var :
|
||||
t -> t -> t -> int -> unit = "ml_secp256k1_mul_shift_var" [@@noalloc]
|
||||
|
||||
let set_b32 t buf = set_b32 t (Cstruct.to_bigarray buf)
|
||||
let get_b32 buf t = get_b32 (Cstruct.to_bigarray buf) t
|
||||
end
|
||||
|
||||
module Field = struct
|
||||
type t = Cstruct.buffer
|
||||
|
||||
module Storage = struct
|
||||
type t = Cstruct.buffer
|
||||
let size = 32
|
||||
let to_cstruct t = Cstruct.of_bigarray t
|
||||
let of_cstruct cs =
|
||||
let res = Cstruct.create size in
|
||||
try
|
||||
Cstruct.blit cs 0 res 0 size ;
|
||||
Some res.buffer
|
||||
with _ -> None
|
||||
let of_cstruct_exn cs =
|
||||
match of_cstruct cs with
|
||||
| Some t -> t
|
||||
| None -> invalid_arg "Field.Storage.of_cstruct_exn"
|
||||
|
||||
external const :
|
||||
t -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> unit =
|
||||
"ml_secp256k1_fe_storage_const_bytecode" "ml_secp256k1_fe_storage_const" [@@noalloc]
|
||||
|
||||
let const ?(d7=0L) ?(d6=0L) ?(d5=0L) ?(d4=0L) ?(d3=0L) ?(d2=0L) ?(d1=0L) ?(d0=0L) () =
|
||||
let buf = Cstruct.create size in
|
||||
const buf.buffer d7 d6 d5 d4 d3 d2 d1 d0 ;
|
||||
buf.buffer
|
||||
|
||||
external cmov :
|
||||
t -> t -> bool -> unit = "ml_secp256k1_fe_storage_cmov" [@@noalloc]
|
||||
end
|
||||
|
||||
let size = 40
|
||||
|
||||
external const :
|
||||
t -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> int64 -> unit =
|
||||
"ml_secp256k1_fe_const_bytecode" "ml_secp256k1_fe_const" [@@noalloc]
|
||||
|
||||
let const ?(d7=0L) ?(d6=0L) ?(d5=0L) ?(d4=0L) ?(d3=0L) ?(d2=0L) ?(d1=0L) ?(d0=0L) () =
|
||||
let buf = Cstruct.create size in
|
||||
const buf.buffer d7 d6 d5 d4 d3 d2 d1 d0 ;
|
||||
buf.buffer
|
||||
|
||||
external normalize :
|
||||
t -> unit = "ml_secp256k1_fe_normalize" [@@noalloc]
|
||||
external normalize_weak :
|
||||
t -> unit = "ml_secp256k1_fe_normalize_weak" [@@noalloc]
|
||||
external normalize_var :
|
||||
t -> unit = "ml_secp256k1_fe_normalize_var" [@@noalloc]
|
||||
external normalizes_to_zero :
|
||||
t -> bool = "ml_secp256k1_fe_normalizes_to_zero" [@@noalloc]
|
||||
external normalizes_to_zero_var :
|
||||
t -> bool = "ml_secp256k1_fe_normalizes_to_zero_var" [@@noalloc]
|
||||
external set_int :
|
||||
t -> int -> unit = "ml_secp256k1_fe_set_int" [@@noalloc]
|
||||
external clear :
|
||||
t -> unit = "ml_secp256k1_fe_clear" [@@noalloc]
|
||||
external is_zero :
|
||||
t -> bool = "ml_secp256k1_fe_is_zero" [@@noalloc]
|
||||
external is_odd :
|
||||
t -> bool = "ml_secp256k1_fe_is_odd" [@@noalloc]
|
||||
external equal :
|
||||
t -> t -> bool = "ml_secp256k1_fe_equal" [@@noalloc]
|
||||
external equal_var :
|
||||
t -> t -> bool = "ml_secp256k1_fe_equal_var" [@@noalloc]
|
||||
external cmp_var :
|
||||
t -> t -> int = "ml_secp256k1_fe_cmp_var" [@@noalloc]
|
||||
external set_b32 :
|
||||
t -> Cstruct.buffer -> bool = "ml_secp256k1_fe_set_b32" [@@noalloc]
|
||||
external get_b32 :
|
||||
Cstruct.buffer -> t -> unit = "ml_secp256k1_fe_get_b32" [@@noalloc]
|
||||
external negate :
|
||||
t -> t -> int -> unit = "ml_secp256k1_fe_negate" [@@noalloc]
|
||||
external mul_int :
|
||||
t -> int -> unit = "ml_secp256k1_fe_mul_int" [@@noalloc]
|
||||
external add :
|
||||
t -> t -> unit = "ml_secp256k1_fe_add" [@@noalloc]
|
||||
external mul :
|
||||
t -> t -> t -> unit = "ml_secp256k1_fe_mul" [@@noalloc]
|
||||
external sqr :
|
||||
t -> t -> unit = "ml_secp256k1_fe_sqr" [@@noalloc]
|
||||
external sqrt :
|
||||
t -> t -> int = "ml_secp256k1_fe_sqrt" [@@noalloc]
|
||||
external is_quad_var :
|
||||
t -> bool = "ml_secp256k1_fe_is_quad_var" [@@noalloc]
|
||||
external inv :
|
||||
t -> t -> unit = "ml_secp256k1_fe_inv" [@@noalloc]
|
||||
external inv_var :
|
||||
t -> t -> unit = "ml_secp256k1_fe_inv_var" [@@noalloc]
|
||||
external inv_all_var :
|
||||
t -> Cstruct.buffer -> int -> unit = "ml_secp256k1_fe_inv_all_var" [@@noalloc]
|
||||
external to_storage :
|
||||
Storage.t -> t -> unit = "ml_secp256k1_fe_to_storage" [@@noalloc]
|
||||
external from_storage :
|
||||
t -> Storage.t -> unit = "ml_secp256k1_fe_from_storage" [@@noalloc]
|
||||
external cmov :
|
||||
t -> t -> bool -> unit = "ml_secp256k1_fe_cmov" [@@noalloc]
|
||||
|
||||
let inv_all_var r fes =
|
||||
let nb_fe = List.length fes in
|
||||
let cs = Cstruct.create (nb_fe * size) in
|
||||
List.iteri
|
||||
(fun i fe -> Cstruct.(blit (of_bigarray fe) 0 cs (i*size) size)) fes ;
|
||||
inv_all_var r cs.buffer nb_fe ;
|
||||
Cstruct.memset cs 0
|
||||
|
||||
let set_b32 t buf = set_b32 t (Cstruct.to_bigarray buf)
|
||||
let get_b32 buf t = get_b32 (Cstruct.to_bigarray buf) t
|
||||
|
||||
let compare = cmp_var
|
||||
end
|
||||
|
||||
module Group = struct
|
||||
type t = Cstruct.buffer
|
||||
type ge = t
|
||||
|
||||
let size = 2 * Field.size + 8
|
||||
|
||||
module Storage = struct
|
||||
type t = Cstruct.buffer
|
||||
let size = 2 * Field.Storage.size
|
||||
let to_cstruct t = Cstruct.of_bigarray t
|
||||
let of_cstruct cs =
|
||||
let res = Cstruct.create size in
|
||||
try
|
||||
Cstruct.blit cs 0 res 0 size ;
|
||||
Some res.buffer
|
||||
with _ -> None
|
||||
let of_cstruct_exn cs =
|
||||
match of_cstruct cs with
|
||||
| Some t -> t
|
||||
| None -> invalid_arg "Group.Storage.of_cstruct_exn"
|
||||
external of_fields :
|
||||
t -> Field.Storage.t -> Field.Storage.t -> unit =
|
||||
"ml_secp256k1_ge_storage_of_fields" [@@noalloc]
|
||||
let of_fields ?(x=Field.const ()) ?(y=Field.const ()) () =
|
||||
let cs = Cstruct.create size in
|
||||
of_fields cs.buffer x y ;
|
||||
cs.buffer
|
||||
external cmov : t -> t -> bool -> unit =
|
||||
"ml_secp256k1_ge_storage_cmov" [@@noalloc]
|
||||
end
|
||||
|
||||
module Jacobian = struct
|
||||
type t = Cstruct.buffer
|
||||
|
||||
let size = 3 * Field.size + 8
|
||||
|
||||
external of_fields :
|
||||
t -> Field.t -> Field.t -> Field.t -> bool -> unit =
|
||||
"ml_secp256k1_gej_of_fields" [@@noalloc]
|
||||
|
||||
external set_infinity : t -> unit =
|
||||
"ml_secp256k1_gej_set_infinity" [@@noalloc]
|
||||
|
||||
external set_ge : t -> ge -> unit =
|
||||
"ml_secp256k1_gej_set_ge" [@@noalloc]
|
||||
|
||||
external get_ge : ge -> t -> unit =
|
||||
"ml_secp256k1_ge_set_gej" [@@noalloc]
|
||||
|
||||
external eq_x_var : Field.t -> t -> int =
|
||||
"ml_secp256k1_gej_eq_x_var" [@@noalloc]
|
||||
|
||||
external neg : t -> t -> unit =
|
||||
"ml_secp256k1_gej_neg" [@@noalloc]
|
||||
|
||||
external is_infinity : t -> bool =
|
||||
"ml_secp256k1_gej_is_infinity" [@@noalloc]
|
||||
|
||||
external has_quad_y_var : t -> bool =
|
||||
"ml_secp256k1_gej_has_quad_y_var" [@@noalloc]
|
||||
|
||||
external double_nonzero : t -> t -> Field.t option -> unit =
|
||||
"ml_secp256k1_gej_double_nonzero" [@@noalloc]
|
||||
|
||||
external double_var : t -> t -> Field.t option -> unit =
|
||||
"ml_secp256k1_gej_double_var" [@@noalloc]
|
||||
|
||||
external add_var : t -> t -> t -> Field.t option -> unit =
|
||||
"ml_secp256k1_gej_add_var" [@@noalloc]
|
||||
|
||||
external add_ge : t -> t -> ge -> unit =
|
||||
"ml_secp256k1_gej_add_ge" [@@noalloc]
|
||||
|
||||
external add_ge_var : t -> t -> ge -> Field.t option -> unit =
|
||||
"ml_secp256k1_gej_add_ge_var" [@@noalloc]
|
||||
|
||||
external add_zinv_var : t -> t -> ge -> Field.t -> unit =
|
||||
"ml_secp256k1_gej_add_zinv_var" [@@noalloc]
|
||||
|
||||
external mul : t -> ge -> Scalar.t -> unit =
|
||||
"ml_secp256k1_ecmult_const" [@@noalloc]
|
||||
|
||||
external clear : t -> unit =
|
||||
"ml_secp256k1_gej_clear" [@@noalloc]
|
||||
|
||||
external rescale : t -> Field.t -> unit =
|
||||
"ml_secp256k1_gej_rescale" [@@noalloc]
|
||||
|
||||
let of_fields ?(x=Field.const ()) ?(y=Field.const ()) ?(z=Field.const ()) ?(infinity=false) () =
|
||||
let cs = Cstruct.create size in
|
||||
of_fields cs.buffer x y z infinity ;
|
||||
cs.buffer
|
||||
|
||||
let double_nonzero ?rzr r a = double_nonzero r a rzr
|
||||
let double_var ?rzr r a = double_var r a rzr
|
||||
let add_var ?rzr r a b = add_var r a b rzr
|
||||
let add_ge_var ?rzr r a b = add_ge_var r a b rzr
|
||||
end
|
||||
|
||||
external of_fields :
|
||||
t -> Field.t -> Field.t -> bool -> unit =
|
||||
"ml_secp256k1_ge_of_fields" [@@noalloc]
|
||||
|
||||
external set_xy : t -> Field.t -> Field.t -> unit =
|
||||
"ml_secp256k1_ge_set_xy" [@@noalloc]
|
||||
|
||||
external set_xquad : t -> Field.t -> unit =
|
||||
"ml_secp256k1_ge_set_xquad" [@@noalloc]
|
||||
|
||||
external set_xovar : t -> Field.t -> int -> bool =
|
||||
"ml_secp256k1_ge_set_xquad" [@@noalloc]
|
||||
|
||||
external is_infinity : t -> bool =
|
||||
"ml_secp256k1_ge_is_infinity" [@@noalloc]
|
||||
|
||||
external is_valid_var : t -> bool =
|
||||
"ml_secp256k1_ge_is_valid_var" [@@noalloc]
|
||||
|
||||
external neg : t -> t -> unit =
|
||||
"ml_secp256k1_ge_neg" [@@noalloc]
|
||||
|
||||
external clear : t -> unit =
|
||||
"ml_secp256k1_ge_clear" [@@noalloc]
|
||||
|
||||
external to_storage : Storage.t -> t -> unit =
|
||||
"ml_secp256k1_ge_to_storage" [@@noalloc]
|
||||
|
||||
external from_storage : t -> Storage.t -> unit =
|
||||
"ml_secp256k1_ge_from_storage" [@@noalloc]
|
||||
|
||||
let of_fields ?(x=Field.const ()) ?(y=Field.const ()) ?(infinity=false) () =
|
||||
let cs = Cstruct.create size in
|
||||
of_fields cs.buffer x y infinity ;
|
||||
cs.buffer
|
||||
|
||||
let g =
|
||||
let x = Field.const
|
||||
~d7:0x79BE667EL ~d6:0xF9DCBBACL ~d5:0x55A06295L ~d4:0xCE870B07L
|
||||
~d3:0x029BFCDBL ~d2:0x2DCE28D9L ~d1:0x59F2815BL ~d0:0x16F81798L () in
|
||||
let y = Field.const
|
||||
~d7:0x483ADA77L ~d6:0x26A3C465L ~d5:0x5DA4FBFCL ~d4:0x0E1108A8L
|
||||
~d3:0xFD17B448L ~d2:0xA6855419L ~d1:0x9C47D08FL ~d0:0xFB10D4B8L () in
|
||||
of_fields ~x ~y ~infinity:false ()
|
||||
|
||||
external serialize : t -> Cstruct.buffer -> int -> bool -> int =
|
||||
"ml_secp256k1_eckey_pubkey_serialize" [@@noalloc]
|
||||
|
||||
external parse : t -> Cstruct.buffer -> int -> bool =
|
||||
"ml_secp256k1_eckey_pubkey_parse" [@@noalloc]
|
||||
|
||||
let to_pubkey ?(compress=true) cs e =
|
||||
match serialize e cs.Cstruct.buffer cs.len compress with
|
||||
| 0 -> failwith "Group.to_pubkey"
|
||||
| len -> Cstruct.sub cs 0 len
|
||||
|
||||
let from_pubkey t cs =
|
||||
match parse t cs.Cstruct.buffer cs.len with
|
||||
| false -> failwith "Group.from_pubkey"
|
||||
| true -> ()
|
||||
end
|
450
vendors/ocaml-secp256k1-internal/src/internal.mli
vendored
Normal file
450
vendors/ocaml-secp256k1-internal/src/internal.mli
vendored
Normal file
@ -0,0 +1,450 @@
|
||||
module Num : sig
|
||||
type t
|
||||
|
||||
val zero : unit -> t
|
||||
val one : unit -> t
|
||||
val of_uint16 : int -> t
|
||||
val of_uint32 : int32 -> t
|
||||
val of_uint64 : int64 -> t
|
||||
|
||||
val copy : t -> t -> unit
|
||||
(** Copy a number. *)
|
||||
|
||||
val get_bin : Cstruct.t -> t -> unit
|
||||
(** Convert a number's absolute value to a binary big-endian string.
|
||||
There must be enough place. *)
|
||||
|
||||
val set_bin : t -> Cstruct.t -> unit
|
||||
(** Set a number to the value of a binary big-endian string. *)
|
||||
|
||||
val mod_inverse : t -> t -> t -> unit
|
||||
(** [mod_inverse r a m] Compute a modular inverse. The input must be
|
||||
less than the modulus. *)
|
||||
|
||||
val jacobi : t -> t -> int
|
||||
(** Compute the jacobi symbol (a|b). b must be positive and odd. *)
|
||||
|
||||
val compare : t -> t -> int
|
||||
(** Compare the absolute value of two numbers. *)
|
||||
|
||||
val equal : t -> t -> bool
|
||||
(** Test whether two number are equal (including sign). *)
|
||||
|
||||
val add : t -> t -> t -> unit
|
||||
(** [add r a b] Add two (signed) numbers. *)
|
||||
|
||||
val sub : t -> t -> t -> unit
|
||||
(** [sub r a b] Subtract two (signed) numbers. *)
|
||||
|
||||
val mul : t -> t -> t -> unit
|
||||
(** [mul r a b] Multiply two (signed) numbers. *)
|
||||
|
||||
val modulo : t -> t -> unit
|
||||
(** Replace a number by its remainder modulo m. M's sign is
|
||||
ignored. The result is a number between 0 and m-1, even if r was
|
||||
negative. *)
|
||||
|
||||
val shift : t -> int -> unit
|
||||
(** [shift t bits] Right-shift the passed number by [bits] bits. *)
|
||||
|
||||
val is_zero : t -> bool
|
||||
(** Check whether a number is zero. *)
|
||||
|
||||
val is_one : t -> bool
|
||||
(** Check whether a number is one. *)
|
||||
|
||||
val is_neg : t -> bool
|
||||
(** Check whether a number is strictly negative. *)
|
||||
|
||||
val negate : t -> unit
|
||||
(** Change a number's sign. *)
|
||||
end
|
||||
|
||||
module Scalar : sig
|
||||
type t
|
||||
(** A scalar modulo the group order of the secp256k1 curve. *)
|
||||
|
||||
val zero : unit -> t
|
||||
val one : unit -> t
|
||||
val copy : t -> t
|
||||
|
||||
val const :
|
||||
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||||
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||||
|
||||
val clear : t -> unit
|
||||
(** Clear a scalar to prevent the leak of sensitive data. *)
|
||||
|
||||
val get_bits : t -> int -> int -> int
|
||||
(** [get_bits a offset count] Access bits from a scalar. All
|
||||
requested bits must belong to the same 32-bit limb. *)
|
||||
|
||||
val get_bits_var : t -> int -> int -> int
|
||||
(** [get_bits a offset count] Access bits from a scalar. Not
|
||||
constant time. *)
|
||||
|
||||
val set_b32 : t -> Cstruct.t -> bool
|
||||
(** Set a scalar from a big endian byte array. *)
|
||||
|
||||
val set_int : t -> int -> unit
|
||||
(** Set a scalar to an unsigned integer. *)
|
||||
|
||||
val get_b32 : Cstruct.t -> t -> unit
|
||||
(** Convert a scalar to a byte array. *)
|
||||
|
||||
val add : t -> t -> t -> bool
|
||||
(** [add r a b] Add two scalars together (modulo the group
|
||||
order). Returns whether it overflowed. *)
|
||||
|
||||
val cadd_bit : t -> int -> bool -> unit
|
||||
(** [cadd_bit r bit flag] Conditionally add a power of two to a
|
||||
scalar. The result is not allowed to overflow. *)
|
||||
|
||||
val mul : t -> t -> t -> unit
|
||||
(** [mul r a b] Multiply two scalars (modulo the group order). *)
|
||||
|
||||
val shr_int : t -> int -> int
|
||||
(** Shift a scalar right by some amount strictly between 0 and 16,
|
||||
returning the low bits that were shifted off *)
|
||||
|
||||
val sqr : t -> t -> unit
|
||||
(** [sqr r a] Compute the square of a scalar (modulo the group
|
||||
order). *)
|
||||
|
||||
val inverse : t -> t -> unit
|
||||
(** [inverse r a] Compute the inverse of a scalar (modulo the group
|
||||
order). *)
|
||||
|
||||
val inverse_var : t -> t -> unit
|
||||
(** [inverse_var r a] Compute the inverse of a scalar (modulo the
|
||||
group order), without constant-time guarantee. *)
|
||||
|
||||
val negate : t -> t -> unit
|
||||
(** [negate r a] Compute the complement of a scalar (modulo the
|
||||
group order). *)
|
||||
|
||||
val is_zero : t -> bool
|
||||
(** Check whether a scalar equals zero. *)
|
||||
|
||||
val is_one : t -> bool
|
||||
(** Check whether a scalar equals one. *)
|
||||
|
||||
val is_even : t -> bool
|
||||
(** Check whether a scalar, considered as an nonnegative integer, is
|
||||
even. *)
|
||||
|
||||
val is_high : t -> bool
|
||||
(** Check whether a scalar is higher than the group order divided by
|
||||
2. *)
|
||||
|
||||
val cond_negate : t -> bool -> bool
|
||||
(** Conditionally negate a number, in constant time. Returns [true]
|
||||
if the number was negated, [false] otherwise *)
|
||||
|
||||
val get_num : Num.t -> t -> unit
|
||||
(** Convert a scalar to a number. *)
|
||||
|
||||
val order_get_num : Num.t -> unit
|
||||
(** Get the order of the group as a number. *)
|
||||
|
||||
val equal : t -> t -> bool
|
||||
(** Compare two scalars. *)
|
||||
|
||||
val mul_shift_var : t -> t -> t -> int -> unit
|
||||
(** Multiply a and b (without taking the modulus!), divide by
|
||||
2**shift, and round to the nearest integer. Shift must be at
|
||||
least 256. *)
|
||||
end
|
||||
|
||||
(** Field element module.
|
||||
*
|
||||
* Field elements can be represented in several ways, but code accessing
|
||||
* it (and implementations) need to take certain properties into account:
|
||||
* - Each field element can be normalized or not.
|
||||
* - Each field element has a magnitude, which represents how far away
|
||||
* its representation is away from normalization. Normalized elements
|
||||
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||||
* normality. *)
|
||||
module Field : sig
|
||||
type t
|
||||
|
||||
module Storage : sig
|
||||
type t
|
||||
val size : int
|
||||
val of_cstruct : Cstruct.t -> t option
|
||||
val of_cstruct_exn : Cstruct.t -> t
|
||||
val to_cstruct : t -> Cstruct.t
|
||||
val const :
|
||||
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||||
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||||
val cmov : t -> t -> bool -> unit
|
||||
(** If flag is true, set *r equal to *a; otherwise leave
|
||||
it. Constant-time. *)
|
||||
end
|
||||
|
||||
val const :
|
||||
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||||
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||||
(** Unpacks a constant into a overlapping multi-limbed FE
|
||||
element. *)
|
||||
|
||||
val normalize : t -> unit
|
||||
(** Normalize a field element. *)
|
||||
|
||||
val normalize_weak : t -> unit
|
||||
(** Weakly normalize a field element: reduce it magnitude to 1, but
|
||||
don't fully normalize. *)
|
||||
|
||||
val normalize_var : t -> unit
|
||||
(** Normalize a field element, without constant-time guarantee. *)
|
||||
|
||||
val normalizes_to_zero : t -> bool
|
||||
(** Verify whether a field element represents zero i.e. would
|
||||
normalize to a zero value. The field implementation may
|
||||
optionally normalize the input, but this should not be relied
|
||||
upon. *)
|
||||
|
||||
val normalizes_to_zero_var : t -> bool
|
||||
(** Verify whether a field element represents zero i.e. would
|
||||
normalize to a zero value. The field implementation may
|
||||
optionally normalize the input, but this should not be relied
|
||||
upon. *)
|
||||
|
||||
val set_int : t -> int -> unit
|
||||
(** Set a field element equal to a small integer. Resulting field
|
||||
element is normalized. *)
|
||||
|
||||
val clear : t -> unit
|
||||
(** Sets a field element equal to zero, initializing all fields. *)
|
||||
|
||||
val is_zero : t -> bool
|
||||
(** Verify whether a field element is zero. Requires the input to be
|
||||
normalized. *)
|
||||
|
||||
val is_odd : t -> bool
|
||||
(** Check the "oddness" of a field element. Requires the input to be
|
||||
normalized. *)
|
||||
|
||||
val equal : t -> t -> bool
|
||||
(** Compare two field elements. Requires magnitude-1 inputs. *)
|
||||
|
||||
val equal_var : t -> t -> bool
|
||||
(** Same as secp256k1_fe_equal, but may be variable time. *)
|
||||
|
||||
val cmp_var : t -> t -> int
|
||||
(** Compare two field elements. Requires both inputs to be
|
||||
normalized. *)
|
||||
|
||||
val compare : t -> t -> int
|
||||
(** Alias to [cmp_var]. *)
|
||||
|
||||
val set_b32 : t -> Cstruct.t -> bool
|
||||
(** Set a field element equal to 32-byte big endian value. If
|
||||
successful, the resulting field element is normalized. *)
|
||||
|
||||
val get_b32 : Cstruct.t -> t -> unit
|
||||
(** Convert a field element to a 32-byte big endian value. Requires
|
||||
the input to be normalized. *)
|
||||
|
||||
val negate : t -> t -> int -> unit
|
||||
(** Set a field element equal to the additive inverse of
|
||||
another. Takes a maximum magnitude of the input as an
|
||||
argument. The magnitude of the output is one higher. *)
|
||||
|
||||
val mul_int : t -> int -> unit
|
||||
(** Multiplies the passed field element with a small integer
|
||||
constant. Multiplies the magnitude by that small integer. *)
|
||||
|
||||
val add : t -> t -> unit
|
||||
(** Adds a field element to another. The result has the sum of the
|
||||
inputs' magnitudes as magnitude. *)
|
||||
|
||||
val mul : t -> t -> t -> unit
|
||||
(** Sets a field element to be the product of two others. Requires
|
||||
the inputs' magnitudes to be at most 8. The output magnitude is
|
||||
1 (but not guaranteed to be normalized). *)
|
||||
|
||||
val sqr : t -> t -> unit
|
||||
(** Sets a field element to be the square of another. Requires the
|
||||
input's magnitude to be at most 8. The output magnitude is 1
|
||||
(but not guaranteed to be normalized). *)
|
||||
|
||||
val sqrt : t -> t -> int
|
||||
(** If a has a square root, it is computed in r and 1 is
|
||||
returned. If a does not have a square root, the root of its
|
||||
negation is computed and 0 is returned. The input's magnitude
|
||||
can be at most 8. The output magnitude is 1 (but not guaranteed
|
||||
to be normalized). The result in r will always be a square
|
||||
itself. *)
|
||||
|
||||
val is_quad_var : t -> bool
|
||||
(** Checks whether a field element is a quadratic residue. *)
|
||||
|
||||
val inv : t -> t -> unit
|
||||
(** Sets a field element to be the (modular) inverse of
|
||||
another. Requires the input's magnitude to be at most 8. The
|
||||
output magnitude is 1 (but not guaranteed to be normalized). *)
|
||||
|
||||
val inv_var : t -> t -> unit
|
||||
(** Potentially faster version of secp256k1_fe_inv, without
|
||||
constant-time guarantee. *)
|
||||
|
||||
val inv_all_var : t -> t list -> unit
|
||||
(** Calculate the (modular) inverses of a batch of field
|
||||
elements. Requires the inputs' magnitudes to be at most 8. The
|
||||
output magnitudes are 1 (but not guaranteed to be
|
||||
normalized). The inputs and outputs must not overlap in
|
||||
memory. *)
|
||||
|
||||
val to_storage : Storage.t -> t -> unit
|
||||
(** Convert a field element to the storage type. *)
|
||||
|
||||
val from_storage : t -> Storage.t -> unit
|
||||
(** Convert a field element back from the storage type. *)
|
||||
|
||||
val cmov : t -> t -> bool -> unit
|
||||
(** If flag is true, set *r equal to *a; otherwise leave
|
||||
it. Constant-time. *)
|
||||
end
|
||||
|
||||
module Group : sig
|
||||
type t
|
||||
(** Type of a group element (affine coordinates). *)
|
||||
|
||||
type ge = t
|
||||
|
||||
module Storage : sig
|
||||
type t
|
||||
val size : int
|
||||
val of_cstruct : Cstruct.t -> t option
|
||||
val of_cstruct_exn : Cstruct.t -> t
|
||||
val to_cstruct : t -> Cstruct.t
|
||||
val of_fields :
|
||||
?x:Field.Storage.t -> ?y:Field.Storage.t -> unit -> t
|
||||
val cmov : t -> t -> bool -> unit
|
||||
(** If flag is true, set *r equal to *a; otherwise leave
|
||||
it. Constant-time. *)
|
||||
end
|
||||
|
||||
module Jacobian : sig
|
||||
type t
|
||||
(** Type of a group element (jacobian). *)
|
||||
|
||||
val of_fields :
|
||||
?x:Field.t -> ?y:Field.t -> ?z:Field.t -> ?infinity:bool -> unit -> t
|
||||
|
||||
val set_infinity : t -> unit
|
||||
(** Set a group element (jacobian) equal to the point at
|
||||
infinity. *)
|
||||
|
||||
val get_ge : ge -> t -> unit
|
||||
(** Set a group element equal to another which is given in jacobian
|
||||
coordinates. *)
|
||||
|
||||
val set_ge : t -> ge -> unit
|
||||
(** Set a group element (jacobian) equal to another which is given
|
||||
in affine coordinates. *)
|
||||
|
||||
val eq_x_var : Field.t -> t -> int
|
||||
(** Compare the X coordinate of a group element (jacobian). *)
|
||||
|
||||
val neg : t -> t -> unit
|
||||
(** [neg r a] Set r equal to the inverse of a (i.e., mirrored
|
||||
around the X axis) *)
|
||||
|
||||
val is_infinity : t -> bool
|
||||
(** Check whether a group element is the point at infinity. *)
|
||||
|
||||
val has_quad_y_var : t -> bool
|
||||
(** Check whether a group element's y coordinate is a quadratic
|
||||
residue. *)
|
||||
|
||||
val double_nonzero : ?rzr:Field.t -> t -> t -> unit
|
||||
(** [double_nonzero ?rzr r a] Set [r] equal to the double of
|
||||
[a]. If rzr is not-None, [r->z = a->z * *rzr] (where infinity
|
||||
means an implicit z = 0). [a] may not be zero. Constant
|
||||
time. *)
|
||||
|
||||
val double_var : ?rzr:Field.t -> t -> t -> unit
|
||||
(** [double_var ?rzr r a] Set [r] equal to the double of [a]. If
|
||||
[rzr] is not-None, [r->z = a->z * *rzr] (where infinity means
|
||||
an implicit z = 0). *)
|
||||
|
||||
val add_var : ?rzr:Field.t -> t -> t -> t -> unit
|
||||
(** [add_var ?rzr r a b] Set [r] equal to the sum of [a] and
|
||||
[b]. If rzr is non-None, [r->z = a->z * *rzr] ([a] cannot be
|
||||
infinity in that case). *)
|
||||
|
||||
val add_ge : t -> t -> ge -> unit
|
||||
(** [add_ge r a b] Set [r] equal to the sum of [a] and [b] (with [b] given
|
||||
in affine coordinates, and not infinity). *)
|
||||
|
||||
val add_ge_var : ?rzr:Field.t -> t -> t -> ge -> unit
|
||||
(** [add_ge_var ?rzr r a b] Set [r] equal to the sum of [a] and [b]
|
||||
(with [b] given in affine coordinates). This is more efficient
|
||||
than [add_var]. It is identical to [add_ge] but without
|
||||
constant-time guarantee, and [b] is allowed to be infinity. If
|
||||
rzr is non-None, [r->z = a->z * *rzr] ([a] cannot be infinity
|
||||
in that case). *)
|
||||
|
||||
val add_zinv_var : t -> t -> ge -> Field.t -> unit
|
||||
(** Set r equal to the sum of a and b (with the inverse of b's Z
|
||||
coordinate passed as bzinv). *)
|
||||
|
||||
val mul : t -> ge -> Scalar.t -> unit
|
||||
|
||||
val clear : t -> unit
|
||||
(** Clear a [t] to prevent leaking sensitive information. *)
|
||||
|
||||
val rescale : t -> Field.t -> unit
|
||||
(** Rescale a jacobian point by b which must be
|
||||
non-zero. Constant-time. *)
|
||||
end
|
||||
|
||||
val of_fields :
|
||||
?x:Field.t -> ?y:Field.t -> ?infinity:bool -> unit -> t
|
||||
|
||||
val g : t
|
||||
|
||||
val set_xy : t -> Field.t -> Field.t -> unit
|
||||
(** Set a group element equal to the point with given X and Y
|
||||
coordinates *)
|
||||
|
||||
val set_xquad : t -> Field.t -> unit
|
||||
(** Set a group element (affine) equal to the point with the given X
|
||||
coordinate and a Y coordinate that is a quadratic residue modulo
|
||||
p. The return value is true iff a coordinate with the given X
|
||||
coordinate exists. *)
|
||||
|
||||
val set_xovar : t -> Field.t -> int -> bool
|
||||
(** Set a group element (affine) equal to the point with the given X
|
||||
coordinate, and given oddness for Y. Return value indicates
|
||||
whether the result is valid. *)
|
||||
|
||||
val is_infinity : t -> bool
|
||||
(** Check whether a group element is the point at infinity. *)
|
||||
|
||||
val is_valid_var : t -> bool
|
||||
(** Check whether a group element is valid (i.e., on the curve). *)
|
||||
|
||||
val neg : t -> t -> unit
|
||||
(** [neg r a] Set r equal to the inverse of a (i.e., mirrored
|
||||
around the X axis) *)
|
||||
|
||||
val clear : t -> unit
|
||||
(** Clear a [t] to prevent leaking sensitive information. *)
|
||||
|
||||
val to_storage : Storage.t -> t -> unit
|
||||
(** Convert a group element to the storage type. *)
|
||||
|
||||
val from_storage : t -> Storage.t -> unit
|
||||
(** Convert a group element back from the storage type. *)
|
||||
|
||||
val to_pubkey : ?compress:bool -> Cstruct.t -> t -> Cstruct.t
|
||||
(** [to_pubkey ?compress buf ge] serializes [ge] in [buf] and
|
||||
returns [buf], adjusted to the actual size. *)
|
||||
|
||||
val from_pubkey : t -> Cstruct.t -> unit
|
||||
(** [from_pubkey ge buf] parses a serialized pubkey in [buf] and
|
||||
writes the result in [ge]. *)
|
||||
end
|
16
vendors/ocaml-secp256k1-internal/src/jbuild
vendored
Normal file
16
vendors/ocaml-secp256k1-internal/src/jbuild
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(library
|
||||
((name secp256k1_ml)
|
||||
(public_name secp256k1-internal)
|
||||
(modules (internal external))
|
||||
(libraries (bigarray cstruct))
|
||||
(c_names (secp256k1
|
||||
secp256k1_wrap))
|
||||
(c_flags (:include c_flags.sexp))
|
||||
(c_library_flags (-lgmp))))
|
||||
|
||||
(rule
|
||||
((targets (c_flags.sexp))
|
||||
(deps (../config/discover.exe))
|
||||
(action (run ${<} -ocamlc ${OCAMLC}))))
|
74
vendors/ocaml-secp256k1-internal/src/num.h
vendored
Normal file
74
vendors/ocaml-secp256k1-internal/src/num.h
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_NUM_H
|
||||
#define SECP256K1_NUM_H
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_NUM_GMP)
|
||||
#include "num_gmp.h"
|
||||
#else
|
||||
#error "Please select num implementation"
|
||||
#endif
|
||||
|
||||
/** Copy a number. */
|
||||
static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a);
|
||||
|
||||
/** Convert a number's absolute value to a binary big-endian string.
|
||||
* There must be enough place. */
|
||||
static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a);
|
||||
|
||||
/** Set a number to the value of a binary big-endian string. */
|
||||
static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen);
|
||||
|
||||
/** Compute a modular inverse. The input must be less than the modulus. */
|
||||
static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m);
|
||||
|
||||
/** Compute the jacobi symbol (a|b). b must be positive and odd. */
|
||||
static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Compare the absolute value of two numbers. */
|
||||
static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Test whether two number are equal (including sign). */
|
||||
static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Add two (signed) numbers. */
|
||||
static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Subtract two (signed) numbers. */
|
||||
static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Multiply two (signed) numbers. */
|
||||
static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b);
|
||||
|
||||
/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1,
|
||||
even if r was negative. */
|
||||
static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m);
|
||||
|
||||
/** Right-shift the passed number by bits bits. */
|
||||
static void secp256k1_num_shift(secp256k1_num *r, int bits);
|
||||
|
||||
/** Check whether a number is zero. */
|
||||
static int secp256k1_num_is_zero(const secp256k1_num *a);
|
||||
|
||||
/** Check whether a number is one. */
|
||||
static int secp256k1_num_is_one(const secp256k1_num *a);
|
||||
|
||||
/** Check whether a number is strictly negative. */
|
||||
static int secp256k1_num_is_neg(const secp256k1_num *a);
|
||||
|
||||
/** Change a number's sign. */
|
||||
static void secp256k1_num_negate(secp256k1_num *r);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_NUM_H */
|
20
vendors/ocaml-secp256k1-internal/src/num_gmp.h
vendored
Normal file
20
vendors/ocaml-secp256k1-internal/src/num_gmp.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_NUM_REPR_H
|
||||
#define SECP256K1_NUM_REPR_H
|
||||
|
||||
#include <gmp.h>
|
||||
|
||||
#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS)
|
||||
|
||||
typedef struct {
|
||||
mp_limb_t data[2*NUM_LIMBS];
|
||||
int neg;
|
||||
int limbs;
|
||||
} secp256k1_num;
|
||||
|
||||
#endif /* SECP256K1_NUM_REPR_H */
|
288
vendors/ocaml-secp256k1-internal/src/num_gmp_impl.h
vendored
Normal file
288
vendors/ocaml-secp256k1-internal/src/num_gmp_impl.h
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_NUM_REPR_IMPL_H
|
||||
#define SECP256K1_NUM_REPR_IMPL_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmp.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "num.h"
|
||||
|
||||
#ifdef VERIFY
|
||||
static void secp256k1_num_sanity(const secp256k1_num *a) {
|
||||
VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0));
|
||||
}
|
||||
#else
|
||||
#define secp256k1_num_sanity(a) do { } while(0)
|
||||
#endif
|
||||
|
||||
static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) {
|
||||
*r = *a;
|
||||
}
|
||||
|
||||
static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) {
|
||||
unsigned char tmp[65];
|
||||
int len = 0;
|
||||
int shift = 0;
|
||||
if (a->limbs>1 || a->data[0] != 0) {
|
||||
len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
|
||||
}
|
||||
while (shift < len && tmp[shift] == 0) shift++;
|
||||
VERIFY_CHECK(len-shift <= (int)rlen);
|
||||
memset(r, 0, rlen - len + shift);
|
||||
if (len > shift) {
|
||||
memcpy(r + rlen - len + shift, tmp + shift, len - shift);
|
||||
}
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
}
|
||||
|
||||
static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) {
|
||||
int len;
|
||||
VERIFY_CHECK(alen > 0);
|
||||
VERIFY_CHECK(alen <= 64);
|
||||
len = mpn_set_str(r->data, a, alen, 256);
|
||||
if (len == 0) {
|
||||
r->data[0] = 0;
|
||||
len = 1;
|
||||
}
|
||||
VERIFY_CHECK(len <= NUM_LIMBS*2);
|
||||
r->limbs = len;
|
||||
r->neg = 0;
|
||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
|
||||
r->limbs = a->limbs;
|
||||
if (c != 0) {
|
||||
VERIFY_CHECK(r->limbs < 2*NUM_LIMBS);
|
||||
r->data[r->limbs++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
|
||||
(void)c;
|
||||
VERIFY_CHECK(c == 0);
|
||||
r->limbs = a->limbs;
|
||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) {
|
||||
secp256k1_num_sanity(r);
|
||||
secp256k1_num_sanity(m);
|
||||
|
||||
if (r->limbs >= m->limbs) {
|
||||
mp_limb_t t[2*NUM_LIMBS];
|
||||
mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
|
||||
memset(t, 0, sizeof(t));
|
||||
r->limbs = m->limbs;
|
||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->neg && (r->limbs > 1 || r->data[0] != 0)) {
|
||||
secp256k1_num_sub_abs(r, m, r);
|
||||
r->neg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) {
|
||||
int i;
|
||||
mp_limb_t g[NUM_LIMBS+1];
|
||||
mp_limb_t u[NUM_LIMBS+1];
|
||||
mp_limb_t v[NUM_LIMBS+1];
|
||||
mp_size_t sn;
|
||||
mp_size_t gn;
|
||||
secp256k1_num_sanity(a);
|
||||
secp256k1_num_sanity(m);
|
||||
|
||||
/** mpn_gcdext computes: (G,S) = gcdext(U,V), where
|
||||
* * G = gcd(U,V)
|
||||
* * G = U*S + V*T
|
||||
* * U has equal or more limbs than V, and V has no padding
|
||||
* If we set U to be (a padded version of) a, and V = m:
|
||||
* G = a*S + m*T
|
||||
* G = a*S mod m
|
||||
* Assuming G=1:
|
||||
* S = 1/a mod m
|
||||
*/
|
||||
VERIFY_CHECK(m->limbs <= NUM_LIMBS);
|
||||
VERIFY_CHECK(m->data[m->limbs-1] != 0);
|
||||
for (i = 0; i < m->limbs; i++) {
|
||||
u[i] = (i < a->limbs) ? a->data[i] : 0;
|
||||
v[i] = m->data[i];
|
||||
}
|
||||
sn = NUM_LIMBS+1;
|
||||
gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
|
||||
(void)gn;
|
||||
VERIFY_CHECK(gn == 1);
|
||||
VERIFY_CHECK(g[0] == 1);
|
||||
r->neg = a->neg ^ m->neg;
|
||||
if (sn < 0) {
|
||||
mpn_sub(r->data, m->data, m->limbs, r->data, -sn);
|
||||
r->limbs = m->limbs;
|
||||
while (r->limbs > 1 && r->data[r->limbs-1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
} else {
|
||||
r->limbs = sn;
|
||||
}
|
||||
memset(g, 0, sizeof(g));
|
||||
memset(u, 0, sizeof(u));
|
||||
memset(v, 0, sizeof(v));
|
||||
}
|
||||
|
||||
static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) {
|
||||
int ret;
|
||||
mpz_t ga, gb;
|
||||
secp256k1_num_sanity(a);
|
||||
secp256k1_num_sanity(b);
|
||||
VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1));
|
||||
|
||||
mpz_inits(ga, gb, NULL);
|
||||
|
||||
mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data);
|
||||
mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data);
|
||||
if (a->neg) {
|
||||
mpz_neg(ga, ga);
|
||||
}
|
||||
|
||||
ret = mpz_jacobi(ga, gb);
|
||||
|
||||
mpz_clears(ga, gb, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int secp256k1_num_is_one(const secp256k1_num *a) {
|
||||
return (a->limbs == 1 && a->data[0] == 1);
|
||||
}
|
||||
|
||||
static int secp256k1_num_is_zero(const secp256k1_num *a) {
|
||||
return (a->limbs == 1 && a->data[0] == 0);
|
||||
}
|
||||
|
||||
static int secp256k1_num_is_neg(const secp256k1_num *a) {
|
||||
return (a->limbs > 1 || a->data[0] != 0) && a->neg;
|
||||
}
|
||||
|
||||
static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) {
|
||||
if (a->limbs > b->limbs) {
|
||||
return 1;
|
||||
}
|
||||
if (a->limbs < b->limbs) {
|
||||
return -1;
|
||||
}
|
||||
return mpn_cmp(a->data, b->data, a->limbs);
|
||||
}
|
||||
|
||||
static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) {
|
||||
if (a->limbs > b->limbs) {
|
||||
return 0;
|
||||
}
|
||||
if (a->limbs < b->limbs) {
|
||||
return 0;
|
||||
}
|
||||
if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) {
|
||||
return 0;
|
||||
}
|
||||
return mpn_cmp(a->data, b->data, a->limbs) == 0;
|
||||
}
|
||||
|
||||
static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) {
|
||||
if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */
|
||||
r->neg = a->neg;
|
||||
if (a->limbs >= b->limbs) {
|
||||
secp256k1_num_add_abs(r, a, b);
|
||||
} else {
|
||||
secp256k1_num_add_abs(r, b, a);
|
||||
}
|
||||
} else {
|
||||
if (secp256k1_num_cmp(a, b) > 0) {
|
||||
r->neg = a->neg;
|
||||
secp256k1_num_sub_abs(r, a, b);
|
||||
} else {
|
||||
r->neg = b->neg ^ bneg;
|
||||
secp256k1_num_sub_abs(r, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
secp256k1_num_sanity(a);
|
||||
secp256k1_num_sanity(b);
|
||||
secp256k1_num_subadd(r, a, b, 0);
|
||||
}
|
||||
|
||||
static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
secp256k1_num_sanity(a);
|
||||
secp256k1_num_sanity(b);
|
||||
secp256k1_num_subadd(r, a, b, 1);
|
||||
}
|
||||
|
||||
static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
|
||||
mp_limb_t tmp[2*NUM_LIMBS+1];
|
||||
secp256k1_num_sanity(a);
|
||||
secp256k1_num_sanity(b);
|
||||
|
||||
VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
|
||||
if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
|
||||
r->limbs = 1;
|
||||
r->neg = 0;
|
||||
r->data[0] = 0;
|
||||
return;
|
||||
}
|
||||
if (a->limbs >= b->limbs) {
|
||||
mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs);
|
||||
} else {
|
||||
mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs);
|
||||
}
|
||||
r->limbs = a->limbs + b->limbs;
|
||||
if (r->limbs > 1 && tmp[r->limbs - 1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS);
|
||||
mpn_copyi(r->data, tmp, r->limbs);
|
||||
r->neg = a->neg ^ b->neg;
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
}
|
||||
|
||||
static void secp256k1_num_shift(secp256k1_num *r, int bits) {
|
||||
if (bits % GMP_NUMB_BITS) {
|
||||
/* Shift within limbs. */
|
||||
mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS);
|
||||
}
|
||||
if (bits >= GMP_NUMB_BITS) {
|
||||
int i;
|
||||
/* Shift full limbs. */
|
||||
for (i = 0; i < r->limbs; i++) {
|
||||
int index = i + (bits / GMP_NUMB_BITS);
|
||||
if (index < r->limbs && index < 2*NUM_LIMBS) {
|
||||
r->data[i] = r->data[index];
|
||||
} else {
|
||||
r->data[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (r->limbs>1 && r->data[r->limbs-1]==0) {
|
||||
r->limbs--;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_num_negate(secp256k1_num *r) {
|
||||
r->neg ^= 1;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_NUM_REPR_IMPL_H */
|
24
vendors/ocaml-secp256k1-internal/src/num_impl.h
vendored
Normal file
24
vendors/ocaml-secp256k1-internal/src/num_impl.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_NUM_IMPL_H
|
||||
#define SECP256K1_NUM_IMPL_H
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include "num.h"
|
||||
|
||||
#if defined(USE_NUM_GMP)
|
||||
#include "num_gmp_impl.h"
|
||||
#elif defined(USE_NUM_NONE)
|
||||
/* Nothing. */
|
||||
#else
|
||||
#error "Please select num implementation"
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_NUM_IMPL_H */
|
193
vendors/ocaml-secp256k1-internal/src/recovery.h
vendored
Normal file
193
vendors/ocaml-secp256k1-internal/src/recovery.h
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H
|
||||
#define SECP256K1_MODULE_RECOVERY_MAIN_H
|
||||
|
||||
#include "secp256k1_recovery.h"
|
||||
|
||||
static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) {
|
||||
(void)ctx;
|
||||
if (sizeof(secp256k1_scalar) == 32) {
|
||||
/* When the secp256k1_scalar type is exactly 32 byte, use its
|
||||
* representation inside secp256k1_ecdsa_signature, as conversion is very fast.
|
||||
* Note that secp256k1_ecdsa_signature_save must use the same representation. */
|
||||
memcpy(r, &sig->data[0], 32);
|
||||
memcpy(s, &sig->data[32], 32);
|
||||
} else {
|
||||
secp256k1_scalar_set_b32(r, &sig->data[0], NULL);
|
||||
secp256k1_scalar_set_b32(s, &sig->data[32], NULL);
|
||||
}
|
||||
*recid = sig->data[64];
|
||||
}
|
||||
|
||||
static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) {
|
||||
if (sizeof(secp256k1_scalar) == 32) {
|
||||
memcpy(&sig->data[0], r, 32);
|
||||
memcpy(&sig->data[32], s, 32);
|
||||
} else {
|
||||
secp256k1_scalar_get_b32(&sig->data[0], r);
|
||||
secp256k1_scalar_get_b32(&sig->data[32], s);
|
||||
}
|
||||
sig->data[64] = recid;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) {
|
||||
secp256k1_scalar r, s;
|
||||
int ret = 1;
|
||||
int overflow = 0;
|
||||
|
||||
(void)ctx;
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(input64 != NULL);
|
||||
ARG_CHECK(recid >= 0 && recid <= 3);
|
||||
|
||||
secp256k1_scalar_set_b32(&r, &input64[0], &overflow);
|
||||
ret &= !overflow;
|
||||
secp256k1_scalar_set_b32(&s, &input64[32], &overflow);
|
||||
ret &= !overflow;
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid);
|
||||
} else {
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) {
|
||||
secp256k1_scalar r, s;
|
||||
|
||||
(void)ctx;
|
||||
ARG_CHECK(output64 != NULL);
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(recid != NULL);
|
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig);
|
||||
secp256k1_scalar_get_b32(&output64[0], &r);
|
||||
secp256k1_scalar_get_b32(&output64[32], &s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) {
|
||||
secp256k1_scalar r, s;
|
||||
int recid;
|
||||
|
||||
(void)ctx;
|
||||
ARG_CHECK(sig != NULL);
|
||||
ARG_CHECK(sigin != NULL);
|
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin);
|
||||
secp256k1_ecdsa_signature_save(sig, &r, &s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe fx;
|
||||
secp256k1_ge x;
|
||||
secp256k1_gej xj;
|
||||
secp256k1_scalar rn, u1, u2;
|
||||
secp256k1_gej qj;
|
||||
int r;
|
||||
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(brx, sigr);
|
||||
r = secp256k1_fe_set_b32(&fx, brx);
|
||||
(void)r;
|
||||
VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||
if (recid & 2) {
|
||||
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe);
|
||||
}
|
||||
if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_scalar_inverse_var(&rn, sigr);
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
|
||||
secp256k1_scalar r, s;
|
||||
secp256k1_scalar sec, non, msg;
|
||||
int recid;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
ARG_CHECK(msg32 != NULL);
|
||||
ARG_CHECK(signature != NULL);
|
||||
ARG_CHECK(seckey != NULL);
|
||||
if (noncefp == NULL) {
|
||||
noncefp = secp256k1_nonce_function_default;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
/* Fail if the secret key is invalid. */
|
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
|
||||
unsigned char nonce32[32];
|
||||
unsigned int count = 0;
|
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL);
|
||||
while (1) {
|
||||
ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
|
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
memset(nonce32, 0, 32);
|
||||
secp256k1_scalar_clear(&msg);
|
||||
secp256k1_scalar_clear(&non);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
}
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
|
||||
} else {
|
||||
memset(signature, 0, sizeof(*signature));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) {
|
||||
secp256k1_ge q;
|
||||
secp256k1_scalar r, s;
|
||||
secp256k1_scalar m;
|
||||
int recid;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
ARG_CHECK(msg32 != NULL);
|
||||
ARG_CHECK(signature != NULL);
|
||||
ARG_CHECK(pubkey != NULL);
|
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature);
|
||||
VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) {
|
||||
secp256k1_pubkey_save(pubkey, &q);
|
||||
return 1;
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */
|
106
vendors/ocaml-secp256k1-internal/src/scalar.h
vendored
Normal file
106
vendors/ocaml-secp256k1-internal/src/scalar.h
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_H
|
||||
#define SECP256K1_SCALAR_H
|
||||
|
||||
#include "num.h"
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
#include "scalar_low.h"
|
||||
#elif defined(USE_SCALAR_4X64)
|
||||
#include "scalar_4x64.h"
|
||||
#elif defined(USE_SCALAR_8X32)
|
||||
#include "scalar_8x32.h"
|
||||
#else
|
||||
#error "Please select scalar implementation"
|
||||
#endif
|
||||
|
||||
/** Clear a scalar to prevent the leak of sensitive data. */
|
||||
static void secp256k1_scalar_clear(secp256k1_scalar *r);
|
||||
|
||||
/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */
|
||||
static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count);
|
||||
|
||||
/** Access bits from a scalar. Not constant time. */
|
||||
static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count);
|
||||
|
||||
/** Set a scalar from a big endian byte array. */
|
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow);
|
||||
|
||||
/** Set a scalar to an unsigned integer. */
|
||||
static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v);
|
||||
|
||||
/** Convert a scalar to a byte array. */
|
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a);
|
||||
|
||||
/** Add two scalars together (modulo the group order). Returns whether it overflowed. */
|
||||
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b);
|
||||
|
||||
/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */
|
||||
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag);
|
||||
|
||||
/** Multiply two scalars (modulo the group order). */
|
||||
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b);
|
||||
|
||||
/** Shift a scalar right by some amount strictly between 0 and 16, returning
|
||||
* the low bits that were shifted off */
|
||||
static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n);
|
||||
|
||||
/** Compute the square of a scalar (modulo the group order). */
|
||||
static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a);
|
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order). */
|
||||
static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a);
|
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */
|
||||
static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a);
|
||||
|
||||
/** Compute the complement of a scalar (modulo the group order). */
|
||||
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a);
|
||||
|
||||
/** Check whether a scalar equals zero. */
|
||||
static int secp256k1_scalar_is_zero(const secp256k1_scalar *a);
|
||||
|
||||
/** Check whether a scalar equals one. */
|
||||
static int secp256k1_scalar_is_one(const secp256k1_scalar *a);
|
||||
|
||||
/** Check whether a scalar, considered as an nonnegative integer, is even. */
|
||||
static int secp256k1_scalar_is_even(const secp256k1_scalar *a);
|
||||
|
||||
/** Check whether a scalar is higher than the group order divided by 2. */
|
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar *a);
|
||||
|
||||
/** Conditionally negate a number, in constant time.
|
||||
* Returns -1 if the number was negated, 1 otherwise */
|
||||
static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag);
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
/** Convert a scalar to a number. */
|
||||
static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a);
|
||||
|
||||
/** Get the order of the group as a number. */
|
||||
static void secp256k1_scalar_order_get_num(secp256k1_num *r);
|
||||
#endif
|
||||
|
||||
/** Compare two scalars. */
|
||||
static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b);
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
/** Find r1 and r2 such that r1+r2*2^128 = a. */
|
||||
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a);
|
||||
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */
|
||||
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a);
|
||||
#endif
|
||||
|
||||
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
|
||||
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
|
||||
|
||||
#endif /* SECP256K1_SCALAR_H */
|
19
vendors/ocaml-secp256k1-internal/src/scalar_4x64.h
vendored
Normal file
19
vendors/ocaml-secp256k1-internal/src/scalar_4x64.h
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_H
|
||||
#define SECP256K1_SCALAR_REPR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** A scalar modulo the group order of the secp256k1 curve. */
|
||||
typedef struct {
|
||||
uint64_t d[4];
|
||||
} secp256k1_scalar;
|
||||
|
||||
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_H */
|
949
vendors/ocaml-secp256k1-internal/src/scalar_4x64_impl.h
vendored
Normal file
949
vendors/ocaml-secp256k1-internal/src/scalar_4x64_impl.h
vendored
Normal file
@ -0,0 +1,949 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
|
||||
#define SECP256K1_SCALAR_REPR_IMPL_H
|
||||
|
||||
/* Limbs of the secp256k1 order. */
|
||||
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
|
||||
#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL)
|
||||
#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL)
|
||||
#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
|
||||
|
||||
/* Limbs of 2^256 minus the secp256k1 order. */
|
||||
#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1)
|
||||
#define SECP256K1_N_C_1 (~SECP256K1_N_1)
|
||||
#define SECP256K1_N_C_2 (1)
|
||||
|
||||
/* Limbs of half the secp256k1 order. */
|
||||
#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL)
|
||||
#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL)
|
||||
#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
|
||||
#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL)
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) {
|
||||
r->d[0] = 0;
|
||||
r->d[1] = 0;
|
||||
r->d[2] = 0;
|
||||
r->d[3] = 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) {
|
||||
r->d[0] = v;
|
||||
r->d[1] = 0;
|
||||
r->d[2] = 0;
|
||||
r->d[3] = 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6);
|
||||
return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
VERIFY_CHECK(count < 32);
|
||||
VERIFY_CHECK(offset + count <= 256);
|
||||
if ((offset + count - 1) >> 6 == offset >> 6) {
|
||||
return secp256k1_scalar_get_bits(a, offset, count);
|
||||
} else {
|
||||
VERIFY_CHECK((offset >> 6) + 1 < 4);
|
||||
return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) {
|
||||
int yes = 0;
|
||||
int no = 0;
|
||||
no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */
|
||||
no |= (a->d[2] < SECP256K1_N_2);
|
||||
yes |= (a->d[2] > SECP256K1_N_2) & ~no;
|
||||
no |= (a->d[1] < SECP256K1_N_1);
|
||||
yes |= (a->d[1] > SECP256K1_N_1) & ~no;
|
||||
yes |= (a->d[0] >= SECP256K1_N_0) & ~no;
|
||||
return yes;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) {
|
||||
uint128_t t;
|
||||
VERIFY_CHECK(overflow <= 1);
|
||||
t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0;
|
||||
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1;
|
||||
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2;
|
||||
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint64_t)r->d[3];
|
||||
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
|
||||
return overflow;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
int overflow;
|
||||
uint128_t t = (uint128_t)a->d[0] + b->d[0];
|
||||
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)a->d[1] + b->d[1];
|
||||
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)a->d[2] + b->d[2];
|
||||
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)a->d[3] + b->d[3];
|
||||
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
overflow = t + secp256k1_scalar_check_overflow(r);
|
||||
VERIFY_CHECK(overflow == 0 || overflow == 1);
|
||||
secp256k1_scalar_reduce(r, overflow);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
|
||||
uint128_t t;
|
||||
VERIFY_CHECK(bit < 256);
|
||||
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
|
||||
t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
|
||||
r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F));
|
||||
r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F));
|
||||
r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64;
|
||||
t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F));
|
||||
r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK((t >> 64) == 0);
|
||||
VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) {
|
||||
int over;
|
||||
r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56;
|
||||
r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56;
|
||||
r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56;
|
||||
r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56;
|
||||
over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
|
||||
if (overflow) {
|
||||
*overflow = over;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) {
|
||||
bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3];
|
||||
bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2];
|
||||
bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1];
|
||||
bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0];
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) {
|
||||
return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0);
|
||||
uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1;
|
||||
r->d[0] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(~a->d[1]) + SECP256K1_N_1;
|
||||
r->d[1] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(~a->d[2]) + SECP256K1_N_2;
|
||||
r->d[2] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(~a->d[3]) + SECP256K1_N_3;
|
||||
r->d[3] = t & nonzero;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
|
||||
return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
|
||||
int yes = 0;
|
||||
int no = 0;
|
||||
no |= (a->d[3] < SECP256K1_N_H_3);
|
||||
yes |= (a->d[3] > SECP256K1_N_H_3) & ~no;
|
||||
no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */
|
||||
no |= (a->d[1] < SECP256K1_N_H_1) & ~yes;
|
||||
yes |= (a->d[1] > SECP256K1_N_H_1) & ~no;
|
||||
yes |= (a->d[0] > SECP256K1_N_H_0) & ~no;
|
||||
return yes;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
|
||||
/* If we are flag = 0, mask = 00...00 and this is a no-op;
|
||||
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
|
||||
uint64_t mask = !flag - 1;
|
||||
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
|
||||
uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
|
||||
r->d[0] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask);
|
||||
r->d[1] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask);
|
||||
r->d[2] = t & nonzero; t >>= 64;
|
||||
t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask);
|
||||
r->d[3] = t & nonzero;
|
||||
return 2 * (mask == 0) - 1;
|
||||
}
|
||||
|
||||
/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */
|
||||
|
||||
/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define muladd(a,b) { \
|
||||
uint64_t tl, th; \
|
||||
{ \
|
||||
uint128_t t = (uint128_t)a * b; \
|
||||
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
c0 += tl; /* overflow is handled on the next line */ \
|
||||
th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
|
||||
c1 += th; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \
|
||||
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
|
||||
}
|
||||
|
||||
/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */
|
||||
#define muladd_fast(a,b) { \
|
||||
uint64_t tl, th; \
|
||||
{ \
|
||||
uint128_t t = (uint128_t)a * b; \
|
||||
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
c0 += tl; /* overflow is handled on the next line */ \
|
||||
th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
|
||||
c1 += th; /* never overflows by contract (verified in the next line) */ \
|
||||
VERIFY_CHECK(c1 >= th); \
|
||||
}
|
||||
|
||||
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define muladd2(a,b) { \
|
||||
uint64_t tl, th, th2, tl2; \
|
||||
{ \
|
||||
uint128_t t = (uint128_t)a * b; \
|
||||
th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \
|
||||
c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
|
||||
tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \
|
||||
th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
|
||||
c0 += tl2; /* overflow is handled on the next line */ \
|
||||
th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
|
||||
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
|
||||
c1 += th2; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
|
||||
}
|
||||
|
||||
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define sumadd(a) { \
|
||||
unsigned int over; \
|
||||
c0 += (a); /* overflow is handled on the next line */ \
|
||||
over = (c0 < (a)) ? 1 : 0; \
|
||||
c1 += over; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
|
||||
}
|
||||
|
||||
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
|
||||
#define sumadd_fast(a) { \
|
||||
c0 += (a); /* overflow is handled on the next line */ \
|
||||
c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
|
||||
VERIFY_CHECK(c2 == 0); \
|
||||
}
|
||||
|
||||
/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */
|
||||
#define extract(n) { \
|
||||
(n) = c0; \
|
||||
c0 = c1; \
|
||||
c1 = c2; \
|
||||
c2 = 0; \
|
||||
}
|
||||
|
||||
/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */
|
||||
#define extract_fast(n) { \
|
||||
(n) = c0; \
|
||||
c0 = c1; \
|
||||
c1 = 0; \
|
||||
VERIFY_CHECK(c2 == 0); \
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) {
|
||||
#ifdef USE_ASM_X86_64
|
||||
/* Reduce 512 bits into 385. */
|
||||
uint64_t m0, m1, m2, m3, m4, m5, m6;
|
||||
uint64_t p0, p1, p2, p3, p4;
|
||||
uint64_t c;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* Preload. */
|
||||
"movq 32(%%rsi), %%r11\n"
|
||||
"movq 40(%%rsi), %%r12\n"
|
||||
"movq 48(%%rsi), %%r13\n"
|
||||
"movq 56(%%rsi), %%r14\n"
|
||||
/* Initialize r8,r9,r10 */
|
||||
"movq 0(%%rsi), %%r8\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9) += n0 * c0 */
|
||||
"movq %8, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
/* extract m0 */
|
||||
"movq %%r8, %q0\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10) += l1 */
|
||||
"addq 8(%%rsi), %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r9,r10,r8) += n1 * c0 */
|
||||
"movq %8, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += n0 * c1 */
|
||||
"movq %9, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* extract m1 */
|
||||
"movq %%r9, %q1\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r10,r8,r9) += l2 */
|
||||
"addq 16(%%rsi), %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += n2 * c0 */
|
||||
"movq %8, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += n1 * c1 */
|
||||
"movq %9, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += n0 */
|
||||
"addq %%r11, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* extract m2 */
|
||||
"movq %%r10, %q2\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9,r10) += l3 */
|
||||
"addq 24(%%rsi), %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += n3 * c0 */
|
||||
"movq %8, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += n2 * c1 */
|
||||
"movq %9, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += n1 */
|
||||
"addq %%r12, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* extract m3 */
|
||||
"movq %%r8, %q3\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10,r8) += n3 * c1 */
|
||||
"movq %9, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += n2 */
|
||||
"addq %%r13, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* extract m4 */
|
||||
"movq %%r9, %q4\n"
|
||||
/* (r10,r8) += n3 */
|
||||
"addq %%r14, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* extract m5 */
|
||||
"movq %%r10, %q5\n"
|
||||
/* extract m6 */
|
||||
"movq %%r8, %q6\n"
|
||||
: "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
|
||||
: "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
|
||||
: "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc");
|
||||
|
||||
/* Reduce 385 bits into 258. */
|
||||
__asm__ __volatile__(
|
||||
/* Preload */
|
||||
"movq %q9, %%r11\n"
|
||||
"movq %q10, %%r12\n"
|
||||
"movq %q11, %%r13\n"
|
||||
/* Initialize (r8,r9,r10) */
|
||||
"movq %q5, %%r8\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9) += m4 * c0 */
|
||||
"movq %12, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
/* extract p0 */
|
||||
"movq %%r8, %q0\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10) += m1 */
|
||||
"addq %q6, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r9,r10,r8) += m5 * c0 */
|
||||
"movq %12, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += m4 * c1 */
|
||||
"movq %13, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* extract p1 */
|
||||
"movq %%r9, %q1\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r10,r8,r9) += m2 */
|
||||
"addq %q7, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += m6 * c0 */
|
||||
"movq %12, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += m5 * c1 */
|
||||
"movq %13, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += m4 */
|
||||
"addq %%r11, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* extract p2 */
|
||||
"movq %%r10, %q2\n"
|
||||
/* (r8,r9) += m3 */
|
||||
"addq %q8, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r8,r9) += m6 * c1 */
|
||||
"movq %13, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
/* (r8,r9) += m5 */
|
||||
"addq %%r12, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* extract p3 */
|
||||
"movq %%r8, %q3\n"
|
||||
/* (r9) += m6 */
|
||||
"addq %%r13, %%r9\n"
|
||||
/* extract p4 */
|
||||
"movq %%r9, %q4\n"
|
||||
: "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4)
|
||||
: "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
|
||||
: "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc");
|
||||
|
||||
/* Reduce 258 bits into 256. */
|
||||
__asm__ __volatile__(
|
||||
/* Preload */
|
||||
"movq %q5, %%r10\n"
|
||||
/* (rax,rdx) = p4 * c0 */
|
||||
"movq %7, %%rax\n"
|
||||
"mulq %%r10\n"
|
||||
/* (rax,rdx) += p0 */
|
||||
"addq %q1, %%rax\n"
|
||||
"adcq $0, %%rdx\n"
|
||||
/* extract r0 */
|
||||
"movq %%rax, 0(%q6)\n"
|
||||
/* Move to (r8,r9) */
|
||||
"movq %%rdx, %%r8\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r8,r9) += p1 */
|
||||
"addq %q2, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r8,r9) += p4 * c1 */
|
||||
"movq %8, %%rax\n"
|
||||
"mulq %%r10\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
/* Extract r1 */
|
||||
"movq %%r8, 8(%q6)\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r8) += p4 */
|
||||
"addq %%r10, %%r9\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r8) += p2 */
|
||||
"addq %q3, %%r9\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* Extract r2 */
|
||||
"movq %%r9, 16(%q6)\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r8,r9) += p3 */
|
||||
"addq %q4, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* Extract r3 */
|
||||
"movq %%r8, 24(%q6)\n"
|
||||
/* Extract c */
|
||||
"movq %%r9, %q0\n"
|
||||
: "=g"(c)
|
||||
: "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1)
|
||||
: "rax", "rdx", "r8", "r9", "r10", "cc", "memory");
|
||||
#else
|
||||
uint128_t c;
|
||||
uint64_t c0, c1, c2;
|
||||
uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
|
||||
uint64_t m0, m1, m2, m3, m4, m5;
|
||||
uint32_t m6;
|
||||
uint64_t p0, p1, p2, p3;
|
||||
uint32_t p4;
|
||||
|
||||
/* Reduce 512 bits into 385. */
|
||||
/* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */
|
||||
c0 = l[0]; c1 = 0; c2 = 0;
|
||||
muladd_fast(n0, SECP256K1_N_C_0);
|
||||
extract_fast(m0);
|
||||
sumadd_fast(l[1]);
|
||||
muladd(n1, SECP256K1_N_C_0);
|
||||
muladd(n0, SECP256K1_N_C_1);
|
||||
extract(m1);
|
||||
sumadd(l[2]);
|
||||
muladd(n2, SECP256K1_N_C_0);
|
||||
muladd(n1, SECP256K1_N_C_1);
|
||||
sumadd(n0);
|
||||
extract(m2);
|
||||
sumadd(l[3]);
|
||||
muladd(n3, SECP256K1_N_C_0);
|
||||
muladd(n2, SECP256K1_N_C_1);
|
||||
sumadd(n1);
|
||||
extract(m3);
|
||||
muladd(n3, SECP256K1_N_C_1);
|
||||
sumadd(n2);
|
||||
extract(m4);
|
||||
sumadd_fast(n3);
|
||||
extract_fast(m5);
|
||||
VERIFY_CHECK(c0 <= 1);
|
||||
m6 = c0;
|
||||
|
||||
/* Reduce 385 bits into 258. */
|
||||
/* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */
|
||||
c0 = m0; c1 = 0; c2 = 0;
|
||||
muladd_fast(m4, SECP256K1_N_C_0);
|
||||
extract_fast(p0);
|
||||
sumadd_fast(m1);
|
||||
muladd(m5, SECP256K1_N_C_0);
|
||||
muladd(m4, SECP256K1_N_C_1);
|
||||
extract(p1);
|
||||
sumadd(m2);
|
||||
muladd(m6, SECP256K1_N_C_0);
|
||||
muladd(m5, SECP256K1_N_C_1);
|
||||
sumadd(m4);
|
||||
extract(p2);
|
||||
sumadd_fast(m3);
|
||||
muladd_fast(m6, SECP256K1_N_C_1);
|
||||
sumadd_fast(m5);
|
||||
extract_fast(p3);
|
||||
p4 = c0 + m6;
|
||||
VERIFY_CHECK(p4 <= 2);
|
||||
|
||||
/* Reduce 258 bits into 256. */
|
||||
/* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
|
||||
c = p0 + (uint128_t)SECP256K1_N_C_0 * p4;
|
||||
r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
|
||||
c += p1 + (uint128_t)SECP256K1_N_C_1 * p4;
|
||||
r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
|
||||
c += p2 + (uint128_t)p4;
|
||||
r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
|
||||
c += p3;
|
||||
r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
|
||||
#endif
|
||||
|
||||
/* Final reduction of r. */
|
||||
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
#ifdef USE_ASM_X86_64
|
||||
const uint64_t *pb = b->d;
|
||||
__asm__ __volatile__(
|
||||
/* Preload */
|
||||
"movq 0(%%rdi), %%r15\n"
|
||||
"movq 8(%%rdi), %%rbx\n"
|
||||
"movq 16(%%rdi), %%rcx\n"
|
||||
"movq 0(%%rdx), %%r11\n"
|
||||
"movq 8(%%rdx), %%r12\n"
|
||||
"movq 16(%%rdx), %%r13\n"
|
||||
"movq 24(%%rdx), %%r14\n"
|
||||
/* (rax,rdx) = a0 * b0 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
/* Extract l0 */
|
||||
"movq %%rax, 0(%%rsi)\n"
|
||||
/* (r8,r9,r10) = (rdx) */
|
||||
"movq %%rdx, %%r8\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9,r10) += a0 * b1 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += a1 * b0 */
|
||||
"movq %%rbx, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* Extract l1 */
|
||||
"movq %%r8, 8(%%rsi)\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10,r8) += a0 * b2 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += a1 * b1 */
|
||||
"movq %%rbx, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += a2 * b0 */
|
||||
"movq %%rcx, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* Extract l2 */
|
||||
"movq %%r9, 16(%%rsi)\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r10,r8,r9) += a0 * b3 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* Preload a3 */
|
||||
"movq 24(%%rdi), %%r15\n"
|
||||
/* (r10,r8,r9) += a1 * b2 */
|
||||
"movq %%rbx, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += a2 * b1 */
|
||||
"movq %%rcx, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += a3 * b0 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* Extract l3 */
|
||||
"movq %%r10, 24(%%rsi)\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9,r10) += a1 * b3 */
|
||||
"movq %%rbx, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += a2 * b2 */
|
||||
"movq %%rcx, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += a3 * b1 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* Extract l4 */
|
||||
"movq %%r8, 32(%%rsi)\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10,r8) += a2 * b3 */
|
||||
"movq %%rcx, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += a3 * b2 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* Extract l5 */
|
||||
"movq %%r9, 40(%%rsi)\n"
|
||||
/* (r10,r8) += a3 * b3 */
|
||||
"movq %%r15, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
/* Extract l6 */
|
||||
"movq %%r10, 48(%%rsi)\n"
|
||||
/* Extract l7 */
|
||||
"movq %%r8, 56(%%rsi)\n"
|
||||
: "+d"(pb)
|
||||
: "S"(l), "D"(a->d)
|
||||
: "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory");
|
||||
#else
|
||||
/* 160 bit accumulator. */
|
||||
uint64_t c0 = 0, c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
|
||||
/* l[0..7] = a[0..3] * b[0..3]. */
|
||||
muladd_fast(a->d[0], b->d[0]);
|
||||
extract_fast(l[0]);
|
||||
muladd(a->d[0], b->d[1]);
|
||||
muladd(a->d[1], b->d[0]);
|
||||
extract(l[1]);
|
||||
muladd(a->d[0], b->d[2]);
|
||||
muladd(a->d[1], b->d[1]);
|
||||
muladd(a->d[2], b->d[0]);
|
||||
extract(l[2]);
|
||||
muladd(a->d[0], b->d[3]);
|
||||
muladd(a->d[1], b->d[2]);
|
||||
muladd(a->d[2], b->d[1]);
|
||||
muladd(a->d[3], b->d[0]);
|
||||
extract(l[3]);
|
||||
muladd(a->d[1], b->d[3]);
|
||||
muladd(a->d[2], b->d[2]);
|
||||
muladd(a->d[3], b->d[1]);
|
||||
extract(l[4]);
|
||||
muladd(a->d[2], b->d[3]);
|
||||
muladd(a->d[3], b->d[2]);
|
||||
extract(l[5]);
|
||||
muladd_fast(a->d[3], b->d[3]);
|
||||
extract_fast(l[6]);
|
||||
VERIFY_CHECK(c1 == 0);
|
||||
l[7] = c0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) {
|
||||
#ifdef USE_ASM_X86_64
|
||||
__asm__ __volatile__(
|
||||
/* Preload */
|
||||
"movq 0(%%rdi), %%r11\n"
|
||||
"movq 8(%%rdi), %%r12\n"
|
||||
"movq 16(%%rdi), %%r13\n"
|
||||
"movq 24(%%rdi), %%r14\n"
|
||||
/* (rax,rdx) = a0 * a0 */
|
||||
"movq %%r11, %%rax\n"
|
||||
"mulq %%r11\n"
|
||||
/* Extract l0 */
|
||||
"movq %%rax, 0(%%rsi)\n"
|
||||
/* (r8,r9,r10) = (rdx,0) */
|
||||
"movq %%rdx, %%r8\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9,r10) += 2 * a0 * a1 */
|
||||
"movq %%r11, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* Extract l1 */
|
||||
"movq %%r8, 8(%%rsi)\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10,r8) += 2 * a0 * a2 */
|
||||
"movq %%r11, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* (r9,r10,r8) += a1 * a1 */
|
||||
"movq %%r12, %%rax\n"
|
||||
"mulq %%r12\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* Extract l2 */
|
||||
"movq %%r9, 16(%%rsi)\n"
|
||||
"xorq %%r9, %%r9\n"
|
||||
/* (r10,r8,r9) += 2 * a0 * a3 */
|
||||
"movq %%r11, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* (r10,r8,r9) += 2 * a1 * a2 */
|
||||
"movq %%r12, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
"adcq $0, %%r9\n"
|
||||
/* Extract l3 */
|
||||
"movq %%r10, 24(%%rsi)\n"
|
||||
"xorq %%r10, %%r10\n"
|
||||
/* (r8,r9,r10) += 2 * a1 * a3 */
|
||||
"movq %%r12, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* (r8,r9,r10) += a2 * a2 */
|
||||
"movq %%r13, %%rax\n"
|
||||
"mulq %%r13\n"
|
||||
"addq %%rax, %%r8\n"
|
||||
"adcq %%rdx, %%r9\n"
|
||||
"adcq $0, %%r10\n"
|
||||
/* Extract l4 */
|
||||
"movq %%r8, 32(%%rsi)\n"
|
||||
"xorq %%r8, %%r8\n"
|
||||
/* (r9,r10,r8) += 2 * a2 * a3 */
|
||||
"movq %%r13, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
"addq %%rax, %%r9\n"
|
||||
"adcq %%rdx, %%r10\n"
|
||||
"adcq $0, %%r8\n"
|
||||
/* Extract l5 */
|
||||
"movq %%r9, 40(%%rsi)\n"
|
||||
/* (r10,r8) += a3 * a3 */
|
||||
"movq %%r14, %%rax\n"
|
||||
"mulq %%r14\n"
|
||||
"addq %%rax, %%r10\n"
|
||||
"adcq %%rdx, %%r8\n"
|
||||
/* Extract l6 */
|
||||
"movq %%r10, 48(%%rsi)\n"
|
||||
/* Extract l7 */
|
||||
"movq %%r8, 56(%%rsi)\n"
|
||||
:
|
||||
: "S"(l), "D"(a->d)
|
||||
: "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory");
|
||||
#else
|
||||
/* 160 bit accumulator. */
|
||||
uint64_t c0 = 0, c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
|
||||
/* l[0..7] = a[0..3] * b[0..3]. */
|
||||
muladd_fast(a->d[0], a->d[0]);
|
||||
extract_fast(l[0]);
|
||||
muladd2(a->d[0], a->d[1]);
|
||||
extract(l[1]);
|
||||
muladd2(a->d[0], a->d[2]);
|
||||
muladd(a->d[1], a->d[1]);
|
||||
extract(l[2]);
|
||||
muladd2(a->d[0], a->d[3]);
|
||||
muladd2(a->d[1], a->d[2]);
|
||||
extract(l[3]);
|
||||
muladd2(a->d[1], a->d[3]);
|
||||
muladd(a->d[2], a->d[2]);
|
||||
extract(l[4]);
|
||||
muladd2(a->d[2], a->d[3]);
|
||||
extract(l[5]);
|
||||
muladd_fast(a->d[3], a->d[3]);
|
||||
extract_fast(l[6]);
|
||||
VERIFY_CHECK(c1 == 0);
|
||||
l[7] = c0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef sumadd
|
||||
#undef sumadd_fast
|
||||
#undef muladd
|
||||
#undef muladd_fast
|
||||
#undef muladd2
|
||||
#undef extract
|
||||
#undef extract_fast
|
||||
|
||||
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
uint64_t l[8];
|
||||
secp256k1_scalar_mul_512(l, a, b);
|
||||
secp256k1_scalar_reduce_512(r, l);
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) {
|
||||
int ret;
|
||||
VERIFY_CHECK(n > 0);
|
||||
VERIFY_CHECK(n < 16);
|
||||
ret = r->d[0] & ((1 << n) - 1);
|
||||
r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n));
|
||||
r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n));
|
||||
r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n));
|
||||
r->d[3] = (r->d[3] >> n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
uint64_t l[8];
|
||||
secp256k1_scalar_sqr_512(l, a);
|
||||
secp256k1_scalar_reduce_512(r, l);
|
||||
}
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
|
||||
r1->d[0] = a->d[0];
|
||||
r1->d[1] = a->d[1];
|
||||
r1->d[2] = 0;
|
||||
r1->d[3] = 0;
|
||||
r2->d[0] = a->d[2];
|
||||
r2->d[1] = a->d[3];
|
||||
r2->d[2] = 0;
|
||||
r2->d[3] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) {
|
||||
uint64_t l[8];
|
||||
unsigned int shiftlimbs;
|
||||
unsigned int shiftlow;
|
||||
unsigned int shifthigh;
|
||||
VERIFY_CHECK(shift >= 256);
|
||||
secp256k1_scalar_mul_512(l, a, b);
|
||||
shiftlimbs = shift >> 6;
|
||||
shiftlow = shift & 0x3F;
|
||||
shifthigh = 64 - shiftlow;
|
||||
r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0;
|
||||
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
19
vendors/ocaml-secp256k1-internal/src/scalar_8x32.h
vendored
Normal file
19
vendors/ocaml-secp256k1-internal/src/scalar_8x32.h
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_H
|
||||
#define SECP256K1_SCALAR_REPR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** A scalar modulo the group order of the secp256k1 curve. */
|
||||
typedef struct {
|
||||
uint32_t d[8];
|
||||
} secp256k1_scalar;
|
||||
|
||||
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_H */
|
721
vendors/ocaml-secp256k1-internal/src/scalar_8x32_impl.h
vendored
Normal file
721
vendors/ocaml-secp256k1-internal/src/scalar_8x32_impl.h
vendored
Normal file
@ -0,0 +1,721 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
|
||||
#define SECP256K1_SCALAR_REPR_IMPL_H
|
||||
|
||||
/* Limbs of the secp256k1 order. */
|
||||
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
|
||||
#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL)
|
||||
#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL)
|
||||
#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL)
|
||||
#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL)
|
||||
#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL)
|
||||
#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL)
|
||||
#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL)
|
||||
|
||||
/* Limbs of 2^256 minus the secp256k1 order. */
|
||||
#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1)
|
||||
#define SECP256K1_N_C_1 (~SECP256K1_N_1)
|
||||
#define SECP256K1_N_C_2 (~SECP256K1_N_2)
|
||||
#define SECP256K1_N_C_3 (~SECP256K1_N_3)
|
||||
#define SECP256K1_N_C_4 (1)
|
||||
|
||||
/* Limbs of half the secp256k1 order. */
|
||||
#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL)
|
||||
#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL)
|
||||
#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL)
|
||||
#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL)
|
||||
#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL)
|
||||
#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL)
|
||||
#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL)
|
||||
#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL)
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) {
|
||||
r->d[0] = 0;
|
||||
r->d[1] = 0;
|
||||
r->d[2] = 0;
|
||||
r->d[3] = 0;
|
||||
r->d[4] = 0;
|
||||
r->d[5] = 0;
|
||||
r->d[6] = 0;
|
||||
r->d[7] = 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) {
|
||||
r->d[0] = v;
|
||||
r->d[1] = 0;
|
||||
r->d[2] = 0;
|
||||
r->d[3] = 0;
|
||||
r->d[4] = 0;
|
||||
r->d[5] = 0;
|
||||
r->d[6] = 0;
|
||||
r->d[7] = 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5);
|
||||
return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
VERIFY_CHECK(count < 32);
|
||||
VERIFY_CHECK(offset + count <= 256);
|
||||
if ((offset + count - 1) >> 5 == offset >> 5) {
|
||||
return secp256k1_scalar_get_bits(a, offset, count);
|
||||
} else {
|
||||
VERIFY_CHECK((offset >> 5) + 1 < 8);
|
||||
return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) {
|
||||
int yes = 0;
|
||||
int no = 0;
|
||||
no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */
|
||||
no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */
|
||||
no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */
|
||||
no |= (a->d[4] < SECP256K1_N_4);
|
||||
yes |= (a->d[4] > SECP256K1_N_4) & ~no;
|
||||
no |= (a->d[3] < SECP256K1_N_3) & ~yes;
|
||||
yes |= (a->d[3] > SECP256K1_N_3) & ~no;
|
||||
no |= (a->d[2] < SECP256K1_N_2) & ~yes;
|
||||
yes |= (a->d[2] > SECP256K1_N_2) & ~no;
|
||||
no |= (a->d[1] < SECP256K1_N_1) & ~yes;
|
||||
yes |= (a->d[1] > SECP256K1_N_1) & ~no;
|
||||
yes |= (a->d[0] >= SECP256K1_N_0) & ~no;
|
||||
return yes;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) {
|
||||
uint64_t t;
|
||||
VERIFY_CHECK(overflow <= 1);
|
||||
t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0;
|
||||
r->d[0] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1;
|
||||
r->d[1] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2;
|
||||
r->d[2] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3;
|
||||
r->d[3] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4;
|
||||
r->d[4] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[5];
|
||||
r->d[5] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[6];
|
||||
r->d[6] = t & 0xFFFFFFFFUL; t >>= 32;
|
||||
t += (uint64_t)r->d[7];
|
||||
r->d[7] = t & 0xFFFFFFFFUL;
|
||||
return overflow;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
int overflow;
|
||||
uint64_t t = (uint64_t)a->d[0] + b->d[0];
|
||||
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[1] + b->d[1];
|
||||
r->d[1] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[2] + b->d[2];
|
||||
r->d[2] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[3] + b->d[3];
|
||||
r->d[3] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[4] + b->d[4];
|
||||
r->d[4] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[5] + b->d[5];
|
||||
r->d[5] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[6] + b->d[6];
|
||||
r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)a->d[7] + b->d[7];
|
||||
r->d[7] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
overflow = t + secp256k1_scalar_check_overflow(r);
|
||||
VERIFY_CHECK(overflow == 0 || overflow == 1);
|
||||
secp256k1_scalar_reduce(r, overflow);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
|
||||
uint64_t t;
|
||||
VERIFY_CHECK(bit < 256);
|
||||
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
|
||||
t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F));
|
||||
r->d[0] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F));
|
||||
r->d[1] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F));
|
||||
r->d[2] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F));
|
||||
r->d[3] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F));
|
||||
r->d[4] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F));
|
||||
r->d[5] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F));
|
||||
r->d[6] = t & 0xFFFFFFFFULL; t >>= 32;
|
||||
t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F));
|
||||
r->d[7] = t & 0xFFFFFFFFULL;
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK((t >> 32) == 0);
|
||||
VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) {
|
||||
int over;
|
||||
r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24;
|
||||
r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24;
|
||||
r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24;
|
||||
r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24;
|
||||
r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24;
|
||||
r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24;
|
||||
r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24;
|
||||
r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24;
|
||||
over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r));
|
||||
if (overflow) {
|
||||
*overflow = over;
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) {
|
||||
bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7];
|
||||
bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6];
|
||||
bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5];
|
||||
bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4];
|
||||
bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3];
|
||||
bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2];
|
||||
bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1];
|
||||
bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0];
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) {
|
||||
return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0);
|
||||
uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1;
|
||||
r->d[0] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[1]) + SECP256K1_N_1;
|
||||
r->d[1] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[2]) + SECP256K1_N_2;
|
||||
r->d[2] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[3]) + SECP256K1_N_3;
|
||||
r->d[3] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[4]) + SECP256K1_N_4;
|
||||
r->d[4] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[5]) + SECP256K1_N_5;
|
||||
r->d[5] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[6]) + SECP256K1_N_6;
|
||||
r->d[6] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(~a->d[7]) + SECP256K1_N_7;
|
||||
r->d[7] = t & nonzero;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
|
||||
return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
|
||||
int yes = 0;
|
||||
int no = 0;
|
||||
no |= (a->d[7] < SECP256K1_N_H_7);
|
||||
yes |= (a->d[7] > SECP256K1_N_H_7) & ~no;
|
||||
no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */
|
||||
no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */
|
||||
no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */
|
||||
no |= (a->d[3] < SECP256K1_N_H_3) & ~yes;
|
||||
yes |= (a->d[3] > SECP256K1_N_H_3) & ~no;
|
||||
no |= (a->d[2] < SECP256K1_N_H_2) & ~yes;
|
||||
yes |= (a->d[2] > SECP256K1_N_H_2) & ~no;
|
||||
no |= (a->d[1] < SECP256K1_N_H_1) & ~yes;
|
||||
yes |= (a->d[1] > SECP256K1_N_H_1) & ~no;
|
||||
yes |= (a->d[0] > SECP256K1_N_H_0) & ~no;
|
||||
return yes;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
|
||||
/* If we are flag = 0, mask = 00...00 and this is a no-op;
|
||||
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
|
||||
uint32_t mask = !flag - 1;
|
||||
uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0);
|
||||
uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
|
||||
r->d[0] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask);
|
||||
r->d[1] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask);
|
||||
r->d[2] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask);
|
||||
r->d[3] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask);
|
||||
r->d[4] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask);
|
||||
r->d[5] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask);
|
||||
r->d[6] = t & nonzero; t >>= 32;
|
||||
t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask);
|
||||
r->d[7] = t & nonzero;
|
||||
return 2 * (mask == 0) - 1;
|
||||
}
|
||||
|
||||
|
||||
/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */
|
||||
|
||||
/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define muladd(a,b) { \
|
||||
uint32_t tl, th; \
|
||||
{ \
|
||||
uint64_t t = (uint64_t)a * b; \
|
||||
th = t >> 32; /* at most 0xFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
c0 += tl; /* overflow is handled on the next line */ \
|
||||
th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
|
||||
c1 += th; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \
|
||||
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
|
||||
}
|
||||
|
||||
/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */
|
||||
#define muladd_fast(a,b) { \
|
||||
uint32_t tl, th; \
|
||||
{ \
|
||||
uint64_t t = (uint64_t)a * b; \
|
||||
th = t >> 32; /* at most 0xFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
c0 += tl; /* overflow is handled on the next line */ \
|
||||
th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
|
||||
c1 += th; /* never overflows by contract (verified in the next line) */ \
|
||||
VERIFY_CHECK(c1 >= th); \
|
||||
}
|
||||
|
||||
/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define muladd2(a,b) { \
|
||||
uint32_t tl, th, th2, tl2; \
|
||||
{ \
|
||||
uint64_t t = (uint64_t)a * b; \
|
||||
th = t >> 32; /* at most 0xFFFFFFFE */ \
|
||||
tl = t; \
|
||||
} \
|
||||
th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \
|
||||
c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
|
||||
tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \
|
||||
th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
|
||||
c0 += tl2; /* overflow is handled on the next line */ \
|
||||
th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
|
||||
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
|
||||
c1 += th2; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
|
||||
}
|
||||
|
||||
/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */
|
||||
#define sumadd(a) { \
|
||||
unsigned int over; \
|
||||
c0 += (a); /* overflow is handled on the next line */ \
|
||||
over = (c0 < (a)) ? 1 : 0; \
|
||||
c1 += over; /* overflow is handled on the next line */ \
|
||||
c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
|
||||
}
|
||||
|
||||
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
|
||||
#define sumadd_fast(a) { \
|
||||
c0 += (a); /* overflow is handled on the next line */ \
|
||||
c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
|
||||
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
|
||||
VERIFY_CHECK(c2 == 0); \
|
||||
}
|
||||
|
||||
/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */
|
||||
#define extract(n) { \
|
||||
(n) = c0; \
|
||||
c0 = c1; \
|
||||
c1 = c2; \
|
||||
c2 = 0; \
|
||||
}
|
||||
|
||||
/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */
|
||||
#define extract_fast(n) { \
|
||||
(n) = c0; \
|
||||
c0 = c1; \
|
||||
c1 = 0; \
|
||||
VERIFY_CHECK(c2 == 0); \
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) {
|
||||
uint64_t c;
|
||||
uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15];
|
||||
uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12;
|
||||
uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8;
|
||||
|
||||
/* 96 bit accumulator. */
|
||||
uint32_t c0, c1, c2;
|
||||
|
||||
/* Reduce 512 bits into 385. */
|
||||
/* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */
|
||||
c0 = l[0]; c1 = 0; c2 = 0;
|
||||
muladd_fast(n0, SECP256K1_N_C_0);
|
||||
extract_fast(m0);
|
||||
sumadd_fast(l[1]);
|
||||
muladd(n1, SECP256K1_N_C_0);
|
||||
muladd(n0, SECP256K1_N_C_1);
|
||||
extract(m1);
|
||||
sumadd(l[2]);
|
||||
muladd(n2, SECP256K1_N_C_0);
|
||||
muladd(n1, SECP256K1_N_C_1);
|
||||
muladd(n0, SECP256K1_N_C_2);
|
||||
extract(m2);
|
||||
sumadd(l[3]);
|
||||
muladd(n3, SECP256K1_N_C_0);
|
||||
muladd(n2, SECP256K1_N_C_1);
|
||||
muladd(n1, SECP256K1_N_C_2);
|
||||
muladd(n0, SECP256K1_N_C_3);
|
||||
extract(m3);
|
||||
sumadd(l[4]);
|
||||
muladd(n4, SECP256K1_N_C_0);
|
||||
muladd(n3, SECP256K1_N_C_1);
|
||||
muladd(n2, SECP256K1_N_C_2);
|
||||
muladd(n1, SECP256K1_N_C_3);
|
||||
sumadd(n0);
|
||||
extract(m4);
|
||||
sumadd(l[5]);
|
||||
muladd(n5, SECP256K1_N_C_0);
|
||||
muladd(n4, SECP256K1_N_C_1);
|
||||
muladd(n3, SECP256K1_N_C_2);
|
||||
muladd(n2, SECP256K1_N_C_3);
|
||||
sumadd(n1);
|
||||
extract(m5);
|
||||
sumadd(l[6]);
|
||||
muladd(n6, SECP256K1_N_C_0);
|
||||
muladd(n5, SECP256K1_N_C_1);
|
||||
muladd(n4, SECP256K1_N_C_2);
|
||||
muladd(n3, SECP256K1_N_C_3);
|
||||
sumadd(n2);
|
||||
extract(m6);
|
||||
sumadd(l[7]);
|
||||
muladd(n7, SECP256K1_N_C_0);
|
||||
muladd(n6, SECP256K1_N_C_1);
|
||||
muladd(n5, SECP256K1_N_C_2);
|
||||
muladd(n4, SECP256K1_N_C_3);
|
||||
sumadd(n3);
|
||||
extract(m7);
|
||||
muladd(n7, SECP256K1_N_C_1);
|
||||
muladd(n6, SECP256K1_N_C_2);
|
||||
muladd(n5, SECP256K1_N_C_3);
|
||||
sumadd(n4);
|
||||
extract(m8);
|
||||
muladd(n7, SECP256K1_N_C_2);
|
||||
muladd(n6, SECP256K1_N_C_3);
|
||||
sumadd(n5);
|
||||
extract(m9);
|
||||
muladd(n7, SECP256K1_N_C_3);
|
||||
sumadd(n6);
|
||||
extract(m10);
|
||||
sumadd_fast(n7);
|
||||
extract_fast(m11);
|
||||
VERIFY_CHECK(c0 <= 1);
|
||||
m12 = c0;
|
||||
|
||||
/* Reduce 385 bits into 258. */
|
||||
/* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */
|
||||
c0 = m0; c1 = 0; c2 = 0;
|
||||
muladd_fast(m8, SECP256K1_N_C_0);
|
||||
extract_fast(p0);
|
||||
sumadd_fast(m1);
|
||||
muladd(m9, SECP256K1_N_C_0);
|
||||
muladd(m8, SECP256K1_N_C_1);
|
||||
extract(p1);
|
||||
sumadd(m2);
|
||||
muladd(m10, SECP256K1_N_C_0);
|
||||
muladd(m9, SECP256K1_N_C_1);
|
||||
muladd(m8, SECP256K1_N_C_2);
|
||||
extract(p2);
|
||||
sumadd(m3);
|
||||
muladd(m11, SECP256K1_N_C_0);
|
||||
muladd(m10, SECP256K1_N_C_1);
|
||||
muladd(m9, SECP256K1_N_C_2);
|
||||
muladd(m8, SECP256K1_N_C_3);
|
||||
extract(p3);
|
||||
sumadd(m4);
|
||||
muladd(m12, SECP256K1_N_C_0);
|
||||
muladd(m11, SECP256K1_N_C_1);
|
||||
muladd(m10, SECP256K1_N_C_2);
|
||||
muladd(m9, SECP256K1_N_C_3);
|
||||
sumadd(m8);
|
||||
extract(p4);
|
||||
sumadd(m5);
|
||||
muladd(m12, SECP256K1_N_C_1);
|
||||
muladd(m11, SECP256K1_N_C_2);
|
||||
muladd(m10, SECP256K1_N_C_3);
|
||||
sumadd(m9);
|
||||
extract(p5);
|
||||
sumadd(m6);
|
||||
muladd(m12, SECP256K1_N_C_2);
|
||||
muladd(m11, SECP256K1_N_C_3);
|
||||
sumadd(m10);
|
||||
extract(p6);
|
||||
sumadd_fast(m7);
|
||||
muladd_fast(m12, SECP256K1_N_C_3);
|
||||
sumadd_fast(m11);
|
||||
extract_fast(p7);
|
||||
p8 = c0 + m12;
|
||||
VERIFY_CHECK(p8 <= 2);
|
||||
|
||||
/* Reduce 258 bits into 256. */
|
||||
/* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */
|
||||
c = p0 + (uint64_t)SECP256K1_N_C_0 * p8;
|
||||
r->d[0] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p1 + (uint64_t)SECP256K1_N_C_1 * p8;
|
||||
r->d[1] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p2 + (uint64_t)SECP256K1_N_C_2 * p8;
|
||||
r->d[2] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p3 + (uint64_t)SECP256K1_N_C_3 * p8;
|
||||
r->d[3] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p4 + (uint64_t)p8;
|
||||
r->d[4] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p5;
|
||||
r->d[5] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p6;
|
||||
r->d[6] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
c += p7;
|
||||
r->d[7] = c & 0xFFFFFFFFUL; c >>= 32;
|
||||
|
||||
/* Final reduction of r. */
|
||||
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
/* 96 bit accumulator. */
|
||||
uint32_t c0 = 0, c1 = 0, c2 = 0;
|
||||
|
||||
/* l[0..15] = a[0..7] * b[0..7]. */
|
||||
muladd_fast(a->d[0], b->d[0]);
|
||||
extract_fast(l[0]);
|
||||
muladd(a->d[0], b->d[1]);
|
||||
muladd(a->d[1], b->d[0]);
|
||||
extract(l[1]);
|
||||
muladd(a->d[0], b->d[2]);
|
||||
muladd(a->d[1], b->d[1]);
|
||||
muladd(a->d[2], b->d[0]);
|
||||
extract(l[2]);
|
||||
muladd(a->d[0], b->d[3]);
|
||||
muladd(a->d[1], b->d[2]);
|
||||
muladd(a->d[2], b->d[1]);
|
||||
muladd(a->d[3], b->d[0]);
|
||||
extract(l[3]);
|
||||
muladd(a->d[0], b->d[4]);
|
||||
muladd(a->d[1], b->d[3]);
|
||||
muladd(a->d[2], b->d[2]);
|
||||
muladd(a->d[3], b->d[1]);
|
||||
muladd(a->d[4], b->d[0]);
|
||||
extract(l[4]);
|
||||
muladd(a->d[0], b->d[5]);
|
||||
muladd(a->d[1], b->d[4]);
|
||||
muladd(a->d[2], b->d[3]);
|
||||
muladd(a->d[3], b->d[2]);
|
||||
muladd(a->d[4], b->d[1]);
|
||||
muladd(a->d[5], b->d[0]);
|
||||
extract(l[5]);
|
||||
muladd(a->d[0], b->d[6]);
|
||||
muladd(a->d[1], b->d[5]);
|
||||
muladd(a->d[2], b->d[4]);
|
||||
muladd(a->d[3], b->d[3]);
|
||||
muladd(a->d[4], b->d[2]);
|
||||
muladd(a->d[5], b->d[1]);
|
||||
muladd(a->d[6], b->d[0]);
|
||||
extract(l[6]);
|
||||
muladd(a->d[0], b->d[7]);
|
||||
muladd(a->d[1], b->d[6]);
|
||||
muladd(a->d[2], b->d[5]);
|
||||
muladd(a->d[3], b->d[4]);
|
||||
muladd(a->d[4], b->d[3]);
|
||||
muladd(a->d[5], b->d[2]);
|
||||
muladd(a->d[6], b->d[1]);
|
||||
muladd(a->d[7], b->d[0]);
|
||||
extract(l[7]);
|
||||
muladd(a->d[1], b->d[7]);
|
||||
muladd(a->d[2], b->d[6]);
|
||||
muladd(a->d[3], b->d[5]);
|
||||
muladd(a->d[4], b->d[4]);
|
||||
muladd(a->d[5], b->d[3]);
|
||||
muladd(a->d[6], b->d[2]);
|
||||
muladd(a->d[7], b->d[1]);
|
||||
extract(l[8]);
|
||||
muladd(a->d[2], b->d[7]);
|
||||
muladd(a->d[3], b->d[6]);
|
||||
muladd(a->d[4], b->d[5]);
|
||||
muladd(a->d[5], b->d[4]);
|
||||
muladd(a->d[6], b->d[3]);
|
||||
muladd(a->d[7], b->d[2]);
|
||||
extract(l[9]);
|
||||
muladd(a->d[3], b->d[7]);
|
||||
muladd(a->d[4], b->d[6]);
|
||||
muladd(a->d[5], b->d[5]);
|
||||
muladd(a->d[6], b->d[4]);
|
||||
muladd(a->d[7], b->d[3]);
|
||||
extract(l[10]);
|
||||
muladd(a->d[4], b->d[7]);
|
||||
muladd(a->d[5], b->d[6]);
|
||||
muladd(a->d[6], b->d[5]);
|
||||
muladd(a->d[7], b->d[4]);
|
||||
extract(l[11]);
|
||||
muladd(a->d[5], b->d[7]);
|
||||
muladd(a->d[6], b->d[6]);
|
||||
muladd(a->d[7], b->d[5]);
|
||||
extract(l[12]);
|
||||
muladd(a->d[6], b->d[7]);
|
||||
muladd(a->d[7], b->d[6]);
|
||||
extract(l[13]);
|
||||
muladd_fast(a->d[7], b->d[7]);
|
||||
extract_fast(l[14]);
|
||||
VERIFY_CHECK(c1 == 0);
|
||||
l[15] = c0;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) {
|
||||
/* 96 bit accumulator. */
|
||||
uint32_t c0 = 0, c1 = 0, c2 = 0;
|
||||
|
||||
/* l[0..15] = a[0..7]^2. */
|
||||
muladd_fast(a->d[0], a->d[0]);
|
||||
extract_fast(l[0]);
|
||||
muladd2(a->d[0], a->d[1]);
|
||||
extract(l[1]);
|
||||
muladd2(a->d[0], a->d[2]);
|
||||
muladd(a->d[1], a->d[1]);
|
||||
extract(l[2]);
|
||||
muladd2(a->d[0], a->d[3]);
|
||||
muladd2(a->d[1], a->d[2]);
|
||||
extract(l[3]);
|
||||
muladd2(a->d[0], a->d[4]);
|
||||
muladd2(a->d[1], a->d[3]);
|
||||
muladd(a->d[2], a->d[2]);
|
||||
extract(l[4]);
|
||||
muladd2(a->d[0], a->d[5]);
|
||||
muladd2(a->d[1], a->d[4]);
|
||||
muladd2(a->d[2], a->d[3]);
|
||||
extract(l[5]);
|
||||
muladd2(a->d[0], a->d[6]);
|
||||
muladd2(a->d[1], a->d[5]);
|
||||
muladd2(a->d[2], a->d[4]);
|
||||
muladd(a->d[3], a->d[3]);
|
||||
extract(l[6]);
|
||||
muladd2(a->d[0], a->d[7]);
|
||||
muladd2(a->d[1], a->d[6]);
|
||||
muladd2(a->d[2], a->d[5]);
|
||||
muladd2(a->d[3], a->d[4]);
|
||||
extract(l[7]);
|
||||
muladd2(a->d[1], a->d[7]);
|
||||
muladd2(a->d[2], a->d[6]);
|
||||
muladd2(a->d[3], a->d[5]);
|
||||
muladd(a->d[4], a->d[4]);
|
||||
extract(l[8]);
|
||||
muladd2(a->d[2], a->d[7]);
|
||||
muladd2(a->d[3], a->d[6]);
|
||||
muladd2(a->d[4], a->d[5]);
|
||||
extract(l[9]);
|
||||
muladd2(a->d[3], a->d[7]);
|
||||
muladd2(a->d[4], a->d[6]);
|
||||
muladd(a->d[5], a->d[5]);
|
||||
extract(l[10]);
|
||||
muladd2(a->d[4], a->d[7]);
|
||||
muladd2(a->d[5], a->d[6]);
|
||||
extract(l[11]);
|
||||
muladd2(a->d[5], a->d[7]);
|
||||
muladd(a->d[6], a->d[6]);
|
||||
extract(l[12]);
|
||||
muladd2(a->d[6], a->d[7]);
|
||||
extract(l[13]);
|
||||
muladd_fast(a->d[7], a->d[7]);
|
||||
extract_fast(l[14]);
|
||||
VERIFY_CHECK(c1 == 0);
|
||||
l[15] = c0;
|
||||
}
|
||||
|
||||
#undef sumadd
|
||||
#undef sumadd_fast
|
||||
#undef muladd
|
||||
#undef muladd_fast
|
||||
#undef muladd2
|
||||
#undef extract
|
||||
#undef extract_fast
|
||||
|
||||
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
uint32_t l[16];
|
||||
secp256k1_scalar_mul_512(l, a, b);
|
||||
secp256k1_scalar_reduce_512(r, l);
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) {
|
||||
int ret;
|
||||
VERIFY_CHECK(n > 0);
|
||||
VERIFY_CHECK(n < 16);
|
||||
ret = r->d[0] & ((1 << n) - 1);
|
||||
r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n));
|
||||
r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n));
|
||||
r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n));
|
||||
r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n));
|
||||
r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n));
|
||||
r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n));
|
||||
r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n));
|
||||
r->d[7] = (r->d[7] >> n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
uint32_t l[16];
|
||||
secp256k1_scalar_sqr_512(l, a);
|
||||
secp256k1_scalar_reduce_512(r, l);
|
||||
}
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
|
||||
r1->d[0] = a->d[0];
|
||||
r1->d[1] = a->d[1];
|
||||
r1->d[2] = a->d[2];
|
||||
r1->d[3] = a->d[3];
|
||||
r1->d[4] = 0;
|
||||
r1->d[5] = 0;
|
||||
r1->d[6] = 0;
|
||||
r1->d[7] = 0;
|
||||
r2->d[0] = a->d[4];
|
||||
r2->d[1] = a->d[5];
|
||||
r2->d[2] = a->d[6];
|
||||
r2->d[3] = a->d[7];
|
||||
r2->d[4] = 0;
|
||||
r2->d[5] = 0;
|
||||
r2->d[6] = 0;
|
||||
r2->d[7] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) {
|
||||
uint32_t l[16];
|
||||
unsigned int shiftlimbs;
|
||||
unsigned int shiftlow;
|
||||
unsigned int shifthigh;
|
||||
VERIFY_CHECK(shift >= 256);
|
||||
secp256k1_scalar_mul_512(l, a, b);
|
||||
shiftlimbs = shift >> 5;
|
||||
shiftlow = shift & 0x1F;
|
||||
shifthigh = 32 - shiftlow;
|
||||
r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0;
|
||||
r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0;
|
||||
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
333
vendors/ocaml-secp256k1-internal/src/scalar_impl.h
vendored
Normal file
333
vendors/ocaml-secp256k1-internal/src/scalar_impl.h
vendored
Normal file
@ -0,0 +1,333 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_IMPL_H
|
||||
#define SECP256K1_SCALAR_IMPL_H
|
||||
|
||||
#include "group.h"
|
||||
#include "scalar.h"
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
#include "scalar_low_impl.h"
|
||||
#elif defined(USE_SCALAR_4X64)
|
||||
#include "scalar_4x64_impl.h"
|
||||
#elif defined(USE_SCALAR_8X32)
|
||||
#include "scalar_8x32_impl.h"
|
||||
#else
|
||||
#error "Please select scalar implementation"
|
||||
#endif
|
||||
|
||||
#ifndef USE_NUM_NONE
|
||||
static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar_get_b32(c, a);
|
||||
secp256k1_num_set_bin(r, c, 32);
|
||||
}
|
||||
|
||||
/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */
|
||||
static void secp256k1_scalar_order_get_num(secp256k1_num *r) {
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
static const unsigned char order[32] = {
|
||||
0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER
|
||||
};
|
||||
#else
|
||||
static const unsigned char order[32] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
|
||||
0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
|
||||
0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
|
||||
};
|
||||
#endif
|
||||
secp256k1_num_set_bin(r, order, 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) {
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
int i;
|
||||
*r = 0;
|
||||
for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++)
|
||||
if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1)
|
||||
*r = i;
|
||||
/* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus
|
||||
* have a composite group order; fix it in exhaustive_tests.c). */
|
||||
VERIFY_CHECK(*r != 0);
|
||||
}
|
||||
#else
|
||||
secp256k1_scalar *t;
|
||||
int i;
|
||||
/* First compute xN as x ^ (2^N - 1) for some values of N,
|
||||
* and uM as x ^ M for some values of M. */
|
||||
secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126;
|
||||
secp256k1_scalar u2, u5, u9, u11, u13;
|
||||
|
||||
secp256k1_scalar_sqr(&u2, x);
|
||||
secp256k1_scalar_mul(&x2, &u2, x);
|
||||
secp256k1_scalar_mul(&u5, &u2, &x2);
|
||||
secp256k1_scalar_mul(&x3, &u5, &u2);
|
||||
secp256k1_scalar_mul(&u9, &x3, &u2);
|
||||
secp256k1_scalar_mul(&u11, &u9, &u2);
|
||||
secp256k1_scalar_mul(&u13, &u11, &u2);
|
||||
|
||||
secp256k1_scalar_sqr(&x6, &u13);
|
||||
secp256k1_scalar_sqr(&x6, &x6);
|
||||
secp256k1_scalar_mul(&x6, &x6, &u11);
|
||||
|
||||
secp256k1_scalar_sqr(&x8, &x6);
|
||||
secp256k1_scalar_sqr(&x8, &x8);
|
||||
secp256k1_scalar_mul(&x8, &x8, &x2);
|
||||
|
||||
secp256k1_scalar_sqr(&x14, &x8);
|
||||
for (i = 0; i < 5; i++) {
|
||||
secp256k1_scalar_sqr(&x14, &x14);
|
||||
}
|
||||
secp256k1_scalar_mul(&x14, &x14, &x6);
|
||||
|
||||
secp256k1_scalar_sqr(&x28, &x14);
|
||||
for (i = 0; i < 13; i++) {
|
||||
secp256k1_scalar_sqr(&x28, &x28);
|
||||
}
|
||||
secp256k1_scalar_mul(&x28, &x28, &x14);
|
||||
|
||||
secp256k1_scalar_sqr(&x56, &x28);
|
||||
for (i = 0; i < 27; i++) {
|
||||
secp256k1_scalar_sqr(&x56, &x56);
|
||||
}
|
||||
secp256k1_scalar_mul(&x56, &x56, &x28);
|
||||
|
||||
secp256k1_scalar_sqr(&x112, &x56);
|
||||
for (i = 0; i < 55; i++) {
|
||||
secp256k1_scalar_sqr(&x112, &x112);
|
||||
}
|
||||
secp256k1_scalar_mul(&x112, &x112, &x56);
|
||||
|
||||
secp256k1_scalar_sqr(&x126, &x112);
|
||||
for (i = 0; i < 13; i++) {
|
||||
secp256k1_scalar_sqr(&x126, &x126);
|
||||
}
|
||||
secp256k1_scalar_mul(&x126, &x126, &x14);
|
||||
|
||||
/* Then accumulate the final result (t starts at x126). */
|
||||
t = &x126;
|
||||
for (i = 0; i < 3; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u5); /* 101 */
|
||||
for (i = 0; i < 4; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 4; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u5); /* 101 */
|
||||
for (i = 0; i < 5; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
|
||||
for (i = 0; i < 4; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 5; i++) { /* 00 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 6; i++) { /* 00 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
|
||||
for (i = 0; i < 4; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u5); /* 101 */
|
||||
for (i = 0; i < 3; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 5; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
|
||||
for (i = 0; i < 6; i++) { /* 000 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u5); /* 101 */
|
||||
for (i = 0; i < 10; i++) { /* 0000000 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 4; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x3); /* 111 */
|
||||
for (i = 0; i < 9; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x8); /* 11111111 */
|
||||
for (i = 0; i < 5; i++) { /* 0 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
|
||||
for (i = 0; i < 6; i++) { /* 00 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
|
||||
for (i = 0; i < 5; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &x2); /* 11 */
|
||||
for (i = 0; i < 6; i++) { /* 00 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
|
||||
for (i = 0; i < 10; i++) { /* 000000 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
|
||||
for (i = 0; i < 4; i++) {
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, &u9); /* 1001 */
|
||||
for (i = 0; i < 6; i++) { /* 00000 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(t, t, x); /* 1 */
|
||||
for (i = 0; i < 8; i++) { /* 00 */
|
||||
secp256k1_scalar_sqr(t, t);
|
||||
}
|
||||
secp256k1_scalar_mul(r, t, &x6); /* 111111 */
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) {
|
||||
return !(a->d[0] & 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) {
|
||||
#if defined(USE_SCALAR_INV_BUILTIN)
|
||||
secp256k1_scalar_inverse(r, x);
|
||||
#elif defined(USE_SCALAR_INV_NUM)
|
||||
unsigned char b[32];
|
||||
secp256k1_num n, m;
|
||||
secp256k1_scalar t = *x;
|
||||
secp256k1_scalar_get_b32(b, &t);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_scalar_order_get_num(&m);
|
||||
secp256k1_num_mod_inverse(&n, &n, &m);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
secp256k1_scalar_set_b32(r, b, NULL);
|
||||
/* Verify that the inverse was computed correctly, without GMP code. */
|
||||
secp256k1_scalar_mul(&t, &t, r);
|
||||
CHECK(secp256k1_scalar_is_one(&t));
|
||||
#else
|
||||
#error "Please select scalar inverse implementation"
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_ENDOMORPHISM
|
||||
#if defined(EXHAUSTIVE_TEST_ORDER)
|
||||
/**
|
||||
* Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the
|
||||
* full case we don't bother making k1 and k2 be small, we just want them to be
|
||||
* nontrivial to get full test coverage for the exhaustive tests. We therefore
|
||||
* (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda.
|
||||
*/
|
||||
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
|
||||
*r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER;
|
||||
*r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where
|
||||
* lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
|
||||
* 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72}
|
||||
*
|
||||
* "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm
|
||||
* (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1
|
||||
* and k2 have a small size.
|
||||
* It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are:
|
||||
*
|
||||
* - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
|
||||
* - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3}
|
||||
* - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8}
|
||||
* - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15}
|
||||
*
|
||||
* The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives
|
||||
* k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and
|
||||
* compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2.
|
||||
*
|
||||
* g1, g2 are precomputed constants used to replace division with a rounded multiplication
|
||||
* when decomposing the scalar for an endomorphism-based point multiplication.
|
||||
*
|
||||
* The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve
|
||||
* Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5.
|
||||
*
|
||||
* The derivation is described in the paper "Efficient Software Implementation of Public-Key
|
||||
* Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez),
|
||||
* Section 4.3 (here we use a somewhat higher-precision estimate):
|
||||
* d = a1*b2 - b1*a2
|
||||
* g1 = round((2^272)*b2/d)
|
||||
* g2 = round((2^272)*b1/d)
|
||||
*
|
||||
* (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found
|
||||
* as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda').
|
||||
*
|
||||
* The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order).
|
||||
*/
|
||||
|
||||
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
|
||||
secp256k1_scalar c1, c2;
|
||||
static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST(
|
||||
0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL,
|
||||
0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL
|
||||
);
|
||||
static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST(
|
||||
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
|
||||
0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL
|
||||
);
|
||||
static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST(
|
||||
0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
|
||||
0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL
|
||||
);
|
||||
static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST(
|
||||
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL,
|
||||
0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL
|
||||
);
|
||||
static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST(
|
||||
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL,
|
||||
0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL
|
||||
);
|
||||
VERIFY_CHECK(r1 != a);
|
||||
VERIFY_CHECK(r2 != a);
|
||||
/* these _var calls are constant time since the shift amount is constant */
|
||||
secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272);
|
||||
secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272);
|
||||
secp256k1_scalar_mul(&c1, &c1, &minus_b1);
|
||||
secp256k1_scalar_mul(&c2, &c2, &minus_b2);
|
||||
secp256k1_scalar_add(r2, &c1, &c2);
|
||||
secp256k1_scalar_mul(r1, r2, &minus_lambda);
|
||||
secp256k1_scalar_add(r1, r1, a);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_SCALAR_IMPL_H */
|
15
vendors/ocaml-secp256k1-internal/src/scalar_low.h
vendored
Normal file
15
vendors/ocaml-secp256k1-internal/src/scalar_low.h
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_H
|
||||
#define SECP256K1_SCALAR_REPR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** A scalar modulo the group order of the secp256k1 curve. */
|
||||
typedef uint32_t secp256k1_scalar;
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_H */
|
114
vendors/ocaml-secp256k1-internal/src/scalar_low_impl.h
vendored
Normal file
114
vendors/ocaml-secp256k1-internal/src/scalar_low_impl.h
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
|
||||
#define SECP256K1_SCALAR_REPR_IMPL_H
|
||||
|
||||
#include "scalar.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) {
|
||||
return !(*a & 1);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; }
|
||||
SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; }
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
if (offset < 32)
|
||||
return ((*a >> offset) & ((((uint32_t)1) << count) - 1));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
|
||||
return secp256k1_scalar_get_bits(a, offset, count);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; }
|
||||
|
||||
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
*r = (*a + *b) % EXHAUSTIVE_TEST_ORDER;
|
||||
return *r < *b;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
|
||||
if (flag && bit < 32)
|
||||
*r += (1 << bit);
|
||||
#ifdef VERIFY
|
||||
VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) {
|
||||
const int base = 0x100 % EXHAUSTIVE_TEST_ORDER;
|
||||
int i;
|
||||
*r = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
*r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER;
|
||||
}
|
||||
/* just deny overflow, it basically always happens */
|
||||
if (overflow) *overflow = 0;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) {
|
||||
memset(bin, 0, 32);
|
||||
bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) {
|
||||
return *a == 0;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
if (*a == 0) {
|
||||
*r = 0;
|
||||
} else {
|
||||
*r = EXHAUSTIVE_TEST_ORDER - *a;
|
||||
}
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
|
||||
return *a == 1;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
|
||||
return *a > EXHAUSTIVE_TEST_ORDER / 2;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
|
||||
if (flag) secp256k1_scalar_negate(r, r);
|
||||
return flag ? -1 : 1;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
*r = (*a * *b) % EXHAUSTIVE_TEST_ORDER;
|
||||
}
|
||||
|
||||
static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) {
|
||||
int ret;
|
||||
VERIFY_CHECK(n > 0);
|
||||
VERIFY_CHECK(n < 16);
|
||||
ret = *r & ((1 << n) - 1);
|
||||
*r >>= n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) {
|
||||
*r = (*a * *a) % EXHAUSTIVE_TEST_ORDER;
|
||||
}
|
||||
|
||||
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
|
||||
*r1 = *a;
|
||||
*r2 = 0;
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) {
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_SCALAR_REPR_IMPL_H */
|
35
vendors/ocaml-secp256k1-internal/src/scratch.h
vendored
Normal file
35
vendors/ocaml-secp256k1-internal/src/scratch.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2017 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_SCRATCH_
|
||||
#define _SECP256K1_SCRATCH_
|
||||
|
||||
/* The typedef is used internally; the struct name is used in the public API
|
||||
* (where it is exposed as a different typedef) */
|
||||
typedef struct secp256k1_scratch_space_struct {
|
||||
void *data;
|
||||
size_t offset;
|
||||
size_t init_size;
|
||||
size_t max_size;
|
||||
const secp256k1_callback* error_callback;
|
||||
} secp256k1_scratch;
|
||||
|
||||
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size);
|
||||
static void secp256k1_scratch_destroy(secp256k1_scratch* scratch);
|
||||
|
||||
/** Returns the maximum allocation the scratch space will allow */
|
||||
static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t n_objects);
|
||||
|
||||
/** Attempts to allocate so that there are `n` available bytes. Returns 1 on success, 0 on failure */
|
||||
static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t n_objects);
|
||||
|
||||
/** Returns a pointer into the scratch space or NULL if there is insufficient available space */
|
||||
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t n);
|
||||
|
||||
/** Resets the returned pointer to the beginning of space */
|
||||
static void secp256k1_scratch_reset(secp256k1_scratch* scratch);
|
||||
|
||||
#endif
|
77
vendors/ocaml-secp256k1-internal/src/scratch_impl.h
vendored
Normal file
77
vendors/ocaml-secp256k1-internal/src/scratch_impl.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2017 Andrew Poelstra *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _SECP256K1_SCRATCH_IMPL_H_
|
||||
#define _SECP256K1_SCRATCH_IMPL_H_
|
||||
|
||||
#include "scratch.h"
|
||||
|
||||
/* Using 16 bytes alignment because common architectures never have alignment
|
||||
* requirements above 8 for any of the types we care about. In addition we
|
||||
* leave some room because currently we don't care about a few bytes.
|
||||
* TODO: Determine this at configure time. */
|
||||
#define ALIGNMENT 16
|
||||
|
||||
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size) {
|
||||
secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret));
|
||||
if (ret != NULL) {
|
||||
ret->data = checked_malloc(error_callback, init_size);
|
||||
if (ret->data == NULL) {
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
ret->offset = 0;
|
||||
ret->init_size = init_size;
|
||||
ret->max_size = max_size;
|
||||
ret->error_callback = error_callback;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) {
|
||||
if (scratch != NULL) {
|
||||
free(scratch->data);
|
||||
free(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) {
|
||||
if (scratch->max_size <= objects * ALIGNMENT) {
|
||||
return 0;
|
||||
}
|
||||
return scratch->max_size - objects * ALIGNMENT;
|
||||
}
|
||||
|
||||
static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t objects) {
|
||||
n += objects * ALIGNMENT;
|
||||
if (n > scratch->init_size && n <= scratch->max_size) {
|
||||
void *tmp = checked_realloc(scratch->error_callback, scratch->data, n);
|
||||
if (tmp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
scratch->init_size = n;
|
||||
scratch->data = tmp;
|
||||
}
|
||||
return n <= scratch->max_size;
|
||||
}
|
||||
|
||||
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) {
|
||||
void *ret;
|
||||
size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
|
||||
if (size + scratch->offset > scratch->init_size) {
|
||||
return NULL;
|
||||
}
|
||||
ret = (void *) ((unsigned char *) scratch->data + scratch->offset);
|
||||
memset(ret, 0, size);
|
||||
scratch->offset += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void secp256k1_scratch_reset(secp256k1_scratch* scratch) {
|
||||
scratch->offset = 0;
|
||||
}
|
||||
|
||||
#endif
|
1124
vendors/ocaml-secp256k1-internal/src/secp256k1.c
vendored
Normal file
1124
vendors/ocaml-secp256k1-internal/src/secp256k1.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
656
vendors/ocaml-secp256k1-internal/src/secp256k1.h
vendored
Normal file
656
vendors/ocaml-secp256k1-internal/src/secp256k1.h
vendored
Normal file
@ -0,0 +1,656 @@
|
||||
#ifndef SECP256K1_H
|
||||
#define SECP256K1_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* These rules specify the order of arguments in API calls:
|
||||
*
|
||||
* 1. Context pointers go first, followed by output arguments, combined
|
||||
* output/input arguments, and finally input-only arguments.
|
||||
* 2. Array lengths always immediately the follow the argument whose length
|
||||
* they describe, even if this violates rule 1.
|
||||
* 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated
|
||||
* later go first. This means: signatures, public nonces, private nonces,
|
||||
* messages, public keys, secret keys, tweaks.
|
||||
* 4. Arguments that are not data pointers go last, from more complex to less
|
||||
* complex: function pointers, algorithm names, messages, void pointers,
|
||||
* counts, flags, booleans.
|
||||
* 5. Opaque data pointers follow the function pointer they are to be passed to.
|
||||
*/
|
||||
|
||||
/** Opaque data structure that holds context information (precomputed tables etc.).
|
||||
*
|
||||
* The purpose of context structures is to cache large precomputed data tables
|
||||
* that are expensive to construct, and also to maintain the randomization data
|
||||
* for blinding.
|
||||
*
|
||||
* Do not create a new context object for each operation, as construction is
|
||||
* far slower than all other API calls (~100 times slower than an ECDSA
|
||||
* verification).
|
||||
*
|
||||
* A constructed context can safely be used from multiple threads
|
||||
* simultaneously, but API call that take a non-const pointer to a context
|
||||
* need exclusive access to it. In particular this is the case for
|
||||
* secp256k1_context_destroy and secp256k1_context_randomize.
|
||||
*
|
||||
* Regarding randomization, either do it once at creation time (in which case
|
||||
* you do not need any locking for the other calls), or use a read-write lock.
|
||||
*/
|
||||
typedef struct secp256k1_context_struct secp256k1_context;
|
||||
|
||||
/** Opaque data structure that holds rewriteable "scratch space"
|
||||
*
|
||||
* The purpose of this structure is to replace dynamic memory allocations,
|
||||
* because we target architectures where this may not be available. It is
|
||||
* essentially a resizable (within specified parameters) block of bytes,
|
||||
* which is initially created either by memory allocation or TODO as a pointer
|
||||
* into some fixed rewritable space.
|
||||
*
|
||||
* Unlike the context object, this cannot safely be shared between threads
|
||||
* without additional synchronization logic.
|
||||
*/
|
||||
typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space;
|
||||
|
||||
/** Opaque data structure that holds a parsed and valid public key.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_pubkey;
|
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage, transmission, or
|
||||
* comparison, use the secp256k1_ecdsa_signature_serialize_* and
|
||||
* secp256k1_ecdsa_signature_parse_* functions.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_ecdsa_signature;
|
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
*
|
||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
|
||||
* Out: nonce32: pointer to a 32-byte array to be filled by the function.
|
||||
* In: msg32: the 32-byte message hash being verified (will not be NULL)
|
||||
* key32: pointer to a 32-byte secret key (will not be NULL)
|
||||
* algo16: pointer to a 16-byte array describing the signature
|
||||
* algorithm (will be NULL for ECDSA for compatibility).
|
||||
* data: Arbitrary data pointer that is passed through.
|
||||
* attempt: how many iterations we have tried to find a nonce.
|
||||
* This will almost always be 0, but different attempt values
|
||||
* are required to result in a different nonce.
|
||||
*
|
||||
* Except for test cases, this function should compute some cryptographic hash of
|
||||
* the message, the algorithm, the key and the attempt.
|
||||
*/
|
||||
typedef int (*secp256k1_nonce_function)(
|
||||
unsigned char *nonce32,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *key32,
|
||||
const unsigned char *algo16,
|
||||
void *data,
|
||||
unsigned int attempt
|
||||
);
|
||||
|
||||
# if !defined(SECP256K1_GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if SECP256K1_GNUC_PREREQ(2,7)
|
||||
# define SECP256K1_INLINE __inline__
|
||||
# elif (defined(_MSC_VER))
|
||||
# define SECP256K1_INLINE __inline
|
||||
# else
|
||||
# define SECP256K1_INLINE
|
||||
# endif
|
||||
# else
|
||||
# define SECP256K1_INLINE inline
|
||||
# endif
|
||||
|
||||
#ifndef SECP256K1_API
|
||||
# if defined(_WIN32)
|
||||
# ifdef SECP256K1_BUILD
|
||||
# define SECP256K1_API __declspec(dllexport)
|
||||
# else
|
||||
# define SECP256K1_API
|
||||
# endif
|
||||
# elif defined(__GNUC__) && defined(SECP256K1_BUILD)
|
||||
# define SECP256K1_API __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define SECP256K1_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**Warning attributes
|
||||
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
|
||||
* some paranoid null checks. */
|
||||
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
|
||||
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
|
||||
# else
|
||||
# define SECP256K1_WARN_UNUSED_RESULT
|
||||
# endif
|
||||
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
|
||||
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
|
||||
# else
|
||||
# define SECP256K1_ARG_NONNULL(_x)
|
||||
# endif
|
||||
|
||||
/** All flags' lower 8 bits indicate what they're for. Do not use directly. */
|
||||
#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)
|
||||
#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)
|
||||
#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)
|
||||
/** The higher bits contain the actual data. Do not use directly. */
|
||||
#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)
|
||||
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
|
||||
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
|
||||
|
||||
/** Flags to pass to secp256k1_context_create. */
|
||||
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
|
||||
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
|
||||
#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
|
||||
|
||||
/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */
|
||||
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
|
||||
#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)
|
||||
|
||||
/** Prefix byte used to tag various encoded curvepoints for specific purposes */
|
||||
#define SECP256K1_TAG_PUBKEY_EVEN 0x02
|
||||
#define SECP256K1_TAG_PUBKEY_ODD 0x03
|
||||
#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04
|
||||
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
|
||||
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
|
||||
|
||||
/** Create a secp256k1 context object.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* In: flags: which parts of the context to initialize.
|
||||
*
|
||||
* See also secp256k1_context_randomize.
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_create(
|
||||
unsigned int flags
|
||||
) SECP256K1_WARN_UNUSED_RESULT;
|
||||
|
||||
/** Copies a secp256k1 context object.
|
||||
*
|
||||
* Returns: a newly created context object.
|
||||
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
||||
const secp256k1_context* ctx
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
||||
|
||||
/** Destroy a secp256k1 context object.
|
||||
*
|
||||
* The context pointer may not be used afterwards.
|
||||
* Args: ctx: an existing context to destroy (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_destroy(
|
||||
secp256k1_context* ctx
|
||||
);
|
||||
|
||||
/** Set a callback function to be called when an illegal argument is passed to
|
||||
* an API call. It will only trigger for violations that are mentioned
|
||||
* explicitly in the header.
|
||||
*
|
||||
* The philosophy is that these shouldn't be dealt with through a
|
||||
* specific return value, as calling code should not have branches to deal with
|
||||
* the case that this code itself is broken.
|
||||
*
|
||||
* On the other hand, during debug stage, one would want to be informed about
|
||||
* such mistakes, and the default (crashing) may be inadvisable.
|
||||
* When this callback is triggered, the API function called is guaranteed not
|
||||
* to cause a crash, though its return value and output arguments are
|
||||
* undefined.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* In: fun: a pointer to a function to call when an illegal argument is
|
||||
* passed to the API, taking a message and an opaque pointer
|
||||
* (NULL restores a default handler that calls abort).
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_set_illegal_callback(
|
||||
secp256k1_context* ctx,
|
||||
void (*fun)(const char* message, void* data),
|
||||
const void* data
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Set a callback function to be called when an internal consistency check
|
||||
* fails. The default is crashing.
|
||||
*
|
||||
* This can only trigger in case of a hardware failure, miscompilation,
|
||||
* memory corruption, serious bug in the library, or other error would can
|
||||
* otherwise result in undefined behaviour. It will not trigger due to mere
|
||||
* incorrect usage of the API (see secp256k1_context_set_illegal_callback
|
||||
* for that). After this callback returns, anything may happen, including
|
||||
* crashing.
|
||||
*
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* In: fun: a pointer to a function to call when an internal error occurs,
|
||||
* taking a message and an opaque pointer (NULL restores a default
|
||||
* handler that calls abort).
|
||||
* data: the opaque pointer to pass to fun above.
|
||||
*/
|
||||
SECP256K1_API void secp256k1_context_set_error_callback(
|
||||
secp256k1_context* ctx,
|
||||
void (*fun)(const char* message, void* data),
|
||||
const void* data
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Create a secp256k1 scratch space object.
|
||||
*
|
||||
* Returns: a newly created scratch space.
|
||||
* Args: ctx: an existing context object (cannot be NULL)
|
||||
* In: init_size: initial amount of memory to allocate
|
||||
* max_size: maximum amount of memory to allocate
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create(
|
||||
const secp256k1_context* ctx,
|
||||
size_t init_size,
|
||||
size_t max_size
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Destroy a secp256k1 scratch space.
|
||||
*
|
||||
* The pointer may not be used afterwards.
|
||||
* Args: scratch: space to destroy
|
||||
*/
|
||||
SECP256K1_API void secp256k1_scratch_space_destroy(
|
||||
secp256k1_scratch_space* scratch
|
||||
);
|
||||
|
||||
/** Parse a variable-length public key into the pubkey object.
|
||||
*
|
||||
* Returns: 1 if the public key was fully valid.
|
||||
* 0 if the public key could not be parsed or is invalid.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
|
||||
* parsed version of input. If not, its value is undefined.
|
||||
* In: input: pointer to a serialized public key
|
||||
* inputlen: length of the array pointed to by input
|
||||
*
|
||||
* This function supports parsing compressed (33 bytes, header byte 0x02 or
|
||||
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
|
||||
* byte 0x06 or 0x07) format public keys.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey* pubkey,
|
||||
const unsigned char *input,
|
||||
size_t inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize a pubkey object into a serialized byte sequence.
|
||||
*
|
||||
* Returns: 1 always.
|
||||
* Args: ctx: a secp256k1 context object.
|
||||
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if
|
||||
* compressed==1) byte array to place the serialized key
|
||||
* in.
|
||||
* In/Out: outputlen: a pointer to an integer which is initially set to the
|
||||
* size of output, and is overwritten with the written
|
||||
* size.
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an
|
||||
* initialized public key.
|
||||
* flags: SECP256K1_EC_COMPRESSED if serialization should be in
|
||||
* compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ec_pubkey_serialize(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
size_t *outputlen,
|
||||
const secp256k1_pubkey* pubkey,
|
||||
unsigned int flags
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Parse an ECDSA signature in compact (64 bytes) format.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input64: a pointer to the 64-byte array to parse
|
||||
*
|
||||
* The signature must consist of a 32-byte big endian R value, followed by a
|
||||
* 32-byte big endian S value. If R or S fall outside of [0..order-1], the
|
||||
* encoding is invalid. R and S with value 0 are allowed in the encoding.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or R or
|
||||
* S are zero, the resulting sig value is guaranteed to fail validation for any
|
||||
* message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const unsigned char *input64
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Parse a DER ECDSA signature.
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input: a pointer to the signature to be parsed
|
||||
* inputlen: the length of the array pointed to be input
|
||||
*
|
||||
* This function will accept any valid DER encoded signature, even if the
|
||||
* encoded numbers are out of range.
|
||||
*
|
||||
* After the call, sig will always be initialized. If parsing failed or the
|
||||
* encoded numbers are out of range, signature validation with it is
|
||||
* guaranteed to fail for every message and public key.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const unsigned char *input,
|
||||
size_t inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize an ECDSA signature in DER format.
|
||||
*
|
||||
* Returns: 1 if enough space was available to serialize, 0 otherwise
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output: a pointer to an array to store the DER serialization
|
||||
* In/Out: outputlen: a pointer to a length integer. Initially, this integer
|
||||
* should be set to the length of output. After the call
|
||||
* it will be set to the length of the serialization (even
|
||||
* if 0 was returned).
|
||||
* In: sig: a pointer to an initialized signature object
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output,
|
||||
size_t *outputlen,
|
||||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Serialize an ECDSA signature in compact (64 byte) format.
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array to store the compact serialization
|
||||
* In: sig: a pointer to an initialized signature object
|
||||
*
|
||||
* See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output64,
|
||||
const secp256k1_ecdsa_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Verify an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect or unparseable signature
|
||||
* Args: ctx: a secp256k1 context object, initialized for verification.
|
||||
* In: sig: the signature being verified (cannot be NULL)
|
||||
* msg32: the 32-byte message hash being verified (cannot be NULL)
|
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
|
||||
*
|
||||
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
|
||||
* form are accepted.
|
||||
*
|
||||
* If you need to accept ECDSA signatures from sources that do not obey this
|
||||
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
|
||||
* validation, but be aware that doing so results in malleable signatures.
|
||||
*
|
||||
* For details, see the comments for that function.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
||||
const secp256k1_context* ctx,
|
||||
const secp256k1_ecdsa_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const secp256k1_pubkey *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Convert a signature to a normalized lower-S form.
|
||||
*
|
||||
* Returns: 1 if sigin was not normalized, 0 if it already was.
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sigout: a pointer to a signature to fill with the normalized form,
|
||||
* or copy if the input was already normalized. (can be NULL if
|
||||
* you're only interested in whether the input was already
|
||||
* normalized).
|
||||
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
|
||||
* can be identical to sigout)
|
||||
*
|
||||
* With ECDSA a third-party can forge a second distinct signature of the same
|
||||
* message, given a single initial signature, but without knowing the key. This
|
||||
* is done by negating the S value modulo the order of the curve, 'flipping'
|
||||
* the sign of the random point R which is not included in the signature.
|
||||
*
|
||||
* Forgery of the same message isn't universally problematic, but in systems
|
||||
* where message malleability or uniqueness of signatures is important this can
|
||||
* cause issues. This forgery can be blocked by all verifiers forcing signers
|
||||
* to use a normalized form.
|
||||
*
|
||||
* The lower-S form reduces the size of signatures slightly on average when
|
||||
* variable length encodings (such as DER) are used and is cheap to verify,
|
||||
* making it a good choice. Security of always using lower-S is assured because
|
||||
* anyone can trivially modify a signature after the fact to enforce this
|
||||
* property anyway.
|
||||
*
|
||||
* The lower S value is always between 0x1 and
|
||||
* 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
|
||||
* inclusive.
|
||||
*
|
||||
* No other forms of ECDSA malleability are known and none seem likely, but
|
||||
* there is no formal proof that ECDSA, even with this additional restriction,
|
||||
* is free of other malleability. Commonly used serialization schemes will also
|
||||
* accept various non-unique encodings, so care should be taken when this
|
||||
* property is required for an application.
|
||||
*
|
||||
* The secp256k1_ecdsa_sign function will by default create signatures in the
|
||||
* lower-S form, and secp256k1_ecdsa_verify will not accept others. In case
|
||||
* signatures come from a system that cannot enforce this property,
|
||||
* secp256k1_ecdsa_signature_normalize must be called before verification.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_signature_normalize(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature *sigout,
|
||||
const secp256k1_ecdsa_signature *sigin
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
|
||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
|
||||
* extra entropy.
|
||||
*/
|
||||
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
|
||||
|
||||
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
|
||||
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default;
|
||||
|
||||
/** Create an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the private key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
*
|
||||
* The created signature is always in lower-S form. See
|
||||
* secp256k1_ecdsa_signature_normalize for more details.
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function noncefp,
|
||||
const void *ndata
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Verify an ECDSA secret key.
|
||||
*
|
||||
* Returns: 1: secret key is valid
|
||||
* 0: secret key is invalid
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
|
||||
const secp256k1_context* ctx,
|
||||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Compute the public key for a secret key.
|
||||
*
|
||||
* Returns: 1: secret was valid, public key stores
|
||||
* 0: secret was invalid, try again
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: pubkey: pointer to the created public key (cannot be NULL)
|
||||
* In: seckey: pointer to a 32-byte private key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Negates a private key in place.
|
||||
*
|
||||
* Returns: 1 always
|
||||
* Args: ctx: pointer to a context object
|
||||
* In/Out: seckey: pointer to the 32-byte private key to be negated (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Negates a public key in place.
|
||||
*
|
||||
* Returns: 1 always
|
||||
* Args: ctx: pointer to a context object
|
||||
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Tweak a private key by adding tweak to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or if the resulting private key
|
||||
* would be invalid (only when the tweak is the complement of the
|
||||
* private key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* In/Out: seckey: pointer to a 32-byte private key.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a public key by adding tweak times the generator to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or if the resulting public key
|
||||
* would be invalid (only when the tweak is the complement of the
|
||||
* corresponding private key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* In/Out: pubkey: pointer to a public key object.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a private key by multiplying it by a tweak.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object (cannot be NULL).
|
||||
* In/Out: seckey: pointer to a 32-byte private key.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *seckey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a public key by multiplying it by a tweak value.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for validation
|
||||
* (cannot be NULL).
|
||||
* In/Out: pubkey: pointer to a public key obkect.
|
||||
* In: tweak: pointer to a 32-byte tweak.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Updates the context randomization to protect against side-channel leakage.
|
||||
* Returns: 1: randomization successfully updated
|
||||
* 0: error
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
|
||||
*
|
||||
* While secp256k1 code is written to be constant-time no matter what secret
|
||||
* values are, it's possible that a future compiler may output code which isn't,
|
||||
* and also that the CPU may not emit the same radio frequencies or draw the same
|
||||
* amount power for all values.
|
||||
*
|
||||
* This function provides a seed which is combined into the blinding value: that
|
||||
* blinding value is added before each multiplication (and removed afterwards) so
|
||||
* that it does not affect function results, but shields against attacks which
|
||||
* rely on any input-dependent behaviour.
|
||||
*
|
||||
* You should call this after secp256k1_context_create or
|
||||
* secp256k1_context_clone, and may call this repeatedly afterwards.
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
|
||||
secp256k1_context* ctx,
|
||||
const unsigned char *seed32
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Add a number of public keys together.
|
||||
* Returns: 1: the sum of the public keys is valid.
|
||||
* 0: the sum of the public keys is not valid.
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: out: pointer to a public key object for placing the resulting public key
|
||||
* (cannot be NULL)
|
||||
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
|
||||
* n: the number of public keys to add together (must be at least 1)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *out,
|
||||
const secp256k1_pubkey * const * ins,
|
||||
size_t n
|
||||
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_H */
|
31
vendors/ocaml-secp256k1-internal/src/secp256k1_ecdh.h
vendored
Normal file
31
vendors/ocaml-secp256k1-internal/src/secp256k1_ecdh.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef SECP256K1_ECDH_H
|
||||
#define SECP256K1_ECDH_H
|
||||
|
||||
#include "secp256k1.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Compute an EC Diffie-Hellman secret in constant time
|
||||
* Returns: 1: exponentiation was successful
|
||||
* 0: scalar was invalid (zero or overflow)
|
||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||
* Out: result: a 32-byte array which will be populated by an ECDH
|
||||
* secret computed from the point and scalar
|
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an
|
||||
* initialized public key
|
||||
* privkey: a 32-byte scalar with which to multiply the point
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *result,
|
||||
const secp256k1_pubkey *pubkey,
|
||||
const unsigned char *privkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_ECDH_H */
|
110
vendors/ocaml-secp256k1-internal/src/secp256k1_recovery.h
vendored
Normal file
110
vendors/ocaml-secp256k1-internal/src/secp256k1_recovery.h
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef SECP256K1_RECOVERY_H
|
||||
#define SECP256K1_RECOVERY_H
|
||||
|
||||
#include "secp256k1.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature,
|
||||
* supporting pubkey recovery.
|
||||
*
|
||||
* The exact representation of data inside is implementation defined and not
|
||||
* guaranteed to be portable between different platforms or versions. It is
|
||||
* however guaranteed to be 65 bytes in size, and can be safely copied/moved.
|
||||
* If you need to convert to a format suitable for storage or transmission, use
|
||||
* the secp256k1_ecdsa_signature_serialize_* and
|
||||
* secp256k1_ecdsa_signature_parse_* functions.
|
||||
*
|
||||
* Furthermore, it is guaranteed that identical signatures (including their
|
||||
* recoverability) will have identical representation, so they can be
|
||||
* memcmp'ed.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[65];
|
||||
} secp256k1_ecdsa_recoverable_signature;
|
||||
|
||||
/** Parse a compact ECDSA signature (64 bytes + recovery id).
|
||||
*
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: sig: a pointer to a signature object
|
||||
* In: input64: a pointer to a 64-byte compact signature
|
||||
* recid: the recovery id (0, 1, 2 or 3)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_recoverable_signature* sig,
|
||||
const unsigned char *input64,
|
||||
int recid
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Convert a recoverable signature into a normal signature.
|
||||
*
|
||||
* Returns: 1
|
||||
* Out: sig: a pointer to a normal signature (cannot be NULL).
|
||||
* In: sigin: a pointer to a recoverable signature (cannot be NULL).
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_signature* sig,
|
||||
const secp256k1_ecdsa_recoverable_signature* sigin
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
|
||||
*
|
||||
* Returns: 1
|
||||
* Args: ctx: a secp256k1 context object
|
||||
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
|
||||
* recid: a pointer to an integer to hold the recovery id (can be NULL).
|
||||
* In: sig: a pointer to an initialized signature object (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||
const secp256k1_context* ctx,
|
||||
unsigned char *output64,
|
||||
int *recid,
|
||||
const secp256k1_ecdsa_recoverable_signature* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Create a recoverable ECDSA signature.
|
||||
*
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, or the private key was invalid.
|
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
*/
|
||||
SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_ecdsa_recoverable_signature *sig,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function noncefp,
|
||||
const void *ndata
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Recover an ECDSA public key from a signature.
|
||||
*
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
|
||||
* 0: otherwise.
|
||||
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
|
||||
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
|
||||
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
|
||||
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *pubkey,
|
||||
const secp256k1_ecdsa_recoverable_signature *sig,
|
||||
const unsigned char *msg32
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_RECOVERY_H */
|
228
vendors/ocaml-secp256k1-internal/src/secp256k1_wrap.c
vendored
Normal file
228
vendors/ocaml-secp256k1-internal/src/secp256k1_wrap.c
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "secp256k1.h"
|
||||
#include "secp256k1_recovery.h"
|
||||
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/memory.h>
|
||||
#include <caml/bigarray.h>
|
||||
#include <caml/custom.h>
|
||||
#include <caml/fail.h>
|
||||
|
||||
/* Accessing the secp256k1_context * part of an OCaml custom block */
|
||||
#define Context_val(v) (*((secp256k1_context **) Data_custom_val(v)))
|
||||
|
||||
void context_destroy(value ctx) {
|
||||
secp256k1_context_destroy (Context_val(ctx));
|
||||
}
|
||||
|
||||
static struct custom_operations secp256k1_context_ops = {
|
||||
.identifier = "secp256k1_context",
|
||||
.finalize = context_destroy,
|
||||
.compare = custom_compare_default,
|
||||
.compare_ext = custom_compare_ext_default,
|
||||
.hash = custom_hash_default,
|
||||
.serialize = custom_serialize_default,
|
||||
.deserialize = custom_deserialize_default
|
||||
};
|
||||
|
||||
static value alloc_context (secp256k1_context *ctx) {
|
||||
value ml_ctx = alloc_custom(&secp256k1_context_ops, sizeof(secp256k1_context *), 0, 1);
|
||||
Context_val(ml_ctx) = ctx;
|
||||
return ml_ctx;
|
||||
}
|
||||
|
||||
CAMLprim value context_flags (value buf) {
|
||||
uint16_t *a = Caml_ba_data_val(buf);
|
||||
a[0] = SECP256K1_CONTEXT_NONE;
|
||||
a[1] = SECP256K1_CONTEXT_VERIFY;
|
||||
a[2] = SECP256K1_CONTEXT_SIGN;
|
||||
return Val_int(3 * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
CAMLprim value context_create (value flags) {
|
||||
CAMLparam1(flags);
|
||||
secp256k1_context *ctx = secp256k1_context_create (Int_val(flags));
|
||||
if (!ctx) caml_failwith("context_create");
|
||||
CAMLreturn(alloc_context(ctx));
|
||||
}
|
||||
|
||||
CAMLprim value context_randomize (value ctx, value seed) {
|
||||
return Val_bool(secp256k1_context_randomize(Context_val(ctx),
|
||||
String_val(seed)));
|
||||
}
|
||||
|
||||
CAMLprim value context_clone (value ctx) {
|
||||
CAMLparam1(ctx);
|
||||
secp256k1_context *new = secp256k1_context_clone (Context_val(ctx));
|
||||
if (!new) caml_failwith("context_clone");
|
||||
CAMLreturn(alloc_context(new));
|
||||
}
|
||||
|
||||
CAMLprim value ec_seckey_verify (value ctx, value sk) {
|
||||
return Val_bool(secp256k1_ec_seckey_verify(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(sk)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_privkey_negate(value ctx, value sk) {
|
||||
int ret = secp256k1_ec_privkey_negate(Context_val (ctx),
|
||||
Caml_ba_data_val(sk));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value ec_privkey_tweak_add(value ctx, value sk, value tweak) {
|
||||
return Val_bool(secp256k1_ec_privkey_tweak_add(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(sk),
|
||||
Caml_ba_data_val(tweak)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_privkey_tweak_mul(value ctx, value sk, value tweak) {
|
||||
return Val_bool(secp256k1_ec_privkey_tweak_mul(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(sk),
|
||||
Caml_ba_data_val(tweak)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_create (value ctx, value buf, value sk) {
|
||||
return Val_bool(secp256k1_ec_pubkey_create (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(sk)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_serialize (value ctx, value buf, value pk) {
|
||||
size_t size = Caml_ba_array_val(buf)->dim[0];
|
||||
unsigned int flags =
|
||||
size == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED;
|
||||
|
||||
secp256k1_ec_pubkey_serialize(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
&size,
|
||||
Caml_ba_data_val(pk),
|
||||
flags);
|
||||
|
||||
return Val_int(size);
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_parse(value ctx, value buf, value pk) {
|
||||
return Val_bool(secp256k1_ec_pubkey_parse(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(pk),
|
||||
Caml_ba_array_val(pk)->dim[0]));
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_negate(value ctx, value pk) {
|
||||
int ret = secp256k1_ec_pubkey_negate(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(pk));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_tweak_add(value ctx, value pk, value tweak) {
|
||||
return Val_bool(secp256k1_ec_pubkey_tweak_add(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(pk),
|
||||
Caml_ba_data_val(tweak)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_tweak_mul(value ctx, value pk, value tweak) {
|
||||
return Val_bool(secp256k1_ec_pubkey_tweak_mul(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(pk),
|
||||
Caml_ba_data_val(tweak)));
|
||||
}
|
||||
|
||||
CAMLprim value ec_pubkey_combine(value ctx, value out, value pks) {
|
||||
int size = 0;
|
||||
const secp256k1_pubkey* cpks[1024] = {0};
|
||||
|
||||
while(Field(pks, 1) != Val_unit) {
|
||||
cpks[size] = Caml_ba_data_val(Field(pks, 0));
|
||||
size++;
|
||||
pks = Field(pks, 1);
|
||||
}
|
||||
|
||||
return Val_int(secp256k1_ec_pubkey_combine(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(out),
|
||||
cpks,
|
||||
size));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_signature_parse_compact (value ctx, value buf, value sig) {
|
||||
return Val_bool(secp256k1_ecdsa_signature_parse_compact (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(sig)));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_signature_parse_der (value ctx, value buf, value sig) {
|
||||
return Val_bool(secp256k1_ecdsa_signature_parse_der (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(sig),
|
||||
Caml_ba_array_val(sig)->dim[0]));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_verify (value ctx, value pubkey, value msg, value signature) {
|
||||
return Val_bool(secp256k1_ecdsa_verify (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(signature),
|
||||
Caml_ba_data_val(msg),
|
||||
Caml_ba_data_val(pubkey)));
|
||||
}
|
||||
|
||||
|
||||
CAMLprim value ecdsa_sign (value ctx, value buf, value seckey, value msg) {
|
||||
return Val_bool(secp256k1_ecdsa_sign (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(msg),
|
||||
Caml_ba_data_val(seckey),
|
||||
NULL, NULL));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_signature_serialize_der(value ctx, value buf, value signature) {
|
||||
size_t size = Caml_ba_array_val(buf)->dim[0];
|
||||
int ret = secp256k1_ecdsa_signature_serialize_der(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
&size,
|
||||
Caml_ba_data_val(signature));
|
||||
|
||||
return (ret == 0 ? Val_int(ret) : Val_int(size));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_signature_serialize_compact(value ctx, value buf, value signature) {
|
||||
secp256k1_ecdsa_signature_serialize_compact(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(signature));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_recoverable_signature_parse_compact (value ctx, value buf, value signature, value recid) {
|
||||
return Val_bool(secp256k1_ecdsa_recoverable_signature_parse_compact (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(signature),
|
||||
Int_val(recid)));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_sign_recoverable (value ctx, value buf, value seckey, value msg) {
|
||||
return Val_bool(secp256k1_ecdsa_sign_recoverable (Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(msg),
|
||||
Caml_ba_data_val(seckey),
|
||||
NULL, NULL));
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_recoverable_signature_serialize_compact(value ctx, value buf, value signature) {
|
||||
int recid;
|
||||
secp256k1_ecdsa_recoverable_signature_serialize_compact(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
&recid,
|
||||
Caml_ba_data_val(signature));
|
||||
return Val_int(recid);
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_recoverable_signature_convert(value ctx, value buf, value signature) {
|
||||
secp256k1_ecdsa_recoverable_signature_convert(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(signature));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value ecdsa_recover(value ctx, value buf, value signature, value msg) {
|
||||
return Val_bool(secp256k1_ecdsa_recover(Caml_ba_data_val(ctx),
|
||||
Caml_ba_data_val(buf),
|
||||
Caml_ba_data_val(signature),
|
||||
Caml_ba_data_val(msg)));
|
||||
}
|
38
vendors/ocaml-secp256k1-internal/src/testrand.h
vendored
Normal file
38
vendors/ocaml-secp256k1-internal/src/testrand.h
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_TESTRAND_H
|
||||
#define SECP256K1_TESTRAND_H
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
/* A non-cryptographic RNG used only for test infrastructure. */
|
||||
|
||||
/** Seed the pseudorandom number generator for testing. */
|
||||
SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**32-1]. */
|
||||
static uint32_t secp256k1_rand32(void);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or
|
||||
* more. */
|
||||
static uint32_t secp256k1_rand_bits(int bits);
|
||||
|
||||
/** Generate a pseudorandom number in the range [0..range-1]. */
|
||||
static uint32_t secp256k1_rand_int(uint32_t range);
|
||||
|
||||
/** Generate a pseudorandom 32-byte array. */
|
||||
static void secp256k1_rand256(unsigned char *b32);
|
||||
|
||||
/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */
|
||||
static void secp256k1_rand256_test(unsigned char *b32);
|
||||
|
||||
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
|
||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
|
||||
|
||||
#endif /* SECP256K1_TESTRAND_H */
|
110
vendors/ocaml-secp256k1-internal/src/testrand_impl.h
vendored
Normal file
110
vendors/ocaml-secp256k1-internal/src/testrand_impl.h
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_TESTRAND_IMPL_H
|
||||
#define SECP256K1_TESTRAND_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "testrand.h"
|
||||
#include "hash.h"
|
||||
|
||||
static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng;
|
||||
static uint32_t secp256k1_test_rng_precomputed[8];
|
||||
static int secp256k1_test_rng_precomputed_used = 8;
|
||||
static uint64_t secp256k1_test_rng_integer;
|
||||
static int secp256k1_test_rng_integer_bits_left = 0;
|
||||
|
||||
SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) {
|
||||
secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16);
|
||||
}
|
||||
|
||||
SECP256K1_INLINE static uint32_t secp256k1_rand32(void) {
|
||||
if (secp256k1_test_rng_precomputed_used == 8) {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed));
|
||||
secp256k1_test_rng_precomputed_used = 0;
|
||||
}
|
||||
return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++];
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_rand_bits(int bits) {
|
||||
uint32_t ret;
|
||||
if (secp256k1_test_rng_integer_bits_left < bits) {
|
||||
secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left);
|
||||
secp256k1_test_rng_integer_bits_left += 32;
|
||||
}
|
||||
ret = secp256k1_test_rng_integer;
|
||||
secp256k1_test_rng_integer >>= bits;
|
||||
secp256k1_test_rng_integer_bits_left -= bits;
|
||||
ret &= ((~((uint32_t)0)) >> (32 - bits));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t secp256k1_rand_int(uint32_t range) {
|
||||
/* We want a uniform integer between 0 and range-1, inclusive.
|
||||
* B is the smallest number such that range <= 2**B.
|
||||
* two mechanisms implemented here:
|
||||
* - generate B bits numbers until one below range is found, and return it
|
||||
* - find the largest multiple M of range that is <= 2**(B+A), generate B+A
|
||||
* bits numbers until one below M is found, and return it modulo range
|
||||
* The second mechanism consumes A more bits of entropy in every iteration,
|
||||
* but may need fewer iterations due to M being closer to 2**(B+A) then
|
||||
* range is to 2**B. The array below (indexed by B) contains a 0 when the
|
||||
* first mechanism is to be used, and the number A otherwise.
|
||||
*/
|
||||
static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
|
||||
uint32_t trange, mult;
|
||||
int bits = 0;
|
||||
if (range <= 1) {
|
||||
return 0;
|
||||
}
|
||||
trange = range - 1;
|
||||
while (trange > 0) {
|
||||
trange >>= 1;
|
||||
bits++;
|
||||
}
|
||||
if (addbits[bits]) {
|
||||
bits = bits + addbits[bits];
|
||||
mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
|
||||
trange = range * mult;
|
||||
} else {
|
||||
trange = range;
|
||||
mult = 1;
|
||||
}
|
||||
while(1) {
|
||||
uint32_t x = secp256k1_rand_bits(bits);
|
||||
if (x < trange) {
|
||||
return (mult == 1) ? x : (x % range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_rand256(unsigned char *b32) {
|
||||
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32);
|
||||
}
|
||||
|
||||
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) {
|
||||
size_t bits = 0;
|
||||
memset(bytes, 0, len);
|
||||
while (bits < len * 8) {
|
||||
int now;
|
||||
uint32_t val;
|
||||
now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31;
|
||||
val = secp256k1_rand_bits(1);
|
||||
while (now > 0 && bits < len * 8) {
|
||||
bytes[bits / 8] |= val << (bits % 8);
|
||||
now--;
|
||||
bits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_rand256_test(unsigned char *b32) {
|
||||
secp256k1_rand_bytes_test(b32, 32);
|
||||
}
|
||||
|
||||
#endif /* SECP256K1_TESTRAND_IMPL_H */
|
121
vendors/ocaml-secp256k1-internal/src/util.h
vendored
Normal file
121
vendors/ocaml-secp256k1-internal/src/util.h
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_UTIL_H
|
||||
#define SECP256K1_UTIL_H
|
||||
|
||||
#if defined HAVE_CONFIG_H
|
||||
#include "libsecp256k1-config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
void (*fn)(const char *text, void* data);
|
||||
const void* data;
|
||||
} secp256k1_callback;
|
||||
|
||||
static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) {
|
||||
cb->fn(text, (void*)cb->data);
|
||||
}
|
||||
|
||||
#ifdef DETERMINISTIC
|
||||
#define TEST_FAILURE(msg) do { \
|
||||
fprintf(stderr, "%s\n", msg); \
|
||||
abort(); \
|
||||
} while(0);
|
||||
#else
|
||||
#define TEST_FAILURE(msg) do { \
|
||||
fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \
|
||||
abort(); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BUILTIN_EXPECT
|
||||
#define EXPECT(x,c) __builtin_expect((x),(c))
|
||||
#else
|
||||
#define EXPECT(x,c) (x)
|
||||
#endif
|
||||
|
||||
#ifdef DETERMINISTIC
|
||||
#define CHECK(cond) do { \
|
||||
if (EXPECT(!(cond), 0)) { \
|
||||
TEST_FAILURE("test condition failed"); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define CHECK(cond) do { \
|
||||
if (EXPECT(!(cond), 0)) { \
|
||||
TEST_FAILURE("test condition failed: " #cond); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* Like assert(), but when VERIFY is defined, and side-effect safe. */
|
||||
#if defined(COVERAGE)
|
||||
#define VERIFY_CHECK(check)
|
||||
#define VERIFY_SETUP(stmt)
|
||||
#elif defined(VERIFY)
|
||||
#define VERIFY_CHECK CHECK
|
||||
#define VERIFY_SETUP(stmt) do { stmt; } while(0)
|
||||
#else
|
||||
#define VERIFY_CHECK(cond) do { (void)(cond); } while(0)
|
||||
#define VERIFY_SETUP(stmt)
|
||||
#endif
|
||||
|
||||
static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) {
|
||||
void *ret = malloc(size);
|
||||
if (ret == NULL) {
|
||||
secp256k1_callback_call(cb, "Out of memory");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void *ptr, size_t size) {
|
||||
void *ret = realloc(ptr, size);
|
||||
if (ret == NULL) {
|
||||
secp256k1_callback_call(cb, "Out of memory");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||
# define SECP256K1_RESTRICT
|
||||
#else
|
||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if SECP256K1_GNUC_PREREQ(3,0)
|
||||
# define SECP256K1_RESTRICT __restrict__
|
||||
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define SECP256K1_RESTRICT __restrict
|
||||
# else
|
||||
# define SECP256K1_RESTRICT
|
||||
# endif
|
||||
# else
|
||||
# define SECP256K1_RESTRICT restrict
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define I64FORMAT "I64d"
|
||||
# define I64uFORMAT "I64u"
|
||||
#else
|
||||
# define I64FORMAT "lld"
|
||||
# define I64uFORMAT "llu"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE___INT128)
|
||||
# if defined(__GNUC__)
|
||||
# define SECP256K1_GNUC_EXT __extension__
|
||||
# else
|
||||
# define SECP256K1_GNUC_EXT
|
||||
# endif
|
||||
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
|
||||
#endif
|
||||
|
||||
#endif /* SECP256K1_UTIL_H */
|
10
vendors/ocaml-secp256k1-internal/test/jbuild
vendored
Normal file
10
vendors/ocaml-secp256k1-internal/test/jbuild
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(executable
|
||||
((name test)
|
||||
(libraries (hex secp256k1-internal alcotest))))
|
||||
|
||||
(alias
|
||||
((name runtest)
|
||||
(deps (test.exe))
|
||||
(action (run ${<}))))
|
141
vendors/ocaml-secp256k1-internal/test/test.ml
vendored
Normal file
141
vendors/ocaml-secp256k1-internal/test/test.ml
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
open Secp256k1_ml
|
||||
|
||||
let assert_equal a b = assert (a = b)
|
||||
|
||||
module Num = struct
|
||||
open Internal
|
||||
open Num
|
||||
let basic () =
|
||||
let z = zero () in
|
||||
assert_equal true (is_zero z)
|
||||
|
||||
let runtest =
|
||||
[ "basic", `Quick, basic ;
|
||||
]
|
||||
end
|
||||
|
||||
module Scalar = struct
|
||||
open Internal
|
||||
open Scalar
|
||||
let basic () =
|
||||
let z = zero () in
|
||||
assert_equal true (is_zero z) ;
|
||||
(* set_int z 1 ; *)
|
||||
let z = const ~d0:1L () in
|
||||
assert_equal false (is_zero z) ;
|
||||
assert_equal false (is_even z) ;
|
||||
assert_equal true (is_one z)
|
||||
|
||||
let runtest =
|
||||
[ "basic", `Quick, basic ;
|
||||
]
|
||||
end
|
||||
|
||||
module External = struct
|
||||
open External
|
||||
let buffer_of_hex s =
|
||||
let { Cstruct.buffer; off = _ ; len = _ } = Hex.to_cstruct (`Hex s) in
|
||||
buffer
|
||||
|
||||
let ctx = Context.create [ Sign ; Verify ]
|
||||
|
||||
let cstruct_testable =
|
||||
Alcotest.testable Cstruct.hexdump_pp Cstruct.equal
|
||||
|
||||
let assert_eq_cstruct a b =
|
||||
let a = Cstruct.of_bigarray a in
|
||||
let b = Cstruct.of_bigarray b in
|
||||
assert (Alcotest.equal cstruct_testable a b)
|
||||
|
||||
let test_signature_of_string () =
|
||||
let sign_orig = buffer_of_hex
|
||||
"3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589" in
|
||||
let signature = Sign.read_der_exn ctx sign_orig in
|
||||
let sign = Sign.to_bytes ~der:true ctx signature in
|
||||
assert_eq_cstruct sign_orig sign
|
||||
|
||||
let test_valid_signature _ =
|
||||
let ctx = Context.create [Verify] in
|
||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex
|
||||
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||
let signature = Sign.read_der_exn ctx
|
||||
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
||||
let pk = Key.read_pk_exn ctx
|
||||
(buffer_of_hex "040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40") in
|
||||
assert (Sign.verify_exn ctx ~signature ~pk ~msg)
|
||||
|
||||
let test_invalid_signature _ =
|
||||
let ctx = Context.create [Verify] in
|
||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex
|
||||
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91" in
|
||||
let signature = Sign.read_der_exn ctx
|
||||
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
||||
let pk = Key.read_pk_exn ctx
|
||||
(buffer_of_hex "040a629506e1b65cd9d2e0ba9c75df9c4fed0db16dc9625ed14397f0afc836fae595dc53f8b0efe61e703075bd9b143bac75ec0e19f82a2208caeb32be53414c40") in
|
||||
assert (not (Sign.verify_exn ctx ~signature ~pk ~msg))
|
||||
|
||||
let test_public_module _ =
|
||||
let pubtrue =
|
||||
buffer_of_hex "04c591a8ff19ac9c4e4e5793673b83123437e975285e7b442f4ee2654dffca5e2d2103ed494718c697ac9aebcfd19612e224db46661011863ed2fc54e71861e2a6" in
|
||||
let pub = Key.read_pk_exn ctx pubtrue in
|
||||
let pub_serialized = Key.to_bytes ~compress:false ctx pub in
|
||||
assert_eq_cstruct pubtrue pub_serialized
|
||||
|
||||
let test_pubkey_creation _ =
|
||||
let seckey = buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530" in
|
||||
let pubtrue = buffer_of_hex "04c591a8ff19ac9c4e4e5793673b83123437e975285e7b442f4ee2654dffca5e2d2103ed494718c697ac9aebcfd19612e224db46661011863ed2fc54e71861e2a6" in
|
||||
let seckey = Key.read_sk_exn ctx seckey in
|
||||
let pubkey = Key.neuterize_exn ctx seckey in
|
||||
let buf_pk_comp = Cstruct.create 33 in
|
||||
let buf_pk_uncomp = Cstruct.create 65 in
|
||||
let nb_written = Key.write ~compress:true ctx buf_pk_comp.buffer pubkey in
|
||||
assert (nb_written = 33) ;
|
||||
let nb_written = Key.write ~compress:false ctx buf_pk_uncomp.buffer pubkey in
|
||||
assert (nb_written = 65) ;
|
||||
let nb_written = Key.write ~compress:true ctx buf_pk_uncomp.buffer ~pos:32 pubkey in
|
||||
assert (nb_written = 33) ;
|
||||
let pubkey_serialized = Key.to_bytes ~compress:false ctx pubkey in
|
||||
assert_eq_cstruct pubtrue pubkey_serialized
|
||||
|
||||
let test_sign _ =
|
||||
let ctx = Context.create [Sign] in
|
||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||
let sk = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in
|
||||
let validsign = Sign.read_der_exn ctx (buffer_of_hex "30440220182a108e1448dc8f1fb467d06a0f3bb8ea0533584cb954ef8da112f1d60e39a202201c66f36da211c087f3af88b50edf4f9bdaa6cf5fd6817e74dca34db12390c6e9") in
|
||||
let sign = Sign.sign_exn ctx ~sk ~msg in
|
||||
assert (Sign.equal sign validsign)
|
||||
|
||||
let test_recover _ =
|
||||
let ctx = Context.create [Sign; Verify] in
|
||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||
let seckey = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in
|
||||
let pubkey = Key.neuterize_exn ctx seckey in
|
||||
let recoverable_sign = Sign.sign_recoverable_exn ctx ~sk:seckey msg in
|
||||
let usual_sign = Sign.to_plain ctx recoverable_sign in
|
||||
assert (Sign.verify_exn ctx ~pk:pubkey ~signature:usual_sign ~msg);
|
||||
let compact, recid = Sign.to_bytes_recid ctx recoverable_sign in
|
||||
let usual_sign' = Sign.read_exn ctx compact in
|
||||
assert (Sign.equal usual_sign' usual_sign) ;
|
||||
let parsed = Sign.read_recoverable_exn ctx compact ~recid in
|
||||
assert (Sign.equal parsed recoverable_sign);
|
||||
match Sign.recover ctx ~signature:recoverable_sign ~msg with
|
||||
| Error _ -> assert false
|
||||
| Ok recovered -> assert (Key.equal recovered pubkey)
|
||||
|
||||
let runtest = [
|
||||
"signature_of_string", `Quick, test_signature_of_string ;
|
||||
"valid_signature", `Quick, test_valid_signature ;
|
||||
"invalid_signature", `Quick, test_invalid_signature ;
|
||||
"public_module", `Quick, test_public_module ;
|
||||
"pubkey_creation", `Quick, test_pubkey_creation ;
|
||||
"sign", `Quick, test_sign ;
|
||||
"recover", `Quick, test_recover ;
|
||||
]
|
||||
end
|
||||
|
||||
let () =
|
||||
Alcotest.run "secp256k1" [
|
||||
"Num", Num.runtest ;
|
||||
"Scalar", Scalar.runtest ;
|
||||
"External", External.runtest ;
|
||||
]
|
Loading…
Reference in New Issue
Block a user