iPXE
weierstrass.c File Reference

Weierstrass elliptic curves. More...

#include <string.h>
#include <errno.h>
#include <ipxe/weierstrass.h>

Go to the source code of this file.

Macros

#define WEIERSTRASS_zero   WEIERSTRASS_a
 Zero register (for add/subtract operations.
#define WEIERSTRASS_REGISTER(name)
 Construct big integer register index.
#define WEIERSTRASS_OP(opcode, dest, left, right)
 Define a bytecode operation.
#define WEIERSTRASS_OPCODE(op)
 Extract bytecode operation code.
#define WEIERSTRASS_DEST(op)
 Extract destination big integer register.
#define WEIERSTRASS_LEFT(op)
 Extract left source big integer register.
#define WEIERSTRASS_RIGHT(op)
 Extract right source big integer register.
#define WEIERSTRASS_ADD3(dest, augend, addend)
 Define a three-argument addition operation.
#define WEIERSTRASS_ADD2(augend, addend)
 Define a two-argument addition operation.
#define WEIERSTRASS_MOV(dest, source)
 Define a move operation.
#define WEIERSTRASS_SUB3(dest, minuend, subtrahend, multiple)
 Define a three-argument subtraction operation.
#define WEIERSTRASS_SUB2(minuend, subtrahend, multiple)
 Define a two-argument subtraction operation.
#define WEIERSTRASS_STOP   WEIERSTRASS_SUB2 ( zero, zero, 0N )
 Define a stop operation.
#define WEIERSTRASS_MUL3(dest, multiplicand, multiplier)
 Define a three-argument multiplication operation.
#define WEIERSTRASS_MUL2(multiplicand, multiplier)
 Define a two-argument multiplication operation.
#define weierstrass_add(curve, augend, addend, result)
 Add points on curve.
#define weierstrass_verify(curve, point)
 Verify freshly initialised point is on curve.
#define weierstrass_init(curve, point, temp, data)
 Initialise curve point.
#define weierstrass_done(curve, point, temp, out)
 Finalise curve point.

Enumerations

enum  weierstrass_register {
  WEIERSTRASS_a = 0 , WEIERSTRASS_3b , WEIERSTRASS_x1 , WEIERSTRASS_y1 ,
  WEIERSTRASS_z1 , WEIERSTRASS_x2 , WEIERSTRASS_y2 , WEIERSTRASS_z2 ,
  WEIERSTRASS_Wt , WEIERSTRASS_Wxy , WEIERSTRASS_Wyz , WEIERSTRASS_Wzx ,
  WEIERSTRASS_Wp , WEIERSTRASS_x3 , WEIERSTRASS_y3 , WEIERSTRASS_z3 ,
  WEIERSTRASS_NUM_REGISTERS = 16
}
 Big integer register names. More...
enum  weierstrass_opcode {
  WEIERSTRASS_OP_SUB_0N = 0 , WEIERSTRASS_OP_SUB_2N = WEIERSTRASS_2N , WEIERSTRASS_OP_SUB_4N = WEIERSTRASS_4N , WEIERSTRASS_OP_ADD ,
  WEIERSTRASS_OP_MUL
}
 Bytecode operation codes. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void weierstrass_init_curve (struct elliptic_curve *curve)
 Initialise curve.
static void weierstrass_exec (const struct elliptic_curve *curve, void **regs, unsigned int size, unsigned int op)
 Execute bytecode instruction.
static void weierstrass_add_raw (const struct elliptic_curve *curve, const bigint_element_t *augend0, const bigint_element_t *addend0, bigint_element_t *result0)
 Add points on curve.
static void weierstrass_add_ladder (const bigint_element_t *operand0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp __unused)
 Add points on curve as part of a Montgomery ladder.
static int weierstrass_verify_raw (const struct elliptic_curve *curve, const bigint_element_t *point0)
 Verify freshly initialised point is on curve.
static int weierstrass_init_raw (struct elliptic_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, const void *data)
 Initialise curve point.
static void weierstrass_done_raw (struct elliptic_curve *curve, bigint_element_t *point0, bigint_element_t *temp0, void *out)
 Finalise curve point.
int weierstrass_is_infinity (struct elliptic_curve *curve, const void *point)
 Check if this is the point at infinity.
int weierstrass_multiply (struct elliptic_curve *curve, const void *base, const void *scalar, void *result)
 Multiply curve point by scalar.
int weierstrass_add_once (struct elliptic_curve *curve, const void *addend, const void *augend, void *result)
 Add curve points (as a one-off operation).

Detailed Description

Weierstrass elliptic curves.

The implementation is based upon Algorithm 1 from "Complete addition formulas for prime order elliptic curves" (Joost Renes, Craig Costello, and Lejla Batina), available from

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/06/complete-2.pdf

The steps within the algorithm have been reordered and temporary variables shuffled to reduce stack usage, and calculations are carried out modulo small multiples of the field prime in order to elide reductions after intermediate addition and subtraction operations.

The algorithm is encoded using a bytecode representation, since this substantially reduces the code size compared to direct implementation of the big integer operations.

Definition in file weierstrass.c.

Macro Definition Documentation

◆ WEIERSTRASS_zero

#define WEIERSTRASS_zero   WEIERSTRASS_a

Zero register (for add/subtract operations.

Definition at line 93 of file weierstrass.c.

◆ WEIERSTRASS_REGISTER

#define WEIERSTRASS_REGISTER ( name)
Value:
_C2 ( WEIERSTRASS_, name )
const char * name
Definition ath9k_hw.c:1986
#define _C2(x, y)
Concatenate expanded arguments.
Definition compiler.h:48

Construct big integer register index.

Definition at line 96 of file weierstrass.c.

◆ WEIERSTRASS_OP

#define WEIERSTRASS_OP ( opcode,
dest,
left,
right )
Value:
( ( (opcode) << 12 ) | \
( WEIERSTRASS_REGISTER ( dest ) << 8 ) | \
( WEIERSTRASS_REGISTER ( left ) << 4 ) | \
( WEIERSTRASS_REGISTER ( right ) << 0 ) )
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
uint8_t opcode
Opcode.
Definition ena.h:5
#define WEIERSTRASS_REGISTER(name)
Construct big integer register index.
Definition weierstrass.c:96

Define a bytecode operation.

Parameters
opcodeOperation code
destDestination big integer register name
leftLeft source big integer register name
rightRight source big integer register name

Definition at line 120 of file weierstrass.c.

120#define WEIERSTRASS_OP( opcode, dest, left, right ) \
121 ( ( (opcode) << 12 ) | \
122 ( WEIERSTRASS_REGISTER ( dest ) << 8 ) | \
123 ( WEIERSTRASS_REGISTER ( left ) << 4 ) | \
124 ( WEIERSTRASS_REGISTER ( right ) << 0 ) )

◆ WEIERSTRASS_OPCODE

#define WEIERSTRASS_OPCODE ( op)
Value:
( ( (op) >> 12 ) & 0xf )
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327

Extract bytecode operation code.

Definition at line 127 of file weierstrass.c.

Referenced by weierstrass_exec().

◆ WEIERSTRASS_DEST

#define WEIERSTRASS_DEST ( op)
Value:
( ( (op) >> 8 ) & 0xf )

Extract destination big integer register.

Definition at line 130 of file weierstrass.c.

Referenced by weierstrass_exec().

◆ WEIERSTRASS_LEFT

#define WEIERSTRASS_LEFT ( op)
Value:
( ( (op) >> 4 ) & 0xf )

Extract left source big integer register.

Definition at line 133 of file weierstrass.c.

Referenced by weierstrass_exec().

◆ WEIERSTRASS_RIGHT

#define WEIERSTRASS_RIGHT ( op)
Value:
( ( (op) >> 0 ) & 0xf )

Extract right source big integer register.

Definition at line 136 of file weierstrass.c.

Referenced by weierstrass_exec().

◆ WEIERSTRASS_ADD3

#define WEIERSTRASS_ADD3 ( dest,
augend,
addend )
Value:
#define WEIERSTRASS_OP(opcode, dest, left, right)
Define a bytecode operation.
@ WEIERSTRASS_OP_ADD
Add big integers.

Define a three-argument addition operation.

Definition at line 139 of file weierstrass.c.

139#define WEIERSTRASS_ADD3( dest, augend, addend ) \
140 WEIERSTRASS_OP ( WEIERSTRASS_OP_ADD, dest, augend, addend )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_ADD2

