2013-12-18 14:48:11 +08:00
/* $OpenBSD: sc25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
2013-12-07 08:24:01 +08:00
2013-12-18 14:48:11 +08:00
/*
* Public Domain , Authors : Daniel J . Bernstein , Niels Duif , Tanja Lange ,
* Peter Schwabe , Bo - Yin Yang .
* Copied from supercop - 20130419 / crypto_sign / ed25519 / ref / sc25519 . c
*/
2013-12-07 08:24:01 +08:00
2014-01-17 09:43:43 +08:00
# include "includes.h"
2013-12-07 08:24:01 +08:00
# include "sc25519.h"
/*Arithmetic modulo the group order m = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 */
static const crypto_uint32 m [ 32 ] = { 0xED , 0xD3 , 0xF5 , 0x5C , 0x1A , 0x63 , 0x12 , 0x58 , 0xD6 , 0x9C , 0xF7 , 0xA2 , 0xDE , 0xF9 , 0xDE , 0x14 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ;
static const crypto_uint32 mu [ 33 ] = { 0x1B , 0x13 , 0x2C , 0x0A , 0xA3 , 0xE5 , 0x9C , 0xED , 0xA7 , 0x29 , 0x63 , 0x08 , 0x5D , 0x21 , 0x06 , 0x21 ,
0xEB , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x0F } ;
static crypto_uint32 lt ( crypto_uint32 a , crypto_uint32 b ) /* 16-bit inputs */
{
unsigned int x = a ;
x - = ( unsigned int ) b ; /* 0..65535: no; 4294901761..4294967295: yes */
x > > = 31 ; /* 0: no; 1: yes */
return x ;
}
/* Reduce coefficients of r before calling reduce_add_sub */
static void reduce_add_sub ( sc25519 * r )
{
crypto_uint32 pb = 0 ;
crypto_uint32 b ;
crypto_uint32 mask ;
int i ;
unsigned char t [ 32 ] ;
for ( i = 0 ; i < 32 ; i + + )
{
pb + = m [ i ] ;
b = lt ( r - > v [ i ] , pb ) ;
t [ i ] = r - > v [ i ] - pb + ( b < < 8 ) ;
pb = b ;
}
mask = b - 1 ;
for ( i = 0 ; i < 32 ; i + + )
r - > v [ i ] ^ = mask & ( r - > v [ i ] ^ t [ i ] ) ;
}
/* Reduce coefficients of x before calling barrett_reduce */
static void barrett_reduce ( sc25519 * r , const crypto_uint32 x [ 64 ] )
{
/* See HAC, Alg. 14.42 */
int i , j ;
crypto_uint32 q2 [ 66 ] ;
crypto_uint32 * q3 = q2 + 33 ;
crypto_uint32 r1 [ 33 ] ;
crypto_uint32 r2 [ 33 ] ;
crypto_uint32 carry ;
crypto_uint32 pb = 0 ;
crypto_uint32 b ;
for ( i = 0 ; i < 66 ; + + i ) q2 [ i ] = 0 ;
for ( i = 0 ; i < 33 ; + + i ) r2 [ i ] = 0 ;
for ( i = 0 ; i < 33 ; i + + )
for ( j = 0 ; j < 33 ; j + + )
if ( i + j > = 31 ) q2 [ i + j ] + = mu [ i ] * x [ j + 31 ] ;
carry = q2 [ 31 ] > > 8 ;
q2 [ 32 ] + = carry ;
carry = q2 [ 32 ] > > 8 ;
q2 [ 33 ] + = carry ;
for ( i = 0 ; i < 33 ; i + + ) r1 [ i ] = x [ i ] ;
for ( i = 0 ; i < 32 ; i + + )
for ( j = 0 ; j < 33 ; j + + )
if ( i + j < 33 ) r2 [ i + j ] + = m [ i ] * q3 [ j ] ;
for ( i = 0 ; i < 32 ; i + + )
{
carry = r2 [ i ] > > 8 ;
r2 [ i + 1 ] + = carry ;
r2 [ i ] & = 0xff ;
}
for ( i = 0 ; i < 32 ; i + + )
{
pb + = r2 [ i ] ;
b = lt ( r1 [ i ] , pb ) ;
r - > v [ i ] = r1 [ i ] - pb + ( b < < 8 ) ;
pb = b ;
}
/* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3
* If so : Handle it here !
*/
reduce_add_sub ( r ) ;
reduce_add_sub ( r ) ;
}
void sc25519_from32bytes ( sc25519 * r , const unsigned char x [ 32 ] )
{
int i ;
crypto_uint32 t [ 64 ] ;
for ( i = 0 ; i < 32 ; i + + ) t [ i ] = x [ i ] ;
for ( i = 32 ; i < 64 ; + + i ) t [ i ] = 0 ;
barrett_reduce ( r , t ) ;
}
void shortsc25519_from16bytes ( shortsc25519 * r , const unsigned char x [ 16 ] )
{
int i ;
for ( i = 0 ; i < 16 ; i + + ) r - > v [ i ] = x [ i ] ;
}
void sc25519_from64bytes ( sc25519 * r , const unsigned char x [ 64 ] )
{
int i ;
crypto_uint32 t [ 64 ] ;
for ( i = 0 ; i < 64 ; i + + ) t [ i ] = x [ i ] ;
barrett_reduce ( r , t ) ;
}
void sc25519_from_shortsc ( sc25519 * r , const shortsc25519 * x )
{
int i ;
for ( i = 0 ; i < 16 ; i + + )
r - > v [ i ] = x - > v [ i ] ;
for ( i = 0 ; i < 16 ; i + + )
r - > v [ 16 + i ] = 0 ;
}
void sc25519_to32bytes ( unsigned char r [ 32 ] , const sc25519 * x )
{
int i ;
for ( i = 0 ; i < 32 ; i + + ) r [ i ] = x - > v [ i ] ;
}
int sc25519_iszero_vartime ( const sc25519 * x )
{
int i ;
for ( i = 0 ; i < 32 ; i + + )
if ( x - > v [ i ] ! = 0 ) return 0 ;
return 1 ;
}
int sc25519_isshort_vartime ( const sc25519 * x )
{
int i ;
for ( i = 31 ; i > 15 ; i - - )
if ( x - > v [ i ] ! = 0 ) return 0 ;
return 1 ;
}
int sc25519_lt_vartime ( const sc25519 * x , const sc25519 * y )
{
int i ;
for ( i = 31 ; i > = 0 ; i - - )
{
if ( x - > v [ i ] < y - > v [ i ] ) return 1 ;
if ( x - > v [ i ] > y - > v [ i ] ) return 0 ;
}
return 0 ;
}
void sc25519_add ( sc25519 * r , const sc25519 * x , const sc25519 * y )
{
int i , carry ;
for ( i = 0 ; i < 32 ; i + + ) r - > v [ i ] = x - > v [ i ] + y - > v [ i ] ;
for ( i = 0 ; i < 31 ; i + + )
{
carry = r - > v [ i ] > > 8 ;
r - > v [ i + 1 ] + = carry ;
r - > v [ i ] & = 0xff ;
}
reduce_add_sub ( r ) ;
}
void sc25519_sub_nored ( sc25519 * r , const sc25519 * x , const sc25519 * y )
{
crypto_uint32 b = 0 ;
crypto_uint32 t ;
int i ;
for ( i = 0 ; i < 32 ; i + + )
{
t = x - > v [ i ] - y - > v [ i ] - b ;
r - > v [ i ] = t & 255 ;
b = ( t > > 8 ) & 1 ;
}
}
void sc25519_mul ( sc25519 * r , const sc25519 * x , const sc25519 * y )
{
int i , j , carry ;
crypto_uint32 t [ 64 ] ;
for ( i = 0 ; i < 64 ; i + + ) t [ i ] = 0 ;
for ( i = 0 ; i < 32 ; i + + )
for ( j = 0 ; j < 32 ; j + + )
t [ i + j ] + = x - > v [ i ] * y - > v [ j ] ;
/* Reduce coefficients */
for ( i = 0 ; i < 63 ; i + + )
{
carry = t [ i ] > > 8 ;
t [ i + 1 ] + = carry ;
t [ i ] & = 0xff ;
}
barrett_reduce ( r , t ) ;
}
void sc25519_mul_shortsc ( sc25519 * r , const sc25519 * x , const shortsc25519 * y )
{
sc25519 t ;
sc25519_from_shortsc ( & t , y ) ;
sc25519_mul ( r , x , & t ) ;
}
void sc25519_window3 ( signed char r [ 85 ] , const sc25519 * s )
{
char carry ;
int i ;
for ( i = 0 ; i < 10 ; i + + )
{
r [ 8 * i + 0 ] = s - > v [ 3 * i + 0 ] & 7 ;
r [ 8 * i + 1 ] = ( s - > v [ 3 * i + 0 ] > > 3 ) & 7 ;
r [ 8 * i + 2 ] = ( s - > v [ 3 * i + 0 ] > > 6 ) & 7 ;
r [ 8 * i + 2 ] ^ = ( s - > v [ 3 * i + 1 ] < < 2 ) & 7 ;
r [ 8 * i + 3 ] = ( s - > v [ 3 * i + 1 ] > > 1 ) & 7 ;
r [ 8 * i + 4 ] = ( s - > v [ 3 * i + 1 ] > > 4 ) & 7 ;
r [ 8 * i + 5 ] = ( s - > v [ 3 * i + 1 ] > > 7 ) & 7 ;
r [ 8 * i + 5 ] ^ = ( s - > v [ 3 * i + 2 ] < < 1 ) & 7 ;
r [ 8 * i + 6 ] = ( s - > v [ 3 * i + 2 ] > > 2 ) & 7 ;
r [ 8 * i + 7 ] = ( s - > v [ 3 * i + 2 ] > > 5 ) & 7 ;
}
r [ 8 * i + 0 ] = s - > v [ 3 * i + 0 ] & 7 ;
r [ 8 * i + 1 ] = ( s - > v [ 3 * i + 0 ] > > 3 ) & 7 ;
r [ 8 * i + 2 ] = ( s - > v [ 3 * i + 0 ] > > 6 ) & 7 ;
r [ 8 * i + 2 ] ^ = ( s - > v [ 3 * i + 1 ] < < 2 ) & 7 ;
r [ 8 * i + 3 ] = ( s - > v [ 3 * i + 1 ] > > 1 ) & 7 ;
r [ 8 * i + 4 ] = ( s - > v [ 3 * i + 1 ] > > 4 ) & 7 ;
/* Making it signed */
carry = 0 ;
for ( i = 0 ; i < 84 ; i + + )
{
r [ i ] + = carry ;
r [ i + 1 ] + = r [ i ] > > 3 ;
r [ i ] & = 7 ;
carry = r [ i ] > > 2 ;
r [ i ] - = carry < < 3 ;
}
r [ 84 ] + = carry ;
}
void sc25519_window5 ( signed char r [ 51 ] , const sc25519 * s )
{
char carry ;
int i ;
for ( i = 0 ; i < 6 ; i + + )
{
r [ 8 * i + 0 ] = s - > v [ 5 * i + 0 ] & 31 ;
r [ 8 * i + 1 ] = ( s - > v [ 5 * i + 0 ] > > 5 ) & 31 ;
r [ 8 * i + 1 ] ^ = ( s - > v [ 5 * i + 1 ] < < 3 ) & 31 ;
r [ 8 * i + 2 ] = ( s - > v [ 5 * i + 1 ] > > 2 ) & 31 ;
r [ 8 * i + 3 ] = ( s - > v [ 5 * i + 1 ] > > 7 ) & 31 ;
r [ 8 * i + 3 ] ^ = ( s - > v [ 5 * i + 2 ] < < 1 ) & 31 ;
r [ 8 * i + 4 ] = ( s - > v [ 5 * i + 2 ] > > 4 ) & 31 ;
r [ 8 * i + 4 ] ^ = ( s - > v [ 5 * i + 3 ] < < 4 ) & 31 ;
r [ 8 * i + 5 ] = ( s - > v [ 5 * i + 3 ] > > 1 ) & 31 ;
r [ 8 * i + 6 ] = ( s - > v [ 5 * i + 3 ] > > 6 ) & 31 ;
r [ 8 * i + 6 ] ^ = ( s - > v [ 5 * i + 4 ] < < 2 ) & 31 ;
r [ 8 * i + 7 ] = ( s - > v [ 5 * i + 4 ] > > 3 ) & 31 ;
}
r [ 8 * i + 0 ] = s - > v [ 5 * i + 0 ] & 31 ;
r [ 8 * i + 1 ] = ( s - > v [ 5 * i + 0 ] > > 5 ) & 31 ;
r [ 8 * i + 1 ] ^ = ( s - > v [ 5 * i + 1 ] < < 3 ) & 31 ;
r [ 8 * i + 2 ] = ( s - > v [ 5 * i + 1 ] > > 2 ) & 31 ;
/* Making it signed */
carry = 0 ;
for ( i = 0 ; i < 50 ; i + + )
{
r [ i ] + = carry ;
r [ i + 1 ] + = r [ i ] > > 5 ;
r [ i ] & = 31 ;
carry = r [ i ] > > 4 ;
r [ i ] - = carry < < 5 ;
}
r [ 50 ] + = carry ;
}
void sc25519_2interleave2 ( unsigned char r [ 127 ] , const sc25519 * s1 , const sc25519 * s2 )
{
int i ;
for ( i = 0 ; i < 31 ; i + + )
{
r [ 4 * i ] = ( s1 - > v [ i ] & 3 ) ^ ( ( s2 - > v [ i ] & 3 ) < < 2 ) ;
r [ 4 * i + 1 ] = ( ( s1 - > v [ i ] > > 2 ) & 3 ) ^ ( ( ( s2 - > v [ i ] > > 2 ) & 3 ) < < 2 ) ;
r [ 4 * i + 2 ] = ( ( s1 - > v [ i ] > > 4 ) & 3 ) ^ ( ( ( s2 - > v [ i ] > > 4 ) & 3 ) < < 2 ) ;
r [ 4 * i + 3 ] = ( ( s1 - > v [ i ] > > 6 ) & 3 ) ^ ( ( ( s2 - > v [ i ] > > 6 ) & 3 ) < < 2 ) ;
}
r [ 124 ] = ( s1 - > v [ 31 ] & 3 ) ^ ( ( s2 - > v [ 31 ] & 3 ) < < 2 ) ;
r [ 125 ] = ( ( s1 - > v [ 31 ] > > 2 ) & 3 ) ^ ( ( ( s2 - > v [ 31 ] > > 2 ) & 3 ) < < 2 ) ;
r [ 126 ] = ( ( s1 - > v [ 31 ] > > 4 ) & 3 ) ^ ( ( ( s2 - > v [ 31 ] > > 4 ) & 3 ) < < 2 ) ;
}