Switch to C89 comments in prep for making the whole codebase C89 compatible.

This should be whitespace/comment only changes and should produce the same
object code.
This commit is contained in:
Gregory Maxwell 2014-11-15 15:28:10 +00:00
parent 21288f2d05
commit 71712b27e5
38 changed files with 802 additions and 716 deletions

View File

@ -1,7 +1,8 @@
// 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.
/**********************************************************************
* 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.*
**********************************************************************/
#include <stdio.h>
#include "include/secp256k1.h"

View File

@ -1,7 +1,8 @@
// 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.
/**********************************************************************
* 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.*
**********************************************************************/
#include <stdio.h>
#include <string.h>
@ -25,9 +26,9 @@ int main(void) {
int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(msg, 32, sig, key, nonce, &recid));
for (int j = 0; j < 32; j++) {
nonce[j] = key[j]; // Move former key to nonce
msg[j] = sig[j]; // Move former R to message.
key[j] = sig[j + 32]; // Move former S to key.
nonce[j] = key[j]; /* Move former key to nonce */
msg[j] = sig[j]; /* Move former R to message. */
key[j] = sig[j + 32]; /* Move former S to key. */
}
}

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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.*
**********************************************************************/
#include <stdio.h>
#include <string.h>
@ -22,9 +24,9 @@ int main(void) {
int pubkeylen = 33;
CHECK(secp256k1_ecdsa_recover_compact(msg, 32, sig, pubkey, &pubkeylen, 1, i % 2));
for (int j = 0; j < 32; j++) {
sig[j + 32] = msg[j]; // Move former message to S.
msg[j] = sig[j]; // Move former R to message.
sig[j] = pubkey[j + 1]; // Move recovered pubkey X coordinate to R (which must be a valid X coordinate).
sig[j + 32] = msg[j]; /* Move former message to S. */
msg[j] = sig[j]; /* Move former R to message. */
sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
}
}

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_ECDSA_

View File