#define WEIERSTRASS_ADD2 ( augend,
addend )
Value:
WEIERSTRASS_ADD3 ( augend, augend, addend )
#define WEIERSTRASS_ADD3(dest, augend, addend)
Define a three-argument addition operation.

Define a two-argument addition operation.

Definition at line 143 of file weierstrass.c.

143#define WEIERSTRASS_ADD2( augend, addend ) \
144 WEIERSTRASS_ADD3 ( augend, augend, addend )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_MOV

#define WEIERSTRASS_MOV ( dest,
source )
Value:
WEIERSTRASS_ADD3( dest, source, zero )

Define a move operation.

Definition at line 147 of file weierstrass.c.

147#define WEIERSTRASS_MOV( dest, source ) \
148 WEIERSTRASS_ADD3( dest, source, zero )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_SUB3

#define WEIERSTRASS_SUB3 ( dest,
minuend,
subtrahend,
multiple )
Value:
WEIERSTRASS_OP ( _C2 ( WEIERSTRASS_OP_SUB_, multiple ), \
dest, minuend, subtrahend )

Define a three-argument subtraction operation.

Definition at line 151 of file weierstrass.c.

151#define WEIERSTRASS_SUB3( dest, minuend, subtrahend, multiple ) \
152 WEIERSTRASS_OP ( _C2 ( WEIERSTRASS_OP_SUB_, multiple ), \
153 dest, minuend, subtrahend )

◆ WEIERSTRASS_SUB2

#define WEIERSTRASS_SUB2 ( minuend,
subtrahend,
multiple )
Value:
WEIERSTRASS_SUB3 ( minuend, minuend, subtrahend, multiple )
#define WEIERSTRASS_SUB3(dest, minuend, subtrahend, multiple)
Define a three-argument subtraction operation.

Define a two-argument subtraction operation.

Definition at line 156 of file weierstrass.c.

156#define WEIERSTRASS_SUB2( minuend, subtrahend, multiple ) \
157 WEIERSTRASS_SUB3 ( minuend, minuend, subtrahend, multiple )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_STOP

#define WEIERSTRASS_STOP   WEIERSTRASS_SUB2 ( zero, zero, 0N )

Define a stop operation.

Definition at line 160 of file weierstrass.c.

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_MUL3

#define WEIERSTRASS_MUL3 ( dest,
multiplicand,
multiplier )
Value:
static const uint32_t multiplier
Port multiplier number.
Definition bigint.h:195
@ WEIERSTRASS_OP_MUL
Multiply big integers (and perform Montgomery reduction).

Define a three-argument multiplication operation.

Definition at line 163 of file weierstrass.c.

163#define WEIERSTRASS_MUL3( dest, multiplicand, multiplier ) \
164 WEIERSTRASS_OP ( WEIERSTRASS_OP_MUL, dest, multiplicand, multiplier )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ WEIERSTRASS_MUL2

#define WEIERSTRASS_MUL2 ( multiplicand,
multiplier )
Value:
WEIERSTRASS_MUL3 ( multiplicand, multiplicand, multiplier )
#define WEIERSTRASS_MUL3(dest, multiplicand, multiplier)
Define a three-argument multiplication operation.

Define a two-argument multiplication operation.

Definition at line 167 of file weierstrass.c.

167#define WEIERSTRASS_MUL2( multiplicand, multiplier ) \
168 WEIERSTRASS_MUL3 ( multiplicand, multiplicand, multiplier )

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ weierstrass_add

#define weierstrass_add ( curve,
augend,
addend,
result )
Value:
do { \
weierstrass_add_raw ( (curve), (augend)->all.element, \
(addend)->all.element, \
(result)->all.element ); \
} while ( 0 )
uint16_t result
Definition hyperv.h:33

Add points on curve.

Parameters
curveElliptic curve
augendPoint (x1,y1,z1) to be added
addendPoint (x2,y2,z2) to be added
result0Point (x3,y3,z3) to hold result

Definition at line 635 of file weierstrass.c.

635#define weierstrass_add( curve, augend, addend, result ) do { \
636 weierstrass_add_raw ( (curve), (augend)->all.element, \
637 (addend)->all.element, \
638 (result)->all.element ); \
639 } while ( 0 )

Referenced by weierstrass_add_ladder(), and weierstrass_add_once().

◆ weierstrass_verify

#define weierstrass_verify ( curve,
point )
Value:
( { \
weierstrass_verify_raw ( (curve), (point)->all.element ); \
} )

Verify freshly initialised point is on curve.

Parameters
curveElliptic curve
pointPoint (x,y,z) to be verified
Return values
rcReturn status code

Definition at line 774 of file weierstrass.c.

774#define weierstrass_verify( curve, point ) ( { \
775 weierstrass_verify_raw ( (curve), (point)->all.element ); \
776 } )

Referenced by weierstrass_init_raw().

◆ weierstrass_init

#define weierstrass_init ( curve,
point,
temp,
data )
Value:
( { \
weierstrass_init_raw ( (curve), (point)->all.element, \
(temp)->all.element, (data) ); \
} )
uint8_t data[48]
Additional event data.
Definition ena.h:11

Initialise curve point.

Parameters
curveElliptic curve
pointPoint (x,y,z) to be filled in
tempTemporary point buffer
dataRaw curve point
Return values
rcReturn status code

Definition at line 853 of file weierstrass.c.

853#define weierstrass_init( curve, point, temp, data ) ( { \
854 weierstrass_init_raw ( (curve), (point)->all.element, \
855 (temp)->all.element, (data) ); \
856 } )

Referenced by weierstrass_add_once(), and weierstrass_multiply().

◆ weierstrass_done

#define weierstrass_done ( curve,
point,
temp,
out )
Value:
( { \
weierstrass_done_raw ( (curve), (point)->all.element, \
(temp)->all.element, (out) ); \
} )
__be32 out[4]
Definition CIB_PRM.h:8

Finalise curve point.

Parameters
curveElliptic curve
pointPoint (x,y,z)
tempTemporary point buffer
outOutput buffer
Return values
rcReturn status code

Definition at line 917 of file weierstrass.c.

917#define weierstrass_done( curve, point, temp, out ) ( { \
918 weierstrass_done_raw ( (curve), (point)->all.element, \
919 (temp)->all.element, (out) ); \
920 } )

Referenced by weierstrass_add_once(), and weierstrass_multiply().

Enumeration Type Documentation

◆ weierstrass_register

Big integer register names.

Enumerator
WEIERSTRASS_a 
WEIERSTRASS_3b 
WEIERSTRASS_x1 
WEIERSTRASS_y1 
WEIERSTRASS_z1 
WEIERSTRASS_x2 
WEIERSTRASS_y2 
WEIERSTRASS_z2 
WEIERSTRASS_Wt 
WEIERSTRASS_Wxy 
WEIERSTRASS_Wyz 
WEIERSTRASS_Wzx 
WEIERSTRASS_Wp 
WEIERSTRASS_x3 
WEIERSTRASS_y3 
WEIERSTRASS_z3 
WEIERSTRASS_NUM_REGISTERS 

Definition at line 53 of file weierstrass.c.

53 {
54
55 /*
56 * Read-only registers
57 */
58
59 /* Curve constant "a" (for multiply), zero (for add/subtract) */
60 WEIERSTRASS_a = 0,
61 /* Curve constant "3b" */
63 /* Augend (x,y,z) co-ordinates */
67 /* Addend (x,y,z) co-ordinates */
71
72 /*
73 * Read-write registers
74 */
75
76 /* Temporary working registers */
81 /* Low half of multiplication product */
83 /* Result (x,y,z) co-ordinates */
87
88 /* Number of registers */
90};
@ WEIERSTRASS_Wt
Definition weierstrass.c:77
@ WEIERSTRASS_x3
Definition weierstrass.c:84
@ WEIERSTRASS_NUM_REGISTERS
Definition weierstrass.c:89
@ WEIERSTRASS_a
Definition weierstrass.c:60
@ WEIERSTRASS_y2
Definition weierstrass.c:69
@ WEIERSTRASS_3b
Definition weierstrass.c:62
@ WEIERSTRASS_Wp
Definition weierstrass.c:82
@ WEIERSTRASS_Wxy
Definition weierstrass.c:78
@ WEIERSTRASS_y3
Definition weierstrass.c:85
@ WEIERSTRASS_Wyz
Definition weierstrass.c:79
@ WEIERSTRASS_y1
Definition weierstrass.c:65
@ WEIERSTRASS_x2
Definition weierstrass.c:68
@ WEIERSTRASS_z3
Definition weierstrass.c:86
@ WEIERSTRASS_x1
Definition weierstrass.c:64
@ WEIERSTRASS_z2
Definition weierstrass.c:70
@ WEIERSTRASS_Wzx
Definition weierstrass.c:80
@ WEIERSTRASS_z1
Definition weierstrass.c:66

