Import: ocaml-secp256k1 in vendors
This commit is contained in:
parent
19843b96b0
commit
9adee55234
@ -469,6 +469,10 @@ opam:46:tezos-node:
|
|||||||
variables:
|
variables:
|
||||||
package: tezos-node
|
package: tezos-node
|
||||||
|
|
||||||
|
opam:46:secp256k1-internal:
|
||||||
|
<<: *opam_definition
|
||||||
|
variables:
|
||||||
|
package: secp256k1-internal
|
||||||
|
|
||||||
##END_OPAM##
|
##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