@ -1,6 +1,9 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_ECKEY_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
@ -46,11 +48,11 @@ static void secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char
static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen) {
const unsigned char *end = privkey + privkeylen;
// sequence header
/* sequence header */
if (end < privkey+1 || *privkey != 0x30)
return 0;
privkey++;
// sequence length constructor
/* sequence length constructor */
int lenb = 0;
if (end < privkey+1 || !(*privkey & 0x80))
return 0;
@ -59,17 +61,17 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
return 0;
if (end < privkey+lenb)
return 0;
// sequence length
/* sequence length */
int len = 0;
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
privkey += lenb;
if (end < privkey+len)
return 0;
// sequence element 0: version number (=1)
/* sequence element 0: version number (=1) */
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01)
return 0;
privkey += 3;
// sequence element 1: octet string, up to 32 bytes
/* sequence element 1: octet string, up to 32 bytes */
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1])
return 0;
int overflow = 0;

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_ECMULT_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_ECMULT_GEN_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_IMPL_H_
#define _SECP256K1_ECMULT_GEN_IMPL_H_
@ -10,19 +12,19 @@
#include "ecmult_gen.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.
// To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i.
unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; // prec[j][k][i] = k'th byte of (16^j * i * G + U_i)
/* 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.
* To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i. */
unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; /* prec[j][k][i] = k'th byte of (16^j * i * G + U_i) */
} secp256k1_ecmult_gen_consts_t;
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
@ -31,14 +33,14 @@ static void secp256k1_ecmult_gen_start(void) {
if (secp256k1_ecmult_gen_consts != NULL)
return;
// Allocate the precomputation table.
/* Allocate the precomputation table. */
secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t));
// get the generator
/* get the generator */
const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
// Construct a group element with no known corresponding scalar (nothing up my sleeve).
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */
secp256k1_gej_t nums_gej;
{
static const unsigned char nums_b32[32] = "The scalar for this x is unknown";
@ -47,30 +49,30 @@ static void secp256k1_ecmult_gen_start(void) {
secp256k1_ge_t nums_ge;
VERIFY_CHECK(secp256k1_ge_set_xo(&nums_ge, &nums_x, 0));
secp256k1_gej_set_ge(&nums_gej, &nums_ge);
// Add G to make the bits in x uniformly distributed.
/* Add G to make the bits in x uniformly distributed. */
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, g);
}
// compute prec.
/* compute prec. */
secp256k1_ge_t prec[1024];
{
secp256k1_gej_t precj[1024]; // Jacobian versions of prec.
secp256k1_gej_t gbase; gbase = gj; // 16^j * G
secp256k1_gej_t numsbase; numsbase = nums_gej; // 2^j * nums.
secp256k1_gej_t precj[1024]; /* Jacobian versions of prec. */
secp256k1_gej_t gbase; gbase = gj; /* 16^j * G */
secp256k1_gej_t numsbase; numsbase = nums_gej; /* 2^j * nums. */
for (int j=0; j<64; j++) {
// Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase).
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */
precj[j*16] = numsbase;
for (int i=1; i<16; i++) {
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase);
}
// Multiply gbase by 16.
/* Multiply gbase by 16. */
for (int i=0; i<4; i++) {
secp256k1_gej_double_var(&gbase, &gbase);
}
// Multiply numbase by 2.
/* Multiply numbase by 2. */
secp256k1_gej_double_var(&numsbase, &numsbase);
if (j == 62) {
// In the last iteration, numsbase is (1 - 2^j) * nums instead.
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */
secp256k1_gej_neg(&numsbase, &numsbase);
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej);
}
@ -85,7 +87,7 @@ static void secp256k1_ecmult_gen_start(void) {
}
}
// Set the global pointer to the precomputation table.
/* Set the global pointer to the precomputation table. */
secp256k1_ecmult_gen_consts = ret;
}

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_IMPL_H_
#define _SECP256K1_ECMULT_IMPL_H_
@ -9,11 +11,11 @@
#include "group.h"
#include "ecmult.h"
// optimal for 128-bit and 256-bit exponents.
/* optimal for 128-bit and 256-bit exponents. */
#define WINDOW_A 5
// larger numbers may result in slightly better performance, at the cost of
// exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB.
/** larger numbers may result in slightly better performance, at the cost of
exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB. */
#define WINDOW_G 14
/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
@ -65,9 +67,9 @@ static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const sec
#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
typedef struct {
// For accelerating the computation of a*P + b*G:
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
/* For accelerating the computation of a*P + b*G: */
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */
} secp256k1_ecmult_consts_t;
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
@ -76,23 +78,23 @@ static void secp256k1_ecmult_start(void) {
if (secp256k1_ecmult_consts != NULL)
return;
// Allocate the precomputation table.
/* Allocate the precomputation table. */
secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t));
// get the generator
/* get the generator */
const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
// calculate 2^128*generator
/* calculate 2^128*generator */
secp256k1_gej_t g_128j = gj;
for (int i=0; i<128; i++)
secp256k1_gej_double_var(&g_128j, &g_128j);
// precompute the tables with odd multiples
/* precompute the tables with odd multiples */
secp256k1_ecmult_table_precomp_ge_var(ret->pre_g, &gj, WINDOW_G);
secp256k1_ecmult_table_precomp_ge_var(ret->pre_g_128, &g_128j, WINDOW_G);
// Set the global pointer to the precomputation table.
/* Set the global pointer to the precomputation table. */
secp256k1_ecmult_consts = ret;
}
@ -148,21 +150,21 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
#ifdef USE_ENDOMORPHISM
secp256k1_num_t na_1, na_lam;
// split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit)
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
secp256k1_gej_split_exp_var(&na_1, &na_lam, na);
// build wnaf representation for na_1 and na_lam.
/* build wnaf representation for na_1 and na_lam. */
int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A);
int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
int bits = bits_na_1;
if (bits_na_lam > bits) bits = bits_na_lam;
#else
// build wnaf representation for na.
/* build wnaf representation for na. */
int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A);
int bits = bits_na;
#endif
// calculate odd multiples of a
/* calculate odd multiples of a */
secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ecmult_table_precomp_gej_var(pre_a, a, WINDOW_A);
@ -172,13 +174,13 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]);
#endif
// Splitted G factors.
/* Splitted G factors. */
secp256k1_num_t ng_1, ng_128;
// split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit)
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
secp256k1_num_split(&ng_1, &ng_128, ng, 128);
// Build wnaf representation for ng_1 and ng_128
/* Build wnaf representation for ng_1 and ng_128 */
int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G);
int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
if (bits_ng_1 > bits) bits = bits_ng_1;

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_FIELD_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_FIELD_REPR_
@ -8,7 +10,7 @@
#include <stdint.h>
typedef struct {
// X = sum(i=0..9, elem[i]*2^26) mod n
/* X = sum(i=0..9, elem[i]*2^26) mod n */
uint32_t n[10];
#ifdef VERIFY
int magnitude;

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -50,11 +52,11 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
// Reduce t9 at the start so there will be at most a single carry from the first pass
/* Reduce t9 at the start so there will be at most a single carry from the first pass */
uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
uint32_t m;
// The first pass ensures the magnitude is 1, ...
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x3D1UL; t1 += (x << 6);
t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL;
t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL;
@ -66,14 +68,14 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7;
t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8;
// ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element)
/* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
VERIFY_CHECK(t9 >> 23 == 0);
// At most a single final reduction is needed; check if the value is >= the field characteristic
/* At most a single final reduction is needed; check if the value is >= the field characteristic */
x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL)
& ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
// Apply the final reduction (for constant-time behaviour, we do it always)
/* Apply the final reduction (for constant-time behaviour, we do it always) */
t0 += x * 0x3D1UL; t1 += (x << 6);
t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL;
t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL;
@ -85,10 +87,10 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL;
t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL;
// If t9 didn't carry to bit 22 already, then it should have after any final reduction
/* If t9 didn't carry to bit 22 already, then it should have after any final reduction */
VERIFY_CHECK(t9 >> 22 == x);
// Mask off the possible multiple of 2^256 from the final reduction
/* Mask off the possible multiple of 2^256 from the final reduction */
t9 &= 0x03FFFFFUL;
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
@ -274,9 +276,10 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
VERIFY_BITS(b[9], 26);
const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
// [... a b c] is a shorthand for ... + a<<52 + b<<26 + 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 0 0 0 0 0] = [x*R1 x*R0].
/** [... a b c] is a shorthand for ... + a<<52 + b<<26 + 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 0 0 0 0 0] = [x*R1 x*R0].
*/
uint64_t c, d;
@ -290,16 +293,16 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[7] * b[2]
+ (uint64_t)a[8] * b[1]
+ (uint64_t)a[9] * b[0];
// VERIFY_BITS(d, 64);
// [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
/* VERIFY_BITS(d, 64); */
/* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
uint32_t t9 = d & M; d >>= 26;
VERIFY_BITS(t9, 26);
VERIFY_BITS(d, 38);
// [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
/* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
c = (uint64_t)a[0] * b[0];
VERIFY_BITS(c, 60);
// [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0]
/* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */
d += (uint64_t)a[1] * b[9]
+ (uint64_t)a[2] * b[8]
+ (uint64_t)a[3] * b[7]
@ -310,22 +313,22 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[8] * b[2]
+ (uint64_t)a[9] * b[1];
VERIFY_BITS(d, 63);
// [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
VERIFY_BITS(u0, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 61);
// [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
VERIFY_BITS(t0, 26);
VERIFY_BITS(c, 37);
// [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
c += (uint64_t)a[0] * b[1]
+ (uint64_t)a[1] * b[0];
VERIFY_BITS(c, 62);
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */
d += (uint64_t)a[2] * b[9]
+ (uint64_t)a[3] * b[8]
+ (uint64_t)a[4] * b[7]
@ -335,23 +338,23 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[8] * b[3]
+ (uint64_t)a[9] * b[2];
VERIFY_BITS(d, 63);
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
VERIFY_BITS(u1, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
// [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
VERIFY_BITS(t1, 26);
VERIFY_BITS(c, 38);
// [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
c += (uint64_t)a[0] * b[2]
+ (uint64_t)a[1] * b[1]
+ (uint64_t)a[2] * b[0];
VERIFY_BITS(c, 62);
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
d += (uint64_t)a[3] * b[9]
+ (uint64_t)a[4] * b[8]
+ (uint64_t)a[5] * b[7]
@ -360,24 +363,24 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[8] * b[4]
+ (uint64_t)a[9] * b[3];
VERIFY_BITS(d, 63);
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
VERIFY_BITS(u2, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
// [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
VERIFY_BITS(t2, 26);
VERIFY_BITS(c, 38);
// [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
c += (uint64_t)a[0] * b[3]
+ (uint64_t)a[1] * b[2]
+ (uint64_t)a[2] * b[1]
+ (uint64_t)a[3] * b[0];
VERIFY_BITS(c, 63);
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
d += (uint64_t)a[4] * b[9]
+ (uint64_t)a[5] * b[8]
+ (uint64_t)a[6] * b[7]
@ -385,17 +388,17 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[8] * b[5]
+ (uint64_t)a[9] * b[4];
VERIFY_BITS(d, 63);
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
VERIFY_BITS(u3, 26);
VERIFY_BITS(d, 37);
// VERIFY_BITS(c, 64);
// [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
VERIFY_BITS(t3, 26);
VERIFY_BITS(c, 39);
// [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
c += (uint64_t)a[0] * b[4]
+ (uint64_t)a[1] * b[3]
@ -403,24 +406,24 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[3] * b[1]
+ (uint64_t)a[4] * b[0];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
d += (uint64_t)a[5] * b[9]
+ (uint64_t)a[6] * b[8]
+ (uint64_t)a[7] * b[7]
+ (uint64_t)a[8] * b[6]
+ (uint64_t)a[9] * b[5];
VERIFY_BITS(d, 62);
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
VERIFY_BITS(u4, 26);
VERIFY_BITS(d, 36);
// VERIFY_BITS(c, 64);
// [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
VERIFY_BITS(t4, 26);
VERIFY_BITS(c, 39);
// [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
c += (uint64_t)a[0] * b[5]
+ (uint64_t)a[1] * b[4]
@ -429,23 +432,23 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[4] * b[1]
+ (uint64_t)a[5] * b[0];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)a[6] * b[9]
+ (uint64_t)a[7] * b[8]
+ (uint64_t)a[8] * b[7]
+ (uint64_t)a[9] * b[6];
VERIFY_BITS(d, 62);
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
VERIFY_BITS(u5, 26);
VERIFY_BITS(d, 36);
// VERIFY_BITS(c, 64);
// [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
VERIFY_BITS(t5, 26);
VERIFY_BITS(c, 39);
// [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)a[0] * b[6]
+ (uint64_t)a[1] * b[5]
@ -455,22 +458,22 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[5] * b[1]
+ (uint64_t)a[6] * b[0];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)a[7] * b[9]
+ (uint64_t)a[8] * b[8]
+ (uint64_t)a[9] * b[7];
VERIFY_BITS(d, 61);
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
VERIFY_BITS(u6, 26);
VERIFY_BITS(d, 35);
// VERIFY_BITS(c, 64);
// [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
VERIFY_BITS(t6, 26);
VERIFY_BITS(c, 39);
// [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)a[0] * b[7]
+ (uint64_t)a[1] * b[6]
@ -480,24 +483,24 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[5] * b[2]
+ (uint64_t)a[6] * b[1]
+ (uint64_t)a[7] * b[0];
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x8000007C00000007ULL);
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)a[8] * b[9]
+ (uint64_t)a[9] * b[8];
VERIFY_BITS(d, 58);
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
VERIFY_BITS(u7, 26);
VERIFY_BITS(d, 32);
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
// [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
VERIFY_BITS(t7, 26);
VERIFY_BITS(c, 38);
// [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)a[0] * b[8]
+ (uint64_t)a[1] * b[7]
@ -508,73 +511,73 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uin
+ (uint64_t)a[6] * b[2]
+ (uint64_t)a[7] * b[1]
+ (uint64_t)a[8] * b[0];
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x9000007B80000008ULL);
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)a[9] * b[9];
VERIFY_BITS(d, 57);
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
VERIFY_BITS(u8, 26);
VERIFY_BITS(d, 31);
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[3] = t3;
VERIFY_BITS(r[3], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[4] = t4;
VERIFY_BITS(r[4], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[5] = t5;
VERIFY_BITS(r[5], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[6] = t6;
VERIFY_BITS(r[6], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[7] = t7;
VERIFY_BITS(r[7], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[8] = c & M; c >>= 26; c += u8 * R1;
VERIFY_BITS(r[8], 26);
VERIFY_BITS(c, 39);
// [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
c += d * R0 + t9;
VERIFY_BITS(c, 45);
// [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4);
VERIFY_BITS(r[9], 22);
VERIFY_BITS(c, 46);
// [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d = c * (R0 >> 4) + t0;
VERIFY_BITS(d, 56);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[0] = d & M; d >>= 26;
VERIFY_BITS(r[0], 26);
VERIFY_BITS(d, 30);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += c * (R1 >> 4) + t1;
VERIFY_BITS(d, 53);
VERIFY_CHECK(d <= 0x10000003FFFFBFULL);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[1] = d & M; d >>= 26;
VERIFY_BITS(r[1], 26);
VERIFY_BITS(d, 27);
VERIFY_CHECK(d <= 0x4000000ULL);
// [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += t2;
VERIFY_BITS(d, 27);
// [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[2] = d;
VERIFY_BITS(r[2], 27);
// [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) {
@ -590,9 +593,10 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t
VERIFY_BITS(a[9], 26);
const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
// [... a b c] is a shorthand for ... + a<<52 + b<<26 + 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 0 0 0 0 0] = [x*R1 x*R0].
/** [... a b c] is a shorthand for ... + a<<52 + b<<26 + 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 0 0 0 0 0] = [x*R1 x*R0].
*/
uint64_t c, d;
@ -601,251 +605,251 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t
+ (uint64_t)(a[2]*2) * a[7]
+ (uint64_t)(a[3]*2) * a[6]
+ (uint64_t)(a[4]*2) * a[5];
// VERIFY_BITS(d, 64);
// [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
/* VERIFY_BITS(d, 64); */
/* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
uint32_t t9 = d & M; d >>= 26;
VERIFY_BITS(t9, 26);
VERIFY_BITS(d, 38);
// [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0]
/* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
c = (uint64_t)a[0] * a[0];
VERIFY_BITS(c, 60);
// [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0]
/* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */
d += (uint64_t)(a[1]*2) * a[9]
+ (uint64_t)(a[2]*2) * a[8]
+ (uint64_t)(a[3]*2) * a[7]
+ (uint64_t)(a[4]*2) * a[6]
+ (uint64_t)a[5] * a[5];
VERIFY_BITS(d, 63);
// [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
VERIFY_BITS(u0, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 61);
// [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
VERIFY_BITS(t0, 26);
VERIFY_BITS(c, 37);
// [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0]
/* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
c += (uint64_t)(a[0]*2) * a[1];
VERIFY_BITS(c, 62);
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */
d += (uint64_t)(a[2]*2) * a[9]
+ (uint64_t)(a[3]*2) * a[8]
+ (uint64_t)(a[4]*2) * a[7]
+ (uint64_t)(a[5]*2) * a[6];
VERIFY_BITS(d, 63);
// [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
VERIFY_BITS(u1, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
// [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
VERIFY_BITS(t1, 26);
VERIFY_BITS(c, 38);
// [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0]
/* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
c += (uint64_t)(a[0]*2) * a[2]
+ (uint64_t)a[1] * a[1];
VERIFY_BITS(c, 62);
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
d += (uint64_t)(a[3]*2) * a[9]
+ (uint64_t)(a[4]*2) * a[8]
+ (uint64_t)(a[5]*2) * a[7]
+ (uint64_t)a[6] * a[6];
VERIFY_BITS(d, 63);
// [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
VERIFY_BITS(u2, 26);
VERIFY_BITS(d, 37);
VERIFY_BITS(c, 63);
// [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
VERIFY_BITS(t2, 26);
VERIFY_BITS(c, 38);
// [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0]
/* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[3]
+ (uint64_t)(a[1]*2) * a[2];
VERIFY_BITS(c, 63);
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
d += (uint64_t)(a[4]*2) * a[9]
+ (uint64_t)(a[5]*2) * a[8]
+ (uint64_t)(a[6]*2) * a[7];
VERIFY_BITS(d, 63);
// [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
VERIFY_BITS(u3, 26);
VERIFY_BITS(d, 37);
// VERIFY_BITS(c, 64);
// [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
VERIFY_BITS(t3, 26);
VERIFY_BITS(c, 39);
// [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0]
/* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[4]
+ (uint64_t)(a[1]*2) * a[3]
+ (uint64_t)a[2] * a[2];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
d += (uint64_t)(a[5]*2) * a[9]
+ (uint64_t)(a[6]*2) * a[8]
+ (uint64_t)a[7] * a[7];
VERIFY_BITS(d, 62);
// [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
VERIFY_BITS(u4, 26);
VERIFY_BITS(d, 36);
// VERIFY_BITS(c, 64);
// [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
VERIFY_BITS(t4, 26);
VERIFY_BITS(c, 39);
// [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0]
/* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[5]
+ (uint64_t)(a[1]*2) * a[4]
+ (uint64_t)(a[2]*2) * a[3];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)(a[6]*2) * a[9]
+ (uint64_t)(a[7]*2) * a[8];
VERIFY_BITS(d, 62);
// [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
VERIFY_BITS(u5, 26);
VERIFY_BITS(d, 36);
// VERIFY_BITS(c, 64);
// [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
VERIFY_BITS(t5, 26);
VERIFY_BITS(c, 39);
// [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0]
/* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[6]
+ (uint64_t)(a[1]*2) * a[5]
+ (uint64_t)(a[2]*2) * a[4]
+ (uint64_t)a[3] * a[3];
VERIFY_BITS(c, 63);
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)(a[7]*2) * a[9]
+ (uint64_t)a[8] * a[8];
VERIFY_BITS(d, 61);
// [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
VERIFY_BITS(u6, 26);
VERIFY_BITS(d, 35);
// VERIFY_BITS(c, 64);
// [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* VERIFY_BITS(c, 64); */
/* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
VERIFY_BITS(t6, 26);
VERIFY_BITS(c, 39);
// [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0]
/* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[7]
+ (uint64_t)(a[1]*2) * a[6]
+ (uint64_t)(a[2]*2) * a[5]
+ (uint64_t)(a[3]*2) * a[4];
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x8000007C00000007ULL);
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)(a[8]*2) * a[9];
VERIFY_BITS(d, 58);
// [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
VERIFY_BITS(u7, 26);
VERIFY_BITS(d, 32);
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
// [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
VERIFY_BITS(t7, 26);
VERIFY_BITS(c, 38);
// [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
c += (uint64_t)(a[0]*2) * a[8]
+ (uint64_t)(a[1]*2) * a[7]
+ (uint64_t)(a[2]*2) * a[6]
+ (uint64_t)(a[3]*2) * a[5]
+ (uint64_t)a[4] * a[4];
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x9000007B80000008ULL);
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += (uint64_t)a[9] * a[9];
VERIFY_BITS(d, 57);
// [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
VERIFY_BITS(u8, 26);
VERIFY_BITS(d, 31);
// VERIFY_BITS(c, 64);
/* VERIFY_BITS(c, 64); */
VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[3] = t3;
VERIFY_BITS(r[3], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[4] = t4;
VERIFY_BITS(r[4], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[5] = t5;
VERIFY_BITS(r[5], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[6] = t6;
VERIFY_BITS(r[6], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[7] = t7;
VERIFY_BITS(r[7], 26);
// [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[8] = c & M; c >>= 26; c += u8 * R1;
VERIFY_BITS(r[8], 26);
VERIFY_BITS(c, 39);
// [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
c += d * R0 + t9;
VERIFY_BITS(c, 45);
// [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4);
VERIFY_BITS(r[9], 22);
VERIFY_BITS(c, 46);
// [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d = c * (R0 >> 4) + t0;
VERIFY_BITS(d, 56);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[0] = d & M; d >>= 26;
VERIFY_BITS(r[0], 26);
VERIFY_BITS(d, 30);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += c * (R1 >> 4) + t1;
VERIFY_BITS(d, 53);
VERIFY_CHECK(d <= 0x10000003FFFFBFULL);
// [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
// [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
/* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[1] = d & M; d >>= 26;
VERIFY_BITS(r[1], 26);
VERIFY_BITS(d, 27);
VERIFY_CHECK(d <= 0x4000000ULL);
// [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
d += t2;
VERIFY_BITS(d, 27);
// [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[2] = d;
VERIFY_BITS(r[2], 27);
// [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_FIELD_REPR_
@ -8,7 +10,7 @@
#include <stdint.h>
typedef struct {
// X = sum(i=0..4, elem[i]*2^52) mod n
/* X = sum(i=0..4, elem[i]*2^52) mod n */
uint64_t n[5];
#ifdef VERIFY
int magnitude;

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* Copyright (c) 2013 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_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -60,35 +62,35 @@ static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
static void secp256k1_fe_normalize(secp256k1_fe_t *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
/* 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;
uint64_t m;
// The first pass ensures the magnitude is 1, ...
/* 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)
/* ... 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
/* 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)
/* 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
/* 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
/* 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;

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -26,9 +28,10 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
VERIFY_BITS(b[4], 52);
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
// [... 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].
/* [... 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].
*/
__int128 c, d;
@ -37,18 +40,18 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
+ (__int128)a[2] * b[1]
+ (__int128)a[3] * b[0];
VERIFY_BITS(d, 114);
// [d 0 0 0] = [p3 0 0 0]
/* [d 0 0 0] = [p3 0 0 0] */
c = (__int128)a[4] * b[4];
VERIFY_BITS(c, 112);
// [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0]
/* [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]
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
uint64_t 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]
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
d += (__int128)a[0] * b[4]
+ (__int128)a[1] * b[3]
@ -56,99 +59,99 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uin
+ (__int128)a[3] * b[1]
+ (__int128)a[4] * 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]
/* [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]
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
uint64_t 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]
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
uint64_t 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]
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
c = (__int128)a[0] * b[0];
VERIFY_BITS(c, 112);
// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0]
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
d += (__int128)a[1] * b[4]
+ (__int128)a[2] * b[3]
+ (__int128)a[3] * b[2]
+ (__int128)a[4] * b[1];
VERIFY_BITS(d, 115);
// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
uint64_t 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]
/* [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]
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
c += (__int128)u0 * (R >> 4);
VERIFY_BITS(c, 115);
// [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
/* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
uint64_t t0 = c & M; c >>= 52;
VERIFY_BITS(t0, 52);
VERIFY_BITS(c, 61);
// [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 0 p0]
/* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 0 p0] */
c += (__int128)a[0] * b[1]
+ (__int128)a[1] * b[0];
VERIFY_BITS(c, 114);
// [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 p1 p0]
/* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
d += (__int128)a[2] * b[4]
+ (__int128)a[3] * b[3]
+ (__int128)a[4] * b[2];
VERIFY_BITS(d, 114);
// [d 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
/* [d 0 t4 t3 0 c t0] = [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 t0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
/* [d 0 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
uint64_t t1 = c & M; c >>= 52;
VERIFY_BITS(t1, 52);
VERIFY_BITS(c, 63);
// [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
/* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
c += (__int128)a[0] * b[2]
+ (__int128)a[1] * b[1]
+ (__int128)a[2] * b[0];
VERIFY_BITS(c, 114);
// [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
d += (__int128)a[3] * b[4]
+ (__int128)a[4] * b[3];
VERIFY_BITS(d, 114);
// [d 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 t4 t3 c t1 t0] = [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 t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[0] = t0;
VERIFY_BITS(r[0], 52);
// [d 0 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
r[1] = t1;
VERIFY_BITS(r[1], 52);
// [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]
/* [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]
/* [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]
/* [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;
/* [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]
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r) {
@ -159,9 +162,10 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t
VERIFY_BITS(a[4], 52);
const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL;
// [... 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].
/** [... 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].
*/
__int128 c, d;
@ -170,106 +174,106 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t
d = (__int128)(a0*2) * a3
+ (__int128)(a1*2) * a2;
VERIFY_BITS(d, 114);
// [d 0 0 0] = [p3 0 0 0]
/* [d 0 0 0] = [p3 0 0 0] */
c = (__int128)a4 * a4;
VERIFY_BITS(c, 112);
// [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0]
/* [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]
/* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
uint64_t 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]
/* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
a4 *= 2;
d += (__int128)a0 * a4
+ (__int128)(a1*2) * a3
+ (__int128)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]
/* [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]
/* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
uint64_t 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]
/* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
uint64_t 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]
/* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
c = (__int128)a0 * a0;
VERIFY_BITS(c, 112);
// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0]
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
d += (__int128)a1 * a4
+ (__int128)(a2*2) * a3;
VERIFY_BITS(d, 114);
// [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
/* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
uint64_t 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]
/* [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]
/* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
c += (__int128)u0 * (R >> 4);
VERIFY_BITS(c, 113);
// [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0]
/* [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]
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
a0 *= 2;
c += (__int128)a0 * a1;
VERIFY_BITS(c, 114);
// [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0]
/* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
d += (__int128)a2 * a4
+ (__int128)a3 * a3;
VERIFY_BITS(d, 114);
// [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0]
/* [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]
/* [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]
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
c += (__int128)a0 * a2
+ (__int128)a1 * a1;
VERIFY_BITS(c, 114);
// [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0]
/* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
d += (__int128)a3 * a4;
VERIFY_BITS(d, 114);
// [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0]
/* [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]
/* [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]
/* [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]
/* [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]
/* [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;
/* [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]
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
#endif

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_FIELD_REPR_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -33,7 +35,7 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]);
mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry);
#else
mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) +
mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) +
mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS));
mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry);
mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS));
@ -119,10 +121,11 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1
}
static void secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) {
// <A1 A2 A3 A4> <B1 B2 B3 B4>
// B1 B2 B3 B4
// + C * A1 A2 A3 A4
// + A1 A2 A3 A4
/** <A1 A2 A3 A4> <B1 B2 B3 B4>
* B1 B2 B3 B4
* + C * A1 A2 A3 A4
* + A1 A2 A3 A4
*/
#if (GMP_NUMB_BITS >= 33)
mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL);

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -66,9 +68,10 @@ static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
// 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]
/** 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_t x2;
secp256k1_fe_sqr(&x2, a);
@ -114,7 +117,7 @@ static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
for (int 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.
/* The final result is then assembled using a sliding window over the blocks. */
secp256k1_fe_t t1 = x223;
for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
@ -124,7 +127,7 @@ static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
secp256k1_fe_sqr(&t1, &t1);
secp256k1_fe_sqr(r, &t1);
// Check that a square root was actually calculated
/* Check that a square root was actually calculated */
secp256k1_fe_sqr(&t1, r);
secp256k1_fe_negate(&t1, &t1, 1);
@ -135,9 +138,10 @@ static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
// 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]
/** 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_t x2;
secp256k1_fe_sqr(&x2, a);
@ -183,7 +187,7 @@ static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
for (int 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.
/* The final result is then assembled using a sliding window over the blocks. */
secp256k1_fe_t t1 = x223;
for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
@ -204,7 +208,7 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
secp256k1_fe_t c = *a;
secp256k1_fe_normalize(&c);
secp256k1_fe_get_b32(b, &c);
secp256k1_num_t n;
secp256k1_num_t n;
secp256k1_num_set_bin(&n, b, 32);
secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p);
secp256k1_num_get_bin(b, 32, &n);

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_GROUP_
@ -12,25 +14,25 @@
typedef struct {
secp256k1_fe_t x;
secp256k1_fe_t y;
int infinity; // whether this represents the point at infinity
int infinity; /* whether this represents the point at infinity */
} secp256k1_ge_t;
/** A group element of the secp256k1 curve, in jacobian coordinates. */
typedef struct {
secp256k1_fe_t x; // actual X: x/z^2
secp256k1_fe_t y; // actual Y: y/z^3
secp256k1_fe_t x; /* actual X: x/z^2 */
secp256k1_fe_t y; /* actual Y: y/z^3 */
secp256k1_fe_t z;
int infinity; // whether this represents the point at infinity
int infinity; /* whether this represents the point at infinity */
} secp256k1_gej_t;
/** Global constants related to the group */
typedef struct {
secp256k1_num_t order; // the order of the curve (= order of its generator)
secp256k1_num_t half_order; // half the order of the curve (= order of its generator)
secp256k1_ge_t g; // the generator point
secp256k1_num_t order; /* the order of the curve (= order of its generator) */
secp256k1_num_t half_order; /* half the order of the curve (= order of its generator) */
secp256k1_ge_t g; /* the generator point */
#ifdef USE_ENDOMORPHISM
// constants related to secp256k1's efficiently computable endomorphism
/* constants related to secp256k1's efficiently computable endomorphism */
secp256k1_fe_t beta;
secp256k1_num_t lambda, a1b2, b1, a2;
#endif

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -176,10 +178,11 @@ static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a) {
static int secp256k1_gej_is_valid(const secp256k1_gej_t *a) {
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
/** 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_t y2; secp256k1_fe_sqr(&y2, &a->y);
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
@ -194,7 +197,7 @@ static int secp256k1_gej_is_valid(const secp256k1_gej_t *a) {
static int secp256k1_ge_is_valid(const secp256k1_ge_t *a) {
if (a->infinity)
return 0;
// y^2 = x^3 + 7
/* y^2 = x^3 + 7 */
secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y);
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
@ -219,25 +222,25 @@ static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *
secp256k1_fe_t t1,t2,t3,t4;
secp256k1_fe_mul(&r->z, &t5, &a->z);
secp256k1_fe_mul_int(&r->z, 2); // Z' = 2*Y*Z (2)
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_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */
secp256k1_fe_sqr(&t3, &t5);
secp256k1_fe_mul_int(&t3, 2); // T3 = 2*Y^2 (2)
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, &a->x, &t3); // T3 = 2*X*Y^2 (1)
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */
secp256k1_fe_mul(&t3, &a->x, &t3); /* 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)
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) */
r->infinity = 0;
}
@ -329,63 +332,65 @@ static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c
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 = X1*Z2^3, S2 = X2*Z2^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.)
/** 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 = X1*Z2^3, S2 = X2*Z2^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.)
*/
secp256k1_fe_t zz; secp256k1_fe_sqr(&zz, &a->z); // z = Z1^2
secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); // u1 = U1 = X1*Z2^2 (1)
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &zz); // u2 = U2 = X2*Z1^2 (1)
secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); // s1 = S1 = Y1*Z2^3 (1)
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &zz); // s2 = Y2*Z2^2 (1)
secp256k1_fe_mul(&s2, &s2, &a->z); // s2 = S2 = Y2*Z1^3 (1)
secp256k1_fe_t z = a->z; // z = Z = Z1*Z2 (8)
secp256k1_fe_t t = u1; secp256k1_fe_add(&t, &u2); // t = T = U1+U2 (2)
secp256k1_fe_t m = s1; secp256k1_fe_add(&m, &s2); // m = M = S1+S2 (2)
secp256k1_fe_t n; secp256k1_fe_sqr(&n, &m); // n = M^2 (1)
secp256k1_fe_t q; secp256k1_fe_mul(&q, &n, &t); // q = Q = T*M^2 (1)
secp256k1_fe_sqr(&n, &n); // n = M^4 (1)
secp256k1_fe_t rr; secp256k1_fe_sqr(&rr, &t); // rr = T^2 (1)
secp256k1_fe_mul(&t, &u1, &u2); secp256k1_fe_negate(&t, &t, 1); // t = -U1*U2 (2)
secp256k1_fe_add(&rr, &t); // rr = R = T^2-U1*U2 (3)
secp256k1_fe_sqr(&t, &rr); // t = R^2 (1)
secp256k1_fe_mul(&r->z, &m, &z); // r->z = M*Z (1)
secp256k1_fe_t zz; secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */
secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); /* u1 = U1 = X1*Z2^2 (1) */
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */
secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); /* s1 = S1 = Y1*Z2^3 (1) */
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */
secp256k1_fe_t z = a->z; /* z = Z = Z1*Z2 (8) */
secp256k1_fe_t t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */
secp256k1_fe_t m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */
secp256k1_fe_t n; secp256k1_fe_sqr(&n, &m); /* n = M^2 (1) */
secp256k1_fe_t q; secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*M^2 (1) */
secp256k1_fe_sqr(&n, &n); /* n = M^4 (1) */
secp256k1_fe_t rr; secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */
secp256k1_fe_mul(&t, &u1, &u2); secp256k1_fe_negate(&t, &t, 1); /* t = -U1*U2 (2) */
secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */
secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */
secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */
secp256k1_fe_normalize(&r->z);
int infinity = secp256k1_fe_is_zero(&r->z) * (1 - a->infinity);
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); // r->z = Z3 = 2*M*Z (2)
r->x = t; // r->x = R^2 (1)
secp256k1_fe_negate(&q, &q, 1); // q = -Q (2)
secp256k1_fe_add(&r->x, &q); // r->x = R^2-Q (3)
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */
r->x = t; /* r->x = R^2 (1) */
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
secp256k1_fe_add(&r->x, &q); /* r->x = R^2-Q (3) */
secp256k1_fe_normalize(&r->x);
secp256k1_fe_mul_int(&q, 3); // q = -3*Q (6)
secp256k1_fe_mul_int(&t, 2); // t = 2*R^2 (2)
secp256k1_fe_add(&t, &q); // t = 2*R^2-3*Q (8)
secp256k1_fe_mul(&t, &t, &rr); // t = R*(2*R^2-3*Q) (1)
secp256k1_fe_add(&t, &n); // t = R*(2*R^2-3*Q)+M^4 (2)
secp256k1_fe_negate(&r->y, &t, 2); // r->y = R*(3*Q-2*R^2)-M^4 (3)
secp256k1_fe_mul_int(&q, 3); /* q = -3*Q (6) */
secp256k1_fe_mul_int(&t, 2); /* t = 2*R^2 (2) */
secp256k1_fe_add(&t, &q); /* t = 2*R^2-3*Q (8) */
secp256k1_fe_mul(&t, &t, &rr); /* t = R*(2*R^2-3*Q) (1) */
secp256k1_fe_add(&t, &n); /* t = R*(2*R^2-3*Q)+M^4 (2) */
secp256k1_fe_negate(&r->y, &t, 2); /* r->y = R*(3*Q-2*R^2)-M^4 (3) */
secp256k1_fe_normalize(&r->y);
secp256k1_fe_mul_int(&r->x, 4 * (1 - a->infinity)); // r->x = X3 = 4*(R^2-Q)
secp256k1_fe_mul_int(&r->y, 4 * (1 - a->infinity)); // r->y = Y3 = 4*R*(3*Q-2*R^2)-4*M^4 (4)
secp256k1_fe_mul_int(&r->x, 4 * (1 - a->infinity)); /* r->x = X3 = 4*(R^2-Q) */
secp256k1_fe_mul_int(&r->y, 4 * (1 - a->infinity)); /* r->y = Y3 = 4*R*(3*Q-2*R^2)-4*M^4 (4) */
// In case a->infinity == 1, the above code results in r->x, r->y, and r->z all equal to 0.
// Add b->x to x, b->y to y, and 1 to z in that case.
/** In case a->infinity == 1, the above code results in r->x, r->y, and r->z all equal to 0.
* Add b->x to x, b->y to y, and 1 to z in that case.
*/
t = b->x; secp256k1_fe_mul_int(&t, a->infinity);
secp256k1_fe_add(&r->x, &t);
t = b->y; secp256k1_fe_mul_int(&t, a->infinity);
@ -456,7 +461,7 @@ static void secp256k1_ge_start(void) {
0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8
};
#ifdef USE_ENDOMORPHISM
// properties of secp256k1's efficiently computable endomorphism
/* properties of secp256k1's efficiently computable endomorphism */
static const unsigned char secp256k1_ge_consts_lambda[] = {
0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_NUM_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
#define _SECP256K1_NUM_REPR_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -119,15 +121,16 @@ static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t
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
/** 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);
mp_limb_t g[NUM_LIMBS+1];
@ -180,7 +183,7 @@ static int secp256k1_num_eq(const secp256k1_num_t *a, const secp256k1_num_t *b)
}
static void secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) {
if (!(b->neg ^ bneg ^ a->neg)) { // a and b have the same sign
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);

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_SCALAR_

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_SCALAR_REPR_

View File

@ -1,24 +1,26 @@
// 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.
/**********************************************************************
* 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_
typedef unsigned __int128 uint128_t;
// Limbs of the secp256k1 order.
/* 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.
/* 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.
/* 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)
@ -39,7 +41,7 @@ SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) {
int yes = 0;
int no = 0;
no |= (a->d[3] < SECP256K1_N_3); // No need for a > check.
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);
@ -116,14 +118,14 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
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[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;
}
// Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c.
/* 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) { \
@ -211,12 +213,12 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l) {
uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7];
// 160 bit accumulator.
/* 160 bit accumulator. */
uint64_t c0, c1;
uint32_t c2;
// Reduce 512 bits into 385.
// m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C.
/* 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);
uint64_t m0; extract_fast(m0);
@ -242,8 +244,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l
VERIFY_CHECK(c0 <= 1);
uint32_t m6 = c0;
// Reduce 385 bits into 258.
// p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C.
/* 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);
uint64_t p0; extract_fast(p0);
@ -263,8 +265,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l
uint32_t p4 = c0 + m6;
VERIFY_CHECK(p4 <= 2);
// Reduce 258 bits into 256.
// r[0..3] = p[0..3] + p[4] * SECP256K1_N_C.
/* Reduce 258 bits into 256. */
/* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
uint128_t 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;
@ -274,18 +276,18 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l
c += p3;
r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64;
// Final reduction of r.
/* Final reduction of r. */
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
// 160 bit accumulator.
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
uint64_t l[8];
// l[0..7] = a[0..3] * b[0..3].
/* 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]);
@ -316,13 +318,13 @@ static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t
}
static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
// 160 bit accumulator.
/* 160 bit accumulator. */
uint64_t c0 = 0, c1 = 0;
uint32_t c2 = 0;
uint64_t l[8];
// l[0..7] = a[0..3] * b[0..3].
/* 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]);

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
#define _SECP256K1_SCALAR_REPR_

View File

@ -1,11 +1,13 @@
// 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.
/**********************************************************************
* 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.
/* 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)
@ -15,14 +17,14 @@
#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL)
#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL)
// Limbs of 2^256 minus the secp256k1 order.
/* 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.
/* 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)
@ -51,9 +53,9 @@ SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *
SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *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[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;
@ -166,9 +168,9 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
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[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;
@ -179,7 +181,7 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
return yes;
}
// Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c.
/* 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) { \
@ -267,11 +269,11 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l) {
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];
// 96 bit accumulator.
/* 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.
/* 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);
uint32_t m0; extract_fast(m0);
@ -335,8 +337,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
VERIFY_CHECK(c0 <= 1);
uint32_t m12 = c0;
// Reduce 385 bits into 258.
// p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C.
/* 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);
uint32_t p0; extract_fast(p0);
@ -380,8 +382,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
uint32_t p8 = c0 + m12;
VERIFY_CHECK(p8 <= 2);
// Reduce 258 bits into 256.
// r[0..7] = p[0..7] + p[8] * SECP256K1_N_C.
/* Reduce 258 bits into 256. */
/* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */
uint64_t 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;
@ -399,17 +401,17 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l
c += p7;
r->d[7] = c & 0xFFFFFFFFUL; c >>= 32;
// Final reduction of r.
/* Final reduction of r. */
secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r));
}
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
// 96 bit accumulator.
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
uint32_t l[16];
// l[0..15] = a[0..7] * b[0..7].
/* 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]);
@ -496,12 +498,12 @@ static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t
}
static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
// 96 bit accumulator.
/* 96 bit accumulator. */
uint32_t c0 = 0, c1 = 0, c2 = 0;
uint32_t l[16];
// l[0..15] = a[0..7]^2.
/* 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]);

View File

@ -1,6 +1,8 @@
// 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.
/**********************************************************************
* 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_
@ -29,7 +31,7 @@ static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) {
// First compute x ^ (2^N - 1) for some values of N.
/* First compute x ^ (2^N - 1) for some values of N. */
secp256k1_scalar_t x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127;
secp256k1_scalar_sqr(&x2, x);
@ -76,107 +78,107 @@ static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal
secp256k1_scalar_sqr(&x127, &x127);
secp256k1_scalar_mul(&x127, &x127, &x7);
// Then accumulate the final result (t starts at x127).
/* Then accumulate the final result (t starts at x127). */
secp256k1_scalar_t *t = &x127;
for (int i=0; i<2; i++) // 0
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<4; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<4; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<3; i++) // 0
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<3; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<4; i++) // 0
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<5; i++) // 00
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<5; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<4; i++) // 00
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<4; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<5; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<5; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x4); // 1111
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<3; i++) // 00
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<4; i++) // 000
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<4; i++) /* 000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<10; i++) // 0000000
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<10; i++) /* 0000000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<4; i++) // 0
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<4; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x3); // 111
for (int i=0; i<9; i++) // 0
secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (int i=0; i<9; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x8); // 11111111
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x8); /* 11111111 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<3; i++) // 00
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<3; i++) // 00
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<5; i++) // 0
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<5; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x4); // 1111
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x4); /* 1111 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<5; i++) // 000
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<5; i++) /* 000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<4; i++) // 00
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<4; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<2; i++) // 0
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<2; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<8; i++) // 000000
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<8; i++) /* 000000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<3; i++) // 0
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<3; i++) /* 0 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, &x2); // 11
for (int i=0; i<3; i++) // 00
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (int i=0; i<3; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<6; i++) // 00000
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<6; i++) /* 00000 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(t, t, x); // 1
for (int i=0; i<8; i++) // 00
secp256k1_scalar_mul(t, t, x); /* 1 */
for (int i=0; i<8; i++) /* 00 */
secp256k1_scalar_sqr(t, t);
secp256k1_scalar_mul(r, t, &x6); // 111111
secp256k1_scalar_mul(r, t, &x6); /* 111111 */
}
#endif

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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.*
**********************************************************************/
#define SECP256K1_BUILD (1)
@ -42,7 +44,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned
DEBUG_CHECK(pubkey != NULL);
int ret = -3;
secp256k1_num_t m;
secp256k1_num_t m;
secp256k1_ecdsa_sig_t s;
secp256k1_ge_t q;
secp256k1_num_set_bin(&m, msg, msglen);
@ -140,7 +142,7 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const
DEBUG_CHECK(recid >= 0 && recid <= 3);
int ret = 0;
secp256k1_num_t m;
secp256k1_num_t m;
secp256k1_ecdsa_sig_t sig;
secp256k1_num_set_bin(&sig.r, sig64, 32);
secp256k1_num_set_bin(&sig.s, sig64 + 32, 32);

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_IMPL_H_
#define _SECP256K1_TESTRAND_IMPL_H_

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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.*
**********************************************************************/
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@ -131,12 +133,12 @@ void test_num_get_set_hex(void) {
secp256k1_num_set_hex(&n2, c, 64);
CHECK(secp256k1_num_eq(&n1, &n2));
for (int i=0; i<64; i++) {
// check whether the lower 4 bits correspond to the last hex character
/* check whether the lower 4 bits correspond to the last hex character */
int low1 = secp256k1_num_shift(&n1, 4);
int lowh = c[63];
int low2 = ((lowh>>6)*9+(lowh-'0'))&15;
CHECK(low1 == low2);
// shift bits off the hex representation, and compare
/* shift bits off the hex representation, and compare */
memmove(c+1, c, 63);
c[0] = '0';
secp256k1_num_set_hex(&n2, c, 64);
@ -152,11 +154,11 @@ void test_num_get_set_bin(void) {
secp256k1_num_set_bin(&n2, c, 32);
CHECK(secp256k1_num_eq(&n1, &n2));
for (int i=0; i<32; i++) {
// check whether the lower 8 bits correspond to the last byte
/* check whether the lower 8 bits correspond to the last byte */
int low1 = secp256k1_num_shift(&n1, 8);
int low2 = c[31];
CHECK(low1 == low2);
// shift bits off the byte representation, and compare
/* shift bits off the byte representation, and compare */
memmove(c+1, c, 31);
c[0] = 0;
secp256k1_num_set_bin(&n2, c, 32);
@ -179,20 +181,20 @@ void run_num_int(void) {
void test_num_negate(void) {
secp256k1_num_t n1;
secp256k1_num_t n2;
random_num_order_test(&n1); // n1 = R
random_num_order_test(&n1); /* n1 = R */
random_num_negate(&n1);
secp256k1_num_copy(&n2, &n1); // n2 = R
secp256k1_num_sub(&n1, &n2, &n1); // n1 = n2-n1 = 0
secp256k1_num_copy(&n2, &n1); /* n2 = R */
secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */
CHECK(secp256k1_num_is_zero(&n1));
secp256k1_num_copy(&n1, &n2); // n1 = R
secp256k1_num_negate(&n1); // n1 = -R
secp256k1_num_copy(&n1, &n2); /* n1 = R */
secp256k1_num_negate(&n1); /* n1 = -R */
CHECK(!secp256k1_num_is_zero(&n1));
secp256k1_num_add(&n1, &n2, &n1); // n1 = n2+n1 = 0
secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */
CHECK(secp256k1_num_is_zero(&n1));
secp256k1_num_copy(&n1, &n2); // n1 = R
secp256k1_num_negate(&n1); // n1 = -R
secp256k1_num_copy(&n1, &n2); /* n1 = R */
secp256k1_num_negate(&n1); /* n1 = -R */
CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2));
secp256k1_num_negate(&n1); // n1 = R
secp256k1_num_negate(&n1); /* n1 = R */
CHECK(secp256k1_num_eq(&n1, &n2));
}
@ -200,28 +202,28 @@ void test_num_add_sub(void) {
int r = secp256k1_rand32();
secp256k1_num_t n1;
secp256k1_num_t n2;
random_num_order_test(&n1); // n1 = R1
random_num_order_test(&n1); /* n1 = R1 */
if (r & 1) {
random_num_negate(&n1);
}
random_num_order_test(&n2); // n2 = R2
random_num_order_test(&n2); /* n2 = R2 */
if (r & 2) {
random_num_negate(&n2);
}
secp256k1_num_t n1p2, n2p1, n1m2, n2m1;
secp256k1_num_add(&n1p2, &n1, &n2); // n1p2 = R1 + R2
secp256k1_num_add(&n2p1, &n2, &n1); // n2p1 = R2 + R1
secp256k1_num_sub(&n1m2, &n1, &n2); // n1m2 = R1 - R2
secp256k1_num_sub(&n2m1, &n2, &n1); // n2m1 = R2 - R1
secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */
secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */
secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */
secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */
CHECK(secp256k1_num_eq(&n1p2, &n2p1));
CHECK(!secp256k1_num_eq(&n1p2, &n1m2));
secp256k1_num_negate(&n2m1); // n2m1 = -R2 + R1
secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */
CHECK(secp256k1_num_eq(&n2m1, &n1m2));
CHECK(!secp256k1_num_eq(&n2m1, &n1));
secp256k1_num_add(&n2m1, &n2m1, &n2); // n2m1 = -R2 + R1 + R2 = R1
secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */
CHECK(secp256k1_num_eq(&n2m1, &n1));
CHECK(!secp256k1_num_eq(&n2p1, &n1));
secp256k1_num_sub(&n2p1, &n2p1, &n2); // n2p1 = R2 + R1 - R2 = R1
secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */
CHECK(secp256k1_num_eq(&n2p1, &n1));
}
@ -249,7 +251,7 @@ int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *
void scalar_test(void) {
unsigned char c[32];
// Set 's' to a random scalar, with value 'snum'.
/* Set 's' to a random scalar, with value 'snum'. */
secp256k1_rand256_test(c);
secp256k1_scalar_t s;
secp256k1_scalar_set_b32(&s, c, NULL);
@ -257,7 +259,7 @@ void scalar_test(void) {
secp256k1_num_set_bin(&snum, c, 32);
secp256k1_num_mod(&snum, &secp256k1_ge_consts->order);
// Set 's1' to a random scalar, with value 's1num'.
/* Set 's1' to a random scalar, with value 's1num'. */
secp256k1_rand256_test(c);
secp256k1_scalar_t s1;
secp256k1_scalar_set_b32(&s1, c, NULL);
@ -265,7 +267,7 @@ void scalar_test(void) {
secp256k1_num_set_bin(&s1num, c, 32);
secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order);
// Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'.
/* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */
secp256k1_rand256_test(c);
secp256k1_scalar_t s2;
int overflow = 0;
@ -275,7 +277,7 @@ void scalar_test(void) {
secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order);
{
// Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it.
/* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */
secp256k1_num_t n, t, m;
secp256k1_num_set_int(&n, 0);
secp256k1_num_set_int(&m, 16);
@ -288,18 +290,18 @@ void scalar_test(void) {
}
{
// Test that get_b32 returns the same as get_bin on the number.
/* Test that get_b32 returns the same as get_bin on the number. */
unsigned char r1[32];
secp256k1_scalar_get_b32(r1, &s2);
unsigned char r2[32];
secp256k1_num_get_bin(r2, 32, &s2num);
CHECK(memcmp(r1, r2, 32) == 0);
// If no overflow occurred when assigning, it should also be equal to the original byte array.
/* If no overflow occurred when assigning, it should also be equal to the original byte array. */
CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0));
}
{
// Test that adding the scalars together is equal to adding their numbers together modulo the order.
/* Test that adding the scalars together is equal to adding their numbers together modulo the order. */
secp256k1_num_t rnum;
secp256k1_num_add(&rnum, &snum, &s2num);
secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order);
@ -311,7 +313,7 @@ void scalar_test(void) {
}
{
// Test that multipying the scalars is equal to multiplying their numbers modulo the order.
/* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */
secp256k1_num_t rnum;
secp256k1_num_mul(&rnum, &snum, &s2num);
secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order);
@ -320,41 +322,41 @@ void scalar_test(void) {
secp256k1_num_t r2num;
secp256k1_scalar_get_num(&r2num, &r);
CHECK(secp256k1_num_eq(&rnum, &r2num));
// The result can only be zero if at least one of the factors was zero.
/* The result can only be zero if at least one of the factors was zero. */
CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2)));
// The results can only be equal to one of the factors if that factor was zero, or the other factor was one.
/* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */
CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2)));
CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s)));
}
{
// Check that comparison with zero matches comparison with zero on the number.
/* Check that comparison with zero matches comparison with zero on the number. */
CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s));
// Check that comparison with the half order is equal to testing for high scalar.
/* Check that comparison with the half order is equal to testing for high scalar. */
CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0));
secp256k1_scalar_t neg;
secp256k1_scalar_negate(&neg, &s);
secp256k1_num_t negnum;
secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum);
secp256k1_num_mod(&negnum, &secp256k1_ge_consts->order);
// Check that comparison with the half order is equal to testing for high scalar after negation.
/* Check that comparison with the half order is equal to testing for high scalar after negation. */
CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &secp256k1_ge_consts->half_order) > 0));
// Negating should change the high property, unless the value was already zero.
/* Negating should change the high property, unless the value was already zero. */
CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s));
secp256k1_num_t negnum2;
secp256k1_scalar_get_num(&negnum2, &neg);
// Negating a scalar should be equal to (order - n) mod order on the number.
/* Negating a scalar should be equal to (order - n) mod order on the number. */
CHECK(secp256k1_num_eq(&negnum, &negnum2));
secp256k1_scalar_add(&neg, &neg, &s);
// Adding a number to its negation should result in zero.
/* Adding a number to its negation should result in zero. */
CHECK(secp256k1_scalar_is_zero(&neg));
secp256k1_scalar_negate(&neg, &neg);
// Negating zero should still result in zero.
/* Negating zero should still result in zero. */
CHECK(secp256k1_scalar_is_zero(&neg));
}
{
// Test that scalar inverses are equal to the inverse of their number modulo the order.
/* Test that scalar inverses are equal to the inverse of their number modulo the order. */
if (!secp256k1_scalar_is_zero(&s)) {
secp256k1_scalar_t inv;
secp256k1_scalar_inverse(&inv, &s);
@ -364,16 +366,16 @@ void scalar_test(void) {
secp256k1_scalar_get_num(&invnum2, &inv);
CHECK(secp256k1_num_eq(&invnum, &invnum2));
secp256k1_scalar_mul(&inv, &inv, &s);
// Multiplying a scalar with its inverse must result in one.
/* Multiplying a scalar with its inverse must result in one. */
CHECK(secp256k1_scalar_is_one(&inv));
secp256k1_scalar_inverse(&inv, &inv);
// Inverting one must result in one.
/* Inverting one must result in one. */
CHECK(secp256k1_scalar_is_one(&inv));
}
}
{
// Test commutativity of add.
/* Test commutativity of add. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_add(&r1, &s1, &s2);
secp256k1_scalar_add(&r2, &s2, &s1);
@ -381,7 +383,7 @@ void scalar_test(void) {
}
{
// Test commutativity of mul.
/* Test commutativity of mul. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_mul(&r1, &s1, &s2);
secp256k1_scalar_mul(&r2, &s2, &s1);
@ -389,7 +391,7 @@ void scalar_test(void) {
}
{
// Test associativity of add.
/* Test associativity of add. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_add(&r1, &s1, &s2);
secp256k1_scalar_add(&r1, &r1, &s);
@ -399,7 +401,7 @@ void scalar_test(void) {
}
{
// Test associativity of mul.
/* Test associativity of mul. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_mul(&r1, &s1, &s2);
secp256k1_scalar_mul(&r1, &r1, &s);
@ -409,7 +411,7 @@ void scalar_test(void) {
}
{
// Test distributitivity of mul over add.
/* Test distributitivity of mul over add. */
secp256k1_scalar_t r1, r2, t;
secp256k1_scalar_add(&r1, &s1, &s2);
secp256k1_scalar_mul(&r1, &r1, &s);
@ -420,7 +422,7 @@ void scalar_test(void) {
}
{
// Test square.
/* Test square. */
secp256k1_scalar_t r1, r2;
secp256k1_scalar_sqr(&r1, &s1);
secp256k1_scalar_mul(&r2, &s1, &s1);
@ -450,7 +452,7 @@ void random_fe_non_zero(secp256k1_fe_t *nz) {
if (!secp256k1_fe_is_zero(nz))
break;
}
// Infinitesimal probability of spurious failure here
/* Infinitesimal probability of spurious failure here */
CHECK(tries >= 0);
}
@ -498,7 +500,7 @@ void run_field_inv_var(void) {
void run_field_inv_all(void) {
secp256k1_fe_t x[16], xi[16], xii[16];
// Check it's safe to call for 0 elements
/* Check it's safe to call for 0 elements */
secp256k1_fe_inv_all(0, xi, x);
for (int i=0; i<count; i++) {
size_t len = (secp256k1_rand32() & 15) + 1;
@ -515,7 +517,7 @@ void run_field_inv_all(void) {
void run_field_inv_all_var(void) {
secp256k1_fe_t x[16], xi[16], xii[16];
// Check it's safe to call for 0 elements
/* Check it's safe to call for 0 elements */
secp256k1_fe_inv_all_var(0, xi, x);
for (int i=0; i<count; i++) {
size_t len = (secp256k1_rand32() & 15) + 1;
@ -551,7 +553,7 @@ void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) {
CHECK((v == 0) == (k == NULL));
if (k != NULL) {
// Check that the returned root is +/- the given known answer
/* Check that the returned root is +/- the given known answer */
secp256k1_fe_negate(&r2, &r1, 1);
secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k);
secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2);
@ -562,12 +564,12 @@ void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) {
void run_sqrt(void) {
secp256k1_fe_t ns, x, s, t;
// Check sqrt(0) is 0
/* Check sqrt(0) is 0 */
secp256k1_fe_set_int(&x, 0);
secp256k1_fe_sqr(&s, &x);
test_sqrt(&s, &x);
// Check sqrt of small squares (and their negatives)
/* Check sqrt of small squares (and their negatives) */
for (int i=1; i<=100; i++) {
secp256k1_fe_set_int(&x, i);
secp256k1_fe_sqr(&s, &x);
@ -576,7 +578,7 @@ void run_sqrt(void) {
test_sqrt(&t, NULL);
}
// Consistency checks for large random values
/* Consistency checks for large random values */
for (int i=0; i<10; i++) {
random_fe_non_square(&ns);
for (int j=0; j<count; j++) {
@ -644,7 +646,7 @@ void test_ge(void) {
random_field_element_magnitude(&nj.y);
random_field_element_magnitude(&nj.z);
// gej + gej adds
/* gej + gej adds */
secp256k1_gej_t aaj; secp256k1_gej_add_var(&aaj, &aj, &aj);
secp256k1_gej_t abj; secp256k1_gej_add_var(&abj, &aj, &bj);
secp256k1_gej_t aij; secp256k1_gej_add_var(&aij, &aj, &ij);
@ -652,7 +654,7 @@ void test_ge(void) {
secp256k1_gej_t iaj; secp256k1_gej_add_var(&iaj, &ij, &aj);
secp256k1_gej_t iij; secp256k1_gej_add_var(&iij, &ij, &ij);
// gej + ge adds
/* gej + ge adds */
secp256k1_gej_t aa; secp256k1_gej_add_ge_var(&aa, &aj, &a);
secp256k1_gej_t ab; secp256k1_gej_add_ge_var(&ab, &aj, &b);
secp256k1_gej_t ai; secp256k1_gej_add_ge_var(&ai, &aj, &i);
@ -660,7 +662,7 @@ void test_ge(void) {
secp256k1_gej_t ia; secp256k1_gej_add_ge_var(&ia, &ij, &a);
secp256k1_gej_t ii; secp256k1_gej_add_ge_var(&ii, &ij, &i);
// const gej + ge adds
/* const gej + ge adds */
secp256k1_gej_t aac; secp256k1_gej_add_ge(&aac, &aj, &a);
secp256k1_gej_t abc; secp256k1_gej_add_ge(&abc, &aj, &b);
secp256k1_gej_t anc; secp256k1_gej_add_ge(&anc, &aj, &n);
@ -694,49 +696,49 @@ void run_ge(void) {
/***** ECMULT TESTS *****/
void run_ecmult_chain(void) {
// random starting point A (on the curve)
/* random starting point A (on the curve) */
secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64);
secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
// two random initial factors xn and gn
/* two random initial factors xn and gn */
secp256k1_num_t xn;
secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
secp256k1_num_t gn;
secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
// two small multipliers to be applied to xn and gn in every iteration:
/* two small multipliers to be applied to xn and gn in every iteration: */
secp256k1_num_t xf;
secp256k1_num_set_hex(&xf, "1337", 4);
secp256k1_num_t gf;
secp256k1_num_set_hex(&gf, "7113", 4);
// accumulators with the resulting coefficients to A and G
/* accumulators with the resulting coefficients to A and G */
secp256k1_num_t ae;
secp256k1_num_set_int(&ae, 1);
secp256k1_num_t ge;
secp256k1_num_set_int(&ge, 0);
// the point being computed
/* the point being computed */
secp256k1_gej_t x = a;
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
for (int i=0; i<200*count; i++) {
// in each iteration, compute X = xn*X + gn*G;
/* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&x, &x, &xn, &gn);
// also compute ae and ge: the actual accumulated factors for A and G
// if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
/* also compute ae and ge: the actual accumulated factors for A and G */
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
secp256k1_num_mod_mul(&ae, &ae, &xn, order);
secp256k1_num_mod_mul(&ge, &ge, &xn, order);
secp256k1_num_add(&ge, &ge, &gn);
secp256k1_num_mod(&ge, order);
// modify xn and gn
/* modify xn and gn */
secp256k1_num_mod_mul(&xn, &xn, &xf, order);
secp256k1_num_mod_mul(&gn, &gn, &gf, order);
// verify
/* verify */
if (i == 19999) {
char res[132]; int resl = 132;
secp256k1_gej_get_hex(res, &resl, &x);
CHECK(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
}
}
// redo the computation, but directly with the resulting ae and ge coefficients:
/* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge);
char res[132]; int resl = 132;
char res2[132]; int resl2 = 132;
@ -747,12 +749,12 @@ void run_ecmult_chain(void) {
}
void test_point_times_order(const secp256k1_gej_t *point) {
// multiplying a point by the order results in O
/* multiplying a point by the order results in O */
const secp256k1_num_t *order = &secp256k1_ge_consts->order;
secp256k1_num_t zero;
secp256k1_num_set_int(&zero, 0);
secp256k1_gej_t res;
secp256k1_ecmult(&res, point, order, order); // calc res = order * point + order * G;
secp256k1_ecmult(&res, point, order, order); /* calc res = order * point + order * G; */
CHECK(secp256k1_gej_is_infinity(&res));
}
@ -785,19 +787,19 @@ void test_wnaf(const secp256k1_num_t *number, int w) {
secp256k1_num_mul(&x, &x, &two);
int v = wnaf[i];
if (v) {
CHECK(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */
zeroes=0;
CHECK((v & 1) == 1); // check non-zero elements are odd
CHECK(v <= (1 << (w-1)) - 1); // check range below
CHECK(v >= -(1 << (w-1)) - 1); // check range above
CHECK((v & 1) == 1); /* check non-zero elements are odd */
CHECK(v <= (1 << (w-1)) - 1); /* check range below */
CHECK(v >= -(1 << (w-1)) - 1); /* check range above */
} else {
CHECK(zeroes != -1); // check that no unnecessary zero padding exists
CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */
zeroes++;
}
secp256k1_num_set_int(&t, v);
secp256k1_num_add(&x, &x, &t);
}
CHECK(secp256k1_num_eq(&x, number)); // check that wnaf represents number
CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */
}
void run_wnaf(void) {
@ -842,7 +844,7 @@ void test_ecdsa_end_to_end(void) {
unsigned char privkey[32];
unsigned char message[32];
// Generate a random key and message.
/* Generate a random key and message. */
{
secp256k1_num_t msg, key;
random_num_order_test(&msg);
@ -851,20 +853,20 @@ void test_ecdsa_end_to_end(void) {
secp256k1_num_get_bin(message, 32, &msg);
}
// Construct and verify corresponding public key.
/* Construct and verify corresponding public key. */
CHECK(secp256k1_ec_seckey_verify(privkey) == 1);
unsigned char pubkey[65]; int pubkeylen = 65;
CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1);
CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen));
// Verify private key import and export.
/* Verify private key import and export. */
unsigned char seckey[300]; int seckeylen = 300;
CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1);
unsigned char privkey2[32];
CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1);
CHECK(memcmp(privkey, privkey2, 32) == 0);
// Optionally tweak the keys using addition.
/* Optionally tweak the keys using addition. */
if (secp256k1_rand32() % 3 == 0) {
unsigned char rnd[32];
secp256k1_rand256_test(rnd);
@ -877,7 +879,7 @@ void test_ecdsa_end_to_end(void) {
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
}
// Optionally tweak the keys using multiplication.
/* Optionally tweak the keys using multiplication. */
if (secp256k1_rand32() % 3 == 0) {
unsigned char rnd[32];
secp256k1_rand256_test(rnd);
@ -890,7 +892,7 @@ void test_ecdsa_end_to_end(void) {
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
}
// Sign.
/* Sign. */
unsigned char signature[72]; int signaturelen = 72;
while(1) {
unsigned char rnd[32];
@ -899,13 +901,13 @@ void test_ecdsa_end_to_end(void) {
break;
}
}
// Verify.
/* Verify. */
CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) == 1);
// Destroy signature and verify again.
/* Destroy signature and verify again. */
signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255);
CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) != 1);
// Compact sign.
/* Compact sign. */
unsigned char csignature[64]; int recid = 0;
while(1) {
unsigned char rnd[32];
@ -914,12 +916,12 @@ void test_ecdsa_end_to_end(void) {
break;
}
}
// Recover.
/* Recover. */
unsigned char recpubkey[65]; int recpubkeylen = 0;
CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1);
CHECK(recpubkeylen == pubkeylen);
CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0);
// Destroy signature and verify again.
/* Destroy signature and verify again. */
csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255);
CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 ||
memcmp(pubkey, recpubkey, pubkeylen) != 0);
@ -986,12 +988,12 @@ void run_ecdsa_openssl(void) {
#endif
int main(int argc, char **argv) {
// find iteration count
/* find iteration count */
if (argc > 1) {
count = strtol(argv[1], NULL, 0);
}
// find random seed
/* find random seed */
uint64_t seed;
if (argc > 2) {
seed = strtoull(argv[2], NULL, 0);
@ -1007,16 +1009,16 @@ int main(int argc, char **argv) {
printf("test count = %i\n", count);
printf("random seed = %llu\n", (unsigned long long)seed);
// initialize
/* initialize */
secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
// num tests
/* num tests */
run_num_smalltests();
// scalar tests
/* scalar tests */
run_scalar_tests();
// field tests
/* field tests */
run_field_inv();
run_field_inv_var();
run_field_inv_all();
@ -1024,15 +1026,15 @@ int main(int argc, char **argv) {
run_sqr();
run_sqrt();
// group tests
/* group tests */
run_ge();
// ecmult tests
/* ecmult tests */
run_wnaf();
run_point_times_order();
run_ecmult_chain();
// ecdsa tests
/* ecdsa tests */
run_ecdsa_sign_verify();
run_ecdsa_end_to_end();
#ifdef ENABLE_OPENSSL_TESTS
@ -1041,7 +1043,7 @@ int main(int argc, char **argv) {
printf("random run = %llu\n", (unsigned long long)secp256k1_rand32() + ((unsigned long long)secp256k1_rand32() << 32));
// shutdown
/* shutdown */
secp256k1_stop();
return 0;
}

View File

@ -1,6 +1,8 @@
// Copyright (c) 2013 Pieter Wuille
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**********************************************************************
* 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_
@ -30,14 +32,14 @@
} \
} while(0)
// Like assert(), but safe to use on expressions with side effects.
/* Like assert(), but safe to use on expressions with side effects. */
#ifndef NDEBUG
#define DEBUG_CHECK CHECK
#else
#define DEBUG_CHECK(cond) do { (void)(cond); } while(0)
#endif
// Like DEBUG_CHECK(), but when VERIFY is defined instead of NDEBUG not defined.
/* Like DEBUG_CHECK(), but when VERIFY is defined instead of NDEBUG not defined. */
#ifdef VERIFY
#define VERIFY_CHECK CHECK
#else