◆ weierstrass_opcode

Bytecode operation codes.

Enumerator
WEIERSTRASS_OP_SUB_0N 

Subtract big integers (and add nothing).

WEIERSTRASS_OP_SUB_2N 

Subtract big integers (and add 2N).

WEIERSTRASS_OP_SUB_4N 

Subtract big integers (and add 4N).

WEIERSTRASS_OP_ADD 

Add big integers.

WEIERSTRASS_OP_MUL 

Multiply big integers (and perform Montgomery reduction).

Definition at line 99 of file weierstrass.c.

99 {
100 /** Subtract big integers (and add nothing)*/
102 /** Subtract big integers (and add 2N) */
104 /** Subtract big integers (and add 4N) */
106 /** Add big integers */
108 /** Multiply big integers (and perform Montgomery reduction) */
110};
@ WEIERSTRASS_OP_SUB_2N
Subtract big integers (and add 2N).
@ WEIERSTRASS_OP_SUB_4N
Subtract big integers (and add 4N).
@ WEIERSTRASS_OP_SUB_0N
Subtract big integers (and add nothing).
@ WEIERSTRASS_2N
Definition weierstrass.h:80
@ WEIERSTRASS_4N
Definition weierstrass.h:81

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ weierstrass_init_curve()

void weierstrass_init_curve ( struct elliptic_curve * curve)
static

Initialise curve.

Parameters
curveElliptic curve

Definition at line 175 of file weierstrass.c.

