├── .gitignore ├── .github └── FUNDING.yml ├── curve ├── ed25519 │ ├── d.h │ ├── d2.h │ ├── sqrtm1.h │ ├── nacl_sha512 │ │ ├── .libs │ │ │ ├── hash.o │ │ │ └── blocks.o │ │ ├── hash.c │ │ └── blocks.c │ ├── ge_p2_0.c │ ├── nacl_includes │ │ ├── crypto_int32.h │ │ ├── crypto_int64.h │ │ ├── crypto_uint32.h │ │ ├── crypto_uint64.h │ │ ├── crypto_verify_32.h │ │ ├── crypto_sign.h │ │ └── crypto_sign_edwards25519sha512batch.h │ ├── api.h │ ├── ge_p3_0.c │ ├── ge_precomp_0.c │ ├── additions │ │ ├── compare.h │ │ ├── crypto_hash_sha512.h │ │ ├── zeroize.h │ │ ├── zeroize.c │ │ ├── compare.c │ │ ├── sign_modified.c~ │ │ ├── sign_modified.c │ │ ├── curve_sigs.h │ │ ├── curve_sigs.c~ │ │ └── curve_sigs.c │ ├── ge_p2_dbl.c │ ├── ge_add.c │ ├── ge_sub.c │ ├── ge_madd.c │ ├── ge_msub.c │ ├── ge_p3_dbl.c │ ├── fe_pow22523.c │ ├── fe_invert.c │ ├── ge_p3_to_p2.c │ ├── ge_p1p1_to_p2.c │ ├── fe_0.c │ ├── fe_1.c │ ├── ge_p1p1_to_p3.c │ ├── ge_tobytes.c │ ├── ge_p3_tobytes.c │ ├── ge_p3_to_cached.c │ ├── fe_isnegative.c │ ├── fe_isnonzero.c │ ├── sc.h │ ├── fe_copy.c │ ├── sign.c │ ├── fe_neg.c │ ├── ge_frombytes.c │ ├── open.c │ ├── fe_add.c │ ├── fe_sub.c │ ├── fe_cmov.c │ ├── ge_p2_dbl.h │ ├── fe.h │ ├── ge_madd.h │ ├── ge_msub.h │ ├── ge_add.h │ ├── ge_sub.h │ ├── base2.h │ ├── fe_frombytes.c │ ├── ge_double_scalarmult.c │ ├── ge_scalarmult_base.c │ ├── ge.h │ ├── main │ │ └── main.c │ ├── fe_tobytes.c │ ├── pow22523.h │ ├── pow225521.h │ ├── fe_sq.c │ ├── fe_sq2.c │ ├── sc_reduce.c │ ├── fe_mul.c │ └── sc_muladd.c ├── curve25519-donna.h └── curve25519-donna.c ├── bin ├── linux-osx-php5.6 │ ├── protobuf.so │ └── curve25519.so └── win-php5.6 │ ├── php-protobuf_x86.zip │ └── curve25519-php_x86.zip ├── php_curve25519.h ├── config.w32 ├── config.m4 ├── LICENSE ├── README.md └── curve.c /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [mgp25] 2 | -------------------------------------------------------------------------------- /curve/ed25519/d.h: -------------------------------------------------------------------------------- 1 | -10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116 2 | -------------------------------------------------------------------------------- /curve/ed25519/d2.h: -------------------------------------------------------------------------------- 1 | -21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199 2 | -------------------------------------------------------------------------------- /curve/ed25519/sqrtm1.h: -------------------------------------------------------------------------------- 1 | -32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482 2 | -------------------------------------------------------------------------------- /bin/linux-osx-php5.6/protobuf.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/bin/linux-osx-php5.6/protobuf.so -------------------------------------------------------------------------------- /bin/linux-osx-php5.6/curve25519.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/bin/linux-osx-php5.6/curve25519.so -------------------------------------------------------------------------------- /bin/win-php5.6/php-protobuf_x86.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/bin/win-php5.6/php-protobuf_x86.zip -------------------------------------------------------------------------------- /bin/win-php5.6/curve25519-php_x86.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/bin/win-php5.6/curve25519-php_x86.zip -------------------------------------------------------------------------------- /curve/ed25519/nacl_sha512/.libs/hash.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/curve/ed25519/nacl_sha512/.libs/hash.o -------------------------------------------------------------------------------- /curve/ed25519/nacl_sha512/.libs/blocks.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgp25/curve25519-php/HEAD/curve/ed25519/nacl_sha512/.libs/blocks.o -------------------------------------------------------------------------------- /curve/ed25519/ge_p2_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p2_0(ge_p2 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | } 9 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_int32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int32_h 2 | #define crypto_int32_h 3 | 4 | typedef int crypto_int32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_int64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int64_h 2 | #define crypto_int64_h 3 | 4 | typedef long long crypto_int64; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/api.h: -------------------------------------------------------------------------------- 1 | #define CRYPTO_SECRETKEYBYTES 64 2 | #define CRYPTO_PUBLICKEYBYTES 32 3 | #define CRYPTO_BYTES 64 4 | #define CRYPTO_DETERMINISTIC 1 5 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_uint32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint32_h 2 | #define crypto_uint32_h 3 | 4 | typedef unsigned int crypto_uint32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_uint64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint64_h 2 | #define crypto_uint64_h 3 | 4 | typedef unsigned long long crypto_uint64; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p3_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_0(ge_p3 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | fe_0(h->T); 9 | } 10 | -------------------------------------------------------------------------------- /curve/ed25519/ge_precomp_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_precomp_0(ge_precomp *h) 4 | { 5 | fe_1(h->yplusx); 6 | fe_1(h->yminusx); 7 | fe_0(h->xy2d); 8 | } 9 | -------------------------------------------------------------------------------- /curve/curve25519-donna.h: -------------------------------------------------------------------------------- 1 | #ifndef CURVE25519_DONNA_H 2 | #define CURVE25519_DONNA_H 3 | 4 | extern int curve25519_donna(uint8_t *, const uint8_t *, const uint8_t *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/additions/compare.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMPARE_H__ 2 | #define __COMPARE_H__ 3 | 4 | int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p2_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) 8 | { 9 | fe t0; 10 | #include "ge_p2_dbl.h" 11 | } 12 | -------------------------------------------------------------------------------- /php_curve25519.h: -------------------------------------------------------------------------------- 1 | extern zend_module_entry curve25519_module_entry; 2 | 3 | #define curve25519_module_ptr &curve25519_module_entry 4 | #define phpext_curve25519_ptr curve25519_module_ptr 5 | -------------------------------------------------------------------------------- /curve/ed25519/ge_add.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_add.h" 11 | } 12 | -------------------------------------------------------------------------------- /curve/ed25519/ge_sub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_sub.h" 11 | } 12 | -------------------------------------------------------------------------------- /curve/ed25519/ge_madd.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_madd.h" 11 | } 12 | -------------------------------------------------------------------------------- /curve/ed25519/ge_msub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_msub.h" 11 | } 12 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p3_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) 8 | { 9 | ge_p2 q; 10 | ge_p3_to_p2(&q,p); 11 | ge_p2_dbl(r,&q); 12 | } 13 | -------------------------------------------------------------------------------- /curve/ed25519/fe_pow22523.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_pow22523(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | int i; 9 | 10 | #include "pow22523.h" 11 | 12 | return; 13 | } 14 | -------------------------------------------------------------------------------- /curve/ed25519/additions/crypto_hash_sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_hash_sha512_H 2 | #define crypto_hash_sha512_H 3 | 4 | extern int crypto_hash_sha512(unsigned char *,const unsigned char *,unsigned long long); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /curve/ed25519/fe_invert.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_invert(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | fe t3; 9 | int i; 10 | 11 | #include "pow225521.h" 12 | 13 | return; 14 | } 15 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p3_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) 8 | { 9 | fe_copy(r->X,p->X); 10 | fe_copy(r->Y,p->Y); 11 | fe_copy(r->Z,p->Z); 12 | } 13 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p1p1_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | } 13 | -------------------------------------------------------------------------------- /curve/ed25519/additions/zeroize.h: -------------------------------------------------------------------------------- 1 | #ifndef __ZEROIZE_H__ 2 | #define __ZEROIZE_H__ 3 | 4 | #include 5 | 6 | #define ZEROIZE_STACK_SIZE 2048 7 | 8 | void zeroize(unsigned char* b, size_t len); 9 | 10 | void zeroize_stack(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /curve/ed25519/fe_0.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 0 5 | */ 6 | 7 | void fe_0(fe h) 8 | { 9 | h[0] = 0; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /curve/ed25519/fe_1.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 1 5 | */ 6 | 7 | void fe_1(fe h) 8 | { 9 | h[0] = 1; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p1p1_to_p3.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | fe_mul(r->T,p->X,p->Y); 13 | } 14 | -------------------------------------------------------------------------------- /curve/ed25519/ge_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_tobytes(unsigned char *s,const ge_p2 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p3_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p3_to_cached.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | static const fe d2 = { 8 | #include "d2.h" 9 | } ; 10 | 11 | extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) 12 | { 13 | fe_add(r->YplusX,p->Y,p->X); 14 | fe_sub(r->YminusX,p->Y,p->X); 15 | fe_copy(r->Z,p->Z); 16 | fe_mul(r->T2d,p->T,d2); 17 | } 18 | -------------------------------------------------------------------------------- /curve/ed25519/fe_isnegative.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | return 1 if f is in {1,3,5,...,q-2} 5 | return 0 if f is in {0,2,4,...,q-1} 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 9 | */ 10 | 11 | int fe_isnegative(const fe f) 12 | { 13 | unsigned char s[32]; 14 | fe_tobytes(s,f); 15 | return s[0] & 1; 16 | } 17 | -------------------------------------------------------------------------------- /curve/ed25519/additions/zeroize.c: -------------------------------------------------------------------------------- 1 | #include "zeroize.h" 2 | 3 | void zeroize(unsigned char* b, size_t len) 4 | { 5 | size_t count = 0; 6 | //unsigned long retval = 0; 7 | volatile unsigned char *p = b; 8 | 9 | for (count = 0; count < len; count++) 10 | p[count] = 0; 11 | } 12 | 13 | void zeroize_stack(void) 14 | { 15 | unsigned char m[ZEROIZE_STACK_SIZE]; 16 | zeroize(m, sizeof m); 17 | } 18 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | ARG_ENABLE('curve25519', 'curve25519 support', 'no'); 2 | 3 | if (PHP_CURVE25519 != 'no') { 4 | AC_DEFINE('HAVE_CURVE25519', 1, 'Whether you have curve25519 extension'); 5 | 6 | EXTENSION('curve25519', 'curve.c', true); 7 | ADD_SOURCES(configure_module_dirname, 'curve\\curve25519-donna.c curve\\ed25519\\*.c curve\\ed25519\\additions\\*.c curve\\ed25519\\nacl_sha512\\*.c', 'curve25519'); 8 | } 9 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(curve25519, whether to enable cuve25519 extension, 2 | [ --enable-curve25519 Enable "php-curve25519" extension support]) 3 | 4 | if test $PHP_CURVE25519 != "no"; then 5 | AC_DEFINE(HAVE_CURVE25519, 1, [Whether you have curve25519 extension]) 6 | PHP_NEW_EXTENSION(curve25519, curve.c curve/curve25519-donna.c curve/ed25519/*.c curve/ed25519/additions/*.c curve/ed25519/nacl_sha512/*.c, $ext_shared) 7 | fi 8 | 9 | -------------------------------------------------------------------------------- /curve/ed25519/fe_isnonzero.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_verify_32.h" 3 | 4 | /* 5 | return 1 if f == 0 6 | return 0 if f != 0 7 | 8 | Preconditions: 9 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 10 | */ 11 | 12 | static const unsigned char zero[32]; 13 | 14 | int fe_isnonzero(const fe f) 15 | { 16 | unsigned char s[32]; 17 | fe_tobytes(s,f); 18 | return crypto_verify_32(s,zero); 19 | } 20 | -------------------------------------------------------------------------------- /curve/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | #define sc_reduce crypto_sign_ed25519_ref10_sc_reduce 10 | #define sc_muladd crypto_sign_ed25519_ref10_sc_muladd 11 | 12 | extern void sc_reduce(unsigned char *); 13 | extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /curve/ed25519/fe_copy.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f 5 | */ 6 | 7 | void fe_copy(fe h,const fe f) 8 | { 9 | crypto_int32 f0 = f[0]; 10 | crypto_int32 f1 = f[1]; 11 | crypto_int32 f2 = f[2]; 12 | crypto_int32 f3 = f[3]; 13 | crypto_int32 f4 = f[4]; 14 | crypto_int32 f5 = f[5]; 15 | crypto_int32 f6 = f[6]; 16 | crypto_int32 f7 = f[7]; 17 | crypto_int32 f8 = f[8]; 18 | crypto_int32 f9 = f[9]; 19 | h[0] = f0; 20 | h[1] = f1; 21 | h[2] = f2; 22 | h[3] = f3; 23 | h[4] = f4; 24 | h[5] = f5; 25 | h[6] = f6; 26 | h[7] = f7; 27 | h[8] = f8; 28 | h[9] = f9; 29 | } 30 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_verify_32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_verify_32_H 2 | #define crypto_verify_32_H 3 | 4 | #define crypto_verify_32_ref_BYTES 32 5 | #ifdef __cplusplus 6 | #include 7 | extern "C" { 8 | #endif 9 | extern int crypto_verify_32_ref(const unsigned char *,const unsigned char *); 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #define crypto_verify_32 crypto_verify_32_ref 15 | #define crypto_verify_32_BYTES crypto_verify_32_ref_BYTES 16 | #define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/ref" 17 | #ifndef crypto_verify_32_ref_VERSION 18 | #define crypto_verify_32_ref_VERSION "-" 19 | #endif 20 | #define crypto_verify_32_VERSION crypto_verify_32_ref_VERSION 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_sign.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_H 2 | #define crypto_sign_H 3 | 4 | #include "crypto_sign_edwards25519sha512batch.h" 5 | 6 | #define crypto_sign crypto_sign_edwards25519sha512batch 7 | #define crypto_sign_open crypto_sign_edwards25519sha512batch_open 8 | #define crypto_sign_keypair crypto_sign_edwards25519sha512batch_keypair 9 | #define crypto_sign_BYTES crypto_sign_edwards25519sha512batch_BYTES 10 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES 11 | #define crypto_sign_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_SECRETKEYBYTES 12 | #define crypto_sign_PRIMITIVE "edwards25519sha512batch" 13 | #define crypto_sign_IMPLEMENTATION crypto_sign_edwards25519sha512batch_IMPLEMENTATION 14 | #define crypto_sign_VERSION crypto_sign_edwards25519sha512batch_VERSION 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /curve/ed25519/additions/compare.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "compare.h" 3 | 4 | /* Const-time comparison from SUPERCOP, but here it's only used for 5 | signature verification, so doesn't need to be const-time. But 6 | copied the nacl version anyways. */ 7 | int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y) 8 | { 9 | unsigned int differentbits = 0; 10 | #define F(i) differentbits |= x[i] ^ y[i]; 11 | F(0) 12 | F(1) 13 | F(2) 14 | F(3) 15 | F(4) 16 | F(5) 17 | F(6) 18 | F(7) 19 | F(8) 20 | F(9) 21 | F(10) 22 | F(11) 23 | F(12) 24 | F(13) 25 | F(14) 26 | F(15) 27 | F(16) 28 | F(17) 29 | F(18) 30 | F(19) 31 | F(20) 32 | F(21) 33 | F(22) 34 | F(23) 35 | F(24) 36 | F(25) 37 | F(26) 38 | F(27) 39 | F(28) 40 | F(29) 41 | F(30) 42 | F(31) 43 | return (1 & ((differentbits - 1) >> 8)) - 1; 44 | } 45 | -------------------------------------------------------------------------------- /curve/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nacl_includes/crypto_sign.h" 3 | #include "additions/crypto_hash_sha512.h" 4 | #include "ge.h" 5 | #include "sc.h" 6 | 7 | int crypto_sign( 8 | unsigned char *sm,unsigned long long *smlen, 9 | const unsigned char *m,unsigned long long mlen, 10 | const unsigned char *sk 11 | ) 12 | { 13 | unsigned char pk[32]; 14 | unsigned char az[64]; 15 | unsigned char nonce[64]; 16 | unsigned char hram[64]; 17 | ge_p3 R; 18 | 19 | memmove(pk,sk + 32,32); 20 | 21 | crypto_hash_sha512(az,sk,32); 22 | az[0] &= 248; 23 | az[31] &= 63; 24 | az[31] |= 64; 25 | 26 | *smlen = mlen + 64; 27 | memmove(sm + 64,m,mlen); 28 | memmove(sm + 32,az + 32,32); 29 | crypto_hash_sha512(nonce,sm + 32,mlen + 32); 30 | memmove(sm + 32,pk,32); 31 | 32 | sc_reduce(nonce); 33 | ge_scalarmult_base(&R,nonce); 34 | ge_p3_tobytes(sm,&R); 35 | 36 | crypto_hash_sha512(hram,sm,mlen + 64); 37 | sc_reduce(hram); 38 | sc_muladd(sm + 32,hram,az,nonce); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /curve/ed25519/fe_neg.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = -f 5 | 6 | Preconditions: 7 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 8 | 9 | Postconditions: 10 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 11 | */ 12 | 13 | void fe_neg(fe h,const fe f) 14 | { 15 | crypto_int32 f0 = f[0]; 16 | crypto_int32 f1 = f[1]; 17 | crypto_int32 f2 = f[2]; 18 | crypto_int32 f3 = f[3]; 19 | crypto_int32 f4 = f[4]; 20 | crypto_int32 f5 = f[5]; 21 | crypto_int32 f6 = f[6]; 22 | crypto_int32 f7 = f[7]; 23 | crypto_int32 f8 = f[8]; 24 | crypto_int32 f9 = f[9]; 25 | crypto_int32 h0 = -f0; 26 | crypto_int32 h1 = -f1; 27 | crypto_int32 h2 = -f2; 28 | crypto_int32 h3 = -f3; 29 | crypto_int32 h4 = -f4; 30 | crypto_int32 h5 = -f5; 31 | crypto_int32 h6 = -f6; 32 | crypto_int32 h7 = -f7; 33 | crypto_int32 h8 = -f8; 34 | crypto_int32 h9 = -f9; 35 | h[0] = h0; 36 | h[1] = h1; 37 | h[2] = h2; 38 | h[3] = h3; 39 | h[4] = h4; 40 | h[5] = h5; 41 | h[6] = h6; 42 | h[7] = h7; 43 | h[8] = h8; 44 | h[9] = h9; 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 mgp25 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /curve/ed25519/ge_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static const fe d = { 4 | #include "d.h" 5 | } ; 6 | 7 | static const fe sqrtm1 = { 8 | #include "sqrtm1.h" 9 | } ; 10 | 11 | int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) 12 | { 13 | fe u; 14 | fe v; 15 | fe v3; 16 | fe vxx; 17 | fe check; 18 | 19 | fe_frombytes(h->Y,s); 20 | fe_1(h->Z); 21 | fe_sq(u,h->Y); 22 | fe_mul(v,u,d); 23 | fe_sub(u,u,h->Z); /* u = y^2-1 */ 24 | fe_add(v,v,h->Z); /* v = dy^2+1 */ 25 | 26 | fe_sq(v3,v); 27 | fe_mul(v3,v3,v); /* v3 = v^3 */ 28 | fe_sq(h->X,v3); 29 | fe_mul(h->X,h->X,v); 30 | fe_mul(h->X,h->X,u); /* x = uv^7 */ 31 | 32 | fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ 33 | fe_mul(h->X,h->X,v3); 34 | fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ 35 | 36 | fe_sq(vxx,h->X); 37 | fe_mul(vxx,vxx,v); 38 | fe_sub(check,vxx,u); /* vx^2-u */ 39 | if (fe_isnonzero(check)) { 40 | fe_add(check,vxx,u); /* vx^2+u */ 41 | if (fe_isnonzero(check)) return -1; 42 | fe_mul(h->X,h->X,sqrtm1); 43 | } 44 | 45 | if (fe_isnegative(h->X) == (s[31] >> 7)) 46 | fe_neg(h->X,h->X); 47 | 48 | fe_mul(h->T,h->X,h->Y); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /curve/ed25519/open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "nacl_includes/crypto_sign.h" 3 | #include "additions/crypto_hash_sha512.h" 4 | #include "nacl_includes/crypto_verify_32.h" 5 | #include "ge.h" 6 | #include "sc.h" 7 | 8 | int crypto_sign_open( 9 | unsigned char *m,unsigned long long *mlen, 10 | const unsigned char *sm,unsigned long long smlen, 11 | const unsigned char *pk 12 | ) 13 | { 14 | unsigned char pkcopy[32]; 15 | unsigned char rcopy[32]; 16 | unsigned char scopy[32]; 17 | unsigned char h[64]; 18 | unsigned char rcheck[32]; 19 | ge_p3 A; 20 | ge_p2 R; 21 | 22 | if (smlen < 64) goto badsig; 23 | if (sm[63] & 224) goto badsig; 24 | if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; 25 | 26 | memmove(pkcopy,pk,32); 27 | memmove(rcopy,sm,32); 28 | memmove(scopy,sm + 32,32); 29 | 30 | memmove(m,sm,smlen); 31 | memmove(m + 32,pkcopy,32); 32 | crypto_hash_sha512(h,m,smlen); 33 | sc_reduce(h); 34 | 35 | ge_double_scalarmult_vartime(&R,h,&A,scopy); 36 | ge_tobytes(rcheck,&R); 37 | if (crypto_verify_32(rcheck,rcopy) == 0) { 38 | memmove(m,m + 64,smlen - 64); 39 | memset(m + smlen - 64,0,64); 40 | *mlen = smlen - 64; 41 | return 0; 42 | } 43 | 44 | badsig: 45 | *mlen = -1; 46 | memset(m,0,smlen); 47 | return -1; 48 | } 49 | -------------------------------------------------------------------------------- /curve/ed25519/additions/sign_modified.c~: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../nacl_includes/crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "ge.h" 5 | #include "sc.h" 6 | #include "zeroize.h" 7 | 8 | /* NEW: Compare to pristine crypto_sign() 9 | Uses explicit private key for nonce derivation and as scalar, 10 | instead of deriving both from a master key. 11 | */ 12 | int crypto_sign_modified( 13 | unsigned char *sm, 14 | const unsigned char *m,unsigned long long mlen, 15 | const unsigned char *sk, const unsigned char* pk, 16 | const unsigned char* random 17 | ) 18 | { 19 | unsigned char nonce[64]; 20 | unsigned char hram[64]; 21 | ge_p3 R; 22 | int count=0; 23 | 24 | memmove(sm + 64,m,mlen); 25 | memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */ 26 | 27 | /* NEW : add prefix to separate hash uses - see .h */ 28 | sm[0] = 0xFE; 29 | for (count = 1; count < 32; count++) 30 | sm[count] = 0xFF; 31 | 32 | /* NEW: add suffix of random data */ 33 | memmove(sm + mlen + 64, random, 64); 34 | 35 | crypto_hash_sha512(nonce,sm,mlen + 128); 36 | memmove(sm + 32,pk,32); 37 | 38 | sc_reduce(nonce); 39 | ge_scalarmult_base(&R,nonce); 40 | ge_p3_tobytes(sm,&R); 41 | 42 | crypto_hash_sha512(hram,sm,mlen + 64); 43 | sc_reduce(hram); 44 | sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */ 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /curve/ed25519/additions/sign_modified.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../nacl_includes/crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "../ge.h" 5 | #include "../sc.h" 6 | #include "zeroize.h" 7 | 8 | /* NEW: Compare to pristine crypto_sign() 9 | Uses explicit private key for nonce derivation and as scalar, 10 | instead of deriving both from a master key. 11 | */ 12 | int crypto_sign_modified( 13 | unsigned char *sm, 14 | const unsigned char *m,unsigned long long mlen, 15 | const unsigned char *sk, const unsigned char* pk, 16 | const unsigned char* random 17 | ) 18 | { 19 | unsigned char nonce[64]; 20 | unsigned char hram[64]; 21 | ge_p3 R; 22 | int count=0; 23 | 24 | memmove(sm + 64,m,mlen); 25 | memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */ 26 | 27 | /* NEW : add prefix to separate hash uses - see .h */ 28 | sm[0] = 0xFE; 29 | for (count = 1; count < 32; count++) 30 | sm[count] = 0xFF; 31 | 32 | /* NEW: add suffix of random data */ 33 | memmove(sm + mlen + 64, random, 64); 34 | 35 | crypto_hash_sha512(nonce,sm,mlen + 128); 36 | memmove(sm + 32,pk,32); 37 | 38 | sc_reduce(nonce); 39 | ge_scalarmult_base(&R,nonce); 40 | ge_p3_tobytes(sm,&R); 41 | 42 | crypto_hash_sha512(hram,sm,mlen + 64); 43 | sc_reduce(hram); 44 | sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */ 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /curve/ed25519/fe_add.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f + g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_add(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 + g0; 38 | crypto_int32 h1 = f1 + g1; 39 | crypto_int32 h2 = f2 + g2; 40 | crypto_int32 h3 = f3 + g3; 41 | crypto_int32 h4 = f4 + g4; 42 | crypto_int32 h5 = f5 + g5; 43 | crypto_int32 h6 = f6 + g6; 44 | crypto_int32 h7 = f7 + g7; 45 | crypto_int32 h8 = f8 + g8; 46 | crypto_int32 h9 = f9 + g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /curve/ed25519/fe_sub.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f - g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_sub(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 - g0; 38 | crypto_int32 h1 = f1 - g1; 39 | crypto_int32 h2 = f2 - g2; 40 | crypto_int32 h3 = f3 - g3; 41 | crypto_int32 h4 = f4 - g4; 42 | crypto_int32 h5 = f5 - g5; 43 | crypto_int32 h6 = f6 - g6; 44 | crypto_int32 h7 = f7 - g7; 45 | crypto_int32 h8 = f8 - g8; 46 | crypto_int32 h9 = f9 - g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /curve/ed25519/fe_cmov.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Replace (f,g) with (g,g) if b == 1; 5 | replace (f,g) with (f,g) if b == 0. 6 | 7 | Preconditions: b in {0,1}. 8 | */ 9 | 10 | void fe_cmov(fe f,const fe g,unsigned int b) 11 | { 12 | crypto_int32 f0 = f[0]; 13 | crypto_int32 f1 = f[1]; 14 | crypto_int32 f2 = f[2]; 15 | crypto_int32 f3 = f[3]; 16 | crypto_int32 f4 = f[4]; 17 | crypto_int32 f5 = f[5]; 18 | crypto_int32 f6 = f[6]; 19 | crypto_int32 f7 = f[7]; 20 | crypto_int32 f8 = f[8]; 21 | crypto_int32 f9 = f[9]; 22 | crypto_int32 g0 = g[0]; 23 | crypto_int32 g1 = g[1]; 24 | crypto_int32 g2 = g[2]; 25 | crypto_int32 g3 = g[3]; 26 | crypto_int32 g4 = g[4]; 27 | crypto_int32 g5 = g[5]; 28 | crypto_int32 g6 = g[6]; 29 | crypto_int32 g7 = g[7]; 30 | crypto_int32 g8 = g[8]; 31 | crypto_int32 g9 = g[9]; 32 | crypto_int32 x0 = f0 ^ g0; 33 | crypto_int32 x1 = f1 ^ g1; 34 | crypto_int32 x2 = f2 ^ g2; 35 | crypto_int32 x3 = f3 ^ g3; 36 | crypto_int32 x4 = f4 ^ g4; 37 | crypto_int32 x5 = f5 ^ g5; 38 | crypto_int32 x6 = f6 ^ g6; 39 | crypto_int32 x7 = f7 ^ g7; 40 | crypto_int32 x8 = f8 ^ g8; 41 | crypto_int32 x9 = f9 ^ g9; 42 | b = -b; 43 | x0 &= b; 44 | x1 &= b; 45 | x2 &= b; 46 | x3 &= b; 47 | x4 &= b; 48 | x5 &= b; 49 | x6 &= b; 50 | x7 &= b; 51 | x8 &= b; 52 | x9 &= b; 53 | f[0] = f0 ^ x0; 54 | f[1] = f1 ^ x1; 55 | f[2] = f2 ^ x2; 56 | f[3] = f3 ^ x3; 57 | f[4] = f4 ^ x4; 58 | f[5] = f5 ^ x5; 59 | f[6] = f6 ^ x6; 60 | f[7] = f7 ^ x7; 61 | f[8] = f8 ^ x8; 62 | f[9] = f9 ^ x9; 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curve25519 extension for PHP 2 | 3 | ![php](https://img.shields.io/badge/php-%3E%3D%207.0-blue.svg) [![sponsor](https://img.shields.io/badge/-Become%20a%20sponsor%20❤-ff6964)](https://github.com/sponsors/mgp25) 4 | 5 | Curve25519 library with Ed25519 signatures extension for PHP. It supports PHP 8. 6 | 7 | ## Usage 8 | 9 | ```php 10 | $randomBytes = random_bytes(32); 11 | $private = curve25519_private($randomBytes); 12 | $public = curve25519_public($private); 13 | 14 | $agreement = curve25519_shared($private, $public); 15 | $signature = curve25519_sign(random_bytes(64), $private, $message); 16 | $verified = curve25519_verify($public, $message, $signature) == 0; 17 | ``` 18 | 19 | If you are using it in combination with [LibSignal for PHP](https://github.com/mgp25/libsignal-php): 20 | 21 | ```php 22 | $randomBytes = random_bytes(32); 23 | $private = curve25519_private($randomBytes); 24 | $public = curve25519_public($private); 25 | $keyPair = new ECKeyPair(new DjbECPublicKey($public), new DjbECPrivateKey($private)); 26 | 27 | $agreement = curve25519_shared($keyPair->getPrivateKey(), $keyPair->getPublicKey()); 28 | $signature = curve25519_sign(random_bytes(64), $signingKey->getPrivateKey(), $message); 29 | $verified = curve25519_verify($signingKey->getPublicKey(), $message, $signature) == 0; 30 | ``` 31 | 32 | # Installation 33 | ## Linux and MacOS 34 | 35 | ``` 36 | phpize 37 | ./configure 38 | make 39 | sudo make install 40 | ``` 41 | 42 | When installed, make sure to add it in your `php.ini` env: 43 | 44 | ``` 45 | php --ini # will reveal your .ini path 46 | # Edit the file and add: 47 | extension=curve25519 48 | ``` 49 | -------------------------------------------------------------------------------- /curve/ed25519/ge_p2_dbl.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_p2_dbl */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe A */ 11 | 12 | /* qhasm: fe AA */ 13 | 14 | /* qhasm: fe XX */ 15 | 16 | /* qhasm: fe YY */ 17 | 18 | /* qhasm: fe B */ 19 | 20 | /* qhasm: fe X3 */ 21 | 22 | /* qhasm: fe Y3 */ 23 | 24 | /* qhasm: fe Z3 */ 25 | 26 | /* qhasm: fe T3 */ 27 | 28 | /* qhasm: XX=X1^2 */ 29 | /* asm 1: fe_sq(>XX=fe#1,XX=r->X,X); */ 31 | fe_sq(r->X,p->X); 32 | 33 | /* qhasm: YY=Y1^2 */ 34 | /* asm 1: fe_sq(>YY=fe#3,YY=r->Z,Y); */ 36 | fe_sq(r->Z,p->Y); 37 | 38 | /* qhasm: B=2*Z1^2 */ 39 | /* asm 1: fe_sq2(>B=fe#4,B=r->T,Z); */ 41 | fe_sq2(r->T,p->Z); 42 | 43 | /* qhasm: A=X1+Y1 */ 44 | /* asm 1: fe_add(>A=fe#2,A=r->Y,X,Y); */ 46 | fe_add(r->Y,p->X,p->Y); 47 | 48 | /* qhasm: AA=A^2 */ 49 | /* asm 1: fe_sq(>AA=fe#5,AA=t0,Y); */ 51 | fe_sq(t0,r->Y); 52 | 53 | /* qhasm: Y3=YY+XX */ 54 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,X); */ 56 | fe_add(r->Y,r->Z,r->X); 57 | 58 | /* qhasm: Z3=YY-XX */ 59 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,Z,X); */ 61 | fe_sub(r->Z,r->Z,r->X); 62 | 63 | /* qhasm: X3=AA-Y3 */ 64 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Y); */ 66 | fe_sub(r->X,t0,r->Y); 67 | 68 | /* qhasm: T3=B-Z3 */ 69 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T,Z); */ 71 | fe_sub(r->T,r->T,r->Z); 72 | 73 | /* qhasm: return */ 74 | -------------------------------------------------------------------------------- /curve/ed25519/additions/curve_sigs.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CURVE_SIGS_H__ 3 | #define __CURVE_SIGS_H__ 4 | 5 | #define MAX_MSG_LEN 8192 6 | 7 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ 8 | const unsigned char* curve25519_privkey_in); /* 32 bytes */ 9 | 10 | /* returns 0 on success */ 11 | int curve25519_sign(unsigned char* signature_out, /* 64 bytes */ 12 | const unsigned char* curve25519_privkey, /* 32 bytes */ 13 | const unsigned char* msg, const unsigned long msg_len, 14 | const unsigned char* random); /* 64 bytes */ 15 | 16 | /* returns 0 on success */ 17 | int curve25519_verify(const unsigned char* signature, /* 64 bytes */ 18 | const unsigned char* curve25519_pubkey, /* 32 bytes */ 19 | const unsigned char* msg, const unsigned long msg_len); 20 | 21 | /* helper function - modified version of crypto_sign() to use 22 | explicit private key. In particular: 23 | 24 | sk : private key 25 | pk : public key 26 | msg : message 27 | prefix : 0xFE || [0xFF]*31 28 | random : 64 bytes random 29 | q : main subgroup order 30 | 31 | The prefix is chosen to distinguish the two SHA512 uses below, since 32 | prefix is an invalid encoding for R (it would encode a "field element" 33 | of 2^255 - 2). 0xFF*32 is set aside for use in ECDH protocols, which 34 | is why the first byte here ix 0xFE. 35 | 36 | sig_nonce = SHA512(prefix || sk || msg || random) % q 37 | R = g^sig_nonce 38 | M = SHA512(R || pk || m) 39 | S = sig_nonce + (m * sk) 40 | signature = (R || S) 41 | */ 42 | int crypto_sign_modified( 43 | unsigned char *sm, 44 | const unsigned char *m,unsigned long long mlen, 45 | const unsigned char *sk, /* Curve/Ed25519 private key */ 46 | const unsigned char *pk, /* Ed25519 public key */ 47 | const unsigned char *random /* 64 bytes random to hash into nonce */ 48 | ); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_sha512/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | 20080913 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #include 8 | typedef uint64_t uint64; 9 | 10 | extern int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen); 11 | 12 | #define blocks crypto_hashblocks_sha512 13 | 14 | static const unsigned char iv[64] = { 15 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, 16 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, 17 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, 18 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, 19 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, 20 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, 21 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, 22 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 23 | } ; 24 | 25 | int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen) 26 | { 27 | unsigned char h[64]; 28 | unsigned char padded[256]; 29 | int i; 30 | unsigned long long bytes = inlen; 31 | 32 | for (i = 0;i < 64;++i) h[i] = iv[i]; 33 | 34 | blocks(h,in,inlen); 35 | in += inlen; 36 | inlen &= 127; 37 | in -= inlen; 38 | 39 | for (i = 0;i < inlen;++i) padded[i] = in[i]; 40 | padded[inlen] = 0x80; 41 | 42 | if (inlen < 112) { 43 | for (i = inlen + 1;i < 119;++i) padded[i] = 0; 44 | padded[119] = bytes >> 61; 45 | padded[120] = bytes >> 53; 46 | padded[121] = bytes >> 45; 47 | padded[122] = bytes >> 37; 48 | padded[123] = bytes >> 29; 49 | padded[124] = bytes >> 21; 50 | padded[125] = bytes >> 13; 51 | padded[126] = bytes >> 5; 52 | padded[127] = bytes << 3; 53 | blocks(h,padded,128); 54 | } else { 55 | for (i = inlen + 1;i < 247;++i) padded[i] = 0; 56 | padded[247] = bytes >> 61; 57 | padded[248] = bytes >> 53; 58 | padded[249] = bytes >> 45; 59 | padded[250] = bytes >> 37; 60 | padded[251] = bytes >> 29; 61 | padded[252] = bytes >> 21; 62 | padded[253] = bytes >> 13; 63 | padded[254] = bytes >> 5; 64 | padded[255] = bytes << 3; 65 | blocks(h,padded,256); 66 | } 67 | 68 | for (i = 0;i < 64;++i) out[i] = h[i]; 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /curve/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "nacl_includes/crypto_int32.h" 5 | 6 | typedef crypto_int32 fe[10]; 7 | 8 | /* 9 | fe means field element. 10 | Here the field is \Z/(2^255-19). 11 | An element t, entries t[0]...t[9], represents the integer 12 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 13 | Bounds on each t[i] vary depending on context. 14 | */ 15 | 16 | #define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes 17 | #define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes 18 | #define fe_copy crypto_sign_ed25519_ref10_fe_copy 19 | #define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero 20 | #define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative 21 | #define fe_0 crypto_sign_ed25519_ref10_fe_0 22 | #define fe_1 crypto_sign_ed25519_ref10_fe_1 23 | #define fe_cswap crypto_sign_ed25519_ref10_fe_cswap 24 | #define fe_cmov crypto_sign_ed25519_ref10_fe_cmov 25 | #define fe_add crypto_sign_ed25519_ref10_fe_add 26 | #define fe_sub crypto_sign_ed25519_ref10_fe_sub 27 | #define fe_neg crypto_sign_ed25519_ref10_fe_neg 28 | #define fe_mul crypto_sign_ed25519_ref10_fe_mul 29 | #define fe_sq crypto_sign_ed25519_ref10_fe_sq 30 | #define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2 31 | #define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666 32 | #define fe_invert crypto_sign_ed25519_ref10_fe_invert 33 | #define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523 34 | 35 | extern void fe_frombytes(fe,const unsigned char *); 36 | extern void fe_tobytes(unsigned char *,const fe); 37 | 38 | extern void fe_copy(fe,const fe); 39 | extern int fe_isnonzero(const fe); 40 | extern int fe_isnegative(const fe); 41 | extern void fe_0(fe); 42 | extern void fe_1(fe); 43 | extern void fe_cswap(fe,fe,unsigned int); 44 | extern void fe_cmov(fe,const fe,unsigned int); 45 | 46 | extern void fe_add(fe,const fe,const fe); 47 | extern void fe_sub(fe,const fe,const fe); 48 | extern void fe_neg(fe,const fe); 49 | extern void fe_mul(fe,const fe,const fe); 50 | extern void fe_sq(fe,const fe); 51 | extern void fe_sq2(fe,const fe); 52 | extern void fe_mul121666(fe,const fe); 53 | extern void fe_invert(fe,const fe); 54 | extern void fe_pow22523(fe,const fe); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_includes/crypto_sign_edwards25519sha512batch.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_edwards25519sha512batch_H 2 | #define crypto_sign_edwards25519sha512batch_H 3 | 4 | #define crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 64 5 | #define crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 32 6 | #define crypto_sign_edwards25519sha512batch_ref10_BYTES 64 7 | #ifdef __cplusplus 8 | #include 9 | extern std::string crypto_sign_edwards25519sha512batch_ref10(const std::string &,const std::string &); 10 | extern std::string crypto_sign_edwards25519sha512batch_ref10_open(const std::string &,const std::string &); 11 | extern std::string crypto_sign_edwards25519sha512batch_ref10_keypair(std::string *); 12 | extern "C" { 13 | #endif 14 | extern int crypto_sign_edwards25519sha512batch_ref10(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 15 | extern int crypto_sign_edwards25519sha512batch_ref10_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); 16 | extern int crypto_sign_edwards25519sha512batch_ref10_keypair(unsigned char *,unsigned char *); 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #define crypto_sign_edwards25519sha512batch crypto_sign_edwards25519sha512batch_ref10 22 | #define crypto_sign_edwards25519sha512batch_open crypto_sign_edwards25519sha512batch_ref10_open 23 | #define crypto_sign_edwards25519sha512batch_keypair crypto_sign_edwards25519sha512batch_ref10_keypair 24 | #define crypto_sign_edwards25519sha512batch_BYTES crypto_sign_edwards25519sha512batch_ref10_BYTES 25 | #define crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 26 | #define crypto_sign_edwards25519sha512batch_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 27 | #define crypto_sign_edwards25519sha512batch_IMPLEMENTATION "crypto_sign/edwards25519sha512batch/ref10" 28 | #ifndef crypto_sign_edwards25519sha512batch_ref10_VERSION 29 | #define crypto_sign_edwards25519sha512batch_ref10_VERSION "-" 30 | #endif 31 | #define crypto_sign_edwards25519sha512batch_VERSION crypto_sign_edwards25519sha512batch_ref10_VERSION 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /curve/ed25519/ge_madd.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_madd */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ypx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yplusx); */ 51 | fe_mul(r->Z,r->X,q->yplusx); 52 | 53 | /* qhasm: B = YmX1*ymx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yminusx); */ 56 | fe_mul(r->Y,r->Y,q->yminusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D+C */ 79 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_add(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D-C */ 84 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 86 | fe_sub(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /curve/ed25519/ge_msub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_msub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ymx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yminusx); */ 51 | fe_mul(r->Z,r->X,q->yminusx); 52 | 53 | /* qhasm: B = YmX1*ypx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yplusx); */ 56 | fe_mul(r->Y,r->Y,q->yplusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D-C */ 79 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_sub(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D+C */ 84 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 86 | fe_add(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /curve/ed25519/ge_add.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_add */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YpX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YplusX); */ 55 | fe_mul(r->Z,r->X,q->YplusX); 56 | 57 | /* qhasm: B = YmX1*YmX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YminusX); */ 60 | fe_mul(r->Y,r->Y,q->YminusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D+C */ 88 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_add(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D-C */ 93 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 95 | fe_sub(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /curve/ed25519/ge_sub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_sub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YmX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YminusX); */ 55 | fe_mul(r->Z,r->X,q->YminusX); 56 | 57 | /* qhasm: B = YmX1*YpX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YplusX); */ 60 | fe_mul(r->Y,r->Y,q->YplusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D-C */ 88 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_sub(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D+C */ 93 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 95 | fe_add(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /curve/ed25519/base2.h: -------------------------------------------------------------------------------- 1 | { 2 | { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, 3 | { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, 4 | { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, 5 | }, 6 | { 7 | { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, 8 | { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, 9 | { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, 10 | }, 11 | { 12 | { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, 13 | { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, 14 | { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, 15 | }, 16 | { 17 | { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, 18 | { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, 19 | { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, 20 | }, 21 | { 22 | { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, 23 | { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, 24 | { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 }, 25 | }, 26 | { 27 | { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, 28 | { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, 29 | { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 }, 30 | }, 31 | { 32 | { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, 33 | { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, 34 | { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 }, 35 | }, 36 | { 37 | { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, 38 | { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, 39 | { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, 40 | }, 41 | -------------------------------------------------------------------------------- /curve/ed25519/fe_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | #include "nacl_includes/crypto_uint64.h" 4 | 5 | static crypto_uint64 load_3(const unsigned char *in) 6 | { 7 | crypto_uint64 result; 8 | result = (crypto_uint64) in[0]; 9 | result |= ((crypto_uint64) in[1]) << 8; 10 | result |= ((crypto_uint64) in[2]) << 16; 11 | return result; 12 | } 13 | 14 | static crypto_uint64 load_4(const unsigned char *in) 15 | { 16 | crypto_uint64 result; 17 | result = (crypto_uint64) in[0]; 18 | result |= ((crypto_uint64) in[1]) << 8; 19 | result |= ((crypto_uint64) in[2]) << 16; 20 | result |= ((crypto_uint64) in[3]) << 24; 21 | return result; 22 | } 23 | 24 | /* 25 | Ignores top bit of h. 26 | */ 27 | 28 | void fe_frombytes(fe h,const unsigned char *s) 29 | { 30 | crypto_int64 h0 = load_4(s); 31 | crypto_int64 h1 = load_3(s + 4) << 6; 32 | crypto_int64 h2 = load_3(s + 7) << 5; 33 | crypto_int64 h3 = load_3(s + 10) << 3; 34 | crypto_int64 h4 = load_3(s + 13) << 2; 35 | crypto_int64 h5 = load_4(s + 16); 36 | crypto_int64 h6 = load_3(s + 20) << 7; 37 | crypto_int64 h7 = load_3(s + 23) << 5; 38 | crypto_int64 h8 = load_3(s + 26) << 4; 39 | crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; 40 | crypto_int64 carry0; 41 | crypto_int64 carry1; 42 | crypto_int64 carry2; 43 | crypto_int64 carry3; 44 | crypto_int64 carry4; 45 | crypto_int64 carry5; 46 | crypto_int64 carry6; 47 | crypto_int64 carry7; 48 | crypto_int64 carry8; 49 | crypto_int64 carry9; 50 | 51 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 52 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 53 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 54 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 55 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 56 | 57 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 58 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 59 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 60 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 61 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 62 | 63 | h[0] = h0; 64 | h[1] = h1; 65 | h[2] = h2; 66 | h[3] = h3; 67 | h[4] = h4; 68 | h[5] = h5; 69 | h[6] = h6; 70 | h[7] = h7; 71 | h[8] = h8; 72 | h[9] = h9; 73 | } 74 | -------------------------------------------------------------------------------- /curve/ed25519/ge_double_scalarmult.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static void slide(signed char *r,const unsigned char *a) 4 | { 5 | int i; 6 | int b; 7 | int k; 8 | 9 | for (i = 0;i < 256;++i) 10 | r[i] = 1 & (a[i >> 3] >> (i & 7)); 11 | 12 | for (i = 0;i < 256;++i) 13 | if (r[i]) { 14 | for (b = 1;b <= 6 && i + b < 256;++b) { 15 | if (r[i + b]) { 16 | if (r[i] + (r[i + b] << b) <= 15) { 17 | r[i] += r[i + b] << b; r[i + b] = 0; 18 | } else if (r[i] - (r[i + b] << b) >= -15) { 19 | r[i] -= r[i + b] << b; 20 | for (k = i + b;k < 256;++k) { 21 | if (!r[k]) { 22 | r[k] = 1; 23 | break; 24 | } 25 | r[k] = 0; 26 | } 27 | } else 28 | break; 29 | } 30 | } 31 | } 32 | 33 | } 34 | 35 | static ge_precomp Bi[8] = { 36 | #include "base2.h" 37 | } ; 38 | 39 | /* 40 | r = a * A + b * B 41 | where a = a[0]+256*a[1]+...+256^31 a[31]. 42 | and b = b[0]+256*b[1]+...+256^31 b[31]. 43 | B is the Ed25519 base point (x,4/5) with x positive. 44 | */ 45 | 46 | void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b) 47 | { 48 | signed char aslide[256]; 49 | signed char bslide[256]; 50 | ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ 51 | ge_p1p1 t; 52 | ge_p3 u; 53 | ge_p3 A2; 54 | int i; 55 | 56 | slide(aslide,a); 57 | slide(bslide,b); 58 | 59 | ge_p3_to_cached(&Ai[0],A); 60 | ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); 61 | ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); 62 | ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); 63 | ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); 64 | ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); 65 | ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); 66 | ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); 67 | ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); 68 | 69 | ge_p2_0(r); 70 | 71 | for (i = 255;i >= 0;--i) { 72 | if (aslide[i] || bslide[i]) break; 73 | } 74 | 75 | for (;i >= 0;--i) { 76 | ge_p2_dbl(&t,r); 77 | 78 | if (aslide[i] > 0) { 79 | ge_p1p1_to_p3(&u,&t); 80 | ge_add(&t,&u,&Ai[aslide[i]/2]); 81 | } else if (aslide[i] < 0) { 82 | ge_p1p1_to_p3(&u,&t); 83 | ge_sub(&t,&u,&Ai[(-aslide[i])/2]); 84 | } 85 | 86 | if (bslide[i] > 0) { 87 | ge_p1p1_to_p3(&u,&t); 88 | ge_madd(&t,&u,&Bi[bslide[i]/2]); 89 | } else if (bslide[i] < 0) { 90 | ge_p1p1_to_p3(&u,&t); 91 | ge_msub(&t,&u,&Bi[(-bslide[i])/2]); 92 | } 93 | 94 | ge_p1p1_to_p2(r,&t); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /curve/ed25519/ge_scalarmult_base.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | #include "nacl_includes/crypto_uint32.h" 3 | 4 | static unsigned char equal(signed char b,signed char c) 5 | { 6 | unsigned char ub = b; 7 | unsigned char uc = c; 8 | unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ 9 | crypto_uint32 y = x; /* 0: yes; 1..255: no */ 10 | y -= 1; /* 4294967295: yes; 0..254: no */ 11 | y >>= 31; /* 1: yes; 0: no */ 12 | return y; 13 | } 14 | 15 | static unsigned char negative(signed char b) 16 | { 17 | unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 18 | x >>= 63; /* 1: yes; 0: no */ 19 | return x; 20 | } 21 | 22 | static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) 23 | { 24 | fe_cmov(t->yplusx,u->yplusx,b); 25 | fe_cmov(t->yminusx,u->yminusx,b); 26 | fe_cmov(t->xy2d,u->xy2d,b); 27 | } 28 | 29 | /* base[i][j] = (j+1)*256^i*B */ 30 | static ge_precomp base[32][8] = { 31 | #include "base.h" 32 | } ; 33 | 34 | static void select(ge_precomp *t,int pos,signed char b) 35 | { 36 | ge_precomp minust; 37 | unsigned char bnegative = negative(b); 38 | unsigned char babs = b - (((-bnegative) & b) << 1); 39 | 40 | ge_precomp_0(t); 41 | cmov(t,&base[pos][0],equal(babs,1)); 42 | cmov(t,&base[pos][1],equal(babs,2)); 43 | cmov(t,&base[pos][2],equal(babs,3)); 44 | cmov(t,&base[pos][3],equal(babs,4)); 45 | cmov(t,&base[pos][4],equal(babs,5)); 46 | cmov(t,&base[pos][5],equal(babs,6)); 47 | cmov(t,&base[pos][6],equal(babs,7)); 48 | cmov(t,&base[pos][7],equal(babs,8)); 49 | fe_copy(minust.yplusx,t->yminusx); 50 | fe_copy(minust.yminusx,t->yplusx); 51 | fe_neg(minust.xy2d,t->xy2d); 52 | cmov(t,&minust,bnegative); 53 | } 54 | 55 | /* 56 | h = a * B 57 | where a = a[0]+256*a[1]+...+256^31 a[31] 58 | B is the Ed25519 base point (x,4/5) with x positive. 59 | 60 | Preconditions: 61 | a[31] <= 127 62 | */ 63 | 64 | void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) 65 | { 66 | signed char e[64]; 67 | signed char carry; 68 | ge_p1p1 r; 69 | ge_p2 s; 70 | ge_precomp t; 71 | int i; 72 | 73 | for (i = 0;i < 32;++i) { 74 | e[2 * i + 0] = (a[i] >> 0) & 15; 75 | e[2 * i + 1] = (a[i] >> 4) & 15; 76 | } 77 | /* each e[i] is between 0 and 15 */ 78 | /* e[63] is between 0 and 7 */ 79 | 80 | carry = 0; 81 | for (i = 0;i < 63;++i) { 82 | e[i] += carry; 83 | carry = e[i] + 8; 84 | carry >>= 4; 85 | e[i] -= carry << 4; 86 | } 87 | e[63] += carry; 88 | /* each e[i] is between -8 and 8 */ 89 | 90 | ge_p3_0(h); 91 | for (i = 1;i < 64;i += 2) { 92 | select(&t,i / 2,e[i]); 93 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 94 | } 95 | 96 | ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); 97 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 98 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 99 | ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); 100 | 101 | for (i = 0;i < 64;i += 2) { 102 | select(&t,i / 2,e[i]); 103 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /curve/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | /* 5 | ge means group element. 6 | 7 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 8 | satisfying -x^2 + y^2 = 1 + d x^2y^2 9 | where d = -121665/121666. 10 | 11 | Representations: 12 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 13 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 14 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 15 | ge_precomp (Duif): (y+x,y-x,2dxy) 16 | */ 17 | 18 | #include "fe.h" 19 | 20 | typedef struct { 21 | fe X; 22 | fe Y; 23 | fe Z; 24 | } ge_p2; 25 | 26 | typedef struct { 27 | fe X; 28 | fe Y; 29 | fe Z; 30 | fe T; 31 | } ge_p3; 32 | 33 | typedef struct { 34 | fe X; 35 | fe Y; 36 | fe Z; 37 | fe T; 38 | } ge_p1p1; 39 | 40 | typedef struct { 41 | fe yplusx; 42 | fe yminusx; 43 | fe xy2d; 44 | } ge_precomp; 45 | 46 | typedef struct { 47 | fe YplusX; 48 | fe YminusX; 49 | fe Z; 50 | fe T2d; 51 | } ge_cached; 52 | 53 | #define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime 54 | #define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes 55 | #define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes 56 | 57 | #define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0 58 | #define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0 59 | #define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0 60 | #define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2 61 | #define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached 62 | #define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2 63 | #define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3 64 | #define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl 65 | #define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl 66 | 67 | #define ge_madd crypto_sign_ed25519_ref10_ge_madd 68 | #define ge_msub crypto_sign_ed25519_ref10_ge_msub 69 | #define ge_add crypto_sign_ed25519_ref10_ge_add 70 | #define ge_sub crypto_sign_ed25519_ref10_ge_sub 71 | #define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base 72 | #define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime 73 | 74 | extern void ge_tobytes(unsigned char *,const ge_p2 *); 75 | extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); 76 | extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); 77 | 78 | extern void ge_p2_0(ge_p2 *); 79 | extern void ge_p3_0(ge_p3 *); 80 | extern void ge_precomp_0(ge_precomp *); 81 | extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *); 82 | extern void ge_p3_to_cached(ge_cached *,const ge_p3 *); 83 | extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); 84 | extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); 85 | extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); 86 | extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); 87 | 88 | extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 89 | extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 90 | extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); 91 | extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); 92 | extern void ge_scalarmult_base(ge_p3 *,const unsigned char *); 93 | extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /curve/ed25519/main/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "crypto_hash_sha512.h" 4 | #include "curve_sigs.h" 5 | 6 | #define MSG_LEN 200 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | unsigned char privkey[32]; 11 | unsigned char pubkey[32]; 12 | unsigned char signature[64]; 13 | unsigned char msg[MSG_LEN]; 14 | unsigned char random[64]; 15 | 16 | /* Initialize pubkey, privkey, msg */ 17 | memset(msg, 0, MSG_LEN); 18 | memset(privkey, 0, 32); 19 | memset(pubkey, 0, 32); 20 | privkey[0] &= 248; 21 | privkey[31] &= 63; 22 | privkey[31] |= 64; 23 | 24 | privkey[8] = 189; /* just so there's some bits set */ 25 | 26 | 27 | /* SHA512 test */ 28 | unsigned char sha512_input[112] = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; 29 | unsigned char sha512_correct_output[64] = 30 | { 31 | 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 32 | 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 33 | 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 34 | 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 35 | 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 36 | 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 37 | 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 38 | 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 39 | }; 40 | unsigned char sha512_actual_output[64]; 41 | 42 | crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input)); 43 | if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0) 44 | printf("SHA512 bad #1\n"); 45 | else 46 | printf("SHA512 good #1\n"); 47 | 48 | sha512_input[111] ^= 1; 49 | 50 | crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input)); 51 | if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0) 52 | printf("SHA512 good #2\n"); 53 | else 54 | printf("SHA512 bad #2\n"); 55 | 56 | /* Signature test */ 57 | curve25519_keygen(pubkey, privkey); 58 | 59 | curve25519_sign(signature, privkey, msg, MSG_LEN, random); 60 | 61 | if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0) 62 | printf("Signature good #1\n"); 63 | else 64 | printf("Signature bad #1\n"); 65 | 66 | signature[0] ^= 1; 67 | 68 | if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0) 69 | printf("Signature bad #2\n"); 70 | else 71 | printf("Signature good #2\n"); 72 | 73 | 74 | printf("Random testing...\n"); 75 | for (int count = 0; count < 10000; count++) { 76 | unsigned char b[64]; 77 | crypto_hash_sha512(b, privkey, 32); 78 | memmove(privkey, b, 32); 79 | crypto_hash_sha512(b, privkey, 32); 80 | memmove(random, b, 64); 81 | 82 | privkey[0] &= 248; 83 | privkey[31] &= 63; 84 | privkey[31] |= 64; 85 | 86 | curve25519_keygen(pubkey, privkey); 87 | 88 | curve25519_sign(signature, privkey, msg, MSG_LEN, random); 89 | 90 | if (curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0) { 91 | printf("failure #1 %d\n", count); 92 | return -1; 93 | } 94 | 95 | if (b[63] & 1) 96 | signature[count % 64] ^= 1; 97 | else 98 | msg[count % MSG_LEN] ^= 1; 99 | if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0) { 100 | printf("failure #2 %d\n", count); 101 | return -1; 102 | } 103 | } 104 | printf("OK\n"); 105 | return 1; 106 | } 107 | -------------------------------------------------------------------------------- /curve/ed25519/fe_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Preconditions: 5 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 6 | 7 | Write p=2^255-19; q=floor(h/p). 8 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 9 | 10 | Proof: 11 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 12 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 13 | 14 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 15 | Then 0> 25; 53 | q = (h0 + q) >> 26; 54 | q = (h1 + q) >> 25; 55 | q = (h2 + q) >> 26; 56 | q = (h3 + q) >> 25; 57 | q = (h4 + q) >> 26; 58 | q = (h5 + q) >> 25; 59 | q = (h6 + q) >> 26; 60 | q = (h7 + q) >> 25; 61 | q = (h8 + q) >> 26; 62 | q = (h9 + q) >> 25; 63 | 64 | /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ 65 | h0 += 19 * q; 66 | /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ 67 | 68 | carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; 69 | carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; 70 | carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; 71 | carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; 72 | carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; 73 | carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; 74 | carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; 75 | carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; 76 | carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; 77 | carry9 = h9 >> 25; h9 -= carry9 << 25; 78 | /* h10 = carry9 */ 79 | 80 | /* 81 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 82 | Have h0+...+2^230 h9 between 0 and 2^255-1; 83 | evidently 2^255 h10-2^255 q = 0. 84 | Goal: Output h0+...+2^230 h9. 85 | */ 86 | 87 | s[0] = h0 >> 0; 88 | s[1] = h0 >> 8; 89 | s[2] = h0 >> 16; 90 | s[3] = (h0 >> 24) | (h1 << 2); 91 | s[4] = h1 >> 6; 92 | s[5] = h1 >> 14; 93 | s[6] = (h1 >> 22) | (h2 << 3); 94 | s[7] = h2 >> 5; 95 | s[8] = h2 >> 13; 96 | s[9] = (h2 >> 21) | (h3 << 5); 97 | s[10] = h3 >> 3; 98 | s[11] = h3 >> 11; 99 | s[12] = (h3 >> 19) | (h4 << 6); 100 | s[13] = h4 >> 2; 101 | s[14] = h4 >> 10; 102 | s[15] = h4 >> 18; 103 | s[16] = h5 >> 0; 104 | s[17] = h5 >> 8; 105 | s[18] = h5 >> 16; 106 | s[19] = (h5 >> 24) | (h6 << 1); 107 | s[20] = h6 >> 7; 108 | s[21] = h6 >> 15; 109 | s[22] = (h6 >> 23) | (h7 << 3); 110 | s[23] = h7 >> 5; 111 | s[24] = h7 >> 13; 112 | s[25] = (h7 >> 21) | (h8 << 4); 113 | s[26] = h8 >> 4; 114 | s[27] = h8 >> 12; 115 | s[28] = (h8 >> 20) | (h9 << 6); 116 | s[29] = h9 >> 2; 117 | s[30] = h9 >> 10; 118 | s[31] = h9 >> 18; 119 | } 120 | -------------------------------------------------------------------------------- /curve/ed25519/additions/curve_sigs.c~: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ge.h" 3 | #include "curve_sigs.h" 4 | #include "crypto_sign.h" 5 | 6 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, 7 | const unsigned char* curve25519_privkey_in) 8 | { 9 | ge_p3 ed; /* Ed25519 pubkey point */ 10 | fe ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y; 11 | fe mont_x; 12 | 13 | /* Perform a fixed-base multiplication of the Edwards base point, 14 | (which is efficient due to precalculated tables), then convert 15 | to the Curve25519 montgomery-format public key. In particular, 16 | convert Curve25519's "montgomery" x-coordinate into an Ed25519 17 | "edwards" y-coordinate: 18 | 19 | mont_x = (ed_y + 1) / (1 - ed_y) 20 | 21 | with projective coordinates: 22 | 23 | mont_x = (ed_y + ed_z) / (ed_z - ed_y) 24 | 25 | NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp 26 | */ 27 | 28 | ge_scalarmult_base(&ed, curve25519_privkey_in); 29 | fe_add(ed_y_plus_one, ed.Y, ed.Z); 30 | fe_sub(one_minus_ed_y, ed.Z, ed.Y); 31 | fe_invert(inv_one_minus_ed_y, one_minus_ed_y); 32 | fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y); 33 | fe_tobytes(curve25519_pubkey_out, mont_x); 34 | } 35 | 36 | int curve25519_sign(unsigned char* signature_out, 37 | const unsigned char* curve25519_privkey, 38 | const unsigned char* msg, const unsigned long msg_len, 39 | const unsigned char* random) 40 | { 41 | ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ 42 | unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ 43 | unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */ 44 | unsigned char sign_bit = 0; 45 | 46 | if (msg_len > MAX_MSG_LEN) { 47 | memset(signature_out, 0, 64); 48 | return -1; 49 | } 50 | 51 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 52 | ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); 53 | ge_p3_tobytes(ed_pubkey, &ed_pubkey_point); 54 | sign_bit = ed_pubkey[31] & 0x80; 55 | 56 | /* Perform an Ed25519 signature with explicit private key */ 57 | crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey, 58 | ed_pubkey, random); 59 | memmove(signature_out, sigbuf, 64); 60 | 61 | /* Encode the sign bit into signature (in unused high bit of S) */ 62 | signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ 63 | signature_out[63] |= sign_bit; 64 | return 0; 65 | } 66 | 67 | int curve25519_verify(const unsigned char* signature, 68 | const unsigned char* curve25519_pubkey, 69 | const unsigned char* msg, const unsigned long msg_len) 70 | { 71 | fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one; 72 | fe one; 73 | fe ed_y; 74 | unsigned char ed_pubkey[32]; 75 | unsigned long long some_retval; 76 | unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ 77 | unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ 78 | 79 | if (msg_len > MAX_MSG_LEN) { 80 | return -1; 81 | } 82 | 83 | /* Convert the Curve25519 public key into an Ed25519 public key. In 84 | particular, convert Curve25519's "montgomery" x-coordinate into an 85 | Ed25519 "edwards" y-coordinate: 86 | 87 | ed_y = (mont_x - 1) / (mont_x + 1) 88 | 89 | NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp 90 | 91 | Then move the sign bit into the pubkey from the signature. 92 | */ 93 | fe_frombytes(mont_x, curve25519_pubkey); 94 | fe_1(one); 95 | fe_sub(mont_x_minus_one, mont_x, one); 96 | fe_add(mont_x_plus_one, mont_x, one); 97 | fe_invert(inv_mont_x_plus_one, mont_x_plus_one); 98 | fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one); 99 | fe_tobytes(ed_pubkey, ed_y); 100 | 101 | /* Copy the sign bit, and remove it from signature */ 102 | ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ 103 | ed_pubkey[31] |= (signature[63] & 0x80); 104 | memmove(verifybuf, signature, 64); 105 | verifybuf[63] &= 0x7F; 106 | 107 | memmove(verifybuf+64, msg, msg_len); 108 | 109 | /* Then perform a normal Ed25519 verification, return 0 on success */ 110 | /* The below call has a strange API: */ 111 | /* verifybuf = R || S || message */ 112 | /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets 113 | replaced with pubkey for hashing, then the whole thing gets zeroized 114 | (if bad sig), or contains a copy of msg (good sig) */ 115 | return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); 116 | } 117 | -------------------------------------------------------------------------------- /curve/ed25519/additions/curve_sigs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../ge.h" 3 | #include "curve_sigs.h" 4 | #include "../nacl_includes/crypto_sign.h" 5 | 6 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, 7 | const unsigned char* curve25519_privkey_in) 8 | { 9 | ge_p3 ed; /* Ed25519 pubkey point */ 10 | fe ed_y_plus_one, one_minus_ed_y, inv_one_minus_ed_y; 11 | fe mont_x; 12 | 13 | /* Perform a fixed-base multiplication of the Edwards base point, 14 | (which is efficient due to precalculated tables), then convert 15 | to the Curve25519 montgomery-format public key. In particular, 16 | convert Curve25519's "montgomery" x-coordinate into an Ed25519 17 | "edwards" y-coordinate: 18 | 19 | mont_x = (ed_y + 1) / (1 - ed_y) 20 | 21 | with projective coordinates: 22 | 23 | mont_x = (ed_y + ed_z) / (ed_z - ed_y) 24 | 25 | NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp 26 | */ 27 | 28 | ge_scalarmult_base(&ed, curve25519_privkey_in); 29 | fe_add(ed_y_plus_one, ed.Y, ed.Z); 30 | fe_sub(one_minus_ed_y, ed.Z, ed.Y); 31 | fe_invert(inv_one_minus_ed_y, one_minus_ed_y); 32 | fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y); 33 | fe_tobytes(curve25519_pubkey_out, mont_x); 34 | } 35 | 36 | int curve25519_sign(unsigned char* signature_out, 37 | const unsigned char* curve25519_privkey, 38 | const unsigned char* msg, const unsigned long msg_len, 39 | const unsigned char* random) 40 | { 41 | ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ 42 | unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ 43 | unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */ 44 | unsigned char sign_bit = 0; 45 | 46 | if (msg_len > MAX_MSG_LEN) { 47 | memset(signature_out, 0, 64); 48 | return -1; 49 | } 50 | 51 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 52 | ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); 53 | ge_p3_tobytes(ed_pubkey, &ed_pubkey_point); 54 | sign_bit = ed_pubkey[31] & 0x80; 55 | 56 | /* Perform an Ed25519 signature with explicit private key */ 57 | crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey, 58 | ed_pubkey, random); 59 | memmove(signature_out, sigbuf, 64); 60 | 61 | /* Encode the sign bit into signature (in unused high bit of S) */ 62 | signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ 63 | signature_out[63] |= sign_bit; 64 | return 0; 65 | } 66 | 67 | int curve25519_verify(const unsigned char* signature, 68 | const unsigned char* curve25519_pubkey, 69 | const unsigned char* msg, const unsigned long msg_len) 70 | { 71 | fe mont_x, mont_x_minus_one, mont_x_plus_one, inv_mont_x_plus_one; 72 | fe one; 73 | fe ed_y; 74 | unsigned char ed_pubkey[32]; 75 | unsigned long long some_retval; 76 | unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ 77 | unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ 78 | 79 | if (msg_len > MAX_MSG_LEN) { 80 | return -1; 81 | } 82 | 83 | /* Convert the Curve25519 public key into an Ed25519 public key. In 84 | particular, convert Curve25519's "montgomery" x-coordinate into an 85 | Ed25519 "edwards" y-coordinate: 86 | 87 | ed_y = (mont_x - 1) / (mont_x + 1) 88 | 89 | NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp 90 | 91 | Then move the sign bit into the pubkey from the signature. 92 | */ 93 | fe_frombytes(mont_x, curve25519_pubkey); 94 | fe_1(one); 95 | fe_sub(mont_x_minus_one, mont_x, one); 96 | fe_add(mont_x_plus_one, mont_x, one); 97 | fe_invert(inv_mont_x_plus_one, mont_x_plus_one); 98 | fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one); 99 | fe_tobytes(ed_pubkey, ed_y); 100 | 101 | /* Copy the sign bit, and remove it from signature */ 102 | ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ 103 | ed_pubkey[31] |= (signature[63] & 0x80); 104 | memmove(verifybuf, signature, 64); 105 | verifybuf[63] &= 0x7F; 106 | 107 | memmove(verifybuf+64, msg, msg_len); 108 | 109 | /* Then perform a normal Ed25519 verification, return 0 on success */ 110 | /* The below call has a strange API: */ 111 | /* verifybuf = R || S || message */ 112 | /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets 113 | replaced with pubkey for hashing, then the whole thing gets zeroized 114 | (if bad sig), or contains a copy of msg (good sig) */ 115 | return crypto_sign_open(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey); 116 | } 117 | -------------------------------------------------------------------------------- /curve/ed25519/pow22523.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: fe z1 */ 3 | 4 | /* qhasm: fe z2 */ 5 | 6 | /* qhasm: fe z8 */ 7 | 8 | /* qhasm: fe z9 */ 9 | 10 | /* qhasm: fe z11 */ 11 | 12 | /* qhasm: fe z22 */ 13 | 14 | /* qhasm: fe z_5_0 */ 15 | 16 | /* qhasm: fe z_10_5 */ 17 | 18 | /* qhasm: fe z_10_0 */ 19 | 20 | /* qhasm: fe z_20_10 */ 21 | 22 | /* qhasm: fe z_20_0 */ 23 | 24 | /* qhasm: fe z_40_20 */ 25 | 26 | /* qhasm: fe z_40_0 */ 27 | 28 | /* qhasm: fe z_50_10 */ 29 | 30 | /* qhasm: fe z_50_0 */ 31 | 32 | /* qhasm: fe z_100_50 */ 33 | 34 | /* qhasm: fe z_100_0 */ 35 | 36 | /* qhasm: fe z_200_100 */ 37 | 38 | /* qhasm: fe z_200_0 */ 39 | 40 | /* qhasm: fe z_250_50 */ 41 | 42 | /* qhasm: fe z_250_0 */ 43 | 44 | /* qhasm: fe z_252_2 */ 45 | 46 | /* qhasm: fe z_252_3 */ 47 | 48 | /* qhasm: enter pow22523 */ 49 | 50 | /* qhasm: z2 = z1^2^1 */ 51 | /* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ 52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ 53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); 54 | 55 | /* qhasm: z8 = z2^2^2 */ 56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ 57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ 58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); 59 | 60 | /* qhasm: z9 = z1*z8 */ 61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ 72 | /* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */ 73 | fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0); 74 | 75 | /* qhasm: z_5_0 = z9*z22 */ 76 | /* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ 82 | /* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */ 83 | fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1); 84 | 85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */ 86 | /* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ 92 | /* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */ 93 | fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1); 94 | 95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */ 96 | /* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ 102 | /* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */ 103 | fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2); 104 | 105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */ 106 | /* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ 112 | /* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */ 113 | fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1); 114 | 115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */ 116 | /* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ 122 | /* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */ 123 | fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1); 124 | 125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */ 126 | /* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ 132 | /* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */ 133 | fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2); 134 | 135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */ 136 | /* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ 142 | /* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */ 143 | fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1); 144 | 145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */ 146 | /* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ 152 | /* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */ 153 | fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0); 154 | 155 | /* qhasm: z_252_3 = z_252_2*z1 */ 156 | /* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ 52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ 53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); 54 | 55 | /* qhasm: z8 = z2^2^2 */ 56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ 57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ 58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); 59 | 60 | /* qhasm: z9 = z1*z8 */ 61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ 72 | /* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ 73 | fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2); 74 | 75 | /* qhasm: z_5_0 = z9*z22 */ 76 | /* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ 82 | /* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ 83 | fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); 84 | 85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */ 86 | /* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ 92 | /* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ 93 | fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); 94 | 95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */ 96 | /* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ 102 | /* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ 103 | fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); 104 | 105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */ 106 | /* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ 112 | /* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ 113 | fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); 114 | 115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */ 116 | /* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ 122 | /* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ 123 | fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); 124 | 125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */ 126 | /* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ 132 | /* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ 133 | fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); 134 | 135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */ 136 | /* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ 142 | /* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ 143 | fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); 144 | 145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */ 146 | /* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ 152 | /* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ 153 | fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); 154 | 155 | /* qhasm: z_255_21 = z_255_5*z11 */ 156 | /* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,> 26; h1 += carry0; h0 -= carry0 << 26; 121 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 122 | 123 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 124 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 125 | 126 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 127 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 128 | 129 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 130 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 131 | 132 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 133 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 134 | 135 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 136 | 137 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 138 | 139 | h[0] = h0; 140 | h[1] = h1; 141 | h[2] = h2; 142 | h[3] = h3; 143 | h[4] = h4; 144 | h[5] = h5; 145 | h[6] = h6; 146 | h[7] = h7; 147 | h[8] = h8; 148 | h[9] = h9; 149 | } 150 | -------------------------------------------------------------------------------- /curve/ed25519/fe_sq2.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | 4 | /* 5 | h = 2 * f * f 6 | Can overlap h with f. 7 | 8 | Preconditions: 9 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 13 | */ 14 | 15 | /* 16 | See fe_mul.c for discussion of implementation strategy. 17 | */ 18 | 19 | void fe_sq2(fe h,const fe f) 20 | { 21 | crypto_int32 f0 = f[0]; 22 | crypto_int32 f1 = f[1]; 23 | crypto_int32 f2 = f[2]; 24 | crypto_int32 f3 = f[3]; 25 | crypto_int32 f4 = f[4]; 26 | crypto_int32 f5 = f[5]; 27 | crypto_int32 f6 = f[6]; 28 | crypto_int32 f7 = f[7]; 29 | crypto_int32 f8 = f[8]; 30 | crypto_int32 f9 = f[9]; 31 | crypto_int32 f0_2 = 2 * f0; 32 | crypto_int32 f1_2 = 2 * f1; 33 | crypto_int32 f2_2 = 2 * f2; 34 | crypto_int32 f3_2 = 2 * f3; 35 | crypto_int32 f4_2 = 2 * f4; 36 | crypto_int32 f5_2 = 2 * f5; 37 | crypto_int32 f6_2 = 2 * f6; 38 | crypto_int32 f7_2 = 2 * f7; 39 | crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ 40 | crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ 41 | crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ 42 | crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ 43 | crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ 44 | crypto_int64 f0f0 = f0 * (crypto_int64) f0; 45 | crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; 46 | crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; 47 | crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; 48 | crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; 49 | crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; 50 | crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; 51 | crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; 52 | crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; 53 | crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; 54 | crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; 55 | crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; 56 | crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; 57 | crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; 58 | crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; 59 | crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; 60 | crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; 61 | crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; 62 | crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; 63 | crypto_int64 f2f2 = f2 * (crypto_int64) f2; 64 | crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; 65 | crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; 66 | crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; 67 | crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; 68 | crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; 69 | crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; 70 | crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; 71 | crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; 72 | crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; 73 | crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; 74 | crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; 75 | crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; 76 | crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; 77 | crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; 78 | crypto_int64 f4f4 = f4 * (crypto_int64) f4; 79 | crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; 80 | crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; 81 | crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; 82 | crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; 83 | crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; 84 | crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; 85 | crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; 86 | crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; 87 | crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; 88 | crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; 89 | crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; 90 | crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; 91 | crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; 92 | crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; 93 | crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; 94 | crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; 95 | crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; 96 | crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; 97 | crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; 98 | crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; 99 | crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; 100 | crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; 101 | crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; 102 | crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; 103 | crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; 104 | crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; 105 | crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; 106 | crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; 107 | crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; 108 | crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; 109 | crypto_int64 carry0; 110 | crypto_int64 carry1; 111 | crypto_int64 carry2; 112 | crypto_int64 carry3; 113 | crypto_int64 carry4; 114 | crypto_int64 carry5; 115 | crypto_int64 carry6; 116 | crypto_int64 carry7; 117 | crypto_int64 carry8; 118 | crypto_int64 carry9; 119 | 120 | h0 += h0; 121 | h1 += h1; 122 | h2 += h2; 123 | h3 += h3; 124 | h4 += h4; 125 | h5 += h5; 126 | h6 += h6; 127 | h7 += h7; 128 | h8 += h8; 129 | h9 += h9; 130 | 131 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 132 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 133 | 134 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 135 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 136 | 137 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 138 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 139 | 140 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 141 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 142 | 143 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 144 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 145 | 146 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 147 | 148 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 149 | 150 | h[0] = h0; 151 | h[1] = h1; 152 | h[2] = h2; 153 | h[3] = h3; 154 | h[4] = h4; 155 | h[5] = h5; 156 | h[6] = h6; 157 | h[7] = h7; 158 | h[8] = h8; 159 | h[9] = h9; 160 | } 161 | -------------------------------------------------------------------------------- /curve/ed25519/nacl_sha512/blocks.c: -------------------------------------------------------------------------------- 1 | #include 2 | typedef uint64_t uint64; 3 | 4 | static uint64 load_bigendian(const unsigned char *x) 5 | { 6 | return 7 | (uint64) (x[7]) \ 8 | | (((uint64) (x[6])) << 8) \ 9 | | (((uint64) (x[5])) << 16) \ 10 | | (((uint64) (x[4])) << 24) \ 11 | | (((uint64) (x[3])) << 32) \ 12 | | (((uint64) (x[2])) << 40) \ 13 | | (((uint64) (x[1])) << 48) \ 14 | | (((uint64) (x[0])) << 56) 15 | ; 16 | } 17 | 18 | static void store_bigendian(unsigned char *x,uint64 u) 19 | { 20 | x[7] = u; u >>= 8; 21 | x[6] = u; u >>= 8; 22 | x[5] = u; u >>= 8; 23 | x[4] = u; u >>= 8; 24 | x[3] = u; u >>= 8; 25 | x[2] = u; u >>= 8; 26 | x[1] = u; u >>= 8; 27 | x[0] = u; 28 | } 29 | 30 | #define SHR(x,c) ((x) >> (c)) 31 | #define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) 32 | 33 | #define Ch(x,y,z) ((x & y) ^ (~x & z)) 34 | #define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) 35 | #define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) 36 | #define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) 37 | #define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7)) 38 | #define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6)) 39 | 40 | #define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; 41 | 42 | #define EXPAND \ 43 | M(w0 ,w14,w9 ,w1 ) \ 44 | M(w1 ,w15,w10,w2 ) \ 45 | M(w2 ,w0 ,w11,w3 ) \ 46 | M(w3 ,w1 ,w12,w4 ) \ 47 | M(w4 ,w2 ,w13,w5 ) \ 48 | M(w5 ,w3 ,w14,w6 ) \ 49 | M(w6 ,w4 ,w15,w7 ) \ 50 | M(w7 ,w5 ,w0 ,w8 ) \ 51 | M(w8 ,w6 ,w1 ,w9 ) \ 52 | M(w9 ,w7 ,w2 ,w10) \ 53 | M(w10,w8 ,w3 ,w11) \ 54 | M(w11,w9 ,w4 ,w12) \ 55 | M(w12,w10,w5 ,w13) \ 56 | M(w13,w11,w6 ,w14) \ 57 | M(w14,w12,w7 ,w15) \ 58 | M(w15,w13,w8 ,w0 ) 59 | 60 | #define F(w,k) \ 61 | T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ 62 | T2 = Sigma0(a) + Maj(a,b,c); \ 63 | h = g; \ 64 | g = f; \ 65 | f = e; \ 66 | e = d + T1; \ 67 | d = c; \ 68 | c = b; \ 69 | b = a; \ 70 | a = T1 + T2; 71 | 72 | int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) 73 | { 74 | uint64 state[8]; 75 | uint64 a; 76 | uint64 b; 77 | uint64 c; 78 | uint64 d; 79 | uint64 e; 80 | uint64 f; 81 | uint64 g; 82 | uint64 h; 83 | uint64 T1; 84 | uint64 T2; 85 | 86 | a = load_bigendian(statebytes + 0); state[0] = a; 87 | b = load_bigendian(statebytes + 8); state[1] = b; 88 | c = load_bigendian(statebytes + 16); state[2] = c; 89 | d = load_bigendian(statebytes + 24); state[3] = d; 90 | e = load_bigendian(statebytes + 32); state[4] = e; 91 | f = load_bigendian(statebytes + 40); state[5] = f; 92 | g = load_bigendian(statebytes + 48); state[6] = g; 93 | h = load_bigendian(statebytes + 56); state[7] = h; 94 | 95 | while (inlen >= 128) { 96 | uint64 w0 = load_bigendian(in + 0); 97 | uint64 w1 = load_bigendian(in + 8); 98 | uint64 w2 = load_bigendian(in + 16); 99 | uint64 w3 = load_bigendian(in + 24); 100 | uint64 w4 = load_bigendian(in + 32); 101 | uint64 w5 = load_bigendian(in + 40); 102 | uint64 w6 = load_bigendian(in + 48); 103 | uint64 w7 = load_bigendian(in + 56); 104 | uint64 w8 = load_bigendian(in + 64); 105 | uint64 w9 = load_bigendian(in + 72); 106 | uint64 w10 = load_bigendian(in + 80); 107 | uint64 w11 = load_bigendian(in + 88); 108 | uint64 w12 = load_bigendian(in + 96); 109 | uint64 w13 = load_bigendian(in + 104); 110 | uint64 w14 = load_bigendian(in + 112); 111 | uint64 w15 = load_bigendian(in + 120); 112 | 113 | F(w0 ,0x428a2f98d728ae22ULL) 114 | F(w1 ,0x7137449123ef65cdULL) 115 | F(w2 ,0xb5c0fbcfec4d3b2fULL) 116 | F(w3 ,0xe9b5dba58189dbbcULL) 117 | F(w4 ,0x3956c25bf348b538ULL) 118 | F(w5 ,0x59f111f1b605d019ULL) 119 | F(w6 ,0x923f82a4af194f9bULL) 120 | F(w7 ,0xab1c5ed5da6d8118ULL) 121 | F(w8 ,0xd807aa98a3030242ULL) 122 | F(w9 ,0x12835b0145706fbeULL) 123 | F(w10,0x243185be4ee4b28cULL) 124 | F(w11,0x550c7dc3d5ffb4e2ULL) 125 | F(w12,0x72be5d74f27b896fULL) 126 | F(w13,0x80deb1fe3b1696b1ULL) 127 | F(w14,0x9bdc06a725c71235ULL) 128 | F(w15,0xc19bf174cf692694ULL) 129 | 130 | EXPAND 131 | 132 | F(w0 ,0xe49b69c19ef14ad2ULL) 133 | F(w1 ,0xefbe4786384f25e3ULL) 134 | F(w2 ,0x0fc19dc68b8cd5b5ULL) 135 | F(w3 ,0x240ca1cc77ac9c65ULL) 136 | F(w4 ,0x2de92c6f592b0275ULL) 137 | F(w5 ,0x4a7484aa6ea6e483ULL) 138 | F(w6 ,0x5cb0a9dcbd41fbd4ULL) 139 | F(w7 ,0x76f988da831153b5ULL) 140 | F(w8 ,0x983e5152ee66dfabULL) 141 | F(w9 ,0xa831c66d2db43210ULL) 142 | F(w10,0xb00327c898fb213fULL) 143 | F(w11,0xbf597fc7beef0ee4ULL) 144 | F(w12,0xc6e00bf33da88fc2ULL) 145 | F(w13,0xd5a79147930aa725ULL) 146 | F(w14,0x06ca6351e003826fULL) 147 | F(w15,0x142929670a0e6e70ULL) 148 | 149 | EXPAND 150 | 151 | F(w0 ,0x27b70a8546d22ffcULL) 152 | F(w1 ,0x2e1b21385c26c926ULL) 153 | F(w2 ,0x4d2c6dfc5ac42aedULL) 154 | F(w3 ,0x53380d139d95b3dfULL) 155 | F(w4 ,0x650a73548baf63deULL) 156 | F(w5 ,0x766a0abb3c77b2a8ULL) 157 | F(w6 ,0x81c2c92e47edaee6ULL) 158 | F(w7 ,0x92722c851482353bULL) 159 | F(w8 ,0xa2bfe8a14cf10364ULL) 160 | F(w9 ,0xa81a664bbc423001ULL) 161 | F(w10,0xc24b8b70d0f89791ULL) 162 | F(w11,0xc76c51a30654be30ULL) 163 | F(w12,0xd192e819d6ef5218ULL) 164 | F(w13,0xd69906245565a910ULL) 165 | F(w14,0xf40e35855771202aULL) 166 | F(w15,0x106aa07032bbd1b8ULL) 167 | 168 | EXPAND 169 | 170 | F(w0 ,0x19a4c116b8d2d0c8ULL) 171 | F(w1 ,0x1e376c085141ab53ULL) 172 | F(w2 ,0x2748774cdf8eeb99ULL) 173 | F(w3 ,0x34b0bcb5e19b48a8ULL) 174 | F(w4 ,0x391c0cb3c5c95a63ULL) 175 | F(w5 ,0x4ed8aa4ae3418acbULL) 176 | F(w6 ,0x5b9cca4f7763e373ULL) 177 | F(w7 ,0x682e6ff3d6b2b8a3ULL) 178 | F(w8 ,0x748f82ee5defb2fcULL) 179 | F(w9 ,0x78a5636f43172f60ULL) 180 | F(w10,0x84c87814a1f0ab72ULL) 181 | F(w11,0x8cc702081a6439ecULL) 182 | F(w12,0x90befffa23631e28ULL) 183 | F(w13,0xa4506cebde82bde9ULL) 184 | F(w14,0xbef9a3f7b2c67915ULL) 185 | F(w15,0xc67178f2e372532bULL) 186 | 187 | EXPAND 188 | 189 | F(w0 ,0xca273eceea26619cULL) 190 | F(w1 ,0xd186b8c721c0c207ULL) 191 | F(w2 ,0xeada7dd6cde0eb1eULL) 192 | F(w3 ,0xf57d4f7fee6ed178ULL) 193 | F(w4 ,0x06f067aa72176fbaULL) 194 | F(w5 ,0x0a637dc5a2c898a6ULL) 195 | F(w6 ,0x113f9804bef90daeULL) 196 | F(w7 ,0x1b710b35131c471bULL) 197 | F(w8 ,0x28db77f523047d84ULL) 198 | F(w9 ,0x32caab7b40c72493ULL) 199 | F(w10,0x3c9ebe0a15c9bebcULL) 200 | F(w11,0x431d67c49c100d4cULL) 201 | F(w12,0x4cc5d4becb3e42b6ULL) 202 | F(w13,0x597f299cfc657e2aULL) 203 | F(w14,0x5fcb6fab3ad6faecULL) 204 | F(w15,0x6c44198c4a475817ULL) 205 | 206 | a += state[0]; 207 | b += state[1]; 208 | c += state[2]; 209 | d += state[3]; 210 | e += state[4]; 211 | f += state[5]; 212 | g += state[6]; 213 | h += state[7]; 214 | 215 | state[0] = a; 216 | state[1] = b; 217 | state[2] = c; 218 | state[3] = d; 219 | state[4] = e; 220 | state[5] = f; 221 | state[6] = g; 222 | state[7] = h; 223 | 224 | in += 128; 225 | inlen -= 128; 226 | } 227 | 228 | store_bigendian(statebytes + 0,state[0]); 229 | store_bigendian(statebytes + 8,state[1]); 230 | store_bigendian(statebytes + 16,state[2]); 231 | store_bigendian(statebytes + 24,state[3]); 232 | store_bigendian(statebytes + 32,state[4]); 233 | store_bigendian(statebytes + 40,state[5]); 234 | store_bigendian(statebytes + 48,state[6]); 235 | store_bigendian(statebytes + 56,state[7]); 236 | 237 | return 0; 238 | } 239 | -------------------------------------------------------------------------------- /curve.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include "config.h" 3 | #endif 4 | 5 | #include "php.h" 6 | #include "php_curve25519.h" 7 | #include "curve/curve25519-donna.h" 8 | #include "curve/ed25519/additions/curve_sigs.h" 9 | #include "ext/standard/info.h" 10 | #include "zend_exceptions.h" 11 | #include "ext/spl/spl_exceptions.h" 12 | 13 | const unsigned char basepoint[32] = {9}; 14 | 15 | void curve25519_clamp(unsigned char secret[32]) 16 | { 17 | secret[0] &= 248; 18 | secret[31] &= 127; 19 | secret[31] |= 64; 20 | } 21 | 22 | PHP_FUNCTION(curve25519_sign) 23 | { 24 | char *random; 25 | char *privatekey; 26 | char *message; 27 | 28 | #if PHP_VERSION_ID >= 70000 29 | size_t random_len; 30 | size_t private_len; 31 | size_t message_len; 32 | #else 33 | int random_len; 34 | int private_len; 35 | int message_len; 36 | #endif 37 | 38 | char signature[64]; 39 | 40 | #ifndef FAST_ZPP 41 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &random, &random_len, &privatekey, &private_len, &message, &message_len) == FAILURE) { 42 | RETURN_FALSE; 43 | } 44 | #else 45 | ZEND_PARSE_PARAMETERS_START(3, 3) 46 | Z_PARAM_STRING(random, random_len) 47 | Z_PARAM_STRING(privatekey, private_len) 48 | Z_PARAM_STRING(message, message_len) 49 | ZEND_PARSE_PARAMETERS_END(); 50 | #endif 51 | 52 | if (private_len != 32) { 53 | zend_throw_exception(spl_ce_InvalidArgumentException, "Private key must be 32 bytes", 0); 54 | } 55 | 56 | if (random_len != 64) { 57 | zend_throw_exception(spl_ce_InvalidArgumentException, "Random must be 64-byte string", 0); 58 | } 59 | 60 | curve25519_sign((unsigned char *)signature, (unsigned char *)privatekey, 61 | (unsigned char *)message, message_len, (unsigned char *)random); 62 | 63 | #if PHP_VERSION_ID >= 70000 64 | RETURN_STRINGL((char*)signature, 64); 65 | #else 66 | RETURN_STRINGL((char*)signature, 64, 1); 67 | #endif 68 | } 69 | 70 | PHP_FUNCTION(curve25519_verify) 71 | { 72 | char *publickey; 73 | char *message; 74 | char *signature; 75 | 76 | #if PHP_VERSION_ID >= 70000 77 | size_t public_len; 78 | size_t message_len; 79 | size_t signature_len; 80 | #else 81 | unsigned int public_len; 82 | unsigned int message_len; 83 | unsigned int signature_len; 84 | #endif 85 | 86 | #ifndef FAST_ZPP 87 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &publickey, &public_len, &message, &message_len, &signature, &signature_len) == FAILURE) { 88 | RETURN_FALSE; 89 | } 90 | #else 91 | ZEND_PARSE_PARAMETERS_START(3, 3) 92 | Z_PARAM_STRING(publickey, public_len) 93 | Z_PARAM_STRING(message, message_len) 94 | Z_PARAM_STRING(signature, signature_len) 95 | ZEND_PARSE_PARAMETERS_END(); 96 | #endif 97 | 98 | if (public_len != 32) { 99 | zend_throw_exception(spl_ce_InvalidArgumentException, "Public must be 32 bytes", 0); 100 | } 101 | 102 | if (signature_len != 64) { 103 | zend_throw_exception(spl_ce_InvalidArgumentException, "Signature must be 64-byte string", 0); 104 | } 105 | 106 | int result = curve25519_verify((unsigned char *)signature, (unsigned char *)publickey, 107 | (unsigned char *)message, message_len); 108 | RETURN_LONG(result); 109 | } 110 | 111 | PHP_FUNCTION(curve25519_private) 112 | { 113 | char *random; 114 | 115 | #if PHP_VERSION_ID >= 70000 116 | size_t random_len; 117 | #else 118 | int random_len; 119 | #endif 120 | 121 | #ifndef FAST_ZPP 122 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &random, &random_len) == FAILURE) { 123 | RETURN_FALSE; 124 | } 125 | #else 126 | ZEND_PARSE_PARAMETERS_START(1, 1) 127 | Z_PARAM_STRING(random, random_len) 128 | ZEND_PARSE_PARAMETERS_END(); 129 | #endif 130 | 131 | if (random_len != 32) { 132 | zend_throw_exception(spl_ce_InvalidArgumentException, "Random must be 32-byte string", 0); 133 | } 134 | 135 | random[0] &= 248; 136 | random[31] &= 127; 137 | random[31] |= 64; 138 | 139 | #if PHP_VERSION_ID >= 70000 140 | RETURN_STRINGL(random, 32); 141 | #else 142 | RETURN_STRINGL(random, 32, 1); 143 | #endif 144 | } 145 | 146 | PHP_FUNCTION(curve25519_public) 147 | { 148 | char *private; 149 | #if PHP_VERSION_ID >= 70000 150 | size_t private_len; 151 | #else 152 | int private_len; 153 | #endif 154 | 155 | char basepoint[32] = {9}; 156 | 157 | #ifndef FAST_ZPP 158 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &private, &private_len) == FAILURE) { 159 | RETURN_FALSE; 160 | } 161 | #else 162 | ZEND_PARSE_PARAMETERS_START(1, 1) 163 | Z_PARAM_STRING(private, private_len) 164 | ZEND_PARSE_PARAMETERS_END(); 165 | #endif 166 | 167 | if (private_len != 32) { 168 | zend_throw_exception(spl_ce_InvalidArgumentException, "Private key must be 32 bytes", 0); 169 | } 170 | 171 | char public[32]; 172 | curve25519_donna(public, private, basepoint); 173 | 174 | #if PHP_VERSION_ID >= 70000 175 | RETURN_STRINGL((char*)public, 32); 176 | #else 177 | RETURN_STRINGL((char*)public, 32, 1); 178 | #endif 179 | } 180 | 181 | PHP_FUNCTION(curve25519_shared) 182 | { 183 | char *private; 184 | char *public; 185 | 186 | #if PHP_VERSION_ID >= 70000 187 | size_t private_len; 188 | size_t public_len; 189 | #else 190 | int private_len; 191 | int public_len; 192 | #endif 193 | 194 | #ifndef FAST_ZPP 195 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &private, &private_len, &public, &public_len) == FAILURE) { 196 | RETURN_FALSE; 197 | } 198 | #else 199 | ZEND_PARSE_PARAMETERS_START(2, 2) 200 | Z_PARAM_STRING(private, private_len) 201 | Z_PARAM_STRING(public, public_len) 202 | ZEND_PARSE_PARAMETERS_END(); 203 | #endif 204 | 205 | if (private_len != 32) { 206 | zend_throw_exception(spl_ce_InvalidArgumentException, "Private key must be 32 bytes", 0); 207 | } 208 | 209 | if (public_len != 32) { 210 | zend_throw_exception(spl_ce_InvalidArgumentException, "Public must be 32 bytes", 0); 211 | } 212 | 213 | char shared_key[32]; 214 | curve25519_donna(shared_key, private, public); 215 | 216 | #if PHP_VERSION_ID >= 70000 217 | RETURN_STRINGL(shared_key, 32); 218 | #else 219 | RETURN_STRINGL(shared_key, 32, 1); 220 | #endif 221 | } 222 | 223 | ZEND_BEGIN_ARG_INFO_EX(arginfo_curve25519_sign, 0, 0, 1) 224 | ZEND_ARG_INFO(0, random) 225 | ZEND_ARG_INFO(0, private) 226 | ZEND_ARG_INFO(0, message) 227 | ZEND_END_ARG_INFO() 228 | 229 | ZEND_BEGIN_ARG_INFO_EX(arginfo_curve25519_verify, 0, 0, 1) 230 | ZEND_ARG_INFO(0, public) 231 | ZEND_ARG_INFO(0, message) 232 | ZEND_ARG_INFO(0, signature) 233 | ZEND_END_ARG_INFO() 234 | 235 | ZEND_BEGIN_ARG_INFO_EX(arginfo_curve25519_private, 0, 0, 1) 236 | ZEND_ARG_INFO(0, random) 237 | ZEND_END_ARG_INFO() 238 | 239 | ZEND_BEGIN_ARG_INFO_EX(arginfo_curve25519_public, 0, 0, 1) 240 | ZEND_ARG_INFO(0, secret) 241 | ZEND_END_ARG_INFO() 242 | 243 | ZEND_BEGIN_ARG_INFO_EX(arginfo_curve25519_shared, 0, 0, 1) 244 | ZEND_ARG_INFO(0, secret) 245 | ZEND_ARG_INFO(0, public) 246 | ZEND_END_ARG_INFO() 247 | 248 | const zend_function_entry curve25519_functions[] = { 249 | PHP_FE(curve25519_public, arginfo_curve25519_public) 250 | PHP_FE(curve25519_shared, arginfo_curve25519_shared) 251 | PHP_FE(curve25519_private, arginfo_curve25519_private) 252 | PHP_FE(curve25519_sign, arginfo_curve25519_sign) 253 | PHP_FE(curve25519_verify, arginfo_curve25519_verify) 254 | PHP_FE_END 255 | }; 256 | 257 | PHP_MINFO_FUNCTION(curve25519) 258 | { 259 | php_info_print_table_start(); 260 | php_info_print_table_row(2, "curve25519 support", "enabled"); 261 | php_info_print_table_end(); 262 | } 263 | 264 | zend_module_entry curve25519_module_entry = { 265 | STANDARD_MODULE_HEADER, 266 | "curve25519", 267 | curve25519_functions, 268 | NULL, 269 | NULL, 270 | NULL, 271 | NULL, 272 | PHP_MINFO(curve25519), 273 | NO_VERSION_YET, 274 | STANDARD_MODULE_PROPERTIES 275 | }; 276 | 277 | #ifdef COMPILE_DL_CURVE25519 278 | ZEND_GET_MODULE(curve25519) 279 | #endif -------------------------------------------------------------------------------- /curve/ed25519/sc_reduce.c: -------------------------------------------------------------------------------- 1 | #include "sc.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | #include "nacl_includes/crypto_uint32.h" 4 | #include "nacl_includes/crypto_uint64.h" 5 | 6 | static crypto_uint64 load_3(const unsigned char *in) 7 | { 8 | crypto_uint64 result; 9 | result = (crypto_uint64) in[0]; 10 | result |= ((crypto_uint64) in[1]) << 8; 11 | result |= ((crypto_uint64) in[2]) << 16; 12 | return result; 13 | } 14 | 15 | static crypto_uint64 load_4(const unsigned char *in) 16 | { 17 | crypto_uint64 result; 18 | result = (crypto_uint64) in[0]; 19 | result |= ((crypto_uint64) in[1]) << 8; 20 | result |= ((crypto_uint64) in[2]) << 16; 21 | result |= ((crypto_uint64) in[3]) << 24; 22 | return result; 23 | } 24 | 25 | /* 26 | Input: 27 | s[0]+256*s[1]+...+256^63*s[63] = s 28 | 29 | Output: 30 | s[0]+256*s[1]+...+256^31*s[31] = s mod l 31 | where l = 2^252 + 27742317777372353535851937790883648493. 32 | Overwrites s in place. 33 | */ 34 | 35 | void sc_reduce(unsigned char *s) 36 | { 37 | crypto_int64 s0 = 2097151 & load_3(s); 38 | crypto_int64 s1 = 2097151 & (load_4(s + 2) >> 5); 39 | crypto_int64 s2 = 2097151 & (load_3(s + 5) >> 2); 40 | crypto_int64 s3 = 2097151 & (load_4(s + 7) >> 7); 41 | crypto_int64 s4 = 2097151 & (load_4(s + 10) >> 4); 42 | crypto_int64 s5 = 2097151 & (load_3(s + 13) >> 1); 43 | crypto_int64 s6 = 2097151 & (load_4(s + 15) >> 6); 44 | crypto_int64 s7 = 2097151 & (load_3(s + 18) >> 3); 45 | crypto_int64 s8 = 2097151 & load_3(s + 21); 46 | crypto_int64 s9 = 2097151 & (load_4(s + 23) >> 5); 47 | crypto_int64 s10 = 2097151 & (load_3(s + 26) >> 2); 48 | crypto_int64 s11 = 2097151 & (load_4(s + 28) >> 7); 49 | crypto_int64 s12 = 2097151 & (load_4(s + 31) >> 4); 50 | crypto_int64 s13 = 2097151 & (load_3(s + 34) >> 1); 51 | crypto_int64 s14 = 2097151 & (load_4(s + 36) >> 6); 52 | crypto_int64 s15 = 2097151 & (load_3(s + 39) >> 3); 53 | crypto_int64 s16 = 2097151 & load_3(s + 42); 54 | crypto_int64 s17 = 2097151 & (load_4(s + 44) >> 5); 55 | crypto_int64 s18 = 2097151 & (load_3(s + 47) >> 2); 56 | crypto_int64 s19 = 2097151 & (load_4(s + 49) >> 7); 57 | crypto_int64 s20 = 2097151 & (load_4(s + 52) >> 4); 58 | crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1); 59 | crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6); 60 | crypto_int64 s23 = (load_4(s + 60) >> 3); 61 | crypto_int64 carry0; 62 | crypto_int64 carry1; 63 | crypto_int64 carry2; 64 | crypto_int64 carry3; 65 | crypto_int64 carry4; 66 | crypto_int64 carry5; 67 | crypto_int64 carry6; 68 | crypto_int64 carry7; 69 | crypto_int64 carry8; 70 | crypto_int64 carry9; 71 | crypto_int64 carry10; 72 | crypto_int64 carry11; 73 | crypto_int64 carry12; 74 | crypto_int64 carry13; 75 | crypto_int64 carry14; 76 | crypto_int64 carry15; 77 | crypto_int64 carry16; 78 | 79 | s11 += s23 * 666643; 80 | s12 += s23 * 470296; 81 | s13 += s23 * 654183; 82 | s14 -= s23 * 997805; 83 | s15 += s23 * 136657; 84 | s16 -= s23 * 683901; 85 | s23 = 0; 86 | 87 | s10 += s22 * 666643; 88 | s11 += s22 * 470296; 89 | s12 += s22 * 654183; 90 | s13 -= s22 * 997805; 91 | s14 += s22 * 136657; 92 | s15 -= s22 * 683901; 93 | s22 = 0; 94 | 95 | s9 += s21 * 666643; 96 | s10 += s21 * 470296; 97 | s11 += s21 * 654183; 98 | s12 -= s21 * 997805; 99 | s13 += s21 * 136657; 100 | s14 -= s21 * 683901; 101 | s21 = 0; 102 | 103 | s8 += s20 * 666643; 104 | s9 += s20 * 470296; 105 | s10 += s20 * 654183; 106 | s11 -= s20 * 997805; 107 | s12 += s20 * 136657; 108 | s13 -= s20 * 683901; 109 | s20 = 0; 110 | 111 | s7 += s19 * 666643; 112 | s8 += s19 * 470296; 113 | s9 += s19 * 654183; 114 | s10 -= s19 * 997805; 115 | s11 += s19 * 136657; 116 | s12 -= s19 * 683901; 117 | s19 = 0; 118 | 119 | s6 += s18 * 666643; 120 | s7 += s18 * 470296; 121 | s8 += s18 * 654183; 122 | s9 -= s18 * 997805; 123 | s10 += s18 * 136657; 124 | s11 -= s18 * 683901; 125 | s18 = 0; 126 | 127 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 128 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 129 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 130 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; 131 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; 132 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; 133 | 134 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 135 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 136 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 137 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; 138 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; 139 | 140 | s5 += s17 * 666643; 141 | s6 += s17 * 470296; 142 | s7 += s17 * 654183; 143 | s8 -= s17 * 997805; 144 | s9 += s17 * 136657; 145 | s10 -= s17 * 683901; 146 | s17 = 0; 147 | 148 | s4 += s16 * 666643; 149 | s5 += s16 * 470296; 150 | s6 += s16 * 654183; 151 | s7 -= s16 * 997805; 152 | s8 += s16 * 136657; 153 | s9 -= s16 * 683901; 154 | s16 = 0; 155 | 156 | s3 += s15 * 666643; 157 | s4 += s15 * 470296; 158 | s5 += s15 * 654183; 159 | s6 -= s15 * 997805; 160 | s7 += s15 * 136657; 161 | s8 -= s15 * 683901; 162 | s15 = 0; 163 | 164 | s2 += s14 * 666643; 165 | s3 += s14 * 470296; 166 | s4 += s14 * 654183; 167 | s5 -= s14 * 997805; 168 | s6 += s14 * 136657; 169 | s7 -= s14 * 683901; 170 | s14 = 0; 171 | 172 | s1 += s13 * 666643; 173 | s2 += s13 * 470296; 174 | s3 += s13 * 654183; 175 | s4 -= s13 * 997805; 176 | s5 += s13 * 136657; 177 | s6 -= s13 * 683901; 178 | s13 = 0; 179 | 180 | s0 += s12 * 666643; 181 | s1 += s12 * 470296; 182 | s2 += s12 * 654183; 183 | s3 -= s12 * 997805; 184 | s4 += s12 * 136657; 185 | s5 -= s12 * 683901; 186 | s12 = 0; 187 | 188 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; 189 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; 190 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; 191 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 192 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 193 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 194 | 195 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; 196 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; 197 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; 198 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 199 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 200 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 201 | 202 | s0 += s12 * 666643; 203 | s1 += s12 * 470296; 204 | s2 += s12 * 654183; 205 | s3 -= s12 * 997805; 206 | s4 += s12 * 136657; 207 | s5 -= s12 * 683901; 208 | s12 = 0; 209 | 210 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 211 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 212 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 213 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 214 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 215 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; 216 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; 217 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; 218 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; 219 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; 220 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; 221 | carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; 222 | 223 | s0 += s12 * 666643; 224 | s1 += s12 * 470296; 225 | s2 += s12 * 654183; 226 | s3 -= s12 * 997805; 227 | s4 += s12 * 136657; 228 | s5 -= s12 * 683901; 229 | s12 = 0; 230 | 231 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 232 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 233 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 234 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 235 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 236 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; 237 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; 238 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; 239 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; 240 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; 241 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; 242 | 243 | s[0] = s0 >> 0; 244 | s[1] = s0 >> 8; 245 | s[2] = (s0 >> 16) | (s1 << 5); 246 | s[3] = s1 >> 3; 247 | s[4] = s1 >> 11; 248 | s[5] = (s1 >> 19) | (s2 << 2); 249 | s[6] = s2 >> 6; 250 | s[7] = (s2 >> 14) | (s3 << 7); 251 | s[8] = s3 >> 1; 252 | s[9] = s3 >> 9; 253 | s[10] = (s3 >> 17) | (s4 << 4); 254 | s[11] = s4 >> 4; 255 | s[12] = s4 >> 12; 256 | s[13] = (s4 >> 20) | (s5 << 1); 257 | s[14] = s5 >> 7; 258 | s[15] = (s5 >> 15) | (s6 << 6); 259 | s[16] = s6 >> 2; 260 | s[17] = s6 >> 10; 261 | s[18] = (s6 >> 18) | (s7 << 3); 262 | s[19] = s7 >> 5; 263 | s[20] = s7 >> 13; 264 | s[21] = s8 >> 0; 265 | s[22] = s8 >> 8; 266 | s[23] = (s8 >> 16) | (s9 << 5); 267 | s[24] = s9 >> 3; 268 | s[25] = s9 >> 11; 269 | s[26] = (s9 >> 19) | (s10 << 2); 270 | s[27] = s10 >> 6; 271 | s[28] = (s10 >> 14) | (s11 << 7); 272 | s[29] = s11 >> 1; 273 | s[30] = s11 >> 9; 274 | s[31] = s11 >> 17; 275 | } 276 | -------------------------------------------------------------------------------- /curve/ed25519/fe_mul.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | 4 | /* 5 | h = f * g 6 | Can overlap h with f or g. 7 | 8 | Preconditions: 9 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 10 | |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 11 | 12 | Postconditions: 13 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 14 | */ 15 | 16 | /* 17 | Notes on implementation strategy: 18 | 19 | Using schoolbook multiplication. 20 | Karatsuba would save a little in some cost models. 21 | 22 | Most multiplications by 2 and 19 are 32-bit precomputations; 23 | cheaper than 64-bit postcomputations. 24 | 25 | There is one remaining multiplication by 19 in the carry chain; 26 | one *19 precomputation can be merged into this, 27 | but the resulting data flow is considerably less clean. 28 | 29 | There are 12 carries below. 30 | 10 of them are 2-way parallelizable and vectorizable. 31 | Can get away with 11 carries, but then data flow is much deeper. 32 | 33 | With tighter constraints on inputs can squeeze carries into int32. 34 | */ 35 | 36 | void fe_mul(fe h,const fe f,const fe g) 37 | { 38 | crypto_int32 f0 = f[0]; 39 | crypto_int32 f1 = f[1]; 40 | crypto_int32 f2 = f[2]; 41 | crypto_int32 f3 = f[3]; 42 | crypto_int32 f4 = f[4]; 43 | crypto_int32 f5 = f[5]; 44 | crypto_int32 f6 = f[6]; 45 | crypto_int32 f7 = f[7]; 46 | crypto_int32 f8 = f[8]; 47 | crypto_int32 f9 = f[9]; 48 | crypto_int32 g0 = g[0]; 49 | crypto_int32 g1 = g[1]; 50 | crypto_int32 g2 = g[2]; 51 | crypto_int32 g3 = g[3]; 52 | crypto_int32 g4 = g[4]; 53 | crypto_int32 g5 = g[5]; 54 | crypto_int32 g6 = g[6]; 55 | crypto_int32 g7 = g[7]; 56 | crypto_int32 g8 = g[8]; 57 | crypto_int32 g9 = g[9]; 58 | crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */ 59 | crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ 60 | crypto_int32 g3_19 = 19 * g3; 61 | crypto_int32 g4_19 = 19 * g4; 62 | crypto_int32 g5_19 = 19 * g5; 63 | crypto_int32 g6_19 = 19 * g6; 64 | crypto_int32 g7_19 = 19 * g7; 65 | crypto_int32 g8_19 = 19 * g8; 66 | crypto_int32 g9_19 = 19 * g9; 67 | crypto_int32 f1_2 = 2 * f1; 68 | crypto_int32 f3_2 = 2 * f3; 69 | crypto_int32 f5_2 = 2 * f5; 70 | crypto_int32 f7_2 = 2 * f7; 71 | crypto_int32 f9_2 = 2 * f9; 72 | crypto_int64 f0g0 = f0 * (crypto_int64) g0; 73 | crypto_int64 f0g1 = f0 * (crypto_int64) g1; 74 | crypto_int64 f0g2 = f0 * (crypto_int64) g2; 75 | crypto_int64 f0g3 = f0 * (crypto_int64) g3; 76 | crypto_int64 f0g4 = f0 * (crypto_int64) g4; 77 | crypto_int64 f0g5 = f0 * (crypto_int64) g5; 78 | crypto_int64 f0g6 = f0 * (crypto_int64) g6; 79 | crypto_int64 f0g7 = f0 * (crypto_int64) g7; 80 | crypto_int64 f0g8 = f0 * (crypto_int64) g8; 81 | crypto_int64 f0g9 = f0 * (crypto_int64) g9; 82 | crypto_int64 f1g0 = f1 * (crypto_int64) g0; 83 | crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1; 84 | crypto_int64 f1g2 = f1 * (crypto_int64) g2; 85 | crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3; 86 | crypto_int64 f1g4 = f1 * (crypto_int64) g4; 87 | crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5; 88 | crypto_int64 f1g6 = f1 * (crypto_int64) g6; 89 | crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7; 90 | crypto_int64 f1g8 = f1 * (crypto_int64) g8; 91 | crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19; 92 | crypto_int64 f2g0 = f2 * (crypto_int64) g0; 93 | crypto_int64 f2g1 = f2 * (crypto_int64) g1; 94 | crypto_int64 f2g2 = f2 * (crypto_int64) g2; 95 | crypto_int64 f2g3 = f2 * (crypto_int64) g3; 96 | crypto_int64 f2g4 = f2 * (crypto_int64) g4; 97 | crypto_int64 f2g5 = f2 * (crypto_int64) g5; 98 | crypto_int64 f2g6 = f2 * (crypto_int64) g6; 99 | crypto_int64 f2g7 = f2 * (crypto_int64) g7; 100 | crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19; 101 | crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19; 102 | crypto_int64 f3g0 = f3 * (crypto_int64) g0; 103 | crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1; 104 | crypto_int64 f3g2 = f3 * (crypto_int64) g2; 105 | crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3; 106 | crypto_int64 f3g4 = f3 * (crypto_int64) g4; 107 | crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5; 108 | crypto_int64 f3g6 = f3 * (crypto_int64) g6; 109 | crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19; 110 | crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19; 111 | crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19; 112 | crypto_int64 f4g0 = f4 * (crypto_int64) g0; 113 | crypto_int64 f4g1 = f4 * (crypto_int64) g1; 114 | crypto_int64 f4g2 = f4 * (crypto_int64) g2; 115 | crypto_int64 f4g3 = f4 * (crypto_int64) g3; 116 | crypto_int64 f4g4 = f4 * (crypto_int64) g4; 117 | crypto_int64 f4g5 = f4 * (crypto_int64) g5; 118 | crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19; 119 | crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19; 120 | crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19; 121 | crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19; 122 | crypto_int64 f5g0 = f5 * (crypto_int64) g0; 123 | crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1; 124 | crypto_int64 f5g2 = f5 * (crypto_int64) g2; 125 | crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3; 126 | crypto_int64 f5g4 = f5 * (crypto_int64) g4; 127 | crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19; 128 | crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19; 129 | crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19; 130 | crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19; 131 | crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19; 132 | crypto_int64 f6g0 = f6 * (crypto_int64) g0; 133 | crypto_int64 f6g1 = f6 * (crypto_int64) g1; 134 | crypto_int64 f6g2 = f6 * (crypto_int64) g2; 135 | crypto_int64 f6g3 = f6 * (crypto_int64) g3; 136 | crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19; 137 | crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19; 138 | crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19; 139 | crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19; 140 | crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19; 141 | crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19; 142 | crypto_int64 f7g0 = f7 * (crypto_int64) g0; 143 | crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1; 144 | crypto_int64 f7g2 = f7 * (crypto_int64) g2; 145 | crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19; 146 | crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19; 147 | crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19; 148 | crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19; 149 | crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19; 150 | crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19; 151 | crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19; 152 | crypto_int64 f8g0 = f8 * (crypto_int64) g0; 153 | crypto_int64 f8g1 = f8 * (crypto_int64) g1; 154 | crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19; 155 | crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19; 156 | crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19; 157 | crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19; 158 | crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19; 159 | crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19; 160 | crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19; 161 | crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19; 162 | crypto_int64 f9g0 = f9 * (crypto_int64) g0; 163 | crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19; 164 | crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19; 165 | crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19; 166 | crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19; 167 | crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19; 168 | crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19; 169 | crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19; 170 | crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19; 171 | crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19; 172 | crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; 173 | crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; 174 | crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; 175 | crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; 176 | crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; 177 | crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; 178 | crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; 179 | crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; 180 | crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; 181 | crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; 182 | crypto_int64 carry0; 183 | crypto_int64 carry1; 184 | crypto_int64 carry2; 185 | crypto_int64 carry3; 186 | crypto_int64 carry4; 187 | crypto_int64 carry5; 188 | crypto_int64 carry6; 189 | crypto_int64 carry7; 190 | crypto_int64 carry8; 191 | crypto_int64 carry9; 192 | 193 | /* 194 | |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) 195 | i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 196 | |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) 197 | i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 198 | */ 199 | 200 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 201 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 202 | /* |h0| <= 2^25 */ 203 | /* |h4| <= 2^25 */ 204 | /* |h1| <= 1.71*2^59 */ 205 | /* |h5| <= 1.71*2^59 */ 206 | 207 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 208 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 209 | /* |h1| <= 2^24; from now on fits into int32 */ 210 | /* |h5| <= 2^24; from now on fits into int32 */ 211 | /* |h2| <= 1.41*2^60 */ 212 | /* |h6| <= 1.41*2^60 */ 213 | 214 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 215 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 216 | /* |h2| <= 2^25; from now on fits into int32 unchanged */ 217 | /* |h6| <= 2^25; from now on fits into int32 unchanged */ 218 | /* |h3| <= 1.71*2^59 */ 219 | /* |h7| <= 1.71*2^59 */ 220 | 221 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 222 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 223 | /* |h3| <= 2^24; from now on fits into int32 unchanged */ 224 | /* |h7| <= 2^24; from now on fits into int32 unchanged */ 225 | /* |h4| <= 1.72*2^34 */ 226 | /* |h8| <= 1.41*2^60 */ 227 | 228 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 229 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 230 | /* |h4| <= 2^25; from now on fits into int32 unchanged */ 231 | /* |h8| <= 2^25; from now on fits into int32 unchanged */ 232 | /* |h5| <= 1.01*2^24 */ 233 | /* |h9| <= 1.71*2^59 */ 234 | 235 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 236 | /* |h9| <= 2^24; from now on fits into int32 unchanged */ 237 | /* |h0| <= 1.1*2^39 */ 238 | 239 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 240 | /* |h0| <= 2^25; from now on fits into int32 unchanged */ 241 | /* |h1| <= 1.01*2^24 */ 242 | 243 | h[0] = h0; 244 | h[1] = h1; 245 | h[2] = h2; 246 | h[3] = h3; 247 | h[4] = h4; 248 | h[5] = h5; 249 | h[6] = h6; 250 | h[7] = h7; 251 | h[8] = h8; 252 | h[9] = h9; 253 | } 254 | -------------------------------------------------------------------------------- /curve/ed25519/sc_muladd.c: -------------------------------------------------------------------------------- 1 | #include "sc.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | #include "nacl_includes/crypto_uint32.h" 4 | #include "nacl_includes/crypto_uint64.h" 5 | 6 | static crypto_uint64 load_3(const unsigned char *in) 7 | { 8 | crypto_uint64 result; 9 | result = (crypto_uint64) in[0]; 10 | result |= ((crypto_uint64) in[1]) << 8; 11 | result |= ((crypto_uint64) in[2]) << 16; 12 | return result; 13 | } 14 | 15 | static crypto_uint64 load_4(const unsigned char *in) 16 | { 17 | crypto_uint64 result; 18 | result = (crypto_uint64) in[0]; 19 | result |= ((crypto_uint64) in[1]) << 8; 20 | result |= ((crypto_uint64) in[2]) << 16; 21 | result |= ((crypto_uint64) in[3]) << 24; 22 | return result; 23 | } 24 | 25 | /* 26 | Input: 27 | a[0]+256*a[1]+...+256^31*a[31] = a 28 | b[0]+256*b[1]+...+256^31*b[31] = b 29 | c[0]+256*c[1]+...+256^31*c[31] = c 30 | 31 | Output: 32 | s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l 33 | where l = 2^252 + 27742317777372353535851937790883648493. 34 | */ 35 | 36 | void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,const unsigned char *c) 37 | { 38 | crypto_int64 a0 = 2097151 & load_3(a); 39 | crypto_int64 a1 = 2097151 & (load_4(a + 2) >> 5); 40 | crypto_int64 a2 = 2097151 & (load_3(a + 5) >> 2); 41 | crypto_int64 a3 = 2097151 & (load_4(a + 7) >> 7); 42 | crypto_int64 a4 = 2097151 & (load_4(a + 10) >> 4); 43 | crypto_int64 a5 = 2097151 & (load_3(a + 13) >> 1); 44 | crypto_int64 a6 = 2097151 & (load_4(a + 15) >> 6); 45 | crypto_int64 a7 = 2097151 & (load_3(a + 18) >> 3); 46 | crypto_int64 a8 = 2097151 & load_3(a + 21); 47 | crypto_int64 a9 = 2097151 & (load_4(a + 23) >> 5); 48 | crypto_int64 a10 = 2097151 & (load_3(a + 26) >> 2); 49 | crypto_int64 a11 = (load_4(a + 28) >> 7); 50 | crypto_int64 b0 = 2097151 & load_3(b); 51 | crypto_int64 b1 = 2097151 & (load_4(b + 2) >> 5); 52 | crypto_int64 b2 = 2097151 & (load_3(b + 5) >> 2); 53 | crypto_int64 b3 = 2097151 & (load_4(b + 7) >> 7); 54 | crypto_int64 b4 = 2097151 & (load_4(b + 10) >> 4); 55 | crypto_int64 b5 = 2097151 & (load_3(b + 13) >> 1); 56 | crypto_int64 b6 = 2097151 & (load_4(b + 15) >> 6); 57 | crypto_int64 b7 = 2097151 & (load_3(b + 18) >> 3); 58 | crypto_int64 b8 = 2097151 & load_3(b + 21); 59 | crypto_int64 b9 = 2097151 & (load_4(b + 23) >> 5); 60 | crypto_int64 b10 = 2097151 & (load_3(b + 26) >> 2); 61 | crypto_int64 b11 = (load_4(b + 28) >> 7); 62 | crypto_int64 c0 = 2097151 & load_3(c); 63 | crypto_int64 c1 = 2097151 & (load_4(c + 2) >> 5); 64 | crypto_int64 c2 = 2097151 & (load_3(c + 5) >> 2); 65 | crypto_int64 c3 = 2097151 & (load_4(c + 7) >> 7); 66 | crypto_int64 c4 = 2097151 & (load_4(c + 10) >> 4); 67 | crypto_int64 c5 = 2097151 & (load_3(c + 13) >> 1); 68 | crypto_int64 c6 = 2097151 & (load_4(c + 15) >> 6); 69 | crypto_int64 c7 = 2097151 & (load_3(c + 18) >> 3); 70 | crypto_int64 c8 = 2097151 & load_3(c + 21); 71 | crypto_int64 c9 = 2097151 & (load_4(c + 23) >> 5); 72 | crypto_int64 c10 = 2097151 & (load_3(c + 26) >> 2); 73 | crypto_int64 c11 = (load_4(c + 28) >> 7); 74 | crypto_int64 s0; 75 | crypto_int64 s1; 76 | crypto_int64 s2; 77 | crypto_int64 s3; 78 | crypto_int64 s4; 79 | crypto_int64 s5; 80 | crypto_int64 s6; 81 | crypto_int64 s7; 82 | crypto_int64 s8; 83 | crypto_int64 s9; 84 | crypto_int64 s10; 85 | crypto_int64 s11; 86 | crypto_int64 s12; 87 | crypto_int64 s13; 88 | crypto_int64 s14; 89 | crypto_int64 s15; 90 | crypto_int64 s16; 91 | crypto_int64 s17; 92 | crypto_int64 s18; 93 | crypto_int64 s19; 94 | crypto_int64 s20; 95 | crypto_int64 s21; 96 | crypto_int64 s22; 97 | crypto_int64 s23; 98 | crypto_int64 carry0; 99 | crypto_int64 carry1; 100 | crypto_int64 carry2; 101 | crypto_int64 carry3; 102 | crypto_int64 carry4; 103 | crypto_int64 carry5; 104 | crypto_int64 carry6; 105 | crypto_int64 carry7; 106 | crypto_int64 carry8; 107 | crypto_int64 carry9; 108 | crypto_int64 carry10; 109 | crypto_int64 carry11; 110 | crypto_int64 carry12; 111 | crypto_int64 carry13; 112 | crypto_int64 carry14; 113 | crypto_int64 carry15; 114 | crypto_int64 carry16; 115 | crypto_int64 carry17; 116 | crypto_int64 carry18; 117 | crypto_int64 carry19; 118 | crypto_int64 carry20; 119 | crypto_int64 carry21; 120 | crypto_int64 carry22; 121 | 122 | s0 = c0 + a0*b0; 123 | s1 = c1 + a0*b1 + a1*b0; 124 | s2 = c2 + a0*b2 + a1*b1 + a2*b0; 125 | s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; 126 | s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; 127 | s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; 128 | s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; 129 | s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; 130 | s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0; 131 | s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0; 132 | s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0; 133 | s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0; 134 | s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1; 135 | s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2; 136 | s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3; 137 | s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; 138 | s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; 139 | s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; 140 | s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; 141 | s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; 142 | s20 = a9*b11 + a10*b10 + a11*b9; 143 | s21 = a10*b11 + a11*b10; 144 | s22 = a11*b11; 145 | s23 = 0; 146 | 147 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; 148 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; 149 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; 150 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 151 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 152 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 153 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; 154 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; 155 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; 156 | carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; 157 | carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; 158 | carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; 159 | 160 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; 161 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; 162 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; 163 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 164 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 165 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 166 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; 167 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; 168 | carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; 169 | carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; 170 | carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; 171 | 172 | s11 += s23 * 666643; 173 | s12 += s23 * 470296; 174 | s13 += s23 * 654183; 175 | s14 -= s23 * 997805; 176 | s15 += s23 * 136657; 177 | s16 -= s23 * 683901; 178 | s23 = 0; 179 | 180 | s10 += s22 * 666643; 181 | s11 += s22 * 470296; 182 | s12 += s22 * 654183; 183 | s13 -= s22 * 997805; 184 | s14 += s22 * 136657; 185 | s15 -= s22 * 683901; 186 | s22 = 0; 187 | 188 | s9 += s21 * 666643; 189 | s10 += s21 * 470296; 190 | s11 += s21 * 654183; 191 | s12 -= s21 * 997805; 192 | s13 += s21 * 136657; 193 | s14 -= s21 * 683901; 194 | s21 = 0; 195 | 196 | s8 += s20 * 666643; 197 | s9 += s20 * 470296; 198 | s10 += s20 * 654183; 199 | s11 -= s20 * 997805; 200 | s12 += s20 * 136657; 201 | s13 -= s20 * 683901; 202 | s20 = 0; 203 | 204 | s7 += s19 * 666643; 205 | s8 += s19 * 470296; 206 | s9 += s19 * 654183; 207 | s10 -= s19 * 997805; 208 | s11 += s19 * 136657; 209 | s12 -= s19 * 683901; 210 | s19 = 0; 211 | 212 | s6 += s18 * 666643; 213 | s7 += s18 * 470296; 214 | s8 += s18 * 654183; 215 | s9 -= s18 * 997805; 216 | s10 += s18 * 136657; 217 | s11 -= s18 * 683901; 218 | s18 = 0; 219 | 220 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 221 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 222 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 223 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; 224 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; 225 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; 226 | 227 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 228 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 229 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 230 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; 231 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; 232 | 233 | s5 += s17 * 666643; 234 | s6 += s17 * 470296; 235 | s7 += s17 * 654183; 236 | s8 -= s17 * 997805; 237 | s9 += s17 * 136657; 238 | s10 -= s17 * 683901; 239 | s17 = 0; 240 | 241 | s4 += s16 * 666643; 242 | s5 += s16 * 470296; 243 | s6 += s16 * 654183; 244 | s7 -= s16 * 997805; 245 | s8 += s16 * 136657; 246 | s9 -= s16 * 683901; 247 | s16 = 0; 248 | 249 | s3 += s15 * 666643; 250 | s4 += s15 * 470296; 251 | s5 += s15 * 654183; 252 | s6 -= s15 * 997805; 253 | s7 += s15 * 136657; 254 | s8 -= s15 * 683901; 255 | s15 = 0; 256 | 257 | s2 += s14 * 666643; 258 | s3 += s14 * 470296; 259 | s4 += s14 * 654183; 260 | s5 -= s14 * 997805; 261 | s6 += s14 * 136657; 262 | s7 -= s14 * 683901; 263 | s14 = 0; 264 | 265 | s1 += s13 * 666643; 266 | s2 += s13 * 470296; 267 | s3 += s13 * 654183; 268 | s4 -= s13 * 997805; 269 | s5 += s13 * 136657; 270 | s6 -= s13 * 683901; 271 | s13 = 0; 272 | 273 | s0 += s12 * 666643; 274 | s1 += s12 * 470296; 275 | s2 += s12 * 654183; 276 | s3 -= s12 * 997805; 277 | s4 += s12 * 136657; 278 | s5 -= s12 * 683901; 279 | s12 = 0; 280 | 281 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; 282 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; 283 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; 284 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 285 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 286 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 287 | 288 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; 289 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; 290 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; 291 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 292 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 293 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 294 | 295 | s0 += s12 * 666643; 296 | s1 += s12 * 470296; 297 | s2 += s12 * 654183; 298 | s3 -= s12 * 997805; 299 | s4 += s12 * 136657; 300 | s5 -= s12 * 683901; 301 | s12 = 0; 302 | 303 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 304 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 305 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 306 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 307 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 308 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; 309 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; 310 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; 311 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; 312 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; 313 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; 314 | carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; 315 | 316 | s0 += s12 * 666643; 317 | s1 += s12 * 470296; 318 | s2 += s12 * 654183; 319 | s3 -= s12 * 997805; 320 | s4 += s12 * 136657; 321 | s5 -= s12 * 683901; 322 | s12 = 0; 323 | 324 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 325 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 326 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 327 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 328 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 329 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; 330 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; 331 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; 332 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; 333 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; 334 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; 335 | 336 | s[0] = s0 >> 0; 337 | s[1] = s0 >> 8; 338 | s[2] = (s0 >> 16) | (s1 << 5); 339 | s[3] = s1 >> 3; 340 | s[4] = s1 >> 11; 341 | s[5] = (s1 >> 19) | (s2 << 2); 342 | s[6] = s2 >> 6; 343 | s[7] = (s2 >> 14) | (s3 << 7); 344 | s[8] = s3 >> 1; 345 | s[9] = s3 >> 9; 346 | s[10] = (s3 >> 17) | (s4 << 4); 347 | s[11] = s4 >> 4; 348 | s[12] = s4 >> 12; 349 | s[13] = (s4 >> 20) | (s5 << 1); 350 | s[14] = s5 >> 7; 351 | s[15] = (s5 >> 15) | (s6 << 6); 352 | s[16] = s6 >> 2; 353 | s[17] = s6 >> 10; 354 | s[18] = (s6 >> 18) | (s7 << 3); 355 | s[19] = s7 >> 5; 356 | s[20] = s7 >> 13; 357 | s[21] = s8 >> 0; 358 | s[22] = s8 >> 8; 359 | s[23] = (s8 >> 16) | (s9 << 5); 360 | s[24] = s9 >> 3; 361 | s[25] = s9 >> 11; 362 | s[26] = (s9 >> 19) | (s10 << 2); 363 | s[27] = s10 >> 6; 364 | s[28] = (s10 >> 14) | (s11 << 7); 365 | s[29] = s11 >> 1; 366 | s[30] = s11 >> 9; 367 | s[31] = s11 >> 17; 368 | } 369 | -------------------------------------------------------------------------------- /curve/curve25519-donna.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2008, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * curve25519-donna: Curve25519 elliptic curve, public key function 31 | * 32 | * http://code.google.com/p/curve25519-donna/ 33 | * 34 | * Adam Langley 35 | * 36 | * Derived from public domain C code by Daniel J. Bernstein 37 | * 38 | * More information about curve25519 can be found here 39 | * http://cr.yp.to/ecdh.html 40 | * 41 | * djb's sample implementation of curve25519 is written in a special assembly 42 | * language called qhasm and uses the floating point registers. 43 | * 44 | * This is, almost, a clean room reimplementation from the curve25519 paper. It 45 | * uses many of the tricks described therein. Only the crecip function is taken 46 | * from the sample implementation. */ 47 | 48 | #include 49 | #include 50 | 51 | #ifdef _MSC_VER 52 | #define inline __inline 53 | #endif 54 | 55 | typedef uint8_t u8; 56 | typedef int32_t s32; 57 | typedef int64_t limb; 58 | 59 | /* Field element representation: 60 | * 61 | * Field elements are written as an array of signed, 64-bit limbs, least 62 | * significant first. The value of the field element is: 63 | * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... 64 | * 65 | * i.e. the limbs are 26, 25, 26, 25, ... bits wide. */ 66 | 67 | /* Sum two numbers: output += in */ 68 | static void fsum(limb *output, const limb *in) { 69 | unsigned i; 70 | for (i = 0; i < 10; i += 2) { 71 | output[0+i] = output[0+i] + in[0+i]; 72 | output[1+i] = output[1+i] + in[1+i]; 73 | } 74 | } 75 | 76 | /* Find the difference of two numbers: output = in - output 77 | * (note the order of the arguments!). */ 78 | static void fdifference(limb *output, const limb *in) { 79 | unsigned i; 80 | for (i = 0; i < 10; ++i) { 81 | output[i] = in[i] - output[i]; 82 | } 83 | } 84 | 85 | /* Multiply a number by a scalar: output = in * scalar */ 86 | static void fscalar_product(limb *output, const limb *in, const limb scalar) { 87 | unsigned i; 88 | for (i = 0; i < 10; ++i) { 89 | output[i] = in[i] * scalar; 90 | } 91 | } 92 | 93 | /* Multiply two numbers: output = in2 * in 94 | * 95 | * output must be distinct to both inputs. The inputs are reduced coefficient 96 | * form, the output is not. 97 | * 98 | * output[x] <= 14 * the largest product of the input limbs. */ 99 | static void fproduct(limb *output, const limb *in2, const limb *in) { 100 | output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); 101 | output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + 102 | ((limb) ((s32) in2[1])) * ((s32) in[0]); 103 | output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + 104 | ((limb) ((s32) in2[0])) * ((s32) in[2]) + 105 | ((limb) ((s32) in2[2])) * ((s32) in[0]); 106 | output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + 107 | ((limb) ((s32) in2[2])) * ((s32) in[1]) + 108 | ((limb) ((s32) in2[0])) * ((s32) in[3]) + 109 | ((limb) ((s32) in2[3])) * ((s32) in[0]); 110 | output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + 111 | 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + 112 | ((limb) ((s32) in2[3])) * ((s32) in[1])) + 113 | ((limb) ((s32) in2[0])) * ((s32) in[4]) + 114 | ((limb) ((s32) in2[4])) * ((s32) in[0]); 115 | output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + 116 | ((limb) ((s32) in2[3])) * ((s32) in[2]) + 117 | ((limb) ((s32) in2[1])) * ((s32) in[4]) + 118 | ((limb) ((s32) in2[4])) * ((s32) in[1]) + 119 | ((limb) ((s32) in2[0])) * ((s32) in[5]) + 120 | ((limb) ((s32) in2[5])) * ((s32) in[0]); 121 | output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + 122 | ((limb) ((s32) in2[1])) * ((s32) in[5]) + 123 | ((limb) ((s32) in2[5])) * ((s32) in[1])) + 124 | ((limb) ((s32) in2[2])) * ((s32) in[4]) + 125 | ((limb) ((s32) in2[4])) * ((s32) in[2]) + 126 | ((limb) ((s32) in2[0])) * ((s32) in[6]) + 127 | ((limb) ((s32) in2[6])) * ((s32) in[0]); 128 | output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + 129 | ((limb) ((s32) in2[4])) * ((s32) in[3]) + 130 | ((limb) ((s32) in2[2])) * ((s32) in[5]) + 131 | ((limb) ((s32) in2[5])) * ((s32) in[2]) + 132 | ((limb) ((s32) in2[1])) * ((s32) in[6]) + 133 | ((limb) ((s32) in2[6])) * ((s32) in[1]) + 134 | ((limb) ((s32) in2[0])) * ((s32) in[7]) + 135 | ((limb) ((s32) in2[7])) * ((s32) in[0]); 136 | output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + 137 | 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + 138 | ((limb) ((s32) in2[5])) * ((s32) in[3]) + 139 | ((limb) ((s32) in2[1])) * ((s32) in[7]) + 140 | ((limb) ((s32) in2[7])) * ((s32) in[1])) + 141 | ((limb) ((s32) in2[2])) * ((s32) in[6]) + 142 | ((limb) ((s32) in2[6])) * ((s32) in[2]) + 143 | ((limb) ((s32) in2[0])) * ((s32) in[8]) + 144 | ((limb) ((s32) in2[8])) * ((s32) in[0]); 145 | output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + 146 | ((limb) ((s32) in2[5])) * ((s32) in[4]) + 147 | ((limb) ((s32) in2[3])) * ((s32) in[6]) + 148 | ((limb) ((s32) in2[6])) * ((s32) in[3]) + 149 | ((limb) ((s32) in2[2])) * ((s32) in[7]) + 150 | ((limb) ((s32) in2[7])) * ((s32) in[2]) + 151 | ((limb) ((s32) in2[1])) * ((s32) in[8]) + 152 | ((limb) ((s32) in2[8])) * ((s32) in[1]) + 153 | ((limb) ((s32) in2[0])) * ((s32) in[9]) + 154 | ((limb) ((s32) in2[9])) * ((s32) in[0]); 155 | output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + 156 | ((limb) ((s32) in2[3])) * ((s32) in[7]) + 157 | ((limb) ((s32) in2[7])) * ((s32) in[3]) + 158 | ((limb) ((s32) in2[1])) * ((s32) in[9]) + 159 | ((limb) ((s32) in2[9])) * ((s32) in[1])) + 160 | ((limb) ((s32) in2[4])) * ((s32) in[6]) + 161 | ((limb) ((s32) in2[6])) * ((s32) in[4]) + 162 | ((limb) ((s32) in2[2])) * ((s32) in[8]) + 163 | ((limb) ((s32) in2[8])) * ((s32) in[2]); 164 | output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + 165 | ((limb) ((s32) in2[6])) * ((s32) in[5]) + 166 | ((limb) ((s32) in2[4])) * ((s32) in[7]) + 167 | ((limb) ((s32) in2[7])) * ((s32) in[4]) + 168 | ((limb) ((s32) in2[3])) * ((s32) in[8]) + 169 | ((limb) ((s32) in2[8])) * ((s32) in[3]) + 170 | ((limb) ((s32) in2[2])) * ((s32) in[9]) + 171 | ((limb) ((s32) in2[9])) * ((s32) in[2]); 172 | output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + 173 | 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + 174 | ((limb) ((s32) in2[7])) * ((s32) in[5]) + 175 | ((limb) ((s32) in2[3])) * ((s32) in[9]) + 176 | ((limb) ((s32) in2[9])) * ((s32) in[3])) + 177 | ((limb) ((s32) in2[4])) * ((s32) in[8]) + 178 | ((limb) ((s32) in2[8])) * ((s32) in[4]); 179 | output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + 180 | ((limb) ((s32) in2[7])) * ((s32) in[6]) + 181 | ((limb) ((s32) in2[5])) * ((s32) in[8]) + 182 | ((limb) ((s32) in2[8])) * ((s32) in[5]) + 183 | ((limb) ((s32) in2[4])) * ((s32) in[9]) + 184 | ((limb) ((s32) in2[9])) * ((s32) in[4]); 185 | output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + 186 | ((limb) ((s32) in2[5])) * ((s32) in[9]) + 187 | ((limb) ((s32) in2[9])) * ((s32) in[5])) + 188 | ((limb) ((s32) in2[6])) * ((s32) in[8]) + 189 | ((limb) ((s32) in2[8])) * ((s32) in[6]); 190 | output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + 191 | ((limb) ((s32) in2[8])) * ((s32) in[7]) + 192 | ((limb) ((s32) in2[6])) * ((s32) in[9]) + 193 | ((limb) ((s32) in2[9])) * ((s32) in[6]); 194 | output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + 195 | 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + 196 | ((limb) ((s32) in2[9])) * ((s32) in[7])); 197 | output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + 198 | ((limb) ((s32) in2[9])) * ((s32) in[8]); 199 | output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); 200 | } 201 | 202 | /* Reduce a long form to a short form by taking the input mod 2^255 - 19. 203 | * 204 | * On entry: |output[i]| < 14*2^54 205 | * On exit: |output[0..8]| < 280*2^54 */ 206 | static void freduce_degree(limb *output) { 207 | /* Each of these shifts and adds ends up multiplying the value by 19. 208 | * 209 | * For output[0..8], the absolute entry value is < 14*2^54 and we add, at 210 | * most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */ 211 | output[8] += output[18] << 4; 212 | output[8] += output[18] << 1; 213 | output[8] += output[18]; 214 | output[7] += output[17] << 4; 215 | output[7] += output[17] << 1; 216 | output[7] += output[17]; 217 | output[6] += output[16] << 4; 218 | output[6] += output[16] << 1; 219 | output[6] += output[16]; 220 | output[5] += output[15] << 4; 221 | output[5] += output[15] << 1; 222 | output[5] += output[15]; 223 | output[4] += output[14] << 4; 224 | output[4] += output[14] << 1; 225 | output[4] += output[14]; 226 | output[3] += output[13] << 4; 227 | output[3] += output[13] << 1; 228 | output[3] += output[13]; 229 | output[2] += output[12] << 4; 230 | output[2] += output[12] << 1; 231 | output[2] += output[12]; 232 | output[1] += output[11] << 4; 233 | output[1] += output[11] << 1; 234 | output[1] += output[11]; 235 | output[0] += output[10] << 4; 236 | output[0] += output[10] << 1; 237 | output[0] += output[10]; 238 | } 239 | 240 | #if (-1 & 3) != 3 241 | #error "This code only works on a two's complement system" 242 | #endif 243 | 244 | /* return v / 2^26, using only shifts and adds. 245 | * 246 | * On entry: v can take any value. */ 247 | static inline limb 248 | div_by_2_26(const limb v) 249 | { 250 | /* High word of v; no shift needed. */ 251 | const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); 252 | /* Set to all 1s if v was negative; else set to 0s. */ 253 | const int32_t sign = ((int32_t) highword) >> 31; 254 | /* Set to 0x3ffffff if v was negative; else set to 0. */ 255 | const int32_t roundoff = ((uint32_t) sign) >> 6; 256 | /* Should return v / (1<<26) */ 257 | return (v + roundoff) >> 26; 258 | } 259 | 260 | /* return v / (2^25), using only shifts and adds. 261 | * 262 | * On entry: v can take any value. */ 263 | static inline limb 264 | div_by_2_25(const limb v) 265 | { 266 | /* High word of v; no shift needed*/ 267 | const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); 268 | /* Set to all 1s if v was negative; else set to 0s. */ 269 | const int32_t sign = ((int32_t) highword) >> 31; 270 | /* Set to 0x1ffffff if v was negative; else set to 0. */ 271 | const int32_t roundoff = ((uint32_t) sign) >> 7; 272 | /* Should return v / (1<<25) */ 273 | return (v + roundoff) >> 25; 274 | } 275 | 276 | /* return v / (2^25), using only shifts and adds. 277 | * 278 | * On entry: v can take any value. */ 279 | static inline s32 280 | div_s32_by_2_25(const s32 v) 281 | { 282 | const s32 roundoff = ((uint32_t)(v >> 31)) >> 7; 283 | return (v + roundoff) >> 25; 284 | } 285 | 286 | /* Reduce all coefficients of the short form input so that |x| < 2^26. 287 | * 288 | * On entry: |output[i]| < 280*2^54 */ 289 | static void freduce_coefficients(limb *output) { 290 | unsigned i; 291 | 292 | output[10] = 0; 293 | 294 | for (i = 0; i < 10; i += 2) { 295 | limb over = div_by_2_26(output[i]); 296 | /* The entry condition (that |output[i]| < 280*2^54) means that over is, at 297 | * most, 280*2^28 in the first iteration of this loop. This is added to the 298 | * next limb and we can approximate the resulting bound of that limb by 299 | * 281*2^54. */ 300 | output[i] -= over << 26; 301 | output[i+1] += over; 302 | 303 | /* For the first iteration, |output[i+1]| < 281*2^54, thus |over| < 304 | * 281*2^29. When this is added to the next limb, the resulting bound can 305 | * be approximated as 281*2^54. 306 | * 307 | * For subsequent iterations of the loop, 281*2^54 remains a conservative 308 | * bound and no overflow occurs. */ 309 | over = div_by_2_25(output[i+1]); 310 | output[i+1] -= over << 25; 311 | output[i+2] += over; 312 | } 313 | /* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */ 314 | output[0] += output[10] << 4; 315 | output[0] += output[10] << 1; 316 | output[0] += output[10]; 317 | 318 | output[10] = 0; 319 | 320 | /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29 321 | * So |over| will be no more than 2^16. */ 322 | { 323 | limb over = div_by_2_26(output[0]); 324 | output[0] -= over << 26; 325 | output[1] += over; 326 | } 327 | 328 | /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The 329 | * bound on |output[1]| is sufficient to meet our needs. */ 330 | } 331 | 332 | /* A helpful wrapper around fproduct: output = in * in2. 333 | * 334 | * On entry: |in[i]| < 2^27 and |in2[i]| < 2^27. 335 | * 336 | * output must be distinct to both inputs. The output is reduced degree 337 | * (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */ 338 | static void 339 | fmul(limb *output, const limb *in, const limb *in2) { 340 | limb t[19]; 341 | fproduct(t, in, in2); 342 | /* |t[i]| < 14*2^54 */ 343 | freduce_degree(t); 344 | freduce_coefficients(t); 345 | /* |t[i]| < 2^26 */ 346 | memcpy(output, t, sizeof(limb) * 10); 347 | } 348 | 349 | /* Square a number: output = in**2 350 | * 351 | * output must be distinct from the input. The inputs are reduced coefficient 352 | * form, the output is not. 353 | * 354 | * output[x] <= 14 * the largest product of the input limbs. */ 355 | static void fsquare_inner(limb *output, const limb *in) { 356 | output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); 357 | output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); 358 | output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + 359 | ((limb) ((s32) in[0])) * ((s32) in[2])); 360 | output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + 361 | ((limb) ((s32) in[0])) * ((s32) in[3])); 362 | output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + 363 | 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + 364 | 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); 365 | output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + 366 | ((limb) ((s32) in[1])) * ((s32) in[4]) + 367 | ((limb) ((s32) in[0])) * ((s32) in[5])); 368 | output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + 369 | ((limb) ((s32) in[2])) * ((s32) in[4]) + 370 | ((limb) ((s32) in[0])) * ((s32) in[6]) + 371 | 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); 372 | output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + 373 | ((limb) ((s32) in[2])) * ((s32) in[5]) + 374 | ((limb) ((s32) in[1])) * ((s32) in[6]) + 375 | ((limb) ((s32) in[0])) * ((s32) in[7])); 376 | output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + 377 | 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + 378 | ((limb) ((s32) in[0])) * ((s32) in[8]) + 379 | 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + 380 | ((limb) ((s32) in[3])) * ((s32) in[5]))); 381 | output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + 382 | ((limb) ((s32) in[3])) * ((s32) in[6]) + 383 | ((limb) ((s32) in[2])) * ((s32) in[7]) + 384 | ((limb) ((s32) in[1])) * ((s32) in[8]) + 385 | ((limb) ((s32) in[0])) * ((s32) in[9])); 386 | output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + 387 | ((limb) ((s32) in[4])) * ((s32) in[6]) + 388 | ((limb) ((s32) in[2])) * ((s32) in[8]) + 389 | 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + 390 | ((limb) ((s32) in[1])) * ((s32) in[9]))); 391 | output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + 392 | ((limb) ((s32) in[4])) * ((s32) in[7]) + 393 | ((limb) ((s32) in[3])) * ((s32) in[8]) + 394 | ((limb) ((s32) in[2])) * ((s32) in[9])); 395 | output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + 396 | 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + 397 | 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + 398 | ((limb) ((s32) in[3])) * ((s32) in[9]))); 399 | output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + 400 | ((limb) ((s32) in[5])) * ((s32) in[8]) + 401 | ((limb) ((s32) in[4])) * ((s32) in[9])); 402 | output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + 403 | ((limb) ((s32) in[6])) * ((s32) in[8]) + 404 | 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); 405 | output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + 406 | ((limb) ((s32) in[6])) * ((s32) in[9])); 407 | output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + 408 | 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); 409 | output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); 410 | output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); 411 | } 412 | 413 | /* fsquare sets output = in^2. 414 | * 415 | * On entry: The |in| argument is in reduced coefficients form and |in[i]| < 416 | * 2^27. 417 | * 418 | * On exit: The |output| argument is in reduced coefficients form (indeed, one 419 | * need only provide storage for 10 limbs) and |out[i]| < 2^26. */ 420 | static void 421 | fsquare(limb *output, const limb *in) { 422 | limb t[19]; 423 | fsquare_inner(t, in); 424 | /* |t[i]| < 14*2^54 because the largest product of two limbs will be < 425 | * 2^(27+27) and fsquare_inner adds together, at most, 14 of those 426 | * products. */ 427 | freduce_degree(t); 428 | freduce_coefficients(t); 429 | /* |t[i]| < 2^26 */ 430 | memcpy(output, t, sizeof(limb) * 10); 431 | } 432 | 433 | /* Take a little-endian, 32-byte number and expand it into polynomial form */ 434 | static void 435 | fexpand(limb *output, const u8 *input) { 436 | #define F(n,start,shift,mask) \ 437 | output[n] = ((((limb) input[start + 0]) | \ 438 | ((limb) input[start + 1]) << 8 | \ 439 | ((limb) input[start + 2]) << 16 | \ 440 | ((limb) input[start + 3]) << 24) >> shift) & mask; 441 | F(0, 0, 0, 0x3ffffff); 442 | F(1, 3, 2, 0x1ffffff); 443 | F(2, 6, 3, 0x3ffffff); 444 | F(3, 9, 5, 0x1ffffff); 445 | F(4, 12, 6, 0x3ffffff); 446 | F(5, 16, 0, 0x1ffffff); 447 | F(6, 19, 1, 0x3ffffff); 448 | F(7, 22, 3, 0x1ffffff); 449 | F(8, 25, 4, 0x3ffffff); 450 | F(9, 28, 6, 0x1ffffff); 451 | #undef F 452 | } 453 | 454 | #if (-32 >> 1) != -16 455 | #error "This code only works when >> does sign-extension on negative numbers" 456 | #endif 457 | 458 | /* s32_eq returns 0xffffffff iff a == b and zero otherwise. */ 459 | static s32 s32_eq(s32 a, s32 b) { 460 | a = ~(a ^ b); 461 | a &= a << 16; 462 | a &= a << 8; 463 | a &= a << 4; 464 | a &= a << 2; 465 | a &= a << 1; 466 | return a >> 31; 467 | } 468 | 469 | /* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are 470 | * both non-negative. */ 471 | static s32 s32_gte(s32 a, s32 b) { 472 | a -= b; 473 | /* a >= 0 iff a >= b. */ 474 | return ~(a >> 31); 475 | } 476 | 477 | /* Take a fully reduced polynomial form number and contract it into a 478 | * little-endian, 32-byte array. 479 | * 480 | * On entry: |input_limbs[i]| < 2^26 */ 481 | static void 482 | fcontract(u8 *output, limb *input_limbs) { 483 | int i; 484 | int j; 485 | s32 input[10]; 486 | s32 mask; 487 | 488 | /* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */ 489 | for (i = 0; i < 10; i++) { 490 | input[i] = input_limbs[i]; 491 | } 492 | 493 | for (j = 0; j < 2; ++j) { 494 | for (i = 0; i < 9; ++i) { 495 | if ((i & 1) == 1) { 496 | /* This calculation is a time-invariant way to make input[i] 497 | * non-negative by borrowing from the next-larger limb. */ 498 | const s32 mask = input[i] >> 31; 499 | const s32 carry = -((input[i] & mask) >> 25); 500 | input[i] = input[i] + (carry << 25); 501 | input[i+1] = input[i+1] - carry; 502 | } else { 503 | const s32 mask = input[i] >> 31; 504 | const s32 carry = -((input[i] & mask) >> 26); 505 | input[i] = input[i] + (carry << 26); 506 | input[i+1] = input[i+1] - carry; 507 | } 508 | } 509 | 510 | /* There's no greater limb for input[9] to borrow from, but we can multiply 511 | * by 19 and borrow from input[0], which is valid mod 2^255-19. */ 512 | { 513 | const s32 mask = input[9] >> 31; 514 | const s32 carry = -((input[9] & mask) >> 25); 515 | input[9] = input[9] + (carry << 25); 516 | input[0] = input[0] - (carry * 19); 517 | } 518 | 519 | /* After the first iteration, input[1..9] are non-negative and fit within 520 | * 25 or 26 bits, depending on position. However, input[0] may be 521 | * negative. */ 522 | } 523 | 524 | /* The first borrow-propagation pass above ended with every limb 525 | except (possibly) input[0] non-negative. 526 | 527 | If input[0] was negative after the first pass, then it was because of a 528 | carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most, 529 | one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19. 530 | 531 | In the second pass, each limb is decreased by at most one. Thus the second 532 | borrow-propagation pass could only have wrapped around to decrease 533 | input[0] again if the first pass left input[0] negative *and* input[1] 534 | through input[9] were all zero. In that case, input[1] is now 2^25 - 1, 535 | and this last borrow-propagation step will leave input[1] non-negative. */ 536 | { 537 | const s32 mask = input[0] >> 31; 538 | const s32 carry = -((input[0] & mask) >> 26); 539 | input[0] = input[0] + (carry << 26); 540 | input[1] = input[1] - carry; 541 | } 542 | 543 | /* All input[i] are now non-negative. However, there might be values between 544 | * 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */ 545 | for (j = 0; j < 2; j++) { 546 | for (i = 0; i < 9; i++) { 547 | if ((i & 1) == 1) { 548 | const s32 carry = input[i] >> 25; 549 | input[i] &= 0x1ffffff; 550 | input[i+1] += carry; 551 | } else { 552 | const s32 carry = input[i] >> 26; 553 | input[i] &= 0x3ffffff; 554 | input[i+1] += carry; 555 | } 556 | } 557 | 558 | { 559 | const s32 carry = input[9] >> 25; 560 | input[9] &= 0x1ffffff; 561 | input[0] += 19*carry; 562 | } 563 | } 564 | 565 | /* If the first carry-chain pass, just above, ended up with a carry from 566 | * input[9], and that caused input[0] to be out-of-bounds, then input[0] was 567 | * < 2^26 + 2*19, because the carry was, at most, two. 568 | * 569 | * If the second pass carried from input[9] again then input[0] is < 2*19 and 570 | * the input[9] -> input[0] carry didn't push input[0] out of bounds. */ 571 | 572 | /* It still remains the case that input might be between 2^255-19 and 2^255. 573 | * In this case, input[1..9] must take their maximum value and input[0] must 574 | * be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */ 575 | mask = s32_gte(input[0], 0x3ffffed); 576 | for (i = 1; i < 10; i++) { 577 | if ((i & 1) == 1) { 578 | mask &= s32_eq(input[i], 0x1ffffff); 579 | } else { 580 | mask &= s32_eq(input[i], 0x3ffffff); 581 | } 582 | } 583 | 584 | /* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus 585 | * this conditionally subtracts 2^255-19. */ 586 | input[0] -= mask & 0x3ffffed; 587 | 588 | for (i = 1; i < 10; i++) { 589 | if ((i & 1) == 1) { 590 | input[i] -= mask & 0x1ffffff; 591 | } else { 592 | input[i] -= mask & 0x3ffffff; 593 | } 594 | } 595 | 596 | input[1] <<= 2; 597 | input[2] <<= 3; 598 | input[3] <<= 5; 599 | input[4] <<= 6; 600 | input[6] <<= 1; 601 | input[7] <<= 3; 602 | input[8] <<= 4; 603 | input[9] <<= 6; 604 | #define F(i, s) \ 605 | output[s+0] |= input[i] & 0xff; \ 606 | output[s+1] = (input[i] >> 8) & 0xff; \ 607 | output[s+2] = (input[i] >> 16) & 0xff; \ 608 | output[s+3] = (input[i] >> 24) & 0xff; 609 | output[0] = 0; 610 | output[16] = 0; 611 | F(0,0); 612 | F(1,3); 613 | F(2,6); 614 | F(3,9); 615 | F(4,12); 616 | F(5,16); 617 | F(6,19); 618 | F(7,22); 619 | F(8,25); 620 | F(9,28); 621 | #undef F 622 | } 623 | 624 | /* Input: Q, Q', Q-Q' 625 | * Output: 2Q, Q+Q' 626 | * 627 | * x2 z3: long form 628 | * x3 z3: long form 629 | * x z: short form, destroyed 630 | * xprime zprime: short form, destroyed 631 | * qmqp: short form, preserved 632 | * 633 | * On entry and exit, the absolute value of the limbs of all inputs and outputs 634 | * are < 2^26. */ 635 | static void fmonty(limb *x2, limb *z2, /* output 2Q */ 636 | limb *x3, limb *z3, /* output Q + Q' */ 637 | limb *x, limb *z, /* input Q */ 638 | limb *xprime, limb *zprime, /* input Q' */ 639 | const limb *qmqp /* input Q - Q' */) { 640 | limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], 641 | zzprime[19], zzzprime[19], xxxprime[19]; 642 | 643 | memcpy(origx, x, 10 * sizeof(limb)); 644 | fsum(x, z); 645 | /* |x[i]| < 2^27 */ 646 | fdifference(z, origx); /* does x - z */ 647 | /* |z[i]| < 2^27 */ 648 | 649 | memcpy(origxprime, xprime, sizeof(limb) * 10); 650 | fsum(xprime, zprime); 651 | /* |xprime[i]| < 2^27 */ 652 | fdifference(zprime, origxprime); 653 | /* |zprime[i]| < 2^27 */ 654 | fproduct(xxprime, xprime, z); 655 | /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be < 656 | * 2^(27+27) and fproduct adds together, at most, 14 of those products. 657 | * (Approximating that to 2^58 doesn't work out.) */ 658 | fproduct(zzprime, x, zprime); 659 | /* |zzprime[i]| < 14*2^54 */ 660 | freduce_degree(xxprime); 661 | freduce_coefficients(xxprime); 662 | /* |xxprime[i]| < 2^26 */ 663 | freduce_degree(zzprime); 664 | freduce_coefficients(zzprime); 665 | /* |zzprime[i]| < 2^26 */ 666 | memcpy(origxprime, xxprime, sizeof(limb) * 10); 667 | fsum(xxprime, zzprime); 668 | /* |xxprime[i]| < 2^27 */ 669 | fdifference(zzprime, origxprime); 670 | /* |zzprime[i]| < 2^27 */ 671 | fsquare(xxxprime, xxprime); 672 | /* |xxxprime[i]| < 2^26 */ 673 | fsquare(zzzprime, zzprime); 674 | /* |zzzprime[i]| < 2^26 */ 675 | fproduct(zzprime, zzzprime, qmqp); 676 | /* |zzprime[i]| < 14*2^52 */ 677 | freduce_degree(zzprime); 678 | freduce_coefficients(zzprime); 679 | /* |zzprime[i]| < 2^26 */ 680 | memcpy(x3, xxxprime, sizeof(limb) * 10); 681 | memcpy(z3, zzprime, sizeof(limb) * 10); 682 | 683 | fsquare(xx, x); 684 | /* |xx[i]| < 2^26 */ 685 | fsquare(zz, z); 686 | /* |zz[i]| < 2^26 */ 687 | fproduct(x2, xx, zz); 688 | /* |x2[i]| < 14*2^52 */ 689 | freduce_degree(x2); 690 | freduce_coefficients(x2); 691 | /* |x2[i]| < 2^26 */ 692 | fdifference(zz, xx); // does zz = xx - zz 693 | /* |zz[i]| < 2^27 */ 694 | memset(zzz + 10, 0, sizeof(limb) * 9); 695 | fscalar_product(zzz, zz, 121665); 696 | /* |zzz[i]| < 2^(27+17) */ 697 | /* No need to call freduce_degree here: 698 | fscalar_product doesn't increase the degree of its input. */ 699 | freduce_coefficients(zzz); 700 | /* |zzz[i]| < 2^26 */ 701 | fsum(zzz, xx); 702 | /* |zzz[i]| < 2^27 */ 703 | fproduct(z2, zz, zzz); 704 | /* |z2[i]| < 14*2^(26+27) */ 705 | freduce_degree(z2); 706 | freduce_coefficients(z2); 707 | /* |z2|i| < 2^26 */ 708 | } 709 | 710 | /* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave 711 | * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid 712 | * side-channel attacks. 713 | * 714 | * NOTE that this function requires that 'iswap' be 1 or 0; other values give 715 | * wrong results. Also, the two limb arrays must be in reduced-coefficient, 716 | * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped, 717 | * and all all values in a[0..9],b[0..9] must have magnitude less than 718 | * INT32_MAX. */ 719 | static void 720 | swap_conditional(limb a[19], limb b[19], limb iswap) { 721 | unsigned i; 722 | const s32 swap = (s32) -iswap; 723 | 724 | for (i = 0; i < 10; ++i) { 725 | const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); 726 | a[i] = ((s32)a[i]) ^ x; 727 | b[i] = ((s32)b[i]) ^ x; 728 | } 729 | } 730 | 731 | /* Calculates nQ where Q is the x-coordinate of a point on the curve 732 | * 733 | * resultx/resultz: the x coordinate of the resulting curve point (short form) 734 | * n: a little endian, 32-byte number 735 | * q: a point of the curve (short form) */ 736 | static void 737 | cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { 738 | limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; 739 | limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; 740 | limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; 741 | limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; 742 | 743 | unsigned i, j; 744 | 745 | memcpy(nqpqx, q, sizeof(limb) * 10); 746 | 747 | for (i = 0; i < 32; ++i) { 748 | u8 byte = n[31 - i]; 749 | for (j = 0; j < 8; ++j) { 750 | const limb bit = byte >> 7; 751 | 752 | swap_conditional(nqx, nqpqx, bit); 753 | swap_conditional(nqz, nqpqz, bit); 754 | fmonty(nqx2, nqz2, 755 | nqpqx2, nqpqz2, 756 | nqx, nqz, 757 | nqpqx, nqpqz, 758 | q); 759 | swap_conditional(nqx2, nqpqx2, bit); 760 | swap_conditional(nqz2, nqpqz2, bit); 761 | 762 | t = nqx; 763 | nqx = nqx2; 764 | nqx2 = t; 765 | t = nqz; 766 | nqz = nqz2; 767 | nqz2 = t; 768 | t = nqpqx; 769 | nqpqx = nqpqx2; 770 | nqpqx2 = t; 771 | t = nqpqz; 772 | nqpqz = nqpqz2; 773 | nqpqz2 = t; 774 | 775 | byte <<= 1; 776 | } 777 | } 778 | 779 | memcpy(resultx, nqx, sizeof(limb) * 10); 780 | memcpy(resultz, nqz, sizeof(limb) * 10); 781 | } 782 | 783 | // ----------------------------------------------------------------------------- 784 | // Shamelessly copied from djb's code 785 | // ----------------------------------------------------------------------------- 786 | static void 787 | crecip(limb *out, const limb *z) { 788 | limb z2[10]; 789 | limb z9[10]; 790 | limb z11[10]; 791 | limb z2_5_0[10]; 792 | limb z2_10_0[10]; 793 | limb z2_20_0[10]; 794 | limb z2_50_0[10]; 795 | limb z2_100_0[10]; 796 | limb t0[10]; 797 | limb t1[10]; 798 | int i; 799 | 800 | /* 2 */ fsquare(z2,z); 801 | /* 4 */ fsquare(t1,z2); 802 | /* 8 */ fsquare(t0,t1); 803 | /* 9 */ fmul(z9,t0,z); 804 | /* 11 */ fmul(z11,z9,z2); 805 | /* 22 */ fsquare(t0,z11); 806 | /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); 807 | 808 | /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); 809 | /* 2^7 - 2^2 */ fsquare(t1,t0); 810 | /* 2^8 - 2^3 */ fsquare(t0,t1); 811 | /* 2^9 - 2^4 */ fsquare(t1,t0); 812 | /* 2^10 - 2^5 */ fsquare(t0,t1); 813 | /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); 814 | 815 | /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); 816 | /* 2^12 - 2^2 */ fsquare(t1,t0); 817 | /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } 818 | /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); 819 | 820 | /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); 821 | /* 2^22 - 2^2 */ fsquare(t1,t0); 822 | /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } 823 | /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); 824 | 825 | /* 2^41 - 2^1 */ fsquare(t1,t0); 826 | /* 2^42 - 2^2 */ fsquare(t0,t1); 827 | /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } 828 | /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); 829 | 830 | /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); 831 | /* 2^52 - 2^2 */ fsquare(t1,t0); 832 | /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } 833 | /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); 834 | 835 | /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); 836 | /* 2^102 - 2^2 */ fsquare(t0,t1); 837 | /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } 838 | /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); 839 | 840 | /* 2^201 - 2^1 */ fsquare(t0,t1); 841 | /* 2^202 - 2^2 */ fsquare(t1,t0); 842 | /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } 843 | /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); 844 | 845 | /* 2^251 - 2^1 */ fsquare(t1,t0); 846 | /* 2^252 - 2^2 */ fsquare(t0,t1); 847 | /* 2^253 - 2^3 */ fsquare(t1,t0); 848 | /* 2^254 - 2^4 */ fsquare(t0,t1); 849 | /* 2^255 - 2^5 */ fsquare(t1,t0); 850 | /* 2^255 - 21 */ fmul(out,t1,z11); 851 | } 852 | 853 | int 854 | curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { 855 | limb bp[10], x[10], z[11], zmone[10]; 856 | uint8_t e[32]; 857 | int i; 858 | 859 | for (i = 0; i < 32; ++i) e[i] = secret[i]; 860 | // e[0] &= 248; 861 | // e[31] &= 127; 862 | // e[31] |= 64; 863 | 864 | fexpand(bp, basepoint); 865 | cmult(x, z, e, bp); 866 | crecip(zmone, z); 867 | fmul(z, x, zmone); 868 | fcontract(mypublic, z); 869 | return 0; 870 | } 871 | --------------------------------------------------------------------------------