175 {
176 struct weierstrass_curve *weierstrass = curve->priv;
177 unsigned int size = weierstrass->size;
178 bigint_t ( size ) __attribute__ (( may_alias )) *prime =
179 ( ( void * ) weierstrass->prime[0] );
180 bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
181 ( ( void * ) weierstrass->fermat );
182 bigint_t ( size ) __attribute__ (( may_alias )) *square =
183 ( ( void * ) weierstrass->square );
184 bigint_t ( size ) __attribute__ (( may_alias )) *one =
185 ( ( void * ) weierstrass->one );
186 bigint_t ( size ) __attribute__ (( may_alias )) *a =
187 ( ( void * ) weierstrass->a );
188 bigint_t ( size ) __attribute__ (( may_alias )) *b3 =
189 ( ( void * ) weierstrass->b3 );
190 bigint_t ( size ) __attribute__ (( may_alias )) *mont =
191 ( ( void * ) weierstrass->mont[0] );
192 bigint_t ( size ) __attribute__ (( may_alias )) *temp =
193 ( ( void * ) weierstrass->prime[1] );
194 bigint_t ( size * 2 ) __attribute__ (( may_alias )) *product =
195 ( ( void * ) temp );
196 bigint_t ( size ) __attribute__ (( may_alias )) *two =
197 ( ( void * ) temp );
198 static const uint8_t one_raw[] = { 1 };
199 static const uint8_t two_raw[] = { 2 };
200 size_t len = weierstrass->len;
201 unsigned int i;
202
203 /* Initialise field prime */
204 bigint_init ( prime, weierstrass->prime_raw, len );
205 DBGC ( curve, "WEIERSTRASS %s N = %s\n",
206 curve->name, bigint_ntoa ( prime ) );
207
208 /* Calculate Montgomery constant R^2 mod N */
210 DBGC ( curve, "WEIERSTRASS %s R^2 = %s mod N\n",
211 curve->name, bigint_ntoa ( square ) );
212
213 /* Calculate constant "3b" */
214 bigint_init ( b3, weierstrass->b_raw, len );
215 DBGC ( curve, "WEIERSTRASS %s b = %s\n",
216 curve->name, bigint_ntoa ( b3 ) );
217 bigint_copy ( b3, a );
218 bigint_add ( b3, b3 );
219 bigint_add ( a, b3 );
220
221 /* Initialise "a" */
222 bigint_init ( a, weierstrass->a_raw, len );
223 DBGC ( curve, "WEIERSTRASS %s a = %s\n",
224 curve->name, bigint_ntoa ( a ) );
225
226 /* Initialise "1" */
227 bigint_init ( one, one_raw, sizeof ( one_raw ) );
228
229 /* Convert relevant constants to Montgomery form
230 *
231 * We rely on the fact that the prime multiples have not yet
232 * been calculated, and so can be used as a temporary buffer.
233 */
234 for ( i = 0 ; i < WEIERSTRASS_NUM_MONT ; i++ ) {
235 static const char *names[] = { " ", " a", "3b" };
238 DBGC ( curve, "WEIERSTRASS %s %sR = %s mod N\n",
239 curve->name, names[i], bigint_ntoa ( &mont[i] ) );
240 }
241
242 /* Calculate constant "N-2"
243 *
244 * We rely on the fact that the prime multiples have not yet
245 * been calculated, and so can be used as a temporary buffer.
246 */
248 bigint_init ( two, two_raw, sizeof ( two_raw ) );
249 bigint_subtract ( two, fermat );
250 DBGC ( curve, "WEIERSTRASS %s N-2 = %s\n",
251 curve->name, bigint_ntoa ( fermat ) );
252
253 /* Calculate multiples of field prime */
254 for ( i = 1 ; i < WEIERSTRASS_NUM_MULTIPLES ; i++ ) {
255 bigint_copy ( &prime[ i - 1 ], &prime[i] );
256 bigint_add ( &prime[i], &prime[i] );
257 DBGC ( curve, "WEIERSTRASS %s %dN = %s\n",
258 curve->name, ( 1 << i ), bigint_ntoa ( &prime[i] ) );
259 }
260}
unsigned char uint8_t
Definition stdint.h:10
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:530
uint16_t size
Buffer size.
Definition dwmac.h:3
#define __attribute__(x)
Definition compiler.h:10
#define bigint_reduce(modulus, result)
Reduce big integer R^2 modulo N.
Definition bigint.h:275
#define bigint_subtract(subtrahend, value)
Subtract big integers.
Definition bigint.h:100
#define bigint_montgomery(modulus, value, result)
Perform classic Montgomery reduction (REDC) of a big integer.
Definition bigint.h:315
#define bigint_copy(source, dest)
Copy big integer.
Definition bigint.h:236
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:21
#define bigint_multiply(multiplicand, multiplier, result)
Multiply big integers.
Definition bigint.h:261
#define bigint_add(addend, value)
Add big integers.
Definition bigint.h:88
#define bigint_ntoa(value)
Transcribe big integer (for debugging).
Definition bigint.h:51
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:63
uint8_t product
Product string.
Definition smbios.h:5
const char * name
Curve name.
Definition crypto.h:248
void * priv
Algorithm private data.
Definition crypto.h:290
A Weierstrass elliptic curve.
Definition weierstrass.h:99
bigint_element_t * mont[WEIERSTRASS_NUM_MONT]
bigint_element_t * prime[WEIERSTRASS_NUM_CACHED]
Cached field prime "N" (and multiples thereof).
size_t len
Length of raw scalar values.
const uint8_t * a_raw
Constant "a".
bigint_element_t * one
Cached constant "1", in Montgomery form.
bigint_element_t * square
Cached Montgomery constant (R^2 mod N).
bigint_element_t * b3
Cached constant "3b", in Montgomery form.
const unsigned int size
Number of elements in scalar values.
const uint8_t * b_raw
Constant "b".
bigint_element_t * fermat
Cached constant "N-2" (for Fermat's little theorem).
bigint_element_t * a
Cached constant "a", in Montgomery form.
const uint8_t * prime_raw
Field prime.
#define WEIERSTRASS_NUM_MONT
Number of cached in Montgomery form for each Weierstrass curve.
Definition weierstrass.h:86
@ WEIERSTRASS_NUM_MULTIPLES
Definition weierstrass.h:82

References __attribute__, weierstrass_curve::a, weierstrass_curve::a_raw, weierstrass_curve::b3, weierstrass_curve::b_raw, bigint_add, bigint_copy, bigint_init, bigint_montgomery, bigint_multiply, bigint_ntoa, bigint_reduce, bigint_subtract, bigint_t, DBGC, weierstrass_curve::fermat, len, weierstrass_curve::len, weierstrass_curve::mont, elliptic_curve::name, weierstrass_curve::one, weierstrass_curve::prime, weierstrass_curve::prime_raw, elliptic_curve::priv, product, size, weierstrass_curve::size, weierstrass_curve::square, WEIERSTRASS_NUM_MONT, and WEIERSTRASS_NUM_MULTIPLES.

Referenced by weierstrass_init_raw().

◆ weierstrass_exec()

void weierstrass_exec ( const struct elliptic_curve * curve,
void ** regs,
unsigned int size,
unsigned int op )
static

Execute bytecode instruction.

Parameters
curveElliptic curve
regsRegisters
sizeBig integer size
opOperation

Definition at line 270 of file weierstrass.c.

272 {
273 const struct weierstrass_curve *weierstrass = curve->priv;
274 const bigint_t ( size ) __attribute__ (( may_alias ))
275 *prime = ( ( const void * ) weierstrass->prime[0] );
276 bigint_t ( size * 2 ) __attribute__ (( may_alias ))
278 bigint_t ( size ) __attribute__ (( may_alias )) *dest;
279 const bigint_t ( size ) __attribute__ (( may_alias )) *left;
280 const bigint_t ( size ) __attribute__ (( may_alias )) *right;
281 const bigint_t ( size ) __attribute__ (( may_alias )) *addend;
282 const bigint_t ( size ) __attribute__ (( may_alias )) *subtrahend;
283 unsigned int op_code;
284 unsigned int op_dest;
285 unsigned int op_left;
286 unsigned int op_right;
287
288 /* Decode instruction */
289 op_code = WEIERSTRASS_OPCODE ( op );
290 op_dest = WEIERSTRASS_DEST ( op );
291 op_left = WEIERSTRASS_LEFT ( op );
292 op_right = WEIERSTRASS_RIGHT ( op );
293 dest = regs[op_dest];
294 left = regs[op_left];
295 right = regs[op_right];
296
297 /* Check destination is a writable register */
298 assert ( op_dest >= WEIERSTRASS_Wt );
299
300 /* Handle multiplications */
301 if ( op_code == WEIERSTRASS_OP_MUL ) {
302 assert ( op_left != WEIERSTRASS_Wp );
303 assert ( op_right != WEIERSTRASS_Wp );
304 bigint_multiply ( left, right, product );
306 DBGCP ( curve, "WEIERSTRASS %s R%d := R%d x R%d = %s\n",
307 curve->name, op_dest, op_left, op_right,
308 bigint_ntoa ( dest ) );
309 return;
310 }
311
312 /* Copy left source, if required */
313 if ( op_dest != op_left )
314 bigint_copy ( left, dest );
315
316 /* Do nothing more if addend/subtrahend is zero */
317 if ( ! op_right ) {
318 DBGCP ( curve, "WEIERSTRASS %s R%d := R%d = %s\n",
319 curve->name, op_dest, op_left, bigint_ntoa ( dest ) );
320 return;
321 }
322
323 /* Determine addend and subtrahend */
324 addend = NULL;
325 subtrahend = NULL;
326 if ( op_code == WEIERSTRASS_OP_ADD ) {
327 DBGCP ( curve, "WEIERSTRASS %s R%d := R%d + R%d = ",
328 curve->name, op_dest, op_left, op_right );
329 addend = ( ( const void * ) right );
330 } else {
331 subtrahend = ( ( const void * ) right );
332 if ( op_code > WEIERSTRASS_OP_SUB_0N ) {
333 DBGCP ( curve, "WEIERSTRASS %s R%d := R%d - R%d + "
334 "%dN = ", curve->name, op_dest, op_left,
335 op_right, ( 1 << op_code ) );
336 addend = ( ( const void * )
337 weierstrass->prime[op_code] );
338 } else {
339 DBGCP ( curve, "WEIERSTRASS %s R%d := R%d - R%d = ",
340 curve->name, op_dest, op_left, op_right );
341 }
342 }
343
344 /* Perform addition and subtraction */
345 if ( addend )
346 bigint_add ( addend, dest );
347 if ( subtrahend )
348 bigint_subtract ( subtrahend, dest );
349 DBGCP ( curve, "%s\n", bigint_ntoa ( dest ) );
350}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define DBGCP(...)
Definition compiler.h:564
#define bigint_montgomery_relaxed(modulus, value, result)
Perform relaxed Montgomery reduction (REDC) of a big integer.
Definition bigint.h:301
struct i386_regs regs
Definition registers.h:1
#define WEIERSTRASS_DEST(op)
Extract destination big integer register.
#define WEIERSTRASS_RIGHT(op)
Extract right source big integer register.
#define WEIERSTRASS_LEFT(op)
Extract left source big integer register.
#define WEIERSTRASS_OPCODE(op)
Extract bytecode operation code.

References __attribute__, assert, bigint_add, bigint_copy, bigint_montgomery_relaxed, bigint_multiply, bigint_ntoa, bigint_subtract, bigint_t, DBGCP, dest, elliptic_curve::name, NULL, op, weierstrass_curve::prime, elliptic_curve::priv, product, regs, size, WEIERSTRASS_DEST, WEIERSTRASS_LEFT, WEIERSTRASS_OP_ADD, WEIERSTRASS_OP_MUL, WEIERSTRASS_OP_SUB_0N, WEIERSTRASS_OPCODE, WEIERSTRASS_RIGHT, WEIERSTRASS_Wp, and WEIERSTRASS_Wt.

Referenced by weierstrass_add_raw(), and weierstrass_verify_raw().

◆ weierstrass_add_raw()

void weierstrass_add_raw ( const struct elliptic_curve * curve,
const bigint_element_t * augend0,
const bigint_element_t * addend0,
bigint_element_t * result0 )
static

Add points on curve.

Parameters
curveElliptic curve
augend0Element 0 of point (x1,y1,z1) to be added
addend0Element 0 of point (x2,y2,z2) to be added
result0Element 0 of point (x3,y3,z3) to hold result

Points are represented in projective coordinates, with all values in Montgomery form and in the range [0,4N) where N is the field prime.

The augend may have the same value as the addend (i.e. this routine may be used to perform point doubling as well as point addition), and either or both may be the point at infinity.

The result may overlap either input, since the inputs are fully consumed before the result is written.

Definition at line 371 of file weierstrass.c.

374 {
375 const struct weierstrass_curve *weierstrass = curve->priv;
376 unsigned int size = weierstrass->size;
377 const bigint_t ( size ) __attribute__ (( may_alias ))
378 *prime = ( ( const void * ) weierstrass->prime[0] );
379 const bigint_t ( size ) __attribute__ (( may_alias ))
380 *a = ( ( const void * ) weierstrass->a );
381 const bigint_t ( size ) __attribute__ (( may_alias ))
382 *b3 = ( ( const void * ) weierstrass->b3 );
383 const weierstrass_t ( size ) __attribute__ (( may_alias ))
384 *augend = ( ( const void * ) augend0 );
385 const weierstrass_t ( size ) __attribute__ (( may_alias ))
386 *addend = ( ( const void * ) addend0 );
387 weierstrass_t ( size ) __attribute__ (( may_alias ))
388 *result = ( ( void * ) result0 );
389 struct {
390 bigint_t ( size ) Wt;
391 bigint_t ( size ) Wxy;
392 bigint_t ( size ) Wyz;
393 bigint_t ( size ) Wzx;
394 bigint_t ( size * 2 ) Wp;
395 } temp;
397 unsigned int schedule;
398 const uint16_t *op;
399 unsigned int i;
400
401 /* On entry, we assume that x1, x2, y1, y2, z1, z2 are all in
402 * the range [0,4N). Additions will extend the range.
403 * Subtractions will extend the range (and require an addition
404 * of a suitable multiple of the modulus to ensure that the
405 * result is a positive value). Relaxed Montgomery
406 * multiplications will reduce the range to [0,2N). The
407 * outputs x3, y3, z3 will be in the range [0,4N) and
408 * therefore usable as subsequent inputs.
409 */
410 static const uint16_t ops[] = {
411 /* [Wxy] Qxy = (x1+y1)*(x2+y2) (mod 2N) */
412 WEIERSTRASS_ADD3 ( Wt, x1, y1 ),
413 WEIERSTRASS_ADD3 ( Wxy, x2, y2 ),
414 WEIERSTRASS_MUL2 ( Wxy, Wt ),
415 /* [Wyz] Qyz = (y1+z1)*(y2+z2) (mod 2N) */
416 WEIERSTRASS_ADD3 ( Wt, y1, z1 ),
417 WEIERSTRASS_ADD3 ( Wyz, y2, z2 ),
418 WEIERSTRASS_MUL2 ( Wyz, Wt ),
419 /* [Wzx] Qzx = (z1+x1)*(z2+x2) (mod 2N) */
420 WEIERSTRASS_ADD3 ( Wt, z1, x1 ),
421 WEIERSTRASS_ADD3 ( Wzx, z2, x2 ),
422 WEIERSTRASS_MUL2 ( Wzx, Wt ),
423 /* [x3] Px = x1*x2 (mod 2N) */
424 WEIERSTRASS_MUL3 ( x3, x1, x2 ),
425 /* [y3] Py = y1*y2 (mod 2N) */
426 WEIERSTRASS_MUL3 ( y3, y1, y2 ),
427 /* [z3] Pz = z1*z2 (mod 2N) */
428 WEIERSTRASS_MUL3 ( z3, z1, z2 ),
429 /* [Wxy] Rxy = Qxy - Px - Py (mod 6N)
430 * = (x1+y1)*(x2+y2) - x1*x2 - y1*y2 (mod 6N)
431 * = x1*y2 + x2*y1 (mod 6N)
432 */
433 WEIERSTRASS_SUB2 ( Wxy, x3, 0N ),
434 WEIERSTRASS_SUB2 ( Wxy, y3, 4N ),
435 /* [Wyz] Ryz = Qyz - Py - Pz (mod 6N)
436 * = (y1+z1)*(y2+z2) - y1*y2 - z1*z2 (mod 6N)
437 * = y1*z2 + y2*z1 (mod 6N)
438 */
439 WEIERSTRASS_SUB2 ( Wyz, y3, 0N ),
440 WEIERSTRASS_SUB2 ( Wyz, z3, 4N ),
441 /* [Wzx] Rzx = Qzx - Pz - Px (mod 6N)
442 * = (z1+x1)*(z2+x2) - z1*z2 - x1*x2 (mod 6N)
443 * = x1*z2 + x2*z1 (mod 6N)
444 */
445 WEIERSTRASS_SUB2 ( Wzx, z3, 0N ),
446 WEIERSTRASS_SUB2 ( Wzx, x3, 4N ),
447 /* [Wt] aRzx = a * Rzx (mod 2N)
448 * = a * (x1*z2 + x2*z1) (mod 2N)
449 */
450 WEIERSTRASS_MUL3 ( Wt, a, Wzx ),
451 /* [Wp] 3bPz = 3b * Pz (mod 2N)
452 * = 3b*z1*z2 (mod 2N)
453 */
454 WEIERSTRASS_MUL3 ( Wp, 3b, z3 ),
455 /* [Wp] Sy = aRzx + 3bPz (mod 4N)
456 * = a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 4N)
457 */
458 WEIERSTRASS_ADD2 ( Wp, Wt ),
459 /* [Wt] Syz = Py + Sy (mod 6N)
460 * = y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 6N)
461 */
462 WEIERSTRASS_ADD3 ( Wt, y3, Wp ),
463 /* [y3] Sxy = Py - Sy (mod 6N)
464 * = y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2 (mod 6N)
465 */
466 WEIERSTRASS_SUB2 ( y3, Wp, 4N ),
467 /* [z3] aPz = a * Pz (mod 2N)
468 * = a * z1*z2 (mod 2N)
469 */
470 WEIERSTRASS_MUL2 ( z3, a ),
471 /* [Wzx] 3bRzx = 3b * Rzx (mod 2N)
472 * = 3b * (x1*z2 + x2*z1) (mod 2N)
473 */
474 WEIERSTRASS_MUL2 ( Wzx, 3b ),
475 /* [x3] aPzx' = Px - aPz (mod 4N)
476 * = x1*x2 - a*z1*z2 (mod 4N)
477 */
478 WEIERSTRASS_SUB2 ( x3, z3, 2N ),
479 /* [Wp] Szx = a * aPzx' (mod 2N)
480 * = a * (x1*x2 - a*z1*z2) (mod 2N)
481 * = a*x1*x2 - (a^2)*z1*z2 (mod 2N)
482 */
483 WEIERSTRASS_MUL3 ( Wp, a, x3 ),
484 /* [x3] Px = aPzx' + aPz (mod 6N)
485 * = x1*x2 - a*z1*z2 + a*z1*z2 (mod 6N)
486 * = x1*x2 (mod 6N)
487 */
488 WEIERSTRASS_ADD2 ( x3, z3 ),
489 /* [Wzx] Tzx = 3bRzx + Szx (mod 4N)
490 * = a*x1*x2 + 3b*(x1*z2 + x2*z1) -
491 * (a^2)*z1*z2 (mod 4N)
492 */
493 WEIERSTRASS_ADD2 ( Wzx, Wp ),
494 /* [z3] aPzx = Px + aPz (mod 8N)
495 * = x1*x2 + a*z1*z2 (mod 8N)
496 */
497 WEIERSTRASS_ADD2 ( z3, x3 ),
498 /* [x3] 2Px = Px + Px (mod 12N)
499 * = 2*x1*x2 (mod 12N)
500 */
501 WEIERSTRASS_ADD2 ( x3, x3 ),
502 /* [x3] Tyz = 2Px + aPzx (mod 20N)
503 * = 2*x1*x2 + x1*x2 + a*z1*z2 (mod 20N)
504 * = 3*x1*x2 + a*z1*z2 (mod 20N)
505 */
506 WEIERSTRASS_ADD2 ( x3, z3 ),
507 /* [z3] Syz = Syz (mod 6N)
508 * = y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2 (mod 6N)
509 */
510 WEIERSTRASS_MOV ( z3, Wt ),
511 /* [Wt] Tyz = Tyz (mod 20N)
512 * = 3*x1*x2 + a*z1*z2 (mod 20N)
513 */
514 WEIERSTRASS_MOV ( Wt, x3 ),
515 /* [x3] Ux = Rxy * Sxy (mod 2N)
516 * = (x1*y2 + x2*y1) *
517 * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2) (mod 2N)
518 */
519 WEIERSTRASS_MUL3 ( x3, Wxy, y3 ),
520 /* [y3] Uy = Syz * Sxy (mod 2N)
521 * = (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) *
522 * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2) (mod 2N)
523 */
524 WEIERSTRASS_MUL2 ( y3, z3 ),
525 /* [z3] Uz = Ryz * Syz (mod 2N)
526 * = (y1*z2 + y2*z1) *
527 * (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) (mod 2N)
528 */
529 WEIERSTRASS_MUL2 ( z3, Wyz ),
530 /* [Wp] Vx = Ryz * Tzx (mod 2N)
531 * = (y1*z2 + y2*z1) *
532 * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)
533 * (mod 2N)
534 */
535 WEIERSTRASS_MUL3 ( Wp, Wyz, Wzx ),
536 /* [x3] x3 = Ux - Vx (mod 4N)
537 * = ((x1*y2 + x2*y1) *
538 * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2)) -
539 * ((y1*z2 + y2*z1) *
540 * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2))
541 * (mod 4N)
542 */
543 WEIERSTRASS_SUB2 ( x3, Wp, 2N ),
544 /* [Wp] Vy = Tyz * Tzx (mod 2N)
545 * = (3*x1*x2 + a*z1*z2) *
546 * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)
547 * (mod 2N)
548 */
549 WEIERSTRASS_MUL3 ( Wp, Wt, Wzx ),
550 /* [y3] y3 = Vy + Uy (mod 4N)
551 * = ((3*x1*x2 + a*z1*z2) *
552 * (a*x1*x2 + 3b*(x1*z2 + x2*z1) - (a^2)*z1*z2)) +
553 * ((y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2) *
554 * (y1*y2 - a*(x1*z2 + x2*z1) - 3b*z1*z2))
555 * (mod 4N)
556 */
557 WEIERSTRASS_ADD2 ( y3, Wp ),
558 /* [Wp] Vz = Rxy * Tyz (mod 2N)
559 * = (x1*y2 + x2*y1) * (3*x1*x2 + a*z1*z2) (mod 2N)
560 */
561 WEIERSTRASS_MUL3 ( Wp, Wxy, Wt ),
562 /* [z3] z3 = Uz + Vz (mod 4N)
563 * = ((y1*z2 + y2*z1) *
564 * (y1*y2 + a*(x1*z2 + x2*z1) + 3b*z1*z2)) +
565 * ((x1*y2 + x2*y1) * (3*x1*x2 + a*z1*z2))
566 * (mod 4N)
567 */
568 WEIERSTRASS_ADD2 ( z3, Wp ),
569 /* Stop */
571 };
572
573 /* Initialise register list */
574 regs[WEIERSTRASS_a] = ( ( void * ) a );
575 regs[WEIERSTRASS_3b] = ( ( void * ) b3 );
576 regs[WEIERSTRASS_x1] = ( ( void * ) &augend->x );
577 regs[WEIERSTRASS_x2] = ( ( void * ) &addend->x );
578 regs[WEIERSTRASS_x3] = ( ( void * ) &result->x );
579 regs[WEIERSTRASS_Wt] = &temp;
580 schedule = ( ( ( 1 << WEIERSTRASS_NUM_REGISTERS ) - 1 )
581 - ( 1 << WEIERSTRASS_a )
582 - ( 1 << WEIERSTRASS_3b )
583 - ( 1 << WEIERSTRASS_x1 )
584 - ( 1 << WEIERSTRASS_x2 )
585 - ( 1 << WEIERSTRASS_x3 )
586 - ( 1 << WEIERSTRASS_Wt ) );
587 for ( i = 0 ; schedule ; i++, schedule >>= 1 ) {
588 if ( schedule & 1 )
589 regs[i] = ( regs[ i - 1 ] + sizeof ( *prime ) );
590 }
591 DBGC2 ( curve, "WEIERSTRASS %s augend (%s,",
592 curve->name, bigint_ntoa ( &augend->x ) );
593 DBGC2 ( curve, "%s,", bigint_ntoa ( &augend->y ) );
594 DBGC2 ( curve, "%s)\n", bigint_ntoa ( &augend->z ) );
595 DBGC2 ( curve, "WEIERSTRASS %s addend (%s,",
596 curve->name, bigint_ntoa ( &addend->x ) );
597 DBGC2 ( curve, "%s,", bigint_ntoa ( &addend->y ) );
598 DBGC2 ( curve, "%s)\n", bigint_ntoa ( &addend->z ) );
599
600 /* Sanity checks */
601 assert ( regs[WEIERSTRASS_a] == a );
602 assert ( regs[WEIERSTRASS_3b] == b3 );
603 assert ( regs[WEIERSTRASS_x1] == &augend->x );
604 assert ( regs[WEIERSTRASS_y1] == &augend->y );
605 assert ( regs[WEIERSTRASS_z1] == &augend->z );
606 assert ( regs[WEIERSTRASS_x2] == &addend->x );
607 assert ( regs[WEIERSTRASS_y2] == &addend->y );
608 assert ( regs[WEIERSTRASS_z2] == &addend->z );
609 assert ( regs[WEIERSTRASS_x3] == &result->x );
610 assert ( regs[WEIERSTRASS_y3] == &result->y );
611 assert ( regs[WEIERSTRASS_z3] == &result->z );
612 assert ( regs[WEIERSTRASS_Wt] == &temp.Wt );
613 assert ( regs[WEIERSTRASS_Wxy] == &temp.Wxy );
614 assert ( regs[WEIERSTRASS_Wyz] == &temp.Wyz );
615 assert ( regs[WEIERSTRASS_Wzx] == &temp.Wzx );
616 assert ( regs[WEIERSTRASS_Wp] == &temp.Wp );
617
618 /* Execute bytecode instruction sequence */
619 for ( op = ops ; *op != WEIERSTRASS_STOP ; op++ )
620 weierstrass_exec ( curve, regs, size, *op );
621 DBGC2 ( curve, "WEIERSTRASS %s result (%s,",
622 curve->name, bigint_ntoa ( &result->x ) );
623 DBGC2 ( curve, "%s,", bigint_ntoa ( &result->y ) );
624 DBGC2 ( curve, "%s)\n", bigint_ntoa ( &result->z ) );
625}
unsigned short uint16_t
Definition stdint.h:11
#define DBGC2(...)
Definition compiler.h:547
#define WEIERSTRASS_STOP
Define a stop operation.
#define WEIERSTRASS_MUL2(multiplicand, multiplier)
Define a two-argument multiplication operation.
static void weierstrass_exec(const struct elliptic_curve *curve, void **regs, unsigned int size, unsigned int op)
Execute bytecode instruction.
#define WEIERSTRASS_MOV(dest, source)
Define a move operation.
#define WEIERSTRASS_ADD2(augend, addend)
Define a two-argument addition operation.
#define WEIERSTRASS_SUB2(minuend, subtrahend, multiple)
Define a two-argument subtraction operation.
#define weierstrass_t(size)
Define a Weierstrass projective co-ordinate type.
Definition weierstrass.h:65

References __attribute__, weierstrass_curve::a, assert, weierstrass_curve::b3, bigint_ntoa, bigint_t, DBGC2, elliptic_curve::name, op, weierstrass_curve::prime, elliptic_curve::priv, regs, result, size, weierstrass_curve::size, WEIERSTRASS_3b, WEIERSTRASS_a, WEIERSTRASS_ADD2, WEIERSTRASS_ADD3, weierstrass_exec(), WEIERSTRASS_MOV, WEIERSTRASS_MUL2, WEIERSTRASS_MUL3, WEIERSTRASS_NUM_REGISTERS, WEIERSTRASS_STOP, WEIERSTRASS_SUB2, weierstrass_t, WEIERSTRASS_Wp, WEIERSTRASS_Wt, WEIERSTRASS_Wxy, WEIERSTRASS_Wyz, WEIERSTRASS_Wzx, WEIERSTRASS_x1, WEIERSTRASS_x2, WEIERSTRASS_x3, WEIERSTRASS_y1, WEIERSTRASS_y2, WEIERSTRASS_y3, WEIERSTRASS_z1, WEIERSTRASS_z2, and WEIERSTRASS_z3.

◆ weierstrass_add_ladder()

void weierstrass_add_ladder ( const bigint_element_t * operand0,
bigint_element_t * result0,
unsigned int size,
const void * ctx,
void *tmp __unused )
static

Add points on curve as part of a Montgomery ladder.

Parameters
operandElement 0 of first input operand (may overlap result)
resultElement 0 of second input operand and result
sizeNumber of elements in operands and result
ctxOperation context
tmpTemporary working space (not used)

Definition at line 650 of file weierstrass.c.

653 {
654 const struct elliptic_curve *curve = ctx;
655 const struct weierstrass_curve *weierstrass = curve->priv;
656 const weierstrass_t ( weierstrass->size ) __attribute__ (( may_alias ))
657 *operand = ( ( const void * ) operand0 );
658 weierstrass_t ( weierstrass->size ) __attribute__ (( may_alias ))
659 *result = ( ( void * ) result0 );
660
661 /* Add curve points */
662 assert ( size == bigint_size ( &operand->all ) );
663 assert ( size == bigint_size ( &result->all ) );
664 weierstrass_add ( curve, operand, result, result );
665}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
#define bigint_size(bigint)
Determine number of elements in big-integer type.
Definition bigint.h:42
An elliptic curve.
Definition crypto.h:246
#define weierstrass_add(curve, augend, addend, result)
Add points on curve.

References __attribute__, __unused, assert, bigint_size, ctx, elliptic_curve::priv, result, size, weierstrass_curve::size, tmp, weierstrass_add, and weierstrass_t.

Referenced by weierstrass_multiply().

◆ weierstrass_verify_raw()

int weierstrass_verify_raw ( const struct elliptic_curve * curve,
const bigint_element_t * point0 )
static

Verify freshly initialised point is on curve.

Parameters
curveElliptic curve
point0Element 0 of point (x,y,z) to be verified
Return values
rcReturn status code

As with point addition, points are represented in projective coordinates, with all values in Montgomery form and in the range [0,4N) where N is the field prime.

This verification logic is valid only for points that have been freshly constructed via weierstrass_init() (i.e. must either have z=1 or be the point at infinity (0,1,0)).

Definition at line 682 of file weierstrass.c.

683 {
684 const struct weierstrass_curve *weierstrass = curve->priv;
685 unsigned int size = weierstrass->size;
686 const bigint_t ( size ) __attribute__ (( may_alias ))
687 *prime = ( ( const void * ) weierstrass->prime[0] );
688 const bigint_t ( size ) __attribute__ (( may_alias ))
689 *a = ( ( const void * ) weierstrass->a );
690 const bigint_t ( size ) __attribute__ (( may_alias ))
691 *b3 = ( ( const void * ) weierstrass->b3 );
692 const weierstrass_t ( size ) __attribute__ (( may_alias ))
693 *point = ( ( const void * ) point0 );
694 struct {
695 bigint_t ( size ) Wt;
696 bigint_t ( size * 2 ) Wp;
697 } temp;
699 const uint16_t *op;
700
701 /* Calculate 3*(x^3 + a*x + b - y^2) */
702 static const uint16_t ops[] = {
703 /* [Wt] Tx = x^2 (mod 2N) */
704 WEIERSTRASS_MUL3 ( Wt, x1, x1 ),
705 /* [Wt] Txa = Tx + a (mod 3N)
706 * = x^2 + a (mod 3N)
707 */
708 WEIERSTRASS_MOV ( Wp, a ),
709 WEIERSTRASS_ADD2 ( Wt, Wp ),
710 /* [Wt] Txax = Txa * x (mod 2N)
711 * = (x^2 + a)*x (mod 2N)
712 * = x^3 + a*x (mod 2N)
713 */
714 WEIERSTRASS_MUL2 ( Wt, x1 ),
715 /* [Wp] Ty = y^2 (mod 2N) */
716 WEIERSTRASS_MUL3 ( Wp, y1, y1 ),
717 /* [Wt] Txaxy = Txax - Ty (mod 4N)
718 * = x^3 + a*x - y^2 (mod 4N)
719 */
720 WEIERSTRASS_SUB2 ( Wt, Wp, 2N ),
721 /* [Wp] 2Txaxy = Txaxy + Txaxy (mod 8N)
722 * = 2*(x^3 + a*x - y^2) (mod 8N)
723 */
724 WEIERSTRASS_ADD3 ( Wp, Wt, Wt ),
725 /* [Wt] 3Txaxy = 2Txaxy + Txaxy (mod 12N)
726 * = 3*(x^3 + a*x - y^2) (mod 12N)
727 */
728 WEIERSTRASS_ADD2 ( Wt, Wp ),
729 /* [Wt] 3Txaxyb = 3Txaxy + 3b (mod 13N)
730 * = 3*(x^3 + a*x - y^2) + 3b (mod 13N)
731 * = 3*(x^3 + a*x + b - y^2) (mod 13N)
732 */
733 WEIERSTRASS_ADD2 ( Wt, 3b ),
734 /* [Wt] check = 3Txaxyb * z (mod 2N)
735 * = 3*(x^3 + a*x + b - y^2) * z (mod 2N)
736 */
737 WEIERSTRASS_MUL2 ( Wt, z1 ),
738 /* Stop */
740 };
741
742 /* Initialise register list */
743 regs[WEIERSTRASS_a] = ( ( void * ) a );
744 regs[WEIERSTRASS_3b] = ( ( void * ) b3 );
745 regs[WEIERSTRASS_x1] = ( ( void * ) &point->x );
746 regs[WEIERSTRASS_y1] = ( ( void * ) &point->y );
747 regs[WEIERSTRASS_z1] = ( ( void * ) &point->z );
748 regs[WEIERSTRASS_Wt] = &temp.Wt;
749 regs[WEIERSTRASS_Wp] = &temp.Wp;
750
751 /* Execute bytecode instruction sequence */
752 for ( op = ops ; *op != WEIERSTRASS_STOP ; op++ )
753 weierstrass_exec ( curve, regs, size, *op );
754
755 /* Check that result is zero (modulo the field prime) */
756 bigint_grow ( &temp.Wt, &temp.Wp );
757 bigint_montgomery ( prime, &temp.Wp, &temp.Wt );
758 if ( ! bigint_is_zero ( &temp.Wt ) ) {
759 DBGC ( curve, "WEIERSTRASS %s base point is not on curve\n",
760 curve->name );
761 return -EINVAL;
762 }
763
764 return 0;
765}
#define EINVAL
Invalid argument.
Definition errno.h:472
#define bigint_grow(source, dest)
Grow big integer.
Definition bigint.h:210
#define bigint_is_zero(value)
Test if big integer is equal to zero.
Definition bigint.h:135

References __attribute__, weierstrass_curve::a, weierstrass_curve::b3, bigint_grow, bigint_is_zero, bigint_montgomery, bigint_t, DBGC, EINVAL, elliptic_curve::name, op, weierstrass_curve::prime, elliptic_curve::priv, regs, size, weierstrass_curve::size, WEIERSTRASS_3b, WEIERSTRASS_a, WEIERSTRASS_ADD2, WEIERSTRASS_ADD3, weierstrass_exec(), WEIERSTRASS_MOV, WEIERSTRASS_MUL2, WEIERSTRASS_MUL3, WEIERSTRASS_NUM_REGISTERS, WEIERSTRASS_STOP, WEIERSTRASS_SUB2, weierstrass_t, WEIERSTRASS_Wp, WEIERSTRASS_Wt, WEIERSTRASS_x1, WEIERSTRASS_y1, and WEIERSTRASS_z1.

◆ weierstrass_init_raw()

int weierstrass_init_raw ( struct elliptic_curve * curve,
bigint_element_t * point0,
bigint_element_t * temp0,
const void * data )
static

Initialise curve point.

Parameters
curveElliptic curve
point0Element 0 of point (x,y,z) to be filled in
temp0Element 0 of temporary point buffer
dataRaw curve point
Return values
rcReturn status code

Definition at line 787 of file weierstrass.c.

789 {
790 struct weierstrass_curve *weierstrass = curve->priv;
791 unsigned int size = weierstrass->size;
792 size_t len = weierstrass->len;
793 const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
794 ( ( const void * ) weierstrass->prime[0] );
795 const bigint_t ( size ) __attribute__ (( may_alias )) *prime2 =
796 ( ( const void * ) weierstrass->prime[WEIERSTRASS_2N] );
797 const bigint_t ( size ) __attribute__ (( may_alias )) *square =
798 ( ( const void * ) weierstrass->square );
799 const bigint_t ( size ) __attribute__ (( may_alias )) *one =
800 ( ( const void * ) weierstrass->one );
801 weierstrass_t ( size ) __attribute__ (( may_alias ))
802 *point = ( ( void * ) point0 );
803 union {
804 bigint_t ( size * 2 ) product;
805 weierstrass_t ( size ) point;
806 } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
807 size_t offset;
808 int is_infinite;
809 unsigned int i;
810 int rc;
811
812 /* Initialise curve, if not already done
813 *
814 * The least significant element of the field prime must be
815 * odd, and so the least significant element of the
816 * (initialised) first multiple of the field prime must be
817 * non-zero.
818 */
819 if ( ! prime2->element[0] )
820 weierstrass_init_curve ( curve );
821
822 /* Convert input to projective coordinates in Montgomery form */
823 DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
824 for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
825 bigint_init ( &point->axis[i], ( data + offset ), len );
826 DBGC ( curve, "%s%s", ( i ? "," : "" ),
827 bigint_ntoa ( &point->axis[i] ) );
828 bigint_multiply ( &point->axis[i], square, &temp->product );
829 bigint_montgomery_relaxed ( prime, &temp->product,
830 &point->axis[i] );
831 }
832 memset ( &point->z, 0, sizeof ( point->z ) );
833 is_infinite = bigint_is_zero ( &point->xy );
834 bigint_copy ( one, &point->axis[ is_infinite ? 1 : 2 ] );
835 DBGC ( curve, ")\n" );
836
837 /* Verify point is on curve */
838 if ( ( rc = weierstrass_verify ( curve, point ) ) != 0 )
839 return rc;
840
841 return 0;
842}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
uint16_t offset
Offset to command line.
Definition bzimage.h:3
void * memset(void *dest, int character, size_t len) __nonnull
static void weierstrass_init_curve(struct elliptic_curve *curve)
Initialise curve.
#define weierstrass_verify(curve, point)
Verify freshly initialised point is on curve.
#define WEIERSTRASS_AXES
Number of axes in Weierstrass curve point representation.
Definition weierstrass.h:18

References __attribute__, bigint_copy, bigint_init, bigint_is_zero, bigint_montgomery_relaxed, bigint_multiply, bigint_ntoa, bigint_t, data, DBGC, len, weierstrass_curve::len, memset(), elliptic_curve::name, offset, weierstrass_curve::one, weierstrass_curve::prime, elliptic_curve::priv, product, rc, size, weierstrass_curve::size, weierstrass_curve::square, WEIERSTRASS_2N, WEIERSTRASS_AXES, weierstrass_init_curve(), weierstrass_t, and weierstrass_verify.

◆ weierstrass_done_raw()

void weierstrass_done_raw ( struct elliptic_curve * curve,
bigint_element_t * point0,
bigint_element_t * temp0,
void * out )
static

Finalise curve point.

Parameters
curveElliptic curve
point0Element 0 of point (x,y,z)
temp0Element 0 of temporary point buffer
outOutput buffer

Definition at line 866 of file weierstrass.c.

868 {
869 struct weierstrass_curve *weierstrass = curve->priv;
870 unsigned int size = weierstrass->size;
871 size_t len = weierstrass->len;
872 const bigint_t ( size ) __attribute__ (( may_alias )) *prime =
873 ( ( const void * ) weierstrass->prime[0] );
874 const bigint_t ( size ) __attribute__ (( may_alias )) *fermat =
875 ( ( const void * ) weierstrass->fermat );
876 const bigint_t ( size ) __attribute__ (( may_alias )) *one =
877 ( ( const void * ) weierstrass->one );
878 weierstrass_t ( size ) __attribute__ (( may_alias ))
879 *point = ( ( void * ) point0 );
880 union {
881 bigint_t ( size * 2 ) product;
882 weierstrass_t ( size ) point;
883 } __attribute__ (( may_alias )) *temp = ( ( void * ) temp0 );
884 size_t offset;
885 unsigned int i;
886
887 /* Invert result Z co-ordinate (via Fermat's little theorem) */
888 bigint_copy ( one, &temp->point.z );
889 bigint_ladder ( &temp->point.z, &point->z, fermat,
890 bigint_mod_exp_ladder, prime, &temp->product );
891
892 /* Convert result back to affine co-ordinates */
893 DBGC ( curve, "WEIERSTRASS %s result (", curve->name );
894 for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
895 bigint_multiply ( &point->axis[i], &temp->point.z,
896 &temp->product );
897 bigint_montgomery_relaxed ( prime, &temp->product,
898 &point->axis[i] );
899 bigint_grow ( &point->axis[i], &temp->product );
900 bigint_montgomery ( prime, &temp->product, &point->axis[i] );
901 DBGC ( curve, "%s%s", ( i ? "," : "" ),
902 bigint_ntoa ( &point->axis[i] ) );
903 bigint_done ( &point->axis[i], ( out + offset ), len );
904 }
905 DBGC ( curve, ")\n" );
906}
void bigint_mod_exp_ladder(const bigint_element_t *multiplier0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp)
Perform modular multiplication as part of a Montgomery ladder.
Definition bigint.c:854
#define bigint_ladder(result, multiple, exponent, op, ctx, tmp)
Perform generalised exponentiation via a Montgomery ladder.
Definition bigint.h:331
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:76

References __attribute__, bigint_copy, bigint_done, bigint_grow, bigint_ladder, bigint_mod_exp_ladder(), bigint_montgomery, bigint_montgomery_relaxed, bigint_multiply, bigint_ntoa, bigint_t, DBGC, weierstrass_curve::fermat, len, weierstrass_curve::len, elliptic_curve::name, offset, weierstrass_curve::one, out, weierstrass_curve::prime, elliptic_curve::priv, product, size, weierstrass_curve::size, WEIERSTRASS_AXES, and weierstrass_t.

◆ weierstrass_is_infinity()

int weierstrass_is_infinity ( struct elliptic_curve * curve,
const void * point )

Check if this is the point at infinity.

Parameters
curveElliptic curve
pointCurve point
Return values
is_infinityThis is the point at infinity

Definition at line 929 of file weierstrass.c.

930 {
931 struct weierstrass_curve *weierstrass = curve->priv;
932 unsigned int size = weierstrass->size;
933 size_t len = weierstrass->len;
934 struct {
935 bigint_t ( size ) axis;
936 } temp;
937 size_t offset;
938 int is_finite = 0;
939 unsigned int i;
940
941 /* We use all zeroes to represent the point at infinity */
942 DBGC ( curve, "WEIERSTRASS %s point (", curve->name );
943 for ( i = 0, offset = 0 ; i < WEIERSTRASS_AXES ; i++, offset += len ) {
944 bigint_init ( &temp.axis, ( point + offset ), len );
945 DBGC ( curve, "%s%s", ( i ? "," : "" ),
946 bigint_ntoa ( &temp.axis ) );
947 is_finite |= ( ! bigint_is_zero ( &temp.axis ) );
948 }
949 DBGC ( curve, ") is%s infinity\n", ( is_finite ? " not" : "" ) );
950
951 return ( ! is_finite );
952}

References bigint_init, bigint_is_zero, bigint_ntoa, bigint_t, DBGC, len, weierstrass_curve::len, elliptic_curve::name, offset, elliptic_curve::priv, size, weierstrass_curve::size, and WEIERSTRASS_AXES.

◆ weierstrass_multiply()

int weierstrass_multiply ( struct elliptic_curve * curve,
const void * base,
const void * scalar,
void * result )

Multiply curve point by scalar.

Parameters
curveElliptic curve
baseBase point
scalarScalar multiple
resultResult point to fill in
Return values
rcReturn status code

Definition at line 963 of file weierstrass.c.

964 {
965 struct weierstrass_curve *weierstrass = curve->priv;
966 unsigned int size = weierstrass->size;
967 size_t len = weierstrass->len;
968 const bigint_t ( size ) __attribute__ (( may_alias )) *one =
969 ( ( const void * ) weierstrass->one );
970 struct {
972 weierstrass_t ( size ) multiple;
973 bigint_t ( bigint_required_size ( len ) ) scalar;
974 } temp;
975 int rc;
976
977 /* Convert input to projective coordinates in Montgomery form */
978 if ( ( rc = weierstrass_init ( curve, &temp.multiple, &temp.result,
979 base ) ) != 0 ) {
980 return rc;
981 }
982
983 /* Construct identity element (the point at infinity) */
984 memset ( &temp.result, 0, sizeof ( temp.result ) );
985 bigint_copy ( one, &temp.result.y );
986
987 /* Initialise scalar */
988 bigint_init ( &temp.scalar, scalar, len );
989 DBGC ( curve, "WEIERSTRASS %s scalar %s\n",
990 curve->name, bigint_ntoa ( &temp.scalar ) );
991
992 /* Perform multiplication via Montgomery ladder */
993 bigint_ladder ( &temp.result.all, &temp.multiple.all, &temp.scalar,
995
996 /* Convert result back to affine co-ordinates */
997 weierstrass_done ( curve, &temp.result, &temp.multiple, result );
998
999 return 0;
1000}
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition bigint.h:32
uint32_t base
Base.
Definition librm.h:3
#define weierstrass_done(curve, point, temp, out)
Finalise curve point.
static void weierstrass_add_ladder(const bigint_element_t *operand0, bigint_element_t *result0, unsigned int size, const void *ctx, void *tmp __unused)
Add points on curve as part of a Montgomery ladder.
#define weierstrass_init(curve, point, temp, data)
Initialise curve point.

References __attribute__, base, bigint_copy, bigint_init, bigint_ladder, bigint_ntoa, bigint_required_size, bigint_t, DBGC, len, weierstrass_curve::len, memset(), elliptic_curve::name, NULL, weierstrass_curve::one, elliptic_curve::priv, rc, result, size, weierstrass_curve::size, weierstrass_add_ladder(), weierstrass_done, weierstrass_init, and weierstrass_t.

◆ weierstrass_add_once()

int weierstrass_add_once ( struct elliptic_curve * curve,
const void * addend,
const void * augend,
void * result )

Add curve points (as a one-off operation).

Parameters
curveElliptic curve
addendCurve point to add
augendCurve point to add
resultCurve point to hold result
Return values
rcReturn status code

Definition at line 1011 of file weierstrass.c.

1013 {
1014 struct weierstrass_curve *weierstrass = curve->priv;
1015 unsigned int size = weierstrass->size;
1016 struct {
1017 weierstrass_t ( size ) addend;
1018 weierstrass_t ( size ) augend;
1020 } temp;
1021 int rc;
1022
1023 /* Convert inputs to projective coordinates in Montgomery form */
1024 if ( ( rc = weierstrass_init ( curve, &temp.addend, &temp.result,
1025 addend ) ) != 0 ) {
1026 return rc;
1027 }
1028 if ( ( rc = weierstrass_init ( curve, &temp.augend, &temp.result,
1029 augend ) ) != 0 ) {
1030 return rc;
1031 }
1032
1033 /* Add curve points */
1034 weierstrass_add ( curve, &temp.augend, &temp.addend, &temp.result );
1035
1036 /* Convert result back to affine co-ordinates */
1037 weierstrass_done ( curve, &temp.result, &temp.addend, result );
1038
1039 return 0;
1040}

References elliptic_curve::priv, rc, result, size, weierstrass_curve::size, weierstrass_add, weierstrass_done, weierstrass_init, and weierstrass_t.