├── python ├── .gitignore ├── edgold │ └── __init__.py └── setup.py ├── test ├── batarch.map ├── test_templates.cxx ├── CMakeLists.txt ├── shakesum.c ├── test_ct.cxx └── ristretto.cxx ├── src ├── include │ ├── decaf │ │ └── crypto.tmpl.hxx │ ├── arch_ref64 │ │ └── arch_intrinsics.h │ ├── arch_neon │ │ └── arch_intrinsics.h │ ├── arch_32 │ │ └── arch_intrinsics.h │ ├── arch_arm_32 │ │ └── arch_intrinsics.h │ ├── portable_endian.h │ ├── keccak_internal.h │ └── field.h ├── public_include │ ├── decaf │ │ ├── eddsa.tmpl.hxx │ │ ├── sha512.h │ │ ├── spongerng.hxx │ │ ├── sha512.hxx │ │ ├── spongerng.h │ │ ├── common.h │ │ └── shake.hxx │ ├── decaf.tmpl.hxx │ └── decaf.tmpl.h ├── p448 │ ├── CMakeLists.txt │ ├── arch_ref64 │ │ └── f_impl.h │ ├── f_arithmetic.c │ ├── arch_32 │ │ ├── f_impl.h │ │ └── f_impl.c │ ├── arch_arm_32 │ │ └── f_impl.h │ ├── arch_neon │ │ └── f_impl.h │ └── arch_x86_64 │ │ ├── f_impl.h │ │ └── f_impl.c ├── p25519 │ ├── CMakeLists.txt │ ├── arch_x86_64 │ │ ├── f_impl.h │ │ └── f_impl.c │ ├── arch_ref64 │ │ ├── f_impl.h │ │ └── f_impl.c │ ├── f_arithmetic.c │ └── arch_32 │ │ ├── f_impl.h │ │ └── f_impl.c ├── utils.c ├── curve25519 │ └── CMakeLists.txt ├── ed448goldilocks │ └── CMakeLists.txt ├── per_field │ ├── f_field.tmpl.h │ └── f_generic.tmpl.c ├── generator │ ├── template.py │ ├── curve_data.py │ ├── curve25519 │ │ └── CMakeLists.txt │ ├── ed448goldilocks │ │ └── CMakeLists.txt │ └── CMakeLists.txt ├── per_curve │ ├── decaf_gen_tables.tmpl.c │ └── elligator.tmpl.c ├── CMakeLists.txt ├── spongerng.c ├── sha512.c └── shake.c ├── _aux ├── ristretto │ ├── ristretto_work.txt │ └── ristretto.tex ├── attic │ ├── p521 │ │ ├── arch_ref64 │ │ │ └── f_impl.h │ │ ├── f_arithmetic.c │ │ └── arch_x86_64_r12 │ │ │ └── f_impl.h │ └── p480 │ │ ├── f_arithmetic.c │ │ └── arch_x86_64 │ │ ├── f_impl.h │ │ └── f_impl.c └── decaffeinate_curve25519.sage ├── TODO.txt ├── LICENSE.txt ├── cmake └── DecafConfig.cmake.in ├── CMakeLists.txt └── README.md /python/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /test/batarch.map: -------------------------------------------------------------------------------- 1 | neon arch_neon_experimental 2 | arm32 arch_arm_32 3 | 64 arch_ref64 4 | 32 arch_32 5 | amd64 arch_x86_64 6 | -------------------------------------------------------------------------------- /python/edgold/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | '''This is a wrapper around the Goldilocks libdecaf library. 4 | 5 | Currently only the ed448 code is wrapped. It is available in the 6 | submodule ed448. 7 | ''' 8 | -------------------------------------------------------------------------------- /src/include/decaf/crypto.tmpl.hxx: -------------------------------------------------------------------------------- 1 | /** 2 | * Example Decaf crypto routines, C++ metaheader. 3 | * @warning These are merely examples, though they ought to be secure. But real 4 | * protocols will decide differently on magic numbers, formats, which items to 5 | * hash, etc. 6 | */ 7 | 8 | $("\n".join([ 9 | "#include " % g for g in sorted([c["bits"] for _,c in curve.items()]) 10 | ])) 11 | -------------------------------------------------------------------------------- /_aux/ristretto/ristretto_work.txt: -------------------------------------------------------------------------------- 1 | Have (1-ydbl)/(1+ydbl) 2 | = (y^2-1)/(ax^2-1) 3 | 4 | Have (y^2-1)*(ax^2-1) = (a-d) x^2 y^2 5 | 6 | ==> (1-ydbl)/(1+ydbl) has same parity as a-d 7 | 8 | No points at infinity => d nonsqr, ad nonsqr -> a sqr. 9 | 10 | Point of order 8: ax^2=y^2 11 | 2y^2 = 1+day^4 12 | product of roots = 1/ad = nonsquare, so one will be square (if no point at infty) 13 | b^2-4ac = 4(1-ad) -> 1-ad square iff point of order 8 exists 14 | 15 | If a^2 = 1, then 1-ad = a(a-d) 16 | -------------------------------------------------------------------------------- /src/public_include/decaf/eddsa.tmpl.hxx: -------------------------------------------------------------------------------- 1 | /** 2 | * EdDSA crypto routines, metaheader. 3 | */ 4 | 5 | /** Namespace for all libdecaf C++ objects. */ 6 | namespace decaf { 7 | /** How signatures handle hashing. */ 8 | enum Prehashed { 9 | PURE, /**< Sign the message itself. This can't be done in one pass. */ 10 | PREHASHED /**< Sign the hash of the message. */ 11 | }; 12 | } 13 | 14 | $("\n".join([ 15 | "#include " % g for g in sorted([c["bits"] for _,c in curve.items()]) 16 | ])) 17 | -------------------------------------------------------------------------------- /src/public_include/decaf.tmpl.hxx: -------------------------------------------------------------------------------- 1 | /** Master header for Decaf library, C++ version. */ 2 | 3 | $("\n".join([ 4 | "#include " % g for g in sorted([c["bits"] for _,c in curve.items()]) 5 | ])) 6 | 7 | /** Namespace for all C++ decaf objects. */ 8 | namespace decaf { 9 | /** Given a template with a "run" function, run it for all curves */ 10 | template class Run> 11 | void run_for_all_curves() { 12 | $("\n".join([ 13 | " Run<%s>::run();" % cd["cxx_ns"] 14 | for cd in sorted(curve.values(), key=lambda x:x["c_ns"]) 15 | ]) 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/include/arch_ref64/arch_intrinsics.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #ifndef __ARCH_REF64_ARCH_INTRINSICS_H__ 6 | #define __ARCH_REF64_ARCH_INTRINSICS_H__ 7 | 8 | #define ARCH_WORD_BITS 64 9 | 10 | static __inline__ __attribute((always_inline,unused)) 11 | uint64_t word_is_zero(uint64_t a) { 12 | /* let's hope the compiler isn't clever enough to optimize this. */ 13 | return (((__uint128_t)a)-1)>>64; 14 | } 15 | 16 | static __inline__ __attribute((always_inline,unused)) 17 | __uint128_t widemul(uint64_t a, uint64_t b) { 18 | return ((__uint128_t)a) * b; 19 | } 20 | 21 | #endif /* ARCH_REF64_ARCH_INTRINSICS_H__ */ 22 | 23 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.command.build import build 4 | from distutils.core import setup 5 | 6 | import os 7 | 8 | class my_build(build): 9 | def run(self): 10 | build.run(self) 11 | if not self.dry_run: 12 | os.spawnlp(os.P_WAIT, 'sh', 'sh', '-c', 'cd .. && gmake lib') 13 | self.copy_file(os.path.join('..', 'build', 'lib', 'libdecaf.so'), os.path.join(self.build_lib, 'edgold')) 14 | 15 | cmdclass = {} 16 | cmdclass['build'] = my_build 17 | 18 | setup(name='edgold', 19 | version='0.1', 20 | description='The Ed ECC Goldilocks Python wrapper', 21 | author='John-Mark Gurney', 22 | author_email='jmg@funkthat.com', 23 | #url='', 24 | cmdclass=cmdclass, 25 | packages=['edgold', ], 26 | ) 27 | -------------------------------------------------------------------------------- /src/public_include/decaf.tmpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Master header for Decaf library. 3 | * 4 | * The Decaf library implements cryptographic operations on a elliptic curve 5 | * groups of prime order p. It accomplishes this by using a twisted Edwards 6 | * curve (isogenous to Ed448-Goldilocks or Ed25519) and wiping out the cofactor. 7 | * 8 | * The formulas are all complete and have no special cases. However, some 9 | * functions can fail. For example, decoding functions can fail because not 10 | * every string is the encoding of a valid group element. 11 | * 12 | * The formulas contain no data-dependent branches, timing or memory accesses, 13 | * except for decaf_XXX_base_double_scalarmul_non_secret. 14 | */ 15 | 16 | $("\n".join([ 17 | "#include " % g for g in sorted([c["bits"] for _,c in curve.items()]) 18 | ])) 19 | -------------------------------------------------------------------------------- /test/test_templates.cxx: -------------------------------------------------------------------------------- 1 | #include "decaf/expr.hxx" 2 | 3 | class Foo { 4 | private: 5 | template friend class BinExpr; 6 | template friend class UnExpr; 7 | template friend struct Reify; 8 | Foo(const NOINIT&) {} 9 | public: 10 | int x; 11 | Foo(int x) : x(x) {} 12 | }; 13 | 14 | namespace decaf { namespace internal { 15 | DECLARE_BINOP(ADD,Foo,Foo,Foo,out.x = l.x+r.x) 16 | DECLARE_BINOP(SUB,Foo,Foo,Foo,out.x = l.x-r.x) 17 | DECLARE_BINOP(MUL,Foo,Foo,Foo,out.x = l.x*r.x) 18 | DECLARE_BINOP(EQ,Foo,Foo,bool,out = l.x==r.x) 19 | DECLARE_PARTIAL_UNOP(INV,Foo,Foo,out.x = 1/r.x; return (r.x!=0)) 20 | }} 21 | 22 | Foo frobble() { 23 | Foo a(1); 24 | a = a+a+a; 25 | a = a*a; 26 | a = a/a; 27 | (void)(a==(a+a)); 28 | return a; 29 | } 30 | -------------------------------------------------------------------------------- /src/include/arch_neon/arch_intrinsics.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #ifndef __ARCH_NEON_ARCH_INTRINSICS_H__ 6 | #define __ARCH_NEON_ARCH_INTRINSICS_H__ 7 | 8 | #define ARCH_WORD_BITS 32 9 | 10 | static __inline__ __attribute((always_inline,unused)) 11 | uint32_t word_is_zero(uint32_t a) { 12 | uint32_t ret; 13 | __asm__("subs %0, %1, #1;\n\tsbc %0, %0, %0" : "=r"(ret) : "r"(a) : "cc"); 14 | return ret; 15 | } 16 | 17 | static __inline__ __attribute((always_inline,unused)) 18 | uint64_t widemul(uint32_t a, uint32_t b) { 19 | /* Could be UMULL, but it's hard to express to CC that the registers must be different */ 20 | return ((uint64_t)a) * b; 21 | } 22 | 23 | #endif /* __ARCH_NEON_ARCH_INTRINSICS_H__ */ 24 | 25 | -------------------------------------------------------------------------------- /src/include/arch_32/arch_intrinsics.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #ifndef __ARCH_ARCH_32_ARCH_INTRINSICS_H__ 6 | #define __ARCH_ARCH_32_ARCH_INTRINSICS_H__ 7 | 8 | #define ARCH_WORD_BITS 32 9 | 10 | #if defined _MSC_VER 11 | #define __attribute(x) 12 | #define __inline__ __inline 13 | #endif // MSVC 14 | 15 | static __inline__ __attribute((always_inline,unused)) 16 | uint32_t word_is_zero(uint32_t a) { 17 | /* let's hope the compiler isn't clever enough to optimize this. */ 18 | return (((uint64_t)a)-1)>>32; 19 | } 20 | 21 | static __inline__ __attribute((always_inline,unused)) 22 | uint64_t widemul(uint32_t a, uint32_t b) { 23 | return ((uint64_t)a) * b; 24 | } 25 | 26 | #endif /* __ARCH_ARM_32_ARCH_INTRINSICS_H__ */ 27 | 28 | -------------------------------------------------------------------------------- /src/include/arch_arm_32/arch_intrinsics.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #ifndef __ARCH_ARM_32_ARCH_INTRINSICS_H__ 6 | #define __ARCH_ARM_32_ARCH_INTRINSICS_H__ 7 | 8 | #define ARCH_WORD_BITS 32 9 | 10 | static __inline__ __attribute((always_inline,unused)) 11 | uint32_t word_is_zero(uint32_t a) { 12 | uint32_t ret; 13 | __asm__("subs %0, %1, #1;\n\tsbc %0, %0, %0" : "=r"(ret) : "r"(a) : "cc"); 14 | return ret; 15 | } 16 | 17 | static __inline__ __attribute((always_inline,unused)) 18 | uint64_t widemul(uint32_t a, uint32_t b) { 19 | /* Could be UMULL, but it's hard to express to CC that the registers must be different */ 20 | return ((uint64_t)a) * b; 21 | } 22 | 23 | #endif /* __ARCH_ARM_32_ARCH_INTRINSICS_H__ */ 24 | 25 | -------------------------------------------------------------------------------- /src/p448/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | include_directories( 8 | ${PROJECT_SOURCE_DIR}/src/p448 9 | ${GSOURCE_PATH}/c/p448 10 | ${PROJECT_SOURCE_DIR}/src/p448/${TARGET_ARCH_DIR_P448} 11 | ) 12 | 13 | set(P448_HEADER_FILES 14 | ${GSOURCE_PATH}/c/p448/f_field.h 15 | ${TARGET_ARCH_DIR_P448}/f_impl.h 16 | ) 17 | set(P448_SOURCE_FILES_C 18 | ${TARGET_ARCH_DIR_P448}/f_impl.c 19 | f_arithmetic.c 20 | ${GSOURCE_PATH}/c/p448/f_generic.c 21 | ) 22 | 23 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/p448/f_field.h PROPERTIES GENERATED 1) 24 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/p448/f_generic.c PROPERTIES GENERATED 1) 25 | 26 | add_library(p448 OBJECT ${P448_HEADER_FILES} ${P448_SOURCE_FILES_C}) 27 | add_dependencies(p448 generatorP448) 28 | 29 | set_target_properties(p448 PROPERTIES POSITION_INDEPENDENT_CODE True) 30 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | Important work items for Ed448-Goldilocks / decaf / Ristretto. 2 | 3 | * Test signed 32-bit NEON implementation to avoid bias/reduce after subtract 4 | 5 | * Documentation: write high-level API docs, and internal docs to help 6 | other implementors. 7 | * Pretty good progress on Doxygenating the code. 8 | 9 | * Documentation: help work on ristretto.group website. 10 | 11 | * Cleanup: unify intrinsics code 12 | * Generate asm intrinsics with a script? 13 | 14 | * Testing: 15 | * More testing. Testing, testing and testing. 16 | * Test corner cases better. 17 | * Try to formally verify some things. 18 | 19 | * Safety: 20 | * If RNG fails, return error and zeroize 21 | 22 | * Portability: test and make clean with other compilers 23 | * Using a fair amount of __attribute__ code. 24 | * Should work for GCC now. 25 | * Autoconf 26 | 27 | * Portability: try to make the vector code as portable as possible 28 | * Currently using clang ext_vector_length. 29 | * I can't get a simple for-loop to autovectorize :-/ 30 | * Autogenerate somehow? 31 | -------------------------------------------------------------------------------- /_aux/attic/p521/arch_ref64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define LIMB_PLACE_VALUE(i) 58 6 | 7 | void gf_add_RAW (gf out, const gf a, const gf b) { 8 | for (unsigned int i=0; i<9; i++) { 9 | out->limb[i] = a->limb[i] + b->limb[i]; 10 | } 11 | gf_weak_reduce(out); 12 | } 13 | 14 | void gf_sub_RAW (gf out, const gf a, const gf b) { 15 | uint64_t co1 = ((1ull<<58)-1)*4, co2 = ((1ull<<57)-1)*4; 16 | for (unsigned int i=0; i<9; i++) { 17 | out->limb[i] = a->limb[i] - b->limb[i] + ((i==8) ? co2 : co1); 18 | } 19 | gf_weak_reduce(out); 20 | } 21 | 22 | void gf_bias (gf a, int amt) { 23 | (void) a; 24 | (void) amt; 25 | } 26 | 27 | void gf_weak_reduce (gf a) { 28 | uint64_t mask = (1ull<<58) - 1; 29 | uint64_t tmp = a->limb[8] >> 57; 30 | for (unsigned int i=8; i>0; i--) { 31 | a->limb[i] = (a->limb[i] & ((i==8) ? mask>>1 : mask)) + (a->limb[i-1]>>58); 32 | } 33 | a->limb[0] = (a->limb[0] & mask) + tmp; 34 | } 35 | -------------------------------------------------------------------------------- /src/p25519/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | include_directories( 8 | ${PROJECT_SOURCE_DIR}/src/p25519 9 | ${GSOURCE_PATH}/c/p25519 10 | ${PROJECT_SOURCE_DIR}/src/p25519/${TARGET_ARCH_DIR_P25519} 11 | ) 12 | 13 | set(P25519_HEADER_FILES 14 | ${GSOURCE_PATH}/c/p25519/f_field.h 15 | ${TARGET_ARCH_DIR_P25519}/f_impl.h 16 | ) 17 | set(P25519_SOURCE_FILES_C 18 | ${TARGET_ARCH_DIR_P25519}/f_impl.c 19 | f_arithmetic.c 20 | ${GSOURCE_PATH}/c/p25519/f_generic.c 21 | ) 22 | 23 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/p25519/f_field.h PROPERTIES GENERATED 1) 24 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/p25519/f_generic.c PROPERTIES GENERATED 1) 25 | 26 | add_library(p25519 OBJECT ${P25519_HEADER_FILES} ${P25519_SOURCE_FILES_C}) 27 | add_dependencies(p25519 generatorP25519) 28 | 29 | set_target_properties(p25519 PROPERTIES POSITION_INDEPENDENT_CODE True) 30 | -------------------------------------------------------------------------------- /src/p25519/arch_x86_64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 933 6 | #define FIELD_LITERAL(a,b,c,d,e) {{ a,b,c,d,e }} 7 | 8 | #define LIMB_PLACE_VALUE(i) 51 9 | 10 | void gf_add_RAW (gf out, const gf a, const gf b) { 11 | for (unsigned int i=0; i<5; i++) { 12 | out->limb[i] = a->limb[i] + b->limb[i]; 13 | } 14 | } 15 | 16 | void gf_sub_RAW (gf out, const gf a, const gf b) { 17 | for (unsigned int i=0; i<5; i++) { 18 | out->limb[i] = a->limb[i] - b->limb[i]; 19 | } 20 | } 21 | 22 | void gf_bias (gf a, int amt) { 23 | a->limb[0] += ((uint64_t)(amt)<<52) - 38*amt; 24 | for (unsigned int i=1; i<5; i++) { 25 | a->limb[i] += ((uint64_t)(amt)<<52)-2*amt; 26 | } 27 | } 28 | 29 | void gf_weak_reduce (gf a) { 30 | uint64_t mask = (1ull<<51) - 1; 31 | uint64_t tmp = a->limb[4] >> 51; 32 | for (unsigned int i=4; i>0; i--) { 33 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>51); 34 | } 35 | a->limb[0] = (a->limb[0] & mask) + tmp*19; 36 | } 37 | -------------------------------------------------------------------------------- /src/p25519/arch_ref64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 9999 /* Always reduced */ 6 | #define FIELD_LITERAL(a,b,c,d,e) {{ a,b,c,d,e }} 7 | 8 | #define LIMB_PLACE_VALUE(i) 51 9 | 10 | void gf_add_RAW (gf out, const gf a, const gf b) { 11 | for (unsigned int i=0; i<5; i++) { 12 | out->limb[i] = a->limb[i] + b->limb[i]; 13 | } 14 | gf_weak_reduce(out); 15 | } 16 | 17 | void gf_sub_RAW (gf out, const gf a, const gf b) { 18 | uint64_t co1 = ((1ull<<51)-1)*2, co2 = co1-36; 19 | for (unsigned int i=0; i<5; i++) { 20 | out->limb[i] = a->limb[i] - b->limb[i] + ((i==0) ? co2 : co1); 21 | } 22 | gf_weak_reduce(out); 23 | } 24 | 25 | void gf_bias (gf a, int amt) { 26 | (void) a; 27 | (void) amt; 28 | } 29 | 30 | void gf_weak_reduce (gf a) { 31 | uint64_t mask = (1ull<<51) - 1; 32 | uint64_t tmp = a->limb[4] >> 51; 33 | for (unsigned int i=4; i>0; i--) { 34 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>51); 35 | } 36 | a->limb[0] = (a->limb[0] & mask) + tmp*19; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/p448/arch_ref64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 9999 /* Everything is reduced anyway */ 6 | #define FIELD_LITERAL(a,b,c,d,e,f,g,h) {{a,b,c,d,e,f,g,h}} 7 | 8 | #define LIMB_PLACE_VALUE(i) 56 9 | 10 | void gf_add_RAW (gf out, const gf a, const gf b) { 11 | for (unsigned int i=0; i<8; i++) { 12 | out->limb[i] = a->limb[i] + b->limb[i]; 13 | } 14 | gf_weak_reduce(out); 15 | } 16 | 17 | void gf_sub_RAW (gf out, const gf a, const gf b) { 18 | uint64_t co1 = ((1ull<<56)-1)*2, co2 = co1-2; 19 | for (unsigned int i=0; i<8; i++) { 20 | out->limb[i] = a->limb[i] - b->limb[i] + ((i==4) ? co2 : co1); 21 | } 22 | gf_weak_reduce(out); 23 | } 24 | 25 | void gf_bias (gf a, int amt) { 26 | (void) a; 27 | (void) amt; 28 | } 29 | 30 | void gf_weak_reduce (gf a) { 31 | uint64_t mask = (1ull<<56) - 1; 32 | uint64_t tmp = a->limb[7] >> 56; 33 | a->limb[4] += tmp; 34 | for (unsigned int i=7; i>0; i--) { 35 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>56); 36 | } 37 | a->limb[0] = (a->limb[0] & mask) + tmp; 38 | } 39 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | /** 6 | * @file utils.c 7 | * @author Mike Hamburg 8 | * @brief Decaf utility functions. 9 | */ 10 | 11 | #include 12 | 13 | void decaf_bzero ( 14 | void *s, 15 | size_t size 16 | ) { 17 | #ifdef __STDC_LIB_EXT1__ 18 | memset_s(s, size, 0, size); 19 | #else 20 | const size_t sw = sizeof(decaf_word_t); 21 | volatile uint8_t *destroy = (volatile uint8_t *)s; 22 | for (; size && ((uintptr_t)destroy)%sw; size--, destroy++) 23 | *destroy = 0; 24 | for (; size >= sw; size -= sw, destroy += sw) 25 | *(volatile decaf_word_t *)destroy = 0; 26 | for (; size; size--, destroy++) 27 | *destroy = 0; 28 | #endif 29 | } 30 | 31 | decaf_bool_t decaf_memeq ( 32 | const void *data1_, 33 | const void *data2_, 34 | size_t size 35 | ) { 36 | const unsigned char *data1 = (const unsigned char *)data1_; 37 | const unsigned char *data2 = (const unsigned char *)data2_; 38 | unsigned char ret = 0; 39 | for (; size; size--, data1++, data2++) { 40 | ret |= *data1 ^ *data2; 41 | } 42 | return (((decaf_dword_t)ret) - 1) >> 8; 43 | } 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | if(ENABLE_SHARED) 8 | set(DECAF_LIBRARIES_FOR_TESTER decaf) 9 | else() 10 | set(DECAF_LIBRARIES_FOR_TESTER decaf-static) 11 | endif() 12 | 13 | add_executable(decaf_tester test_decaf.cxx) 14 | set_target_properties(decaf_tester PROPERTIES LINKER_LANGUAGE CXX) 15 | target_link_libraries(decaf_tester ${DECAF_LIBRARIES_FOR_TESTER}) 16 | 17 | add_executable(ristretto_tester ristretto.cxx) 18 | set_target_properties(ristretto_tester PROPERTIES LINKER_LANGUAGE CXX) 19 | target_link_libraries(ristretto_tester ${DECAF_LIBRARIES_FOR_TESTER}) 20 | 21 | add_executable(shakesum_tester shakesum.c) 22 | set_target_properties(shakesum_tester PROPERTIES LINKER_LANGUAGE C) 23 | target_link_libraries(shakesum_tester ${DECAF_LIBRARIES_FOR_TESTER}) 24 | 25 | add_executable(bench bench_decaf.cxx) 26 | set_target_properties(bench PROPERTIES LINKER_LANGUAGE CXX) 27 | target_link_libraries(bench ${DECAF_LIBRARIES_FOR_TESTER}) 28 | 29 | add_test(NAME decaf COMMAND decaf_tester) 30 | add_test(NAME bench COMMAND bench) 31 | 32 | -------------------------------------------------------------------------------- /src/p448/f_arithmetic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file f_arithmetic.c 4 | * @copyright 5 | * Copyright (c) 2014 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Field-specific arithmetic. 9 | */ 10 | 11 | #include "field.h" 12 | 13 | mask_t gf_isr ( 14 | gf a, 15 | const gf x 16 | ) { 17 | gf L0, L1, L2; 18 | gf_sqr (L1, x ); 19 | gf_mul (L2, x, L1 ); 20 | gf_sqr (L1, L2 ); 21 | gf_mul (L2, x, L1 ); 22 | gf_sqrn (L1, L2, 3 ); 23 | gf_mul (L0, L2, L1 ); 24 | gf_sqrn (L1, L0, 3 ); 25 | gf_mul (L0, L2, L1 ); 26 | gf_sqrn (L2, L0, 9 ); 27 | gf_mul (L1, L0, L2 ); 28 | gf_sqr (L0, L1 ); 29 | gf_mul (L2, x, L0 ); 30 | gf_sqrn (L0, L2, 18 ); 31 | gf_mul (L2, L1, L0 ); 32 | gf_sqrn (L0, L2, 37 ); 33 | gf_mul (L1, L2, L0 ); 34 | gf_sqrn (L0, L1, 37 ); 35 | gf_mul (L1, L2, L0 ); 36 | gf_sqrn (L0, L1, 111 ); 37 | gf_mul (L2, L1, L0 ); 38 | gf_sqr (L0, L2 ); 39 | gf_mul (L1, x, L0 ); 40 | gf_sqrn (L0, L1, 223 ); 41 | gf_mul (L1, L2, L0 ); 42 | gf_sqr (L2, L1); 43 | gf_mul (L0, L2, x); 44 | gf_copy(a,L1); 45 | return gf_eq(L0,ONE); 46 | } 47 | -------------------------------------------------------------------------------- /src/p448/arch_32/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 2 6 | #define LIMB(x) (x##ull)&((1ull<<28)-1), (x##ull)>>28 7 | #define FIELD_LITERAL(a,b,c,d,e,f,g,h) \ 8 | {{LIMB(a),LIMB(b),LIMB(c),LIMB(d),LIMB(e),LIMB(f),LIMB(g),LIMB(h)}} 9 | 10 | #define LIMB_PLACE_VALUE(i) 28 11 | 12 | void gf_add_RAW (gf out, const gf a, const gf b) { 13 | for (unsigned int i=0; ilimb[0]); i++) { 14 | out->limb[i] = a->limb[i] + b->limb[i]; 15 | } 16 | } 17 | 18 | void gf_sub_RAW (gf out, const gf a, const gf b) { 19 | for (unsigned int i=0; ilimb[0]); i++) { 20 | out->limb[i] = a->limb[i] - b->limb[i]; 21 | } 22 | } 23 | 24 | void gf_bias (gf a, int amt) { 25 | uint32_t co1 = ((1ull<<28)-1)*amt, co2 = co1-amt; 26 | for (unsigned int i=0; ilimb[0]); i++) { 27 | a->limb[i] += (i==sizeof(*a)/sizeof(a->limb[0])/2) ? co2 : co1; 28 | } 29 | } 30 | 31 | void gf_weak_reduce (gf a) { 32 | uint32_t mask = (1ull<<28) - 1; 33 | uint32_t tmp = a->limb[15] >> 28; 34 | a->limb[8] += tmp; 35 | for (unsigned int i=15; i>0; i--) { 36 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>28); 37 | } 38 | a->limb[0] = (a->limb[0] & mask) + tmp; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/curve25519/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | 8 | include_directories( 9 | ${PROJECT_SOURCE_DIR}/src/p25519 10 | ${GSOURCE_PATH}/c/p25519 11 | ${PROJECT_SOURCE_DIR}/src/p25519/${TARGET_ARCH_DIR_P25519} 12 | ) 13 | 14 | set(CURVE25519_SOURCE_FILES_C 15 | ${GSOURCE_PATH}/c/curve25519/decaf.c 16 | ${GSOURCE_PATH}/c/curve25519/elligator.c 17 | ${GSOURCE_PATH}/c/curve25519/scalar.c 18 | ${GSOURCE_PATH}/c/curve25519/eddsa.c 19 | ${PROJECT_SOURCE_DIR}/src/curve25519/decaf_tables.c 20 | ) 21 | 22 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/curve25519/decaf.c PROPERTIES GENERATED 1) 23 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/curve25519/elligator.c PROPERTIES GENERATED 1) 24 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/curve25519/scalar.c PROPERTIES GENERATED 1) 25 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/curve25519/eddsa.c PROPERTIES GENERATED 1) 26 | SET_SOURCE_FILES_PROPERTIES(${PROJECT_SOURCE_DIR}/src/curve25519/decaf_tables.c PROPERTIES GENERATED 1) 27 | 28 | add_library(CURVE25519 OBJECT ${CURVE25519_SOURCE_FILES_C}) 29 | add_dependencies(CURVE25519 generatedCode p25519) 30 | set_target_properties(CURVE25519 PROPERTIES POSITION_INDEPENDENT_CODE True) 31 | -------------------------------------------------------------------------------- /src/include/portable_endian.h: -------------------------------------------------------------------------------- 1 | /* Subset of Mathias Panzenböck's portable endian code, public domain */ 2 | 3 | #ifndef __PORTABLE_ENDIAN_H__ 4 | #define __PORTABLE_ENDIAN_H__ 5 | 6 | #if defined(__linux__) || defined(__CYGWIN__) 7 | # include 8 | #elif defined(__OpenBSD__) 9 | # include 10 | #elif defined(__APPLE__) 11 | # include 12 | # define htole64(x) OSSwapHostToLittleInt64(x) 13 | # define le64toh(x) OSSwapLittleToHostInt64(x) 14 | #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 15 | # include 16 | # ifndef le64toh 17 | # define le64toh(x) letoh64(x) 18 | # endif 19 | #elif defined(__sun) && defined(__SVR4) 20 | # include 21 | # define htole64(x) LE_64(x) 22 | # define le64toh(x) LE_64(x) 23 | #elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__) 24 | # if defined(_MSC_VER) 25 | # define __builtin_bswap64(x) _byteswap_uint64((x)) 26 | # else 27 | # include 28 | # endif 29 | # include 30 | # if BYTE_ORDER == LITTLE_ENDIAN 31 | # define htole64(x) (x) 32 | # define le64toh(x) (x) 33 | # elif BYTE_ORDER == BIG_ENDIAN 34 | # define htole64(x) __builtin_bswap64(x) 35 | # define le64toh(x) __builtin_bswap64(x) 36 | # else 37 | # error byte order not supported 38 | # endif 39 | #else 40 | # error platform not supported 41 | #endif 42 | 43 | #endif // __PORTABLE_ENDIAN_H__ 44 | -------------------------------------------------------------------------------- /src/ed448goldilocks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | 8 | include_directories( 9 | ${PROJECT_SOURCE_DIR}/src/p448 10 | ${GSOURCE_PATH}/c/p448 11 | ${PROJECT_SOURCE_DIR}/src/p448/${TARGET_ARCH_DIR_P448} 12 | ) 13 | 14 | set(CURVE448_SOURCE_FILES_C 15 | ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c 16 | ${GSOURCE_PATH}/c/ed448goldilocks/elligator.c 17 | ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c 18 | ${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c 19 | ${PROJECT_SOURCE_DIR}/src/ed448goldilocks/decaf_tables.c 20 | ) 21 | 22 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/ed448goldilocks/decaf.c PROPERTIES GENERATED 1) 23 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/ed448goldilocks/elligator.c PROPERTIES GENERATED 1) 24 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/ed448goldilocks/scalar.c PROPERTIES GENERATED 1) 25 | SET_SOURCE_FILES_PROPERTIES(${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c PROPERTIES GENERATED 1) 26 | SET_SOURCE_FILES_PROPERTIES(${PROJECT_SOURCE_DIR}/src/ed448goldilocks/decaf_tables.c PROPERTIES GENERATED 1) 27 | 28 | add_library(CURVE448 OBJECT ${CURVE448_SOURCE_FILES_C}) 29 | add_dependencies(CURVE448 generatedCode p448) 30 | set_target_properties(CURVE448 PROPERTIES POSITION_INDEPENDENT_CODE True) 31 | -------------------------------------------------------------------------------- /src/p25519/f_arithmetic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file f_arithmetic.c 4 | * @copyright 5 | * Copyright (c) 2014 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Field-specific arithmetic. 9 | */ 10 | 11 | #include "field.h" 12 | #include "constant_time.h" 13 | 14 | /* Guarantee: a^2 x = 0 if x = 0; else a^2 x = 1 or SQRT_MINUS_ONE; */ 15 | mask_t gf_isr (gf a, const gf x) { 16 | gf L0, L1, L2, L3; 17 | 18 | gf_sqr (L0, x); 19 | gf_mul (L1, L0, x); 20 | gf_sqr (L0, L1); 21 | gf_mul (L1, L0, x); 22 | gf_sqrn(L0, L1, 3); 23 | gf_mul (L2, L0, L1); 24 | gf_sqrn(L0, L2, 6); 25 | gf_mul (L1, L2, L0); 26 | gf_sqr (L2, L1); 27 | gf_mul (L0, L2, x); 28 | gf_sqrn(L2, L0, 12); 29 | gf_mul (L0, L2, L1); 30 | gf_sqrn(L2, L0, 25); 31 | gf_mul (L3, L2, L0); 32 | gf_sqrn(L2, L3, 25); 33 | gf_mul (L1, L2, L0); 34 | gf_sqrn(L2, L1, 50); 35 | gf_mul (L0, L2, L3); 36 | gf_sqrn(L2, L0, 125); 37 | gf_mul (L3, L2, L0); 38 | gf_sqrn(L2, L3, 2); 39 | gf_mul (L0, L2, x); 40 | 41 | gf_sqr (L2, L0); 42 | gf_mul (L3, L2, x); 43 | gf_add(L1,L3,ONE); 44 | mask_t one = gf_eq(L3,ONE); 45 | mask_t succ = one | gf_eq(L1,ZERO); 46 | mask_t qr = one | gf_eq(L3,SQRT_MINUS_ONE); 47 | 48 | constant_time_select(L2, SQRT_MINUS_ONE, ONE, sizeof(L2), qr, 0); 49 | gf_mul (a,L2,L0); 50 | return succ; 51 | } 52 | -------------------------------------------------------------------------------- /src/p25519/arch_32/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 3 /* Would be 5, but 3*19 * 2^26+small is all that fits in a uint32_t */ 6 | #define LIMB(x) (x##ull)&((1ull<<26)-1), (x##ull)>>26 7 | #define FIELD_LITERAL(a,b,c,d,e) {{LIMB(a),LIMB(b),LIMB(c),LIMB(d),LIMB(e)}} 8 | 9 | #define LIMB_PLACE_VALUE(i) (((i)&1)?25:26) 10 | 11 | void gf_add_RAW (gf out, const gf a, const gf b) { 12 | for (unsigned int i=0; i<10; i++) { 13 | out->limb[i] = a->limb[i] + b->limb[i]; 14 | } 15 | } 16 | 17 | void gf_sub_RAW (gf out, const gf a, const gf b) { 18 | for (unsigned int i=0; i<10; i++) { 19 | out->limb[i] = a->limb[i] - b->limb[i]; 20 | } 21 | } 22 | 23 | void gf_bias (gf a, int amt) { 24 | uint32_t coe = ((1ull<<26)-1)*amt, coo = ((1ull<<25)-1)*amt, co0 = coe-18*amt; 25 | for (unsigned int i=0; i<10; i+=2) { 26 | a->limb[i] += ((i==0) ? co0 : coe); 27 | a->limb[i+1] += coo; 28 | } 29 | } 30 | 31 | void gf_weak_reduce (gf a) { 32 | uint32_t maske = (1ull<<26) - 1, masko = (1ull<<25) - 1; 33 | uint32_t tmp = a->limb[9] >> 25; 34 | for (unsigned int i=8; i>0; i-=2) { 35 | a->limb[i+1] = (a->limb[i+1] & masko) + (a->limb[i]>>26); 36 | a->limb[i] = (a->limb[i] & maske) + (a->limb[i-1]>>25); 37 | } 38 | a->limb[1] = (a->limb[1] & masko) + (a->limb[0]>>26); 39 | a->limb[0] = (a->limb[0] & maske) + tmp*19; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /_aux/attic/p480/f_arithmetic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file f_arithmetic.c 4 | * @copyright 5 | * Copyright (c) 2014 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Field-specific arithmetic. 9 | */ 10 | 11 | #include "field.h" 12 | 13 | 14 | const gf MODULUS = {FIELD_LITERAL( 15 | 0xfffffffffffffff, 0xfffffffffffffff, 0xfffffffffffffff, 0xfffffffffffffff, 16 | 0xffffffffffffffe, 0xfffffffffffffff, 0xfffffffffffffff, 0xfffffffffffffff 17 | )}; 18 | 19 | void 20 | gf_isr ( 21 | gf_a_t a, 22 | const gf_a_t x 23 | ) { 24 | gf_a_t L0, L1, L2, L3; 25 | gf_sqr ( L2, x ); 26 | gf_mul ( L1, x, L2 ); 27 | gf_sqrn ( L0, L1, 2 ); 28 | gf_mul ( L2, L1, L0 ); 29 | gf_sqrn ( L0, L2, 4 ); 30 | gf_mul ( L1, L2, L0 ); 31 | gf_sqr ( L0, L1 ); 32 | gf_mul ( L2, x, L0 ); 33 | gf_sqrn ( L0, L2, 8 ); 34 | gf_mul ( L2, L1, L0 ); 35 | gf_sqrn ( L0, L2, 17 ); 36 | gf_mul ( L1, L2, L0 ); 37 | gf_sqrn ( L0, L1, 17 ); 38 | gf_mul ( L1, L2, L0 ); 39 | gf_sqrn ( L3, L1, 17 ); 40 | gf_mul ( L0, L2, L3 ); 41 | gf_sqrn ( L2, L0, 51 ); 42 | gf_mul ( L0, L1, L2 ); 43 | gf_sqrn ( L1, L0, 119 ); 44 | gf_mul ( L2, L0, L1 ); 45 | gf_sqr ( L0, L2 ); 46 | gf_mul ( L1, x, L0 ); 47 | gf_sqrn ( L0, L1, 239 ); 48 | gf_mul ( a, L2, L0 ); 49 | } 50 | -------------------------------------------------------------------------------- /_aux/attic/p521/f_arithmetic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file f_arithmetic.c 4 | * @copyright 5 | * Copyright (c) 2014 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Field-specific arithmetic. 9 | */ 10 | 11 | #include "field.h" 12 | 13 | const gf MODULUS = {FIELD_LITERAL( 14 | 0x3ffffffffffffff, 0x3ffffffffffffff, 0x3ffffffffffffff, 15 | 0x3ffffffffffffff, 0x3ffffffffffffff, 0x3ffffffffffffff, 16 | 0x3ffffffffffffff, 0x3ffffffffffffff, 0x1ffffffffffffff 17 | )}; 18 | 19 | void 20 | gf_isr ( 21 | gf_a_t a, 22 | const gf_a_t x 23 | ) { 24 | gf_a_t L0, L1, L2; 25 | gf_sqr ( L1, x ); 26 | gf_mul ( L0, x, L1 ); 27 | gf_sqrn ( L2, L0, 2 ); 28 | gf_mul ( L1, L0, L2 ); 29 | gf_sqrn ( L2, L1, 4 ); 30 | gf_mul ( L0, L1, L2 ); 31 | gf_sqrn ( L2, L0, 8 ); 32 | gf_mul ( L1, L0, L2 ); 33 | gf_sqrn ( L2, L1, 16 ); 34 | gf_mul ( L0, L1, L2 ); 35 | gf_sqrn ( L2, L0, 32 ); 36 | gf_mul ( L1, L0, L2 ); 37 | gf_sqr ( L2, L1 ); 38 | gf_mul ( L0, x, L2 ); 39 | gf_sqrn ( L2, L0, 64 ); 40 | gf_mul ( L0, L1, L2 ); 41 | gf_sqrn ( L2, L0, 129 ); 42 | gf_mul ( L1, L0, L2 ); 43 | gf_sqr ( L2, L1 ); 44 | gf_mul ( L0, x, L2 ); 45 | gf_sqrn ( L2, L0, 259 ); 46 | gf_mul ( L1, L0, L2 ); 47 | gf_sqr ( L0, L1 ); 48 | gf_mul ( a, x, L0 ); 49 | } 50 | -------------------------------------------------------------------------------- /src/include/keccak_internal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file keccak_internal.h 4 | * @copyright 5 | * Copyright (c) 2016 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Keccak internal interfaces. Will be used by STROBE once reintegrated. 9 | */ 10 | #ifndef __DECAF_KECCAK_INTERNAL_H__ 11 | #define __DECAF_KECCAK_INTERNAL_H__ 1 12 | 13 | #include 14 | 15 | /* Aliasing MSVC preprocessing to GNU preprocessing */ 16 | #if defined _MSC_VER 17 | #define __attribute__(x) // Turn off attribute code 18 | #define __attribute(x) 19 | #define __restrict__ __restrict // Use MSVC restrict code 20 | #endif // MSVC 21 | 22 | /* The internal, non-opaque definition of the decaf_sponge struct. */ 23 | typedef union { 24 | uint64_t w[25]; uint8_t b[25*8]; 25 | } kdomain_t[1]; 26 | 27 | typedef struct decaf_kparams_s { 28 | uint8_t position, flags, rate, start_round, pad, rate_pad, max_out, remaining; 29 | } decaf_kparams_s, decaf_kparams_t[1]; 30 | 31 | typedef struct decaf_keccak_sponge_s { 32 | kdomain_t state; 33 | decaf_kparams_t params; 34 | } decaf_keccak_sponge_s, decaf_keccak_sponge_t[1]; 35 | 36 | #define INTERNAL_SPONGE_STRUCT 1 37 | 38 | void __attribute__((noinline)) keccakf(kdomain_t state, uint8_t start_round); 39 | 40 | static inline void dokeccak (decaf_keccak_sponge_t decaf_sponge) { 41 | keccakf(decaf_sponge->state, decaf_sponge->params->start_round); 42 | decaf_sponge->params->position = 0; 43 | } 44 | 45 | #endif /* __DECAF_KECCAK_INTERNAL_H__ */ 46 | -------------------------------------------------------------------------------- /src/p25519/arch_ref64/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | void gf_mul (gf_s *__restrict__ cs, const gf as, const gf bs) { 8 | const uint64_t *a = as->limb, *b = bs->limb, mask = ((1ull<<51)-1); 9 | 10 | uint64_t bh[4]; 11 | int i,j; 12 | for (i=0; i<4; i++) bh[i] = b[i+1] * 19; 13 | 14 | uint64_t *c = cs->limb; 15 | 16 | __uint128_t accum = 0; 17 | for (i=0; i<5; i++) { 18 | for (j=0; j<=i; j++) { 19 | accum += widemul(b[i-j], a[j]); 20 | } 21 | for (; j<5; j++) { 22 | accum += widemul(bh[i-j+4], a[j]); 23 | } 24 | c[i] = accum & mask; 25 | accum >>= 51; 26 | } 27 | 28 | accum *= 19; 29 | accum += c[0]; 30 | c[0] = accum & mask; 31 | accum >>= 51; 32 | 33 | assert(accum < mask); 34 | c[1] += accum; 35 | } 36 | 37 | void gf_mulw_unsigned (gf_s *__restrict__ cs, const gf as, uint32_t b) { 38 | const uint64_t *a = as->limb, mask = ((1ull<<51)-1); 39 | int i; 40 | 41 | uint64_t *c = cs->limb; 42 | 43 | __uint128_t accum = 0; 44 | for (i=0; i<5; i++) { 45 | accum += widemul(b, a[i]); 46 | c[i] = accum & mask; 47 | accum >>= 51; 48 | } 49 | 50 | accum *= 19; 51 | accum += c[0]; 52 | c[0] = accum & mask; 53 | accum >>= 51; 54 | 55 | assert(accum < mask); 56 | c[1] += accum; 57 | } 58 | 59 | void gf_sqr (gf_s *__restrict__ cs, const gf as) { 60 | gf_mul(cs,as,as); /* Performs better with dedicated square */ 61 | } 62 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The Python bindings are Copyright 2017 John-Mark Gurney, and are provided 2 | under a BSD license as described in python/edgold/ed448.py 3 | 4 | Certain sections of code are public domain or CC0, as marked. 5 | 6 | Earlier versions of this project used small amounts of code which were 7 | Copyright (c) 2011 Stanford University 8 | Copyright (c) 2011 Mike Hamburg 9 | but I believe that all of this code has now been replaced. 10 | 11 | The bulk of this library is 12 | Copyright (c) 2014-2017 Cryptography Research, Inc. 13 | and licensed under the following MIT license. 14 | 15 | 16 | 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2014-2017 Cryptography Research, Inc. 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in 29 | all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. 38 | -------------------------------------------------------------------------------- /src/p448/arch_arm_32/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 2 6 | #define LIMB(x) (x##ull)&((1ull<<28)-1), (x##ull)>>28 7 | #define FIELD_LITERAL(a,b,c,d,e,f,g,h) \ 8 | {{LIMB(a),LIMB(b),LIMB(c),LIMB(d),LIMB(e),LIMB(f),LIMB(g),LIMB(h)}} 9 | 10 | #define LIMB_PLACE_VALUE(i) 28 11 | 12 | void gf_add_RAW (gf out, const gf a, const gf b) { 13 | for (unsigned int i=0; ilimb[0]); i++) { 18 | out->limb[i] = a->limb[i] + b->limb[i]; 19 | } 20 | */ 21 | } 22 | 23 | void gf_sub_RAW (gf out, const gf a, const gf b) { 24 | for (unsigned int i=0; ilimb[0]); i++) { 29 | out->limb[i] = a->limb[i] - b->limb[i]; 30 | } 31 | */ 32 | } 33 | 34 | void gf_bias (gf a, int amt) { 35 | uint32_t co1 = ((1ull<<28)-1)*amt, co2 = co1-amt; 36 | uint32x4_t lo = {co1,co1,co1,co1}, hi = {co2,co1,co1,co1}; 37 | uint32x4_t *aa = (uint32x4_t*) a; 38 | aa[0] += lo; 39 | aa[1] += lo; 40 | aa[2] += hi; 41 | aa[3] += lo; 42 | } 43 | 44 | void gf_weak_reduce (gf a) { 45 | uint64_t mask = (1ull<<28) - 1; 46 | uint64_t tmp = a->limb[15] >> 28; 47 | a->limb[8] += tmp; 48 | for (unsigned int i=15; i>0; i--) { 49 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>28); 50 | } 51 | a->limb[0] = (a->limb[0] & mask) + tmp; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/p448/arch_neon/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 2 6 | #define LIMBPERM(x) (((x)<<1 | (x)>>3) & 15) 7 | #define USE_NEON_PERM 1 8 | #define LIMBHI(x) ((x##ull)>>28) 9 | #define LIMBLO(x) ((x##ull)&((1ull<<28)-1)) 10 | # define FIELD_LITERAL(a,b,c,d,e,f,g,h) \ 11 | {{LIMBLO(a),LIMBLO(e), LIMBHI(a),LIMBHI(e), \ 12 | LIMBLO(b),LIMBLO(f), LIMBHI(b),LIMBHI(f), \ 13 | LIMBLO(c),LIMBLO(g), LIMBHI(c),LIMBHI(g), \ 14 | LIMBLO(d),LIMBLO(h), LIMBHI(d),LIMBHI(h)}} 15 | 16 | #define LIMB_PLACE_VALUE(i) 28 17 | 18 | void gf_add_RAW (gf out, const gf a, const gf b) { 19 | for (unsigned int i=0; ilimb[0]); i++) { 31 | out->limb[i] = a->limb[i] - b->limb[i]; 32 | } 33 | */ 34 | } 35 | 36 | void gf_bias (gf a, int amt) { 37 | uint32_t co1 = ((1ull<<28)-1)*amt, co2 = co1-amt; 38 | uint32x4_t lo = {co1,co2,co1,co1}, hi = {co1,co1,co1,co1}; 39 | uint32x4_t *aa = (uint32x4_t*) a; 40 | aa[0] += lo; 41 | aa[1] += hi; 42 | aa[2] += hi; 43 | aa[3] += hi; 44 | } 45 | 46 | void gf_weak_reduce (gf a) { 47 | 48 | uint32x2_t *aa = (uint32x2_t*) a, vmask = {(1ull<<28)-1, (1ull<<28)-1}, vm2 = {0,-1}, 49 | tmp = vshr_n_u32(aa[7],28); 50 | 51 | for (unsigned int i=7; i>=1; i--) { 52 | aa[i] = vsra_n_u32(aa[i] & vmask, aa[i-1], 28); 53 | } 54 | aa[0] = (aa[0] & vmask) + vrev64_u32(tmp) + (tmp&vm2); 55 | } 56 | 57 | -------------------------------------------------------------------------------- /_aux/attic/p480/arch_x86_64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define LIMB_PLACE_VALUE(i) 60 6 | 7 | void gf_add_RAW (gf out, const gf a, const gf b) { 8 | for (unsigned int i=0; ilimb[0]); i++) { 14 | out->limb[i] = a->limb[i] + b->limb[i]; 15 | } 16 | */ 17 | } 18 | 19 | void gf_sub_RAW (gf out, const gf a, const gf b) { 20 | for (unsigned int i=0; ilimb[0]); i++) { 26 | out->limb[i] = a->limb[i] - b->limb[i]; 27 | } 28 | */ 29 | } 30 | 31 | void gf_bias ( 32 | gf a, int amt 33 | ) { 34 | uint64_t co1 = ((1ull<<60)-1)*amt, co2 = co1-amt; 35 | 36 | #if __AVX2__ 37 | uint64x4_t lo = {co1,co1,co1,co1}, hi = {co2,co1,co1,co1}; 38 | uint64x4_t *aa = (uint64x4_t*) a; 39 | aa[0] += lo; 40 | aa[1] += hi; 41 | #elif __SSE2__ 42 | uint64x2_t lo = {co1,co1}, hi = {co2,co1}; 43 | uint64x2_t *aa = (uint64x2_t*) a; 44 | aa[0] += lo; 45 | aa[1] += lo; 46 | aa[2] += hi; 47 | aa[3] += lo; 48 | #else 49 | for (unsigned int i=0; ilimb[i] += (i==4) ? co2 : co1; 51 | } 52 | #endif 53 | } 54 | 55 | void gf_weak_reduce (gf a) { 56 | /* PERF: use pshufb/palignr if anyone cares about speed of this */ 57 | uint64_t mask = (1ull<<60) - 1; 58 | uint64_t tmp = a->limb[7] >> 60; 59 | a->limb[4] += tmp; 60 | for (unsigned int i=7; i>0; i--) { 61 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>60); 62 | } 63 | a->limb[0] = (a->limb[0] & mask) + tmp; 64 | } 65 | -------------------------------------------------------------------------------- /src/p448/arch_x86_64/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #define GF_HEADROOM 60 6 | #define FIELD_LITERAL(a,b,c,d,e,f,g,h) {{a,b,c,d,e,f,g,h}} 7 | #define LIMB_PLACE_VALUE(i) 56 8 | 9 | void gf_add_RAW (gf out, const gf a, const gf b) { 10 | for (unsigned int i=0; ilimb[0]); i++) { 16 | out->limb[i] = a->limb[i] + b->limb[i]; 17 | } 18 | */ 19 | } 20 | 21 | void gf_sub_RAW (gf out, const gf a, const gf b) { 22 | for (unsigned int i=0; ilimb[0]); i++) { 28 | out->limb[i] = a->limb[i] - b->limb[i]; 29 | } 30 | */ 31 | } 32 | 33 | void gf_bias (gf a, int amt) { 34 | uint64_t co1 = ((1ull<<56)-1)*amt, co2 = co1-amt; 35 | 36 | #if __AVX2__ 37 | uint64x4_t lo = {co1,co1,co1,co1}, hi = {co2,co1,co1,co1}; 38 | uint64x4_t *aa = (uint64x4_t*) a; 39 | aa[0] += lo; 40 | aa[1] += hi; 41 | #elif __SSE2__ 42 | uint64x2_t lo = {co1,co1}, hi = {co2,co1}; 43 | uint64x2_t *aa = (uint64x2_t*) a; 44 | aa[0] += lo; 45 | aa[1] += lo; 46 | aa[2] += hi; 47 | aa[3] += lo; 48 | #else 49 | for (unsigned int i=0; ilimb[i] += (i==4) ? co2 : co1; 51 | } 52 | #endif 53 | } 54 | 55 | void gf_weak_reduce (gf a) { 56 | /* PERF: use pshufb/palignr if anyone cares about speed of this */ 57 | uint64_t mask = (1ull<<56) - 1; 58 | uint64_t tmp = a->limb[7] >> 56; 59 | a->limb[4] += tmp; 60 | for (unsigned int i=7; i>0; i--) { 61 | a->limb[i] = (a->limb[i] & mask) + (a->limb[i-1]>>56); 62 | } 63 | a->limb[0] = (a->limb[0] & mask) + tmp; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /_aux/attic/p521/arch_x86_64_r12/f_impl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014-2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | /* FIXME: Currently this file desn't work at all, because the struct is declared [9] and not [12] */ 6 | #define LIMBPERM(x) (((x)%3)*4 + (x)/3) 7 | #define LIMB_PLACE_VALUE(i) ((((i)&4)==3) ? 0 : 57) 8 | #define USE_P521_3x3_TRANSPOSE 9 | 10 | typedef uint64x4_t uint64x3_t; /* fit it in a vector register */ 11 | 12 | static const uint64x3_t mask58 = { (1ull<<58) - 1, (1ull<<58) - 1, (1ull<<58) - 1, 0 }; 13 | 14 | /* Currently requires CLANG. Sorry. */ 15 | static inline uint64x3_t timesW (uint64x3_t u) { 16 | return u.zxyw + u.zwww; 17 | } 18 | 19 | void gf_add_RAW (gf out, const gf a, const gf b) { 20 | for (unsigned int i=0; ilimb[3] == 0 && a->limb[7] == 0 && a->limb[11] == 0); 43 | for (i=0; i<12; i++) { 44 | assert(a->limb[i] < 3ull<<61); 45 | } 46 | #endif 47 | uint64x3_t 48 | ot0 = ((uint64x4_t*)a)[0], 49 | ot1 = ((uint64x4_t*)a)[1], 50 | ot2 = ((uint64x4_t*)a)[2]; 51 | 52 | uint64x3_t out0 = (ot0 & mask58) + timesW(ot2>>58); 53 | uint64x3_t out1 = (ot1 & mask58) + (ot0>>58); 54 | uint64x3_t out2 = (ot2 & mask58) + (ot1>>58); 55 | 56 | ((uint64x4_t*)a)[0] = out0; 57 | ((uint64x4_t*)a)[1] = out1; 58 | ((uint64x4_t*)a)[2] = out2; 59 | } 60 | -------------------------------------------------------------------------------- /cmake/DecafConfig.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # decafConfig.cmake 3 | # Copyright (C) 2017 Belledonne Communications, Grenoble France 4 | # 5 | ############################################################################ 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | # 21 | ############################################################################ 22 | # 23 | # Config file for the decaf package. 24 | # It defines the following variables: 25 | # 26 | # DECAF_FOUND - system has decaf 27 | # DECAF_INCLUDE_DIRS - the decaf include directory 28 | # DECAF_LIBRARIES - The libraries needed to use decaf 29 | # DECAF_CPPFLAGS - The compilation flags needed to use decaf 30 | 31 | 32 | if(@ENABLE_SHARED@) 33 | set(DECAF_TARGETNAME decaf) 34 | set(DECAF_LIBRARIES ${DECAF_TARGETNAME}) 35 | else() 36 | set(DECAF_TARGETNAME decaf-static) 37 | if(TARGET ${DECAF_TARGETNAME}) 38 | get_target_property(DECAF_LIBRARIES ${DECAF_TARGETNAME} LOCATION) 39 | get_target_property(DECAF_LINK_LIBRARIES ${DECAF_TARGETNAME} INTERFACE_LINK_LIBRARIES) 40 | if(DECAF_LINK_LIBRARIES) 41 | list(APPEND DECAF_LIBRARIES ${DECAF_LINK_LIBRARIES}) 42 | endif() 43 | endif() 44 | endif() 45 | get_target_property(DECAF_INCLUDE_DIRS ${DECAF_TARGETNAME} INTERFACE_INCLUDE_DIRECTORIES) 46 | list(INSERT DECAF_INCLUDE_DIRS 0 "@CMAKE_INSTALL_FULL_INCLUDEDIR@") 47 | list(REMOVE_DUPLICATES DECAF_INCLUDE_DIRS) 48 | 49 | set(DECAF_CPPFLAGS @DECAF_CPPFLAGS@) 50 | set(DECAF_FOUND 1) 51 | -------------------------------------------------------------------------------- /src/public_include/decaf/sha512.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file decaf/shake.h 3 | * @copyright Public domain. 4 | * @author Mike Hamburg 5 | * @brief SHA2-512 6 | */ 7 | 8 | #ifndef __DECAF_SHA512_H__ 9 | #define __DECAF_SHA512_H__ 10 | 11 | #include 12 | #include 13 | #include /* for NULL */ 14 | 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** Hash context for SHA-512 */ 22 | typedef struct decaf_sha512_ctx_s { 23 | /** @cond internal */ 24 | uint64_t state[8]; 25 | uint8_t block[128]; 26 | uint64_t bytes_processed; 27 | /* @endcond */ 28 | } decaf_sha512_ctx_s, decaf_sha512_ctx_t[1]; 29 | 30 | /** Initialize a SHA-512 context. */ 31 | void DECAF_API_VIS decaf_sha512_init(decaf_sha512_ctx_t ctx) DECAF_NONNULL; 32 | 33 | /** Update context by hashing part of a message. */ 34 | void DECAF_API_VIS decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t message_len) DECAF_NONNULL; 35 | 36 | /** Finalize context and write out hash. 37 | * @param [inout] ctx The context. Will be destroyed and re-initialized on return. 38 | * @param [out] output Place to store the output hash. 39 | * @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. 40 | */ 41 | void DECAF_API_VIS decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *output, size_t output_len) DECAF_NONNULL; 42 | 43 | /** Securely destroy a SHA512 context. */ 44 | static inline void decaf_sha512_destroy(decaf_sha512_ctx_t ctx) { 45 | decaf_bzero(ctx,sizeof(*ctx)); 46 | } 47 | 48 | /** Hash a message. 49 | * @param [out] output Place to store the output hash. 50 | * @param [in] output_len Length in bytes of the output hash. Must between 0 and 64, inclusive. 51 | * @param [in] message A message to hash. 52 | * @param [in] message_len Length in bytes of the input message. 53 | */ 54 | static inline void decaf_sha512_hash( 55 | uint8_t *output, 56 | size_t output_len, 57 | const uint8_t *message, 58 | size_t message_len 59 | ) { 60 | decaf_sha512_ctx_t ctx; 61 | decaf_sha512_init(ctx); 62 | decaf_sha512_update(ctx,message,message_len); 63 | decaf_sha512_final(ctx,output,output_len); 64 | decaf_sha512_destroy(ctx); 65 | } 66 | 67 | #ifdef __cplusplus 68 | } /* extern "C" */ 69 | #endif 70 | 71 | #endif /* __DECAF_SHA512_H__ */ 72 | -------------------------------------------------------------------------------- /src/p25519/arch_32/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | void gf_mul (gf_s *__restrict__ cs, const gf as, const gf bs) { 8 | const uint32_t *a = as->limb, *b = bs->limb, maske = ((1<<26)-1), masko = ((1<<25)-1); 9 | 10 | uint32_t bh[9]; 11 | int i,j; 12 | for (i=0; i<9; i++) bh[i] = b[i+1] * 19; 13 | 14 | uint32_t *c = cs->limb; 15 | 16 | uint64_t accum = 0; 17 | for (i=0; i<10; /*i+=2*/) { 18 | /* Even case. */ 19 | for (j=0; j>= 26; 31 | i++; 32 | 33 | /* Odd case is easier: all place values are exact. */ 34 | for (j=0; j<=i; j++) { 35 | accum += widemul(b[i-j], a[j]); 36 | } 37 | for (; j<10; j++) { 38 | accum += widemul(bh[i-j+9], a[j]); 39 | } 40 | c[i] = accum & masko; 41 | accum >>= 25; 42 | i++; 43 | } 44 | 45 | accum *= 19; 46 | accum += c[0]; 47 | c[0] = accum & maske; 48 | accum >>= 26; 49 | 50 | assert(accum < masko); 51 | c[1] += accum; 52 | } 53 | 54 | void gf_mulw_unsigned (gf_s *__restrict__ cs, const gf as, uint32_t b) { 55 | const uint32_t *a = as->limb, maske = ((1<<26)-1), masko = ((1<<25)-1); 56 | uint32_t *c = cs->limb; 57 | uint64_t accum = widemul(b, a[0]); 58 | c[0] = accum & maske; 59 | accum >>= 26; 60 | 61 | accum += widemul(b, a[1]); 62 | c[1] = accum & masko; 63 | accum >>= 25; 64 | 65 | for (int i=2; i<10; /*i+=2*/) { 66 | accum += widemul(b, a[i]); 67 | c[i] = accum & maske; 68 | accum >>= 26; 69 | i++; 70 | 71 | accum += widemul(b, a[i]); 72 | c[i] = accum & masko; 73 | accum >>= 25; 74 | i++; 75 | } 76 | 77 | accum *= 19; 78 | accum += c[0]; 79 | c[0] = accum & maske; 80 | accum >>= 26; 81 | 82 | assert(accum < masko); 83 | c[1] += accum; 84 | } 85 | 86 | void gf_sqr (gf_s *__restrict__ cs, const gf as) { 87 | gf_mul(cs,as,as); /* Performs better with dedicated square */ 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/p448/arch_32/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | #if (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) && !I_HATE_UNROLLED_LOOPS) \ 8 | || defined(DECAF_FORCE_UNROLL) 9 | #define REPEAT8(_x) _x _x _x _x _x _x _x _x 10 | #define FOR_LIMB(_i,_start,_end,_x) do { _i=_start; REPEAT8( if (_i<_end) { _x; } _i++;) } while (0) 11 | #else 12 | #define FOR_LIMB(_i,_start,_end,_x) do { for (_i=_start; _i<_end; _i++) _x; } while (0) 13 | #endif 14 | 15 | void gf_mul (gf_s *__restrict__ cs, const gf as, const gf bs) { 16 | const uint32_t *a = as->limb, *b = bs->limb; 17 | uint32_t *c = cs->limb; 18 | 19 | uint64_t accum0 = 0, accum1 = 0, accum2 = 0; 20 | uint32_t mask = (1<<28) - 1; 21 | 22 | uint32_t aa[8], bb[8]; 23 | 24 | int i,j; 25 | for (i=0; i<8; i++) { 26 | aa[i] = a[i] + a[i+8]; 27 | bb[i] = b[i] + b[i+8]; 28 | } 29 | 30 | FOR_LIMB(j,0,8,{ 31 | accum2 = 0; 32 | 33 | FOR_LIMB (i,0,j+1,{ 34 | accum2 += widemul(a[j-i],b[i]); 35 | accum1 += widemul(aa[j-i],bb[i]); 36 | accum0 += widemul(a[8+j-i], b[8+i]); 37 | }); 38 | 39 | accum1 -= accum2; 40 | accum0 += accum2; 41 | accum2 = 0; 42 | 43 | FOR_LIMB (i,j+1,8,{ 44 | accum0 -= widemul(a[8+j-i], b[i]); 45 | accum2 += widemul(aa[8+j-i], bb[i]); 46 | accum1 += widemul(a[16+j-i], b[8+i]); 47 | }); 48 | 49 | accum1 += accum2; 50 | accum0 += accum2; 51 | 52 | c[j] = ((uint32_t)(accum0)) & mask; 53 | c[j+8] = ((uint32_t)(accum1)) & mask; 54 | 55 | accum0 >>= 28; 56 | accum1 >>= 28; 57 | }); 58 | 59 | accum0 += accum1; 60 | accum0 += c[8]; 61 | accum1 += c[0]; 62 | c[8] = ((uint32_t)(accum0)) & mask; 63 | c[0] = ((uint32_t)(accum1)) & mask; 64 | 65 | accum0 >>= 28; 66 | accum1 >>= 28; 67 | c[9] += ((uint32_t)(accum0)); 68 | c[1] += ((uint32_t)(accum1)); 69 | } 70 | 71 | void gf_mulw_unsigned (gf_s *__restrict__ cs, const gf as, uint32_t b) { 72 | assert(b<1<<28); 73 | 74 | const uint32_t *a = as->limb; 75 | uint32_t *c = cs->limb; 76 | 77 | uint64_t accum0 = 0, accum8 = 0; 78 | uint32_t mask = (1ull<<28)-1; 79 | 80 | int i; 81 | FOR_LIMB(i,0,8,{ 82 | accum0 += widemul(b, a[i]); 83 | accum8 += widemul(b, a[i+8]); 84 | 85 | c[i] = accum0 & mask; accum0 >>= 28; 86 | c[i+8] = accum8 & mask; accum8 >>= 28; 87 | }); 88 | 89 | accum0 += accum8 + c[8]; 90 | c[8] = accum0 & mask; 91 | c[9] += accum0 >> 28; 92 | 93 | accum8 += c[0]; 94 | c[0] = accum8 & mask; 95 | c[1] += accum8 >> 28; 96 | } 97 | 98 | void gf_sqr (gf_s *__restrict__ cs, const gf as) { 99 | gf_mul(cs,as,as); /* Performs better with a dedicated square */ 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/include/field.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file field.h 3 | * @brief Generic gf header. 4 | * @copyright 5 | * Copyright (c) 2014 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | */ 9 | 10 | #ifndef __GF_H__ 11 | #define __GF_H__ 12 | 13 | #include "constant_time.h" 14 | #include "f_field.h" 15 | #include 16 | 17 | /** Square x, n times. */ 18 | static DECAF_INLINE void gf_sqrn ( 19 | gf_s *__restrict__ y, 20 | const gf x, 21 | int n 22 | ) { 23 | gf tmp; 24 | assert(n>0); 25 | if (n&1) { 26 | gf_sqr(y,x); 27 | n--; 28 | } else { 29 | gf_sqr(tmp,x); 30 | gf_sqr(y,tmp); 31 | n-=2; 32 | } 33 | for (; n; n-=2) { 34 | gf_sqr(tmp,y); 35 | gf_sqr(y,tmp); 36 | } 37 | } 38 | 39 | #define gf_add_nr gf_add_RAW 40 | 41 | /** Subtract mod p. Bias by 2 and don't reduce */ 42 | static inline void gf_sub_nr ( gf c, const gf a, const gf b ) { 43 | gf_sub_RAW(c,a,b); 44 | gf_bias(c, 2); 45 | if (GF_HEADROOM < 3) gf_weak_reduce(c); 46 | } 47 | 48 | /** Subtract mod p. Bias by amt but don't reduce. */ 49 | static inline void gf_subx_nr ( gf c, const gf a, const gf b, int amt ) { 50 | gf_sub_RAW(c,a,b); 51 | gf_bias(c, amt); 52 | if (GF_HEADROOM < amt+1) gf_weak_reduce(c); 53 | } 54 | 55 | /** Mul by signed int. Not constant-time WRT the sign of that int. */ 56 | static inline void gf_mulw(gf c, const gf a, int32_t w) { 57 | if (w>0) { 58 | gf_mulw_unsigned(c, a, w); 59 | } else { 60 | gf_mulw_unsigned(c, a, -w); 61 | gf_sub(c,ZERO,c); 62 | } 63 | } 64 | 65 | /** Constant time, x = is_z ? z : y */ 66 | static inline void gf_cond_sel(gf x, const gf y, const gf z, mask_t is_z) { 67 | constant_time_select(x,y,z,sizeof(gf),is_z,0); 68 | } 69 | 70 | /** Constant time, if (neg) x=-x; */ 71 | static inline void gf_cond_neg(gf x, mask_t neg) { 72 | gf y; 73 | gf_sub(y,ZERO,x); 74 | gf_cond_sel(x,x,y,neg); 75 | } 76 | 77 | /** Constant time, if (swap) (x,y) = (y,x); */ 78 | static inline void 79 | gf_cond_swap(gf x, gf_s *__restrict__ y, mask_t swap) { 80 | constant_time_cond_swap(x,y,sizeof(gf_s),swap); 81 | } 82 | 83 | static DECAF_INLINE void gf_mul_qnr(gf_s *__restrict__ out, const gf x) { 84 | #if P_MOD_8 == 5 85 | /* r = QNR * r0^2 */ 86 | gf_mul(out,x,SQRT_MINUS_ONE); 87 | #elif P_MOD_8 == 3 || P_MOD_8 == 7 88 | gf_sub(out,ZERO,x); 89 | #else 90 | #error "Only supporting p=3,5,7 mod 8" 91 | #endif 92 | } 93 | 94 | static DECAF_INLINE void gf_div_qnr(gf_s *__restrict__ out, const gf x) { 95 | #if P_MOD_8 == 5 96 | /* r = QNR * r0^2 */ 97 | gf_mul(out,x,SQRT_MINUS_ONE); 98 | gf_sub(out,ZERO,out); 99 | #elif P_MOD_8 == 3 || P_MOD_8 == 7 100 | gf_sub(out,ZERO,x); 101 | #else 102 | #error "Only supporting p=3,5,7 mod 8" 103 | #endif 104 | } 105 | 106 | #if P_MOD_8 == 5 107 | #define gf_mul_i gf_mul_qnr 108 | #define gf_div_i gf_div_qnr 109 | #endif 110 | 111 | 112 | #endif // __GF_H__ 113 | -------------------------------------------------------------------------------- /test/shakesum.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file decaf_shakesum.c 4 | * @copyright 5 | * Copyright (c) 2015 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief SHA3 utility, to be combined with test vectors eventually... 9 | */ 10 | 11 | #include 12 | #if defined _MSC_VER // MSVC has not unistd.h 13 | #include 14 | #include 15 | typedef SSIZE_T ssize_t; 16 | #else 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | 23 | static void usage() { 24 | fprintf( 25 | stderr, 26 | "decaf_shakesum [shake256|shake128|sha3-224|sha3-384|sha3-512|sha512] < infile > outfile\n" 27 | ); 28 | } 29 | 30 | int main(int argc, char **argv) { 31 | (void)argc; (void)argv; 32 | 33 | decaf_keccak_sponge_t sponge; 34 | decaf_sha512_ctx_t decaf_sha512; 35 | unsigned char buf[1024]; 36 | 37 | unsigned int outlen = 512; 38 | decaf_shake256_gen_init(sponge); 39 | 40 | int use_sha512 = 0; 41 | 42 | /* Sloppy. Real utility would parse --algo, --size ... */ 43 | if (argc > 1) { 44 | if (!strcmp(argv[1], "shake256") || !strcmp(argv[1], "SHAKE256")) { 45 | outlen = 512; 46 | decaf_shake256_gen_init(sponge); 47 | } else if (!strcmp(argv[1], "shake128") || !strcmp(argv[1], "SHAKE128")) { 48 | outlen = 512; 49 | decaf_shake128_gen_init(sponge); 50 | } else if (!strcmp(argv[1], "sha3-224") || !strcmp(argv[1], "SHA3-224")) { 51 | outlen = 224/8; 52 | decaf_sha3_224_gen_init(sponge); 53 | } else if (!strcmp(argv[1], "sha3-256") || !strcmp(argv[1], "SHA3-256")) { 54 | outlen = 256/8; 55 | decaf_sha3_256_gen_init(sponge); 56 | } else if (!strcmp(argv[1], "sha3-384") || !strcmp(argv[1], "SHA3-384")) { 57 | outlen = 384/8; 58 | decaf_sha3_384_gen_init(sponge); 59 | } else if (!strcmp(argv[1], "sha3-512") || !strcmp(argv[1], "SHA3-512")) { 60 | outlen = 512/8; 61 | decaf_sha3_512_gen_init(sponge); 62 | } else if (!strcmp(argv[1], "sha512") || !strcmp(argv[1], "SHA512")) { 63 | outlen = 512/8; 64 | use_sha512 = 1; 65 | decaf_sha512_init(decaf_sha512); 66 | } else { 67 | usage(); 68 | return 2; 69 | } 70 | } 71 | 72 | ssize_t red; 73 | do { 74 | red = read(0, buf, sizeof(buf)); 75 | if (red>0) { 76 | if (use_sha512) decaf_sha512_update(decaf_sha512,buf,red); 77 | else decaf_sha3_update(sponge,buf,red); 78 | } 79 | } while (red>0); 80 | 81 | if (use_sha512) { 82 | decaf_sha512_final(decaf_sha512,buf,outlen); 83 | decaf_sha512_destroy(decaf_sha512); 84 | } else { 85 | decaf_sha3_output(sponge,buf,outlen); 86 | decaf_sha3_destroy(sponge); 87 | } 88 | unsigned i; 89 | for (i=0; i 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | /** @cond internal */ 24 | #if __cplusplus >= 201103L 25 | #define DECAF_NOEXCEPT noexcept 26 | #define DECAF_DELETE = delete 27 | #else 28 | #define DECAF_NOEXCEPT throw() 29 | #define DECAF_DELETE 30 | #endif 31 | /** @endcond */ 32 | 33 | namespace decaf { 34 | 35 | /** Sponge-based random-number generator */ 36 | class SpongeRng : public Rng { 37 | private: 38 | /** C wrapped object */ 39 | decaf_keccak_prng_t sp; 40 | 41 | public: 42 | /** Deterministic flag. 43 | * The idea is that DETERMINISTIC is used for testing or for lockstep computations, 44 | * and NONDETERMINISTIC is used in production. 45 | */ 46 | enum Deterministic { RANDOM = 0, DETERMINISTIC = 1 }; 47 | 48 | /** Exception thrown when The RNG fails (to seed itself) */ 49 | class RngException : public std::exception { 50 | private: 51 | /** @cond internal */ 52 | const char *const what_; 53 | /** @endcond */ 54 | public: 55 | const int err_code; /**< errno that caused the reseed to fail. */ 56 | const char *what() const DECAF_NOEXCEPT { return what_; } /**< Description of exception. */ 57 | RngException(int err_code, const char *what_) DECAF_NOEXCEPT : what_(what_), err_code(err_code) {} /**< Construct */ 58 | }; 59 | 60 | /** Initialize, deterministically by default, from block */ 61 | inline SpongeRng( const Block &in, Deterministic det ) { 62 | decaf_spongerng_init_from_buffer(sp,in.data(),in.size(),(int)det); 63 | } 64 | 65 | /** Initialize, non-deterministically by default, from C/C++ filename */ 66 | inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, Deterministic det = RANDOM ) 67 | /*throw(RngException)*/ { 68 | decaf_error_t ret = decaf_spongerng_init_from_file(sp,in.c_str(),len,det); 69 | if (!decaf_successful(ret)) { 70 | throw RngException(errno, "Couldn't load from file"); 71 | } 72 | } 73 | 74 | /** Stir in new data */ 75 | inline void stir( const Block &data ) DECAF_NOEXCEPT { 76 | decaf_spongerng_stir(sp,data.data(),data.size()); 77 | } 78 | 79 | /** Securely destroy by overwriting state. */ 80 | inline ~SpongeRng() DECAF_NOEXCEPT { decaf_spongerng_destroy(sp); } 81 | 82 | using Rng::read; 83 | 84 | /** Read data to a buffer. */ 85 | virtual inline void read(Buffer buffer) DECAF_NOEXCEPT 86 | #if __cplusplus >= 201103L 87 | final 88 | #endif 89 | { decaf_spongerng_next(sp,buffer.data(),buffer.size()); } 90 | 91 | private: 92 | SpongeRng(const SpongeRng &) DECAF_DELETE; 93 | SpongeRng &operator=(const SpongeRng &) DECAF_DELETE; 94 | }; 95 | /**@endcond*/ 96 | 97 | } /* namespace decaf */ 98 | 99 | #undef DECAF_NOEXCEPT 100 | #undef DECAF_DELETE 101 | 102 | #endif /* __DECAF_SPONGERNG_HXX__ */ 103 | -------------------------------------------------------------------------------- /src/per_field/f_field.tmpl.h: -------------------------------------------------------------------------------- 1 | /** @brief Field-specific code for $(gf_desc). */ 2 | 3 | #include "constant_time.h" 4 | #include 5 | #include 6 | 7 | #include "word.h" 8 | 9 | #define __DECAF_$(gf_shortname)_GF_DEFINED__ 1 10 | #define NLIMBS ($(gf_impl_bits//8)/sizeof(word_t)) 11 | #define X_SER_BYTES $(((gf_bits-1)//8 + 1)) 12 | #define SER_BYTES $(((gf_bits-2)//8 + 1)) 13 | typedef struct gf_$(gf_shortname)_s { 14 | word_t limb[NLIMBS]; 15 | } __attribute__((aligned(32))) gf_$(gf_shortname)_s, gf_$(gf_shortname)_t[1]; 16 | 17 | #define GF_LIT_LIMB_BITS $(gf_lit_limb_bits) 18 | #define GF_BITS $(gf_bits) 19 | #define ZERO gf_$(gf_shortname)_ZERO 20 | #define ONE gf_$(gf_shortname)_ONE 21 | #define MODULUS gf_$(gf_shortname)_MODULUS 22 | #define gf gf_$(gf_shortname)_t 23 | #define gf_s gf_$(gf_shortname)_s 24 | #define gf_eq gf_$(gf_shortname)_eq 25 | #define gf_hibit gf_$(gf_shortname)_hibit 26 | #define gf_lobit gf_$(gf_shortname)_lobit 27 | #define gf_copy gf_$(gf_shortname)_copy 28 | #define gf_add gf_$(gf_shortname)_add 29 | #define gf_sub gf_$(gf_shortname)_sub 30 | #define gf_add_RAW gf_$(gf_shortname)_add_RAW 31 | #define gf_sub_RAW gf_$(gf_shortname)_sub_RAW 32 | #define gf_bias gf_$(gf_shortname)_bias 33 | #define gf_weak_reduce gf_$(gf_shortname)_weak_reduce 34 | #define gf_strong_reduce gf_$(gf_shortname)_strong_reduce 35 | #define gf_mul gf_$(gf_shortname)_mul 36 | #define gf_sqr gf_$(gf_shortname)_sqr 37 | #define gf_mulw_unsigned gf_$(gf_shortname)_mulw_unsigned 38 | #define gf_isr gf_$(gf_shortname)_isr 39 | #define gf_serialize gf_$(gf_shortname)_serialize 40 | #define gf_deserialize gf_$(gf_shortname)_deserialize 41 | 42 | /* RFC 7748 support */ 43 | #define X_PUBLIC_BYTES X_SER_BYTES 44 | #define X_PRIVATE_BYTES X_PUBLIC_BYTES 45 | #define X_PRIVATE_BITS $(gf_bits) 46 | 47 | #define SQRT_MINUS_ONE P$(gf_shortname)_SQRT_MINUS_ONE /* might not be defined */ 48 | 49 | #define INLINE_UNUSED __inline__ __attribute__((unused,always_inline)) 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | /* Defined below in f_impl.h */ 56 | static INLINE_UNUSED void gf_copy (gf out, const gf a) { *out = *a; } 57 | static INLINE_UNUSED void gf_add_RAW (gf out, const gf a, const gf b); 58 | static INLINE_UNUSED void gf_sub_RAW (gf out, const gf a, const gf b); 59 | static INLINE_UNUSED void gf_bias (gf inout, int amount); 60 | static INLINE_UNUSED void gf_weak_reduce (gf inout); 61 | 62 | void gf_strong_reduce (gf inout); 63 | void gf_add (gf out, const gf a, const gf b); 64 | void gf_sub (gf out, const gf a, const gf b); 65 | void gf_mul (gf_s *__restrict__ out, const gf a, const gf b); 66 | void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b); 67 | void gf_sqr (gf_s *__restrict__ out, const gf a); 68 | mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ 69 | mask_t gf_eq (const gf x, const gf y); 70 | mask_t gf_lobit (const gf x); 71 | mask_t gf_hibit (const gf x); 72 | 73 | void gf_serialize (uint8_t *serial, const gf x,int with_highbit); 74 | mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_hibit,uint8_t hi_nmask); 75 | 76 | 77 | #ifdef __cplusplus 78 | } /* extern "C" */ 79 | #endif 80 | 81 | #include "f_impl.h" /* Bring in the inline implementations */ 82 | 83 | #define P_MOD_8 $(modulus % 8) 84 | #if P_MOD_8 == 5 85 | extern const gf SQRT_MINUS_ONE; 86 | #endif 87 | 88 | #ifndef LIMBPERM 89 | #define LIMBPERM(i) (i) 90 | #endif 91 | #define LIMB_MASK(i) (((1ull)< 15 | #include 16 | #include 17 | 18 | /** @cond internal */ 19 | #if __cplusplus >= 201103L 20 | #define DECAF_NOEXCEPT noexcept 21 | #else 22 | #define DECAF_NOEXCEPT throw() 23 | #endif 24 | /** @endcond */ 25 | 26 | namespace decaf { 27 | 28 | /** SHA512 wrapper function */ 29 | class SHA512 { 30 | protected: 31 | /** @cond internal */ 32 | /** The C-wrapper sponge state */ 33 | decaf_sha512_ctx_t wrapped; 34 | /** @endcond */ 35 | 36 | public: 37 | /** Number of bytes ouf output */ 38 | static const size_t OUTPUT_BYTES = 64; 39 | 40 | /** Number of bytes of output */ 41 | static const size_t MAX_OUTPUT_BYTES = OUTPUT_BYTES; 42 | 43 | /** Default number of bytes to output */ 44 | static const size_t DEFAULT_OUTPUT_BYTES = OUTPUT_BYTES; 45 | 46 | /** Constructor */ 47 | inline SHA512() DECAF_NOEXCEPT { decaf_sha512_init(wrapped); } 48 | 49 | /** Add more data to running hash */ 50 | inline void update(const uint8_t *__restrict__ in, size_t len) DECAF_NOEXCEPT { decaf_sha512_update(wrapped,in,len); } 51 | 52 | /** Add more data to running hash, C++ version. */ 53 | inline void update(const Block &s) DECAF_NOEXCEPT { update(s.data(),s.size()); } 54 | 55 | /** Add more data, stream version. */ 56 | inline SHA512 &operator<<(const Block &s) { update(s); return *this; } 57 | 58 | /** Same as <<. */ 59 | inline SHA512 &operator+=(const Block &s) { return *this << s; } 60 | 61 | /** @brief Output bytes from the SHA context, and resets it. */ 62 | inline void final(Buffer b) /*throw(LengthException)*/ { 63 | if (b.size() > OUTPUT_BYTES) throw LengthException(); 64 | decaf_sha512_final(wrapped,b.data(),b.size()); 65 | } 66 | 67 | /** Resets the SHA context */ 68 | inline void reset() DECAF_NOEXCEPT { decaf_sha512_init(wrapped); } 69 | 70 | /** @brief Output bytes from the sponge. */ 71 | inline SecureBuffer final(size_t len = OUTPUT_BYTES) /*throw(LengthException)*/ { 72 | if (len > OUTPUT_BYTES) throw LengthException(); 73 | SecureBuffer buffer(len); 74 | decaf_sha512_final(wrapped,buffer.data(),len); 75 | return buffer; 76 | } 77 | 78 | /** @brief Return the sponge's default output size. */ 79 | inline size_t default_output_size() const DECAF_NOEXCEPT { return OUTPUT_BYTES; } 80 | 81 | /** @brief Return the sponge's maximum output size. */ 82 | inline size_t max_output_size() const DECAF_NOEXCEPT { return MAX_OUTPUT_BYTES; } 83 | 84 | /** @brief Hash a message in one pass */ 85 | static inline SecureBuffer hash ( 86 | const Block &message, 87 | size_t outlen = OUTPUT_BYTES 88 | ) /*throw(LengthException, std::bad_alloc)*/ { 89 | if (outlen > OUTPUT_BYTES) throw LengthException(); 90 | SecureBuffer buffer(outlen); 91 | decaf_sha512_hash(buffer.data(),outlen,message.data(),message.size()); 92 | return buffer; 93 | } 94 | 95 | /** Destructor zeroizes state */ 96 | inline ~SHA512() DECAF_NOEXCEPT { decaf_sha512_destroy(wrapped); } 97 | }; 98 | 99 | } /* namespace decaf */ 100 | 101 | #undef DECAF_NOEXCEPT 102 | 103 | #endif /* __DECAF_SHA512_HXX__ */ 104 | -------------------------------------------------------------------------------- /src/public_include/decaf/spongerng.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file decaf/spongerng.h 3 | * @copyright 4 | * Copyright (c) 2015-2016 Cryptography Research, Inc. \n 5 | * Released under the MIT License. See LICENSE.txt for license information. 6 | * @author Mike Hamburg 7 | * @brief Sponge-based RNGs. 8 | * @warning This construction isn't final. In particular, 9 | * the outputs of deterministic RNGs from this mechanism might change in future versions. 10 | */ 11 | 12 | #ifndef __DECAF_SPONGERNG_H__ 13 | #define __DECAF_SPONGERNG_H__ 14 | 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /** Keccak CSPRNG structure as struct. */ 22 | typedef struct { 23 | decaf_keccak_sponge_t sponge; /**< Internal sponge object. */ 24 | } decaf_keccak_prng_s; 25 | 26 | /** Keccak CSPRNG structure as one-element array */ 27 | typedef decaf_keccak_prng_s decaf_keccak_prng_t[1]; 28 | 29 | /** Initialize a sponge-based CSPRNG from a buffer. */ 30 | void DECAF_API_VIS decaf_spongerng_init_from_buffer ( 31 | decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ 32 | const uint8_t *__restrict__ in, /**< [in] The initialization data. */ 33 | size_t len, /**< [in] The length of the initialization data. */ 34 | int deterministic /**< [in] If zero, allow RNG to stir in nondeterministic data from RDRAND or RDTSC.*/ 35 | ) DECAF_NONNULL; 36 | 37 | /** 38 | * @brief Initialize a sponge-based CSPRNG from a file. 39 | * @retval DECAF_SUCCESS success. 40 | * @retval DECAF_FAILURE failure. 41 | * @note On failure, errno can be used to determine the cause. 42 | */ 43 | decaf_error_t DECAF_API_VIS decaf_spongerng_init_from_file ( 44 | decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ 45 | const char *file, /**< [in] A name of a file containing initial data. */ 46 | size_t len, /**< [in] The length of the initial data. Must be positive. */ 47 | int deterministic /**< [in] If zero, allow RNG to stir in nondeterministic data from RDRAND or RDTSC. */ 48 | ) DECAF_NONNULL DECAF_WARN_UNUSED; 49 | 50 | /** 51 | * @brief Initialize a nondeterministic sponge-based CSPRNG from /dev/urandom. 52 | * @retval DECAF_SUCCESS success. 53 | * @retval DECAF_FAILURE failure. 54 | * @note On failure, errno can be used to determine the cause. 55 | */ 56 | decaf_error_t DECAF_API_VIS decaf_spongerng_init_from_dev_urandom ( 57 | decaf_keccak_prng_t prng /**< [out] sponge The sponge object. */ 58 | ) DECAF_WARN_UNUSED; 59 | 60 | /** Output bytes from a sponge-based CSPRNG. */ 61 | void DECAF_API_VIS decaf_spongerng_next ( 62 | decaf_keccak_prng_t prng, /**< [inout] The PRNG object. */ 63 | uint8_t * __restrict__ out, /**< [out] Output buffer. */ 64 | size_t len /**< [in] Number of bytes to output. */ 65 | ); 66 | 67 | /** Stir entropy data into a sponge-based CSPRNG from a buffer. */ 68 | void DECAF_API_VIS decaf_spongerng_stir ( 69 | decaf_keccak_prng_t prng, /**< [out] The PRNG object. */ 70 | const uint8_t * __restrict__ in, /**< [in] The entropy data. */ 71 | size_t len /**< [in] The length of the initial data. */ 72 | ) DECAF_NONNULL; 73 | 74 | /** Securely destroy a sponge RNG object by overwriting it. */ 75 | static DECAF_INLINE void 76 | decaf_spongerng_destroy ( 77 | decaf_keccak_prng_t doomed /**< [in] The object to destroy. */ 78 | ); 79 | 80 | /** @cond internal */ 81 | /***************************************/ 82 | /* Implementations of inline functions */ 83 | /***************************************/ 84 | void decaf_spongerng_destroy (decaf_keccak_prng_t doomed) { 85 | decaf_sha3_destroy(doomed->sponge); 86 | } 87 | /** @endcond */ /* internal */ 88 | 89 | #ifdef __cplusplus 90 | } /* extern "C" */ 91 | #endif 92 | 93 | #endif /* __DECAF_SPONGERNG_H__ */ 94 | -------------------------------------------------------------------------------- /src/generator/template.py: -------------------------------------------------------------------------------- 1 | from textwrap import dedent 2 | from curve_data import field_data,curve_data,ser,msqrt,ceil_log2 3 | 4 | import os 5 | import argparse 6 | import re 7 | 8 | parser = argparse.ArgumentParser(description='Generate Decaf headers and other such files.') 9 | parser.add_argument('-o', required = True, help = "Output") 10 | parser.add_argument('--per', required = True, help = "Files to be generated are global or per field/curve", choices=["global","field","curve"]) 11 | parser.add_argument('--item', required = False, default = "global", help = "Which curve/field to choose") 12 | parser.add_argument('--guard', required = False, default = None, help = "header guard") 13 | parser.add_argument('files', metavar='file', type=str, nargs='+', help='a list of files to fill') 14 | args = parser.parse_args() 15 | 16 | per_map = {"field":field_data, "curve":curve_data, "global":{"global":{"field":field_data,"curve":curve_data} }} 17 | 18 | def redoc(filename,doc,author): 19 | doc = doc.replace("\n","\n * ") 20 | doc = dedent(""" 21 | /** 22 | * @file %(filename)s 23 | * @author %(author)s 24 | * 25 | * @copyright 26 | * Copyright (c) 2015-2016 Cryptography Research, Inc. \\n 27 | * Released under the MIT License. See LICENSE.txt for license information. 28 | * 29 | * %(doc)s 30 | * 31 | * @warning This file was automatically generated in Python. 32 | * Please do not edit it. 33 | */""") % { "filename": filename, "doc": doc, "author" : author } 34 | doc = doc.replace(" * \n", " *\n") 35 | return doc[1:] 36 | 37 | def gen_file(public,name,doc,code,per="global",author="Mike Hamburg"): 38 | is_header = name.endswith(".h") or name.endswith(".hxx") or name.endswith(".h++") 39 | 40 | def fillin(template,data): 41 | position = 0 42 | ret = "" 43 | while True: 44 | dollars = template.find("$(",position) 45 | if dollars is -1: return ret + template[position:] 46 | ret += template[position:dollars] 47 | position = dollars + 2 48 | parens = 1 49 | while parens > 0: 50 | if template[position] == '(': parens += 1 51 | elif template[position] == ')': parens -= 1 52 | position += 1 53 | ret += str(eval(template[dollars+2:position-1],{'re':re,'ser':ser,'msqrt':msqrt,'ceil_log2':ceil_log2},data)) 54 | 55 | author = "Mike Hamburg" # FUTURE 56 | for name in args.files: 57 | _,_,name_suffix = name.rpartition(".") 58 | template0 = open(name,"r").read() 59 | 60 | data = per_map[args.per][args.item] 61 | 62 | template = template0 63 | 64 | outname = args.o 65 | guard = args.guard 66 | if guard is None: guard = outname 67 | header_guard = "__" + guard.replace(".","_").replace("/","_").upper() + "__" 68 | 69 | # Extract doxygenation 70 | m = re.match(r"^\s*/\*\*([^*]|\*[^/])+\*/[ \t]*\n",template) 71 | if m: 72 | doc = re.sub("^\s*/?\*+/?[ \t]*","",m.group(),flags=re.MULTILINE) 73 | doc = re.sub("\\s*\*/","",doc) 74 | template = template[m.end():] 75 | else: doc = "" 76 | 77 | ns_doc = dedent(doc).strip().rstrip() 78 | ns_doc = redoc(guard, fillin(ns_doc,data), author) 79 | ns_code = fillin(template,data) 80 | ret = ns_doc + "\n" 81 | 82 | if outname.endswith(".h") or outname.endswith(".hxx"): 83 | ns_code = dedent("""\n 84 | #ifndef %(header_guard)s 85 | #define %(header_guard)s 1 86 | %(code)s 87 | #endif /* %(header_guard)s */ 88 | """) % { "header_guard" : header_guard, "code": ns_code } 89 | ret += ns_code[1:-1] 90 | 91 | if not os.path.exists(os.path.dirname(outname)): 92 | os.makedirs(os.path.dirname(outname)) 93 | with open(outname,"w") as f: 94 | f.write(ret + "\n") 95 | 96 | 97 | -------------------------------------------------------------------------------- /_aux/decaffeinate_curve25519.sage: -------------------------------------------------------------------------------- 1 | # This is as sketch of how to decaffeinate Curve25519 2 | 3 | F = GF(2^255-19) 4 | 5 | doPinkBikeShed = True 6 | 7 | if doPinkBikeShed: d = -89747 # PinkBikeShed 8 | else: d = -121665 # Curve25519 9 | 10 | M = EllipticCurve(F,[0,2-4*d,0,1,0]) 11 | 12 | sqrtN1 = sqrt(F(-1)) 13 | 14 | def maybe(): return randint(0,1) 15 | 16 | def qpositive(x): 17 | return int(x) <= (2^255-19-1)/2 18 | 19 | def M_to_E(P): 20 | # P must be even 21 | (x,y) = P.xy() 22 | assert x.is_square() 23 | 24 | s = sqrt(x) 25 | if s == 0: t = 1 26 | else: t = y/s 27 | 28 | X,Y = 2*s / (1+s^2), (1-s^2) / t 29 | if maybe(): X,Y = -X,-Y 30 | if maybe(): X,Y = Y,-X 31 | # OK, have point in ed 32 | return X,Y 33 | 34 | def decaf_encode_from_E(X,Y): 35 | assert X^2 + Y^2 == 1 + d*X^2*Y^2 36 | if not (X==0 or Y==0 or qpositive(1/(X*Y)) or doPinkBikeShed): X,Y = Y,-X 37 | assert X==0 or Y==0 or qpositive(1/(X*Y)) 38 | 39 | assert (1-X^2).is_square() 40 | sx = sqrt(1-X^2) 41 | tos = -2*sx/X/Y 42 | if not qpositive(tos): sx = -sx 43 | s = (1 + sx) / X 44 | if not qpositive(s): s = -s 45 | 46 | return s 47 | 48 | def isqrt(x): 49 | ops = [(1,2),(1,2),(3,1),(6,0),(1,2),(12,1),(25,1),(25,1),(50,0),(125,0),(2,2),(1,2)] 50 | st = [x,x,x] 51 | for i,(sh,add) in enumerate(ops): 52 | od = i&1 53 | st[od] = st[od^^1]^(2^sh)*st[add] 54 | # assert st[2] == x^(2^252-3) 55 | 56 | assert st[1] == 1 or st[1] == -1 57 | if st[1] == 1: return st[0] 58 | else: return st[0] * sqrtN1 59 | 60 | def decaf_encode_from_E_c(X,Y): 61 | Z = F.random_element() 62 | T = X*Y*Z 63 | X = X*Z 64 | Y = Y*Z 65 | assert X^2 + Y^2 == Z^2 + d*T^2 66 | 67 | # Precompute 68 | sd = sqrt(F(1-d)) 69 | 70 | # comments in case of identity point 71 | # (1,0) or (0,1) 72 | zx = Z^2-X^2 # 0^2 or 1 * Z^2 73 | TZ = T*Z # 0 * Z^2 74 | assert zx.is_square 75 | ooAll = isqrt(zx*TZ^2) # inf^2 or inf * 1/Z^3 76 | osx = ooAll * TZ # inf or 1 * 1/Z 77 | ooTZ = ooAll * zx * osx # inf * 1/Z^2 78 | 79 | floop = qpositive(Z^2 * ooTZ) or doPinkBikeShed # 0 80 | if floop: 81 | frob = zx * ooTZ # 0 or inf 82 | # Y = 0 or 1 83 | else: 84 | frob = sd # sd 85 | Y = -X # -1 or 0 * Z 86 | 87 | osx *= frob # 1 or inf * 1/Z || inf sd or sd * 1/Z 88 | # y * osx = 0 or inf or -inf sd or 0 sd 89 | # y * ootz * z = 1 or inf or inf sd or 0^2 sd 90 | # s = 0 or 1 or inf sd or 91 | 92 | if qpositive(-2*osx*Z) != floop: osx = -osx 93 | s = Y*(ooTZ*Z + osx) # 94 | if not qpositive(s): s = -s 95 | 96 | return s 97 | 98 | def is_rotation((X,Y),(x,y)): 99 | return x*Y == X*y or x*X == -y*Y 100 | 101 | def decaf_decode_to_E(s): 102 | assert qpositive(s) 103 | t = sqrt(s^4 + (2-4*d)*s^2 + 1) 104 | if not qpositive(t/s): t = -t 105 | X,Y = 2*s / (1+s^2), (1-s^2) / t 106 | assert X==0 or Y==0 or qpositive(1/(X*Y)) or doPinkBikeShed 107 | return X,Y 108 | 109 | def decaf_decode_to_E_c(s): 110 | assert qpositive(s) 111 | 112 | s2 = s^2 113 | s21 = 1+s2 114 | t2 = s21^2 - 4*d*s2 115 | 116 | alt = s21*s 117 | the = isqrt(t2*alt^2) 118 | oot = the * alt 119 | the *= t2 120 | tos = the * s21 121 | X = 2 * (tos-the) * oot 122 | Y = (1-s2) * oot 123 | 124 | if not qpositive(tos): Y = -Y 125 | assert qpositive(X*Y) or doPinkBikeShed 126 | 127 | return X,Y 128 | 129 | def test(): 130 | P = 2*M.random_point() 131 | X,Y = M_to_E(P) 132 | s = decaf_encode_from_E(X,Y) 133 | assert s == decaf_encode_from_E_c(X,Y) 134 | XX,YY = decaf_decode_to_E(s) 135 | XX2,YY2 = decaf_decode_to_E_c(s) 136 | assert is_rotation((X,Y),(XX,YY)) 137 | assert is_rotation((X,Y),(XX2,YY2)) 138 | 139 | 140 | -------------------------------------------------------------------------------- /src/per_curve/decaf_gen_tables.tmpl.c: -------------------------------------------------------------------------------- 1 | /** @brief Decaf global constant table precomputation. */ 2 | 3 | #define _XOPEN_SOURCE 600 /* for posix_memalign */ 4 | #include 5 | #include 6 | 7 | #include "field.h" 8 | #include "f_field.h" 9 | #include "decaf.h" 10 | 11 | #define API_NS(_id) $(c_ns)_##_id 12 | static const unsigned char base_point_ser_for_pregen[SER_BYTES] = { 13 | $(ser(rist_base_decoded,8)) 14 | }; 15 | 16 | /* To satisfy linker. */ 17 | const gf API_NS(precomputed_base_as_fe)[1]; 18 | const API_NS(point_t) API_NS(point_base); 19 | 20 | struct niels_s; 21 | const gf_s *API_NS(precomputed_wnaf_as_fe); 22 | extern const size_t API_NS(sizeof_precomputed_wnafs); 23 | 24 | void API_NS(precompute_wnafs) ( 25 | struct niels_s *out, 26 | const API_NS(point_t) base 27 | ); 28 | static void field_print(const gf f) { 29 | unsigned char ser[X_SER_BYTES]; 30 | gf_serialize(ser,f,1); 31 | int b=0, i, comma=0; 32 | unsigned long long limb = 0; 33 | printf("{FIELD_LITERAL("); 34 | for (i=0; i= GF_LIT_LIMB_BITS || i == SER_BYTES-1) { 38 | limb &= (1ull<>(8-b); 44 | } 45 | } 46 | printf(")}"); 47 | assert(b<8); 48 | } 49 | 50 | int main(int argc, char **argv) { 51 | (void)argc; (void)argv; 52 | 53 | API_NS(point_t) real_point_base; 54 | int ret = API_NS(point_decode)(real_point_base,base_point_ser_for_pregen,0); 55 | if (ret != DECAF_SUCCESS) { 56 | fprintf(stderr, "Can't decode base point!\n"); 57 | return 1; 58 | } 59 | 60 | API_NS(precomputed_s) *pre; 61 | ret = posix_memalign((void**)&pre, API_NS(alignof_precomputed_s), API_NS(sizeof_precomputed_s)); 62 | if (ret || !pre) { 63 | fprintf(stderr, "Can't allocate space for precomputed table\n"); 64 | return 1; 65 | } 66 | API_NS(precompute)(pre, real_point_base); 67 | 68 | struct niels_s *pre_wnaf; 69 | ret = posix_memalign((void**)&pre_wnaf, API_NS(alignof_precomputed_s), API_NS(sizeof_precomputed_wnafs)); 70 | if (ret || !pre_wnaf) { 71 | fprintf(stderr, "Can't allocate space for precomputed WNAF table\n"); 72 | return 1; 73 | } 74 | API_NS(precompute_wnafs)(pre_wnaf, real_point_base); 75 | 76 | const gf_s *output; 77 | unsigned i; 78 | 79 | printf("/** @warning: this file was automatically generated. */\n"); 80 | printf("#include \"field.h\"\n\n"); 81 | printf("#include \n\n"); 82 | printf("#define API_NS(_id) $(c_ns)_##_id\n"); 83 | 84 | output = (const gf_s *)real_point_base; 85 | printf("const API_NS(point_t) API_NS(point_base) = {{\n"); 86 | for (i=0; i < sizeof(API_NS(point_t)); i+=sizeof(gf)) { 87 | if (i) printf(",\n "); 88 | field_print(output++); 89 | } 90 | printf("\n}};\n"); 91 | 92 | output = (const gf_s *)pre; 93 | printf("const gf API_NS(precomputed_base_as_fe)[%d]\n", 94 | (int)(API_NS(sizeof_precomputed_s) / sizeof(gf))); 95 | #ifndef TARGET_MINGW 96 | printf("VECTOR_ALIGNED __attribute__((visibility(\"hidden\"))) = {\n "); 97 | #else 98 | printf("VECTOR_ALIGNED = {\n "); 99 | #endif 100 | 101 | for (i=0; i < API_NS(sizeof_precomputed_s); i+=sizeof(gf)) { 102 | if (i) printf(",\n "); 103 | field_print(output++); 104 | } 105 | printf("\n};\n"); 106 | 107 | output = (const gf_s *)pre_wnaf; 108 | printf("const gf API_NS(precomputed_wnaf_as_fe)[%d]\n", 109 | (int)(API_NS(sizeof_precomputed_wnafs) / sizeof(gf))); 110 | #ifndef TARGET_MINGW 111 | printf("VECTOR_ALIGNED __attribute__((visibility(\"hidden\"))) = {\n "); 112 | #else 113 | printf("VECTOR_ALIGNED = {\n "); 114 | #endif 115 | for (i=0; i < API_NS(sizeof_precomputed_wnafs); i+=sizeof(gf)) { 116 | if (i) printf(",\n "); 117 | field_print(output++); 118 | } 119 | printf("\n};\n"); 120 | 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | 8 | cmake_minimum_required(VERSION 3.0) 9 | project(DECAF VERSION 1.0 LANGUAGES C CXX) 10 | 11 | set(DECAF_SO_VERSION "0") 12 | 13 | find_package( PythonInterp 2.7 REQUIRED ) 14 | 15 | option(ENABLE_SHARED "Build shared library." ON) 16 | option(ENABLE_STATIC "Build static library." ON) 17 | option(ENABLE_STRICT "Build with strict compile options." YES) 18 | option(ENABLE_TESTS "Enable compilation of tests." YES) 19 | option(GENERATED_SOURCE_PATH "Where the generated source code is stored, default in the building tree" OFF) 20 | 21 | if (GENERATED_SOURCE_PATH) 22 | set(GSOURCE_PATH ${GENERATED_SOURCE_PATH}) 23 | else() 24 | set(GSOURCE_PATH ${PROJECT_BINARY_DIR}/src/GENERATED) 25 | endif() 26 | message("Generated source code in ${GSOURCE_PATH}") 27 | 28 | if(NOT CPACK_GENERATOR AND NOT CMAKE_INSTALL_RPATH AND CMAKE_INSTALL_PREFIX) 29 | set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}) 30 | message(STATUS "Setting install rpath to ${CMAKE_INSTALL_RPATH}") 31 | endif() 32 | 33 | include(GNUInstallDirs) 34 | include(CheckSymbolExists) 35 | include(CMakePushCheckState) 36 | 37 | include_directories( 38 | ${GSOURCE_PATH}/include/ 39 | src/include/ 40 | src/ 41 | ${CMAKE_CURRENT_BINARY_DIR} 42 | ) 43 | 44 | set(STRICT_OPTIONS_CPP ) 45 | set(STRICT_OPTIONS_C ) 46 | set(STRICT_OPTIONS_CXX ) 47 | if(MSVC) 48 | if(ENABLE_STRICT) 49 | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} /WX") 50 | endif() 51 | else() 52 | set(STRICT_OPTIONS_CXX "${STRICT_OPTIONS_CXX} -std=c++11 -O2 ") 53 | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wall -Wuninitialized -Wno-deprecated-declarations -Wno-missing-field-initializers ") 54 | set(STRICT_OPTIONS_C "${STRICT_OPTIONS_C} -std=c99 -O2 -Wstrict-prototypes -Wno-error=strict-prototypes -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer ") 55 | if(CMAKE_C_COMPILER_ID STREQUAL "Clang") 56 | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Qunused-arguments -Wno-array-bounds ") 57 | endif() 58 | if(APPLE) 59 | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare -Wno-unused-function -Wno-array-bounds ") 60 | set(STRICT_OPTIONS_CXX "${STRICT_OPTIONS_CXX} -stdlib=libc++ ") 61 | endif() 62 | if(ENABLE_STRICT) 63 | set(STRICT_OPTIONS_CPP "${STRICT_OPTIONS_CPP} -Werror -Wextra -Wno-unused-parameter -fno-strict-aliasing ") 64 | endif() 65 | endif() 66 | 67 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${STRICT_OPTIONS_C}") 68 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STRICT_OPTIONS_CXX}") 69 | 70 | add_subdirectory(src) 71 | 72 | if(ENABLE_TESTS) 73 | enable_testing() 74 | add_subdirectory(test) 75 | endif() 76 | 77 | include(CMakePackageConfigHelpers) 78 | export(EXPORT ${EXPORT_TARGETS_NAME}Targets 79 | FILE "${CMAKE_CURRENT_BINARY_DIR}/DecafTargets.cmake" 80 | ) 81 | configure_file(cmake/DecafConfig.cmake.in 82 | "${CMAKE_CURRENT_BINARY_DIR}/DecafConfig.cmake" 83 | @ONLY 84 | ) 85 | set(ConfigPackageLocation share/decaf/cmake) 86 | install(EXPORT ${EXPORT_TARGETS_NAME}Targets 87 | FILE DecafTargets.cmake 88 | DESTINATION ${ConfigPackageLocation} 89 | ) 90 | install(FILES 91 | "${CMAKE_CURRENT_BINARY_DIR}/DecafConfig.cmake" 92 | DESTINATION ${ConfigPackageLocation} 93 | ) 94 | 95 | # Doxygen 96 | find_package(Doxygen) 97 | if (DOXYGEN_FOUND) 98 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) 99 | add_custom_target(doc 100 | ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 101 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 102 | DEPENDS generatedCode 103 | COMMENT "Generating API documentation with Doxygen" VERBATIM 104 | ) 105 | endif() 106 | 107 | # CPack settings 108 | set(CPACK_PACKAGE_NAME "decaf") 109 | set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) 110 | set(CPACK_SOURCE_GENERATOR "TGZ") 111 | set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") 112 | set(CPACK_SOURCE_IGNORE_FILES 113 | "^${CMAKE_BINARY_DIR}" 114 | "/\\\\..+" 115 | ) 116 | 117 | include(CPack) 118 | -------------------------------------------------------------------------------- /src/per_field/f_generic.tmpl.c: -------------------------------------------------------------------------------- 1 | /** @brief Generic arithmetic which has to be compiled per field. */ 2 | 3 | #include "field.h" 4 | 5 | static const gf MODULUS = {FIELD_LITERAL( 6 | $(ser(modulus,gf_lit_limb_bits)) 7 | )}; 8 | 9 | #if P_MOD_8 == 5 10 | const gf SQRT_MINUS_ONE = {FIELD_LITERAL( 11 | $(ser(msqrt(-1,modulus),gf_lit_limb_bits) if modulus % 4 == 1 else "/* NOPE */") 12 | )}; 13 | #endif 14 | 15 | /** Serialize to wire format. */ 16 | void gf_serialize (uint8_t serial[SER_BYTES], const gf x, int with_hibit) { 17 | gf red; 18 | gf_copy(red, x); 19 | gf_strong_reduce(red); 20 | if (!with_hibit) { assert(gf_hibit(red) == 0); } 21 | 22 | unsigned int j=0, fill=0; 23 | dword_t buffer = 0; 24 | UNROLL for (unsigned int i=0; i<(with_hibit ? X_SER_BYTES : SER_BYTES); i++) { 25 | if (fill < 8 && j < NLIMBS) { 26 | buffer |= ((dword_t)red->limb[LIMBPERM(j)]) << fill; 27 | fill += LIMB_PLACE_VALUE(LIMBPERM(j)); 28 | j++; 29 | } 30 | serial[i] = buffer; 31 | fill -= 8; 32 | buffer >>= 8; 33 | } 34 | } 35 | 36 | /** Return high bit of x = low bit of 2x mod p */ 37 | mask_t gf_hibit(const gf x) { 38 | gf y; 39 | gf_add(y,x,x); 40 | gf_strong_reduce(y); 41 | return -(y->limb[0]&1); 42 | } 43 | 44 | /** Return high bit of x = low bit of 2x mod p */ 45 | mask_t gf_lobit(const gf x) { 46 | gf y; 47 | gf_copy(y,x); 48 | gf_strong_reduce(y); 49 | return -(y->limb[0]&1); 50 | } 51 | 52 | /** Deserialize from wire format; return -1 on success and 0 on failure. */ 53 | mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask) { 54 | unsigned int j=0, fill=0; 55 | dword_t buffer = 0; 56 | dsword_t scarry = 0; 57 | const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES; 58 | UNROLL for (unsigned int i=0; ilimb[LIMBPERM(i)] = (i>= LIMB_PLACE_VALUE(LIMBPERM(i)); 69 | scarry = (scarry + x->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]) >> (8*sizeof(word_t)); 70 | } 71 | mask_t succ = with_hibit ? -(mask_t)1 : ~gf_hibit(x); 72 | return succ & word_is_zero(buffer) & ~word_is_zero(scarry); 73 | } 74 | 75 | /** Reduce to canonical form. */ 76 | void gf_strong_reduce (gf a) { 77 | /* first, clear high */ 78 | gf_weak_reduce(a); /* Determined to have negligible perf impact. */ 79 | 80 | /* now the total is less than 2p */ 81 | 82 | /* compute total_value - p. No need to reduce mod p. */ 83 | dsword_t scarry = 0; 84 | for (unsigned int i=0; ilimb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]; 86 | a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i)); 87 | scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i)); 88 | } 89 | 90 | /* uncommon case: it was >= p, so now scarry = 0 and this = x 91 | * common case: it was < p, so now scarry = -1 and this = x - p + 2^255 92 | * so let's add back in p. will carry back off the top for 2^255. 93 | */ 94 | assert(word_is_zero(scarry) | word_is_zero(scarry+1)); 95 | 96 | word_t scarry_0 = scarry; 97 | dword_t carry = 0; 98 | 99 | /* add it back */ 100 | for (unsigned int i=0; ilimb[LIMBPERM(i)] + (scarry_0 & MODULUS->limb[LIMBPERM(i)]); 102 | a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i)); 103 | carry >>= LIMB_PLACE_VALUE(LIMBPERM(i)); 104 | } 105 | 106 | assert(word_is_zero(carry + scarry_0)); 107 | } 108 | 109 | /** Subtract two gf elements d=a-b */ 110 | void gf_sub (gf d, const gf a, const gf b) { 111 | gf_sub_RAW ( d, a, b ); 112 | gf_bias( d, 2 ); 113 | gf_weak_reduce ( d ); 114 | } 115 | 116 | /** Add two field elements d = a+b */ 117 | void gf_add (gf d, const gf a, const gf b) { 118 | gf_add_RAW ( d, a, b ); 119 | gf_weak_reduce ( d ); 120 | } 121 | 122 | /** Compare a==b */ 123 | mask_t gf_eq(const gf a, const gf b) { 124 | gf c; 125 | gf_sub(c,a,b); 126 | gf_strong_reduce(c); 127 | mask_t ret=0; 128 | for (unsigned int i=0; ilimb[LIMBPERM(i)]; 130 | } 131 | 132 | return word_is_zero(ret); 133 | } 134 | -------------------------------------------------------------------------------- /test/test_ct.cxx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_decaf.cxx 3 | * @author Mike Hamburg 4 | * 5 | * @copyright 6 | * Copyright (c) 2015 Cryptography Research, Inc. \n 7 | * Released under the MIT License. See LICENSE.txt for license information. 8 | * 9 | * @brief C++ tests, because that's easier. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace decaf; 20 | using namespace decaf::TOY; 21 | 22 | static const long NTESTS = 10; 23 | 24 | const char *undef_str = "Valgrind thinks this string is undefined."; 25 | const Block undef_block(undef_str); 26 | 27 | static inline void ignore_result(decaf_error_t x) { 28 | (void)x; 29 | } 30 | 31 | template struct Tests { 32 | 33 | typedef typename Group::Scalar Scalar; 34 | typedef typename Group::Point Point; 35 | typedef typename Group::Precomputed Precomputed; 36 | 37 | static void test_arithmetic() { 38 | SpongeRng rng(Block("test_arithmetic"),SpongeRng::DETERMINISTIC); 39 | rng.stir(undef_block); 40 | 41 | Scalar x(rng),y(rng),z; 42 | uint8_t ser[Group::Scalar::SER_BYTES]; 43 | 44 | for (int i=0; i inv; 61 | 62 | for (int i=0; i(ser))); 81 | (void)(p*y); 82 | (void)(p+q); 83 | (void)(p-q); 84 | (void)(-p); 85 | (void)(p.times_two()); 86 | (void)(p==q); 87 | (void)(p.debugging_torque()); 88 | /* (void)(p.non_secret_combo_with_base(y,z)); */ /* Should fail */ 89 | (void)(Precomputed(p)*y); 90 | p.dual_scalarmul(q,r,y,z); 91 | Group::Point::double_scalarmul(p,y,q,z); 92 | 93 | } 94 | } 95 | 96 | static void test_cfrg() { 97 | SpongeRng rng(Block("test_cfrg"),SpongeRng::DETERMINISTIC); 98 | rng.stir(undef_block); 99 | 100 | for (int i=0; i pub(rng); 102 | FixedArrayBuffer priv(rng); 103 | 104 | Group::DhLadder::derive_public_key(priv); 105 | ignore_result(Group::DhLadder::shared_secret_noexcept(pub,pub,priv)); 106 | } 107 | } 108 | 109 | /* Specify the same value as you did when compiling decaf_crypto.c */ 110 | #ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT 111 | #define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE 112 | #endif 113 | 114 | static void test_crypto() { 115 | SpongeRng rng(Block("test_crypto"),SpongeRng::DETERMINISTIC); 116 | rng.stir(undef_block); 117 | 118 | #if DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT 119 | SpongeRng defrng(Block("test_crypto_defined")); 120 | #endif 121 | 122 | FixedArrayBuffer shared; 123 | 124 | for (int i=0; i sk1(rng); 126 | SecureBuffer sig = sk1.sign(undef_block); 127 | 128 | #if DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT 129 | PrivateKey sk2(defrng); 130 | ignore_result(sk1.shared_secret_noexcept(shared,sk2.pub(),i&1)); 131 | #else 132 | PrivateKey sk3(rng); 133 | ignore_result(sk1.shared_secret_noexcept(shared,sk3.pub(),i&1)); 134 | #endif 135 | } 136 | } 137 | 138 | static void run() { 139 | printf("Testing %s:\n",Group::name()); 140 | test_arithmetic(); 141 | test_elligator(); 142 | test_ec(); 143 | test_cfrg(); 144 | test_crypto(); 145 | printf("\n"); 146 | } 147 | 148 | }; /* template struct Tests */ 149 | 150 | int main(int argc, char **argv) { 151 | (void) argc; (void) argv; 152 | VALGRIND_MAKE_MEM_UNDEFINED(undef_str, strlen(undef_str)); 153 | run_for_all_curves(); 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /src/p25519/arch_x86_64/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | /** Requires: input limbs < 9*2^51 */ 8 | void gf_mul (gf_s *__restrict__ cs, const gf as, const gf bs) { 9 | const uint64_t *a = as->limb, *b = bs->limb, mask = ((1ull<<51)-1); 10 | uint64_t *c = cs->limb; 11 | 12 | __uint128_t accum0, accum1, accum2; 13 | 14 | uint64_t ai = a[0]; 15 | accum0 = widemul_rm(ai, &b[0]); 16 | accum1 = widemul_rm(ai, &b[1]); 17 | accum2 = widemul_rm(ai, &b[2]); 18 | 19 | ai = a[1]; 20 | mac_rm(&accum2, ai, &b[1]); 21 | mac_rm(&accum1, ai, &b[0]); 22 | ai *= 19; 23 | mac_rm(&accum0, ai, &b[4]); 24 | 25 | ai = a[2]; 26 | mac_rm(&accum2, ai, &b[0]); 27 | ai *= 19; 28 | mac_rm(&accum0, ai, &b[3]); 29 | mac_rm(&accum1, ai, &b[4]); 30 | 31 | ai = a[3] * 19; 32 | mac_rm(&accum0, ai, &b[2]); 33 | mac_rm(&accum1, ai, &b[3]); 34 | mac_rm(&accum2, ai, &b[4]); 35 | 36 | ai = a[4] * 19; 37 | mac_rm(&accum0, ai, &b[1]); 38 | mac_rm(&accum1, ai, &b[2]); 39 | mac_rm(&accum2, ai, &b[3]); 40 | 41 | uint64_t c0 = accum0 & mask; 42 | accum1 += shrld(accum0, 51); 43 | uint64_t c1 = accum1 & mask; 44 | accum2 += shrld(accum1, 51); 45 | c[2] = accum2 & mask; 46 | 47 | accum0 = shrld(accum2, 51); 48 | 49 | mac_rm(&accum0, ai, &b[4]); 50 | 51 | ai = a[0]; 52 | mac_rm(&accum0, ai, &b[3]); 53 | accum1 = widemul_rm(ai, &b[4]); 54 | 55 | ai = a[1]; 56 | mac_rm(&accum0, ai, &b[2]); 57 | mac_rm(&accum1, ai, &b[3]); 58 | 59 | ai = a[2]; 60 | mac_rm(&accum0, ai, &b[1]); 61 | mac_rm(&accum1, ai, &b[2]); 62 | 63 | ai = a[3]; 64 | mac_rm(&accum0, ai, &b[0]); 65 | mac_rm(&accum1, ai, &b[1]); 66 | 67 | ai = a[4]; 68 | mac_rm(&accum1, ai, &b[0]); 69 | /* Here accum1 < 5*(9*2^51)^2 */ 70 | 71 | c[3] = accum0 & mask; 72 | accum1 += shrld(accum0, 51); 73 | c[4] = accum1 & mask; 74 | 75 | uint64_t a1 = shrld(accum1,51); 76 | /* Here a1 < (5*(9*2^51)^2 + small) >> 51 = 405 * 2^51 + small 77 | * a1 * 19 + c0 < (405*19+1)*2^51 + small < 2^13 * 2^51. 78 | */ 79 | accum1 = a1 * 19 + c0; 80 | c[0] = accum1 & mask; 81 | c[1] = c1 + (accum1>>51); 82 | } 83 | 84 | void gf_sqr (gf_s *__restrict__ cs, const gf as) { 85 | const uint64_t *a = as->limb, mask = ((1ull<<51)-1); 86 | uint64_t *c = cs->limb; 87 | 88 | __uint128_t accum0, accum1, accum2; 89 | 90 | uint64_t ai = a[0]; 91 | accum0 = widemul_rr(ai, ai); 92 | ai *= 2; 93 | accum1 = widemul_rm(ai, &a[1]); 94 | accum2 = widemul_rm(ai, &a[2]); 95 | 96 | ai = a[1]; 97 | mac_rr(&accum2, ai, ai); 98 | ai *= 38; 99 | mac_rm(&accum0, ai, &a[4]); 100 | 101 | ai = a[2] * 38; 102 | mac_rm(&accum0, ai, &a[3]); 103 | mac_rm(&accum1, ai, &a[4]); 104 | 105 | ai = a[3] * 19; 106 | mac_rm(&accum1, ai, &a[3]); 107 | ai *= 2; 108 | mac_rm(&accum2, ai, &a[4]); 109 | 110 | uint64_t c0 = accum0 & mask; 111 | accum1 += shrld(accum0, 51); 112 | uint64_t c1 = accum1 & mask; 113 | accum2 += shrld(accum1, 51); 114 | c[2] = accum2 & mask; 115 | 116 | accum0 = accum2 >> 51; 117 | 118 | ai = a[0]*2; 119 | mac_rm(&accum0, ai, &a[3]); 120 | accum1 = widemul_rm(ai, &a[4]); 121 | 122 | ai = a[1]*2; 123 | mac_rm(&accum0, ai, &a[2]); 124 | mac_rm(&accum1, ai, &a[3]); 125 | 126 | mac_rr(&accum0, a[4]*19, a[4]); 127 | mac_rr(&accum1, a[2], a[2]); 128 | 129 | c[3] = accum0 & mask; 130 | accum1 += shrld(accum0, 51); 131 | c[4] = accum1 & mask; 132 | 133 | /* 2^102 * 16 * 5 * 19 * (1+ep) >> 64 134 | * = 2^(-13 + <13) 135 | */ 136 | 137 | uint64_t a1 = shrld(accum1,51); 138 | accum1 = a1 * 19 + c0; 139 | c[0] = accum1 & mask; 140 | c[1] = c1 + (accum1>>51); 141 | } 142 | 143 | void gf_mulw_unsigned (gf_s *__restrict__ cs, const gf as, uint32_t b) { 144 | const uint64_t *a = as->limb, mask = ((1ull<<51)-1); 145 | uint64_t *c = cs->limb; 146 | 147 | __uint128_t accum = widemul_rm(b, &a[0]); 148 | uint64_t c0 = accum & mask; 149 | accum = shrld(accum,51); 150 | 151 | mac_rm(&accum, b, &a[1]); 152 | uint64_t c1 = accum & mask; 153 | accum = shrld(accum,51); 154 | 155 | mac_rm(&accum, b, &a[2]); 156 | c[2] = accum & mask; 157 | accum = shrld(accum,51); 158 | 159 | mac_rm(&accum, b, &a[3]); 160 | c[3] = accum & mask; 161 | accum = shrld(accum,51); 162 | 163 | mac_rm(&accum, b, &a[4]); 164 | c[4] = accum & mask; 165 | 166 | uint64_t a1 = shrld(accum,51); 167 | a1 = a1*19+c0; 168 | 169 | c[0] = a1 & mask; 170 | c[1] = c1 + (a1>>51); 171 | } 172 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | 8 | set(DECAF_HEADER_FILES 9 | include/constant_time.h 10 | include/field.h 11 | include/keccak_internal.h 12 | include/portable_endian.h 13 | include/word.h 14 | ) 15 | set(DECAF_SOURCE_FILES_C 16 | utils.c 17 | shake.c 18 | sha512.c 19 | spongerng.c 20 | 21 | ) 22 | 23 | # default target arch is arch_32 which shall be generic enough to compile mostly on anything 24 | # target arch dirs: 25 | # global one to get the include/arch_intrinsics.h 26 | # availables: arch_32, arch_arm_32, arch_neon, arch_ref64, arch_x86_64 27 | set(TARGET_ARCH_DIR arch_32) 28 | # specific to p25519, to get f_impl.c/h in p25519 29 | #availables: arch_32, arch_ref64, arch_x86_64 30 | set(TARGET_ARCH_DIR_P25519 arch_32) 31 | # specific to p448, to get f_impl.c/h in p448 32 | # availables: arch_32, arch_arm_32, arch_neon, arch_ref64, arch_x86_64 33 | set(TARGET_ARCH_DIR_P448 arch_32) 34 | 35 | if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") # x86_64 36 | message("Target architecture is x86_64") 37 | set(TARGET_ARCH_DIR arch_x86_64) 38 | set(TARGET_ARCH_DIR_P25519 arch_x86_64) 39 | set(TARGET_ARCH_DIR_P448 arch_x86_64) 40 | elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arch64") # shall be arm64 bits, stick to ref64 41 | message("Target architecture is 64 bits general purpose(arm64 shall use this)") 42 | set(TARGET_ARCH_DIR arch_ref64) 43 | set(TARGET_ARCH_DIR_P25519 arch_ref64) 44 | set(TARGET_ARCH_DIR_P448 arch_ref64) 45 | elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") # is an arm 32 bits 46 | if (NOT ${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi") # arm <= 5.0 does not support instructions from the lib, keep arch_32 47 | if(${ANDROID_ARM_NEON}) 48 | message("Target architecture is arm32 NEON") 49 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon") # build with neon flag 50 | set(TARGET_ARCH_DIR arch_neon) 51 | set(TARGET_ARCH_DIR_P25519 arch_32) # nothing specific for neon on p25519 52 | set(TARGET_ARCH_DIR_P448 arch_neon) 53 | else(${ANDROID_ARM_NEON}) 54 | message("Target architecture is arm32 no NEON") 55 | set(TARGET_ARCH_DIR arch_arm_32) 56 | set(TARGET_ARCH_DIR_P25519 arch_32) # nothing specific for arch_arm on p25519 57 | set(TARGET_ARCH_DIR_P448 arch_arm_32) 58 | endif(${ANDROID_ARM_NEON}) 59 | endif (NOT ${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi") 60 | else() # nothing picked yet, stick to the 61 | message("Target architecture is general purpose 32bits") 62 | endif() 63 | 64 | include_directories( 65 | ${PROJECT_SOURCE_DIR}/src/include/${TARGET_ARCH_DIR} 66 | ) 67 | 68 | set(DECAF_SOURCE_FILES_CXX 69 | ) 70 | 71 | add_subdirectory(curve25519) 72 | add_subdirectory(ed448goldilocks) 73 | add_subdirectory(p25519) 74 | add_subdirectory(p448) 75 | 76 | add_subdirectory(generator) 77 | 78 | if(ENABLE_STATIC) 79 | add_library(decaf-static STATIC ${DECAF_HEADER_FILES} ${DECAF_SOURCE_FILES_C} ${DECAF_SOURCE_FILES_CXX} $ $ $ $) 80 | add_dependencies(decaf-static generatedCode) 81 | set_target_properties(decaf-static PROPERTIES OUTPUT_NAME decaf) 82 | target_include_directories(decaf-static PUBLIC) 83 | target_link_libraries(decaf-static INTERFACE) 84 | endif() 85 | if(ENABLE_SHARED) 86 | add_library(decaf SHARED ${DECAF_HEADER_FILES} ${DECAF_SOURCE_FILES_C} ${DECAF_SOURCE_FILES_CXX} $ $ $ $) 87 | add_dependencies(decaf generatedCode) 88 | if(APPLE) 89 | set_target_properties(decaf PROPERTIES LINK_FLAGS "-stdlib=libc++") 90 | endif() 91 | set_target_properties(decaf PROPERTIES VERSION ${DECAF_SO_VERSION}) 92 | target_include_directories(decaf PUBLIC) 93 | target_link_libraries(decaf PRIVATE) 94 | if(MSVC) 95 | if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") 96 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/decaf.pdb 97 | DESTINATION ${CMAKE_INSTALL_BINDIR} 98 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 99 | ) 100 | endif() 101 | endif() 102 | endif() 103 | 104 | if(ENABLE_STATIC) 105 | install(TARGETS decaf-static EXPORT ${EXPORT_TARGETS_NAME}Targets 106 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 107 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 108 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 109 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 110 | ) 111 | endif() 112 | if(ENABLE_SHARED) 113 | install(TARGETS decaf EXPORT ${EXPORT_TARGETS_NAME}Targets 114 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 115 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 116 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 117 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE 118 | ) 119 | endif() 120 | 121 | install(DIRECTORY ${GSOURCE_PATH}/include/ 122 | DESTINATION include/decaf 123 | FILES_MATCHING PATTERN "*.h*" 124 | PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ 125 | ) 126 | -------------------------------------------------------------------------------- /src/public_include/decaf/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file decaf/common.h 3 | * @author Mike Hamburg 4 | * 5 | * @copyright 6 | * Copyright (c) 2015 Cryptography Research, Inc. \n 7 | * Released under the MIT License. See LICENSE.txt for license information. 8 | * 9 | * @brief Common utility headers for Decaf library. 10 | */ 11 | 12 | #ifndef __DECAF_COMMON_H__ 13 | #define __DECAF_COMMON_H__ 1 14 | 15 | #include 16 | #if defined (__GNUC__) // File only exists for GNU compilers 17 | #include 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /* Goldilocks' build flags default to hidden and stripping executables. */ 25 | /** @cond internal */ 26 | #if DOXYGEN || defined(__attribute__) 27 | #define __attribute__(x) 28 | #define NOINLINE 29 | #endif 30 | 31 | /* Aliasing MSVC preprocessing to GNU preprocessing */ 32 | #if defined _MSC_VER 33 | # define __attribute__(x) // Turn off attribute code 34 | # define __attribute(x) 35 | # define __restrict__ __restrict // Use MSVC restrict code 36 | # if defined _DLL 37 | # define DECAF_API_VIS __declspec(dllexport) // MSVC for visibility 38 | # else 39 | # define DECAF_API_VIS __declspec(dllimport) 40 | # endif 41 | 42 | //# define DECAF_NOINLINE __declspec(noinline) // MSVC for noinline 43 | //# define DECAF_INLINE __forceinline // MSVC for always inline 44 | //# define DECAF_WARN_UNUSED _Check_return_ 45 | #else // MSVC 46 | #define DECAF_API_VIS __attribute__((visibility("default"))) 47 | #define DECAF_API_IMPORT 48 | #endif 49 | 50 | // The following are disabled for MSVC 51 | #define DECAF_NOINLINE __attribute__((noinline)) 52 | #define DECAF_INLINE inline __attribute__((always_inline,unused)) 53 | #define DECAF_WARN_UNUSED __attribute__((warn_unused_result)) 54 | #define DECAF_NONNULL __attribute__((nonnull)) 55 | // Cribbed from libnotmuch 56 | #if defined (__clang_major__) && __clang_major__ >= 3 \ 57 | || defined (__GNUC__) && __GNUC__ >= 5 \ 58 | || defined (__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 59 | #define DECAF_DEPRECATED(msg) __attribute__ ((deprecated(msg))) 60 | #else 61 | #define DECAF_DEPRECATED(msg) __attribute__ ((deprecated)) 62 | #endif 63 | /** @endcond */ 64 | 65 | /* Internal word types. 66 | * 67 | * Somewhat tricky. This could be decided separately per platform. However, 68 | * the structs do need to be all the same size and alignment on a given 69 | * platform to support dynamic linking, since even if you header was built 70 | * with eg arch_neon, you might end up linking a library built with arch_arm32. 71 | */ 72 | #ifndef DECAF_WORD_BITS 73 | #if (defined(__ILP64__) || defined(__amd64__) || defined(__x86_64__) || (((__UINT_FAST32_MAX__)>>30)>>30)) 74 | #define DECAF_WORD_BITS 64 /**< The number of bits in a word */ 75 | #else 76 | #define DECAF_WORD_BITS 32 /**< The number of bits in a word */ 77 | #endif 78 | #endif 79 | 80 | #if DECAF_WORD_BITS == 64 81 | typedef uint64_t decaf_word_t; /**< Word size for internal computations */ 82 | typedef int64_t decaf_sword_t; /**< Signed word size for internal computations */ 83 | typedef uint64_t decaf_bool_t; /**< "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */ 84 | typedef __uint128_t decaf_dword_t; /**< Double-word size for internal computations */ 85 | typedef __int128_t decaf_dsword_t; /**< Signed double-word size for internal computations */ 86 | #elif DECAF_WORD_BITS == 32 /**< The number of bits in a word */ 87 | typedef uint32_t decaf_word_t; /**< Word size for internal computations */ 88 | typedef int32_t decaf_sword_t; /**< Signed word size for internal computations */ 89 | typedef uint32_t decaf_bool_t; /**< "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */ 90 | typedef uint64_t decaf_dword_t; /**< Double-word size for internal computations */ 91 | typedef int64_t decaf_dsword_t; /**< Signed double-word size for internal computations */ 92 | #else 93 | #error "Only supporting DECAF_WORD_BITS = 32 or 64 for now" 94 | #endif 95 | 96 | /** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */ 97 | static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1; 98 | 99 | /** DECAF_FALSE = 0 so that DECAF_FALSE & x = 0 */ 100 | static const decaf_bool_t DECAF_FALSE = 0; 101 | 102 | /** Another boolean type used to indicate success or failure. */ 103 | typedef enum { 104 | DECAF_SUCCESS = -1, /**< The operation succeeded. */ 105 | DECAF_FAILURE = 0 /**< The operation failed. */ 106 | } decaf_error_t; 107 | 108 | 109 | /** Return success if x is true */ 110 | static DECAF_INLINE decaf_error_t 111 | decaf_succeed_if(decaf_bool_t x) { 112 | return (decaf_error_t)x; 113 | } 114 | 115 | /** Return DECAF_TRUE iff x == DECAF_SUCCESS */ 116 | static DECAF_INLINE decaf_bool_t 117 | decaf_successful(decaf_error_t e) { 118 | decaf_dword_t w = ((decaf_word_t)e) ^ ((decaf_word_t)DECAF_SUCCESS); 119 | return (w-1)>>DECAF_WORD_BITS; 120 | } 121 | 122 | /** Overwrite data with zeros. Uses memset_s if available. */ 123 | void DECAF_API_VIS decaf_bzero ( 124 | void *data, 125 | size_t size 126 | ) DECAF_NONNULL; 127 | 128 | /** Compare two buffers, returning DECAF_TRUE if they are equal. */ 129 | decaf_bool_t DECAF_API_VIS decaf_memeq ( 130 | const void *data1, 131 | const void *data2, 132 | size_t size 133 | ) DECAF_NONNULL DECAF_WARN_UNUSED; 134 | 135 | #ifdef __cplusplus 136 | } /* extern "C" */ 137 | #endif 138 | 139 | #endif /* __DECAF_COMMON_H__ */ 140 | -------------------------------------------------------------------------------- /src/generator/curve_data.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from binascii import unhexlify 3 | 4 | comb_config = namedtuple("comb_config",["n","t","s"]) 5 | wnaf_config = namedtuple("wnaf_config",["fixed","var"]) 6 | 7 | field_data = { 8 | "p25519" : { 9 | "gf_desc" : "2^255 - 19", 10 | "gf_shortname" : "25519", 11 | "gf_impl_bits" : 320, 12 | "gf_lit_limb_bits" : 51, 13 | "elligator_onto" : 0 14 | }, 15 | "p448" : { 16 | "gf_desc" : "2^448 - 2^224 - 1", 17 | "gf_shortname" : "448", 18 | "gf_impl_bits" : 512, 19 | "gf_lit_limb_bits" : 56, 20 | "elligator_onto" : 0 21 | } 22 | } 23 | 24 | curve_data = { 25 | "curve25519" : { 26 | "altname" : "IsoEd25519", 27 | "iso_to" : "Curve25519", 28 | "name" : "Ristretto", 29 | "cofactor" : 8, 30 | "field" : "p25519", 31 | "scalar_bits" : 253, 32 | "d": -121665, 33 | "trace": -0xa6f7cef517bce6b2c09318d2e7ae9f7a, 34 | "mont_base": 9, 35 | "rist_base": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", 36 | "eddsa_encode_ratio": 4, 37 | "x_encode_ratio": 4, 38 | 39 | "combs":comb_config(3,5,17), 40 | "wnaf":wnaf_config(5,3), 41 | "window_bits":4, 42 | 43 | "eddsa_hash": "sha512", 44 | "eddsa_no_context": 1, 45 | "eddsa_dom": "SigEd25519 no Ed25519 collisions", 46 | "eddsa_sigma_iso": 1 47 | }, 48 | "ed448goldilocks" : { 49 | "eddsa_encode_ratio": 4, 50 | "x_encode_ratio": 2, 51 | "altname": None, 52 | "name" : "Ed448-Goldilocks", 53 | "cofactor" : 4, 54 | "field" : "p448", 55 | "scalar_bits" : 446, 56 | "d": -39081, 57 | "trace": 0x10cd77058eec492d944a725bf7a4cf635c8e9c2ab721cf5b5529eec34, 58 | "rist_base": "6666666666666666666666666666666666666666666666666666666633333333333333333333333333333333333333333333333333333333", 59 | "mont_base": 5, 60 | 61 | "combs":comb_config(5,5,18), 62 | "wnaf":wnaf_config(5,3), 63 | "window_bits":5, 64 | 65 | "eddsa_dom":"SigEd448" 66 | } 67 | } 68 | 69 | def ser(x,bits,paren=None): 70 | out = "" 71 | mask = 2**bits - 1 72 | first = True 73 | while x > 0 or first: 74 | desc = "0x%0*x" % ((bits+3)//4,x&mask) 75 | if paren is not None: 76 | desc = "%s(%s)" % (paren,desc) 77 | if not first: out += ", " 78 | out += desc 79 | x = x >> bits 80 | first = False 81 | return out 82 | 83 | def msqrt(x,p,hi_bit_clear = True, lo_bit_clear = False): 84 | if p % 4 == 3: ret = pow(x,(p+1)//4,p) 85 | elif p % 8 == 5: 86 | for u in range(1,1000): 87 | if pow(u,(p-1)//2,p) != 1: break 88 | u = pow(u,(p-1)//4,p) 89 | ret = pow(x,(p+3)//8,p) 90 | if pow(ret,2,p) != (x % p): ret = (ret * u) % p 91 | else: raise Exception("sqrt only for 3-mod-4 or 5-mod-8") 92 | 93 | if (ret**2-x) % p != 0: raise Exception("No sqrt") 94 | if hi_bit_clear and ret > p//2: ret = p-ret 95 | # lo_bit_clear overrides hi_bit_clear because it's not default 96 | if lo_bit_clear and (ret & 1): ret = p-ret 97 | return ret 98 | 99 | def ceil_log2(x): 100 | out = 0 101 | cmp = 1 102 | while x > cmp: 103 | cmp = cmp<<1 104 | out += 1 105 | return out 106 | 107 | for field,data in field_data.items(): 108 | if "modulus" not in data: 109 | data["modulus"] = eval(data["gf_desc"].replace("^","**")) 110 | 111 | if "gf_bits" not in data: 112 | data["gf_bits"] = ceil_log2(data["modulus"]) 113 | 114 | for curve,data in curve_data.items(): 115 | for key in field_data[data["field"]]: 116 | if key not in data: 117 | data[key] = field_data[data["field"]][key] 118 | 119 | 120 | if "iso_to" not in data: 121 | data["iso_to"] = data["name"] 122 | 123 | if "eddsa_hash" not in data: 124 | data["eddsa_hash"] = "shake256" 125 | 126 | if "eddsa_no_context" not in data: 127 | data["eddsa_no_context"] = 0 128 | 129 | if "cxx_ns" not in data: 130 | data["cxx_ns"] = data["name"].replace("-","") 131 | 132 | if "eddsa_sigma_iso" not in data: 133 | data["eddsa_sigma_iso"] = 0 134 | 135 | if "rist_base_decoded" not in data: 136 | def xord(x): 137 | if isinstance(x,str): return ord(x) 138 | else: return x 139 | data["rist_base_decoded"] = sum( 140 | xord(b)<<(8*i) for i,b in enumerate(unhexlify(data["rist_base"])) 141 | ) 142 | 143 | if "imagine_twist" not in data: 144 | # This is a HACK. The real problem is that iso-Ed25519 145 | # has points at infinity unless you IMAGINE_TWIST. 146 | # 147 | # Also there are lots of bugs when cofactor=8 != IMAGINE_TWIST. 148 | # (FUTURE: fix all this to support other curves, eventually) 149 | if data["modulus"]%4 == 3: data["imagine_twist"] = 0 150 | else: data["imagine_twist"] = 1 151 | # data["imagine_twist"] = 0 152 | 153 | data["q"] = (data["modulus"]+1-data["trace"]) // data["cofactor"] 154 | data["bits"] = ceil_log2(data["modulus"]) 155 | 156 | if "c_ns" not in data: 157 | data["c_ns"] = "decaf_" + str(data["bits"]) 158 | data["C_NS"] = data["c_ns"].upper() 159 | 160 | 161 | -------------------------------------------------------------------------------- /src/generator/curve25519/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | # p25519 field 8 | add_custom_command( 9 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=field --guard=p25519/f_field.h --item=p25519 -o ${GSOURCE_PATH}/c/p25519/f_field.h ${PROJECT_SOURCE_DIR}/src/per_field/f_field.tmpl.h 10 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_field/f_field.tmpl.h 11 | OUTPUT ${GSOURCE_PATH}/c/p25519/f_field.h 12 | COMMENT "Generating code for p25519/f_field.h" 13 | ) 14 | 15 | add_custom_command( 16 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=field --guard=p25519/f_generic.c --item=p25519 -o ${GSOURCE_PATH}/c/p25519/f_generic.c ${PROJECT_SOURCE_DIR}/src/per_field/f_generic.tmpl.c 17 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_field/f_generic.tmpl.c 18 | OUTPUT ${GSOURCE_PATH}/c/p25519/f_generic.c 19 | COMMENT "Generating code for p25519/f_generic.c" 20 | ) 21 | 22 | add_custom_target(generatorP25519 DEPENDS 23 | generatorCommonCode 24 | ${GSOURCE_PATH}/c/p25519/f_field.h 25 | ${GSOURCE_PATH}/c/p25519/f_generic.c 26 | ) 27 | 28 | # curve25519 29 | add_custom_command( 30 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=curve25519/scalar.c -o ${GSOURCE_PATH}/c/curve25519/scalar.c ${PROJECT_SOURCE_DIR}/src/per_curve/scalar.tmpl.c 31 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/scalar.tmpl.c 32 | OUTPUT ${GSOURCE_PATH}/c/curve25519/scalar.c 33 | COMMENT "Generating code for curve25519/scalar.c" 34 | ) 35 | 36 | add_custom_command( 37 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=curve25519/decaf.c -o ${GSOURCE_PATH}/c/curve25519/decaf.c ${PROJECT_SOURCE_DIR}/src/per_curve/decaf.tmpl.c 38 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/decaf.tmpl.c 39 | OUTPUT ${GSOURCE_PATH}/c/curve25519/decaf.c 40 | COMMENT "Generating code for curve25519/decaf.c" 41 | ) 42 | 43 | add_custom_command( 44 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=curve25519/elligator.c -o ${GSOURCE_PATH}/c/curve25519/elligator.c ${PROJECT_SOURCE_DIR}/src/per_curve/elligator.tmpl.c 45 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/elligator.tmpl.c 46 | OUTPUT ${GSOURCE_PATH}/c/curve25519/elligator.c 47 | COMMENT "Generating code for curve25519/elligator.c" 48 | ) 49 | 50 | add_custom_command( 51 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=curve25519/eddsa.c -o ${GSOURCE_PATH}/c/curve25519/eddsa.c ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.c 52 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.c 53 | OUTPUT ${GSOURCE_PATH}/c/curve25519/eddsa.c 54 | COMMENT "Generating code for curve25519/eddsa.c" 55 | ) 56 | 57 | add_custom_command( 58 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=curve25519/decaf_gen_tables.c -o ${GSOURCE_PATH}/c/curve25519/decaf_gen_tables.c ${PROJECT_SOURCE_DIR}/src/per_curve/decaf_gen_tables.tmpl.c 59 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/decaf_gen_tables.tmpl.c 60 | OUTPUT ${GSOURCE_PATH}/c/curve25519/decaf_gen_tables.c 61 | COMMENT "Generating code for curve25519/decaf_gen_tables.c" 62 | ) 63 | 64 | add_custom_command( 65 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=decaf/point_255.hxx -o ${GSOURCE_PATH}/include/decaf/point_255.hxx ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.hxx 66 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.hxx 67 | OUTPUT ${GSOURCE_PATH}/include/decaf/point_255.hxx 68 | COMMENT "Generating code for include/decaf/point_255.hxx" 69 | ) 70 | 71 | add_custom_command( 72 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=decaf/ed255.hxx -o ${GSOURCE_PATH}/include/decaf/ed255.hxx ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.hxx 73 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.hxx 74 | OUTPUT ${GSOURCE_PATH}/include/decaf/ed255.hxx 75 | COMMENT "Generating code for include/decaf/ed255.hxx" 76 | ) 77 | 78 | add_custom_target(generatorCurve25519 DEPENDS 79 | generatorP25519 80 | ${GSOURCE_PATH}/c/curve25519/scalar.c 81 | ${GSOURCE_PATH}/c/curve25519/decaf.c 82 | ${GSOURCE_PATH}/c/curve25519/elligator.c 83 | ${GSOURCE_PATH}/c/curve25519/eddsa.c 84 | ${GSOURCE_PATH}/include/decaf/point_255.hxx 85 | ${GSOURCE_PATH}/include/decaf/ed255.hxx 86 | ) 87 | include_directories( 88 | ${PROJECT_SOURCE_DIR}/src/p25519 89 | ${GSOURCE_PATH}/c/p25519 90 | ${PROJECT_SOURCE_DIR}/src/p25519/${TARGET_ARCH_DIR_P25519} 91 | ) 92 | 93 | add_executable(decaf_gen_tables_curve25519 EXCLUDE_FROM_ALL ${GSOURCE_PATH}/c/curve25519/decaf_gen_tables.c 94 | ${GSOURCE_PATH}/c/curve25519/decaf.c 95 | ${GSOURCE_PATH}/c/curve25519/scalar.c 96 | ${PROJECT_SOURCE_DIR}/src/utils.c 97 | $) 98 | 99 | add_custom_target(decaf_tables_curve25519 100 | COMMAND decaf_gen_tables_curve25519 > ${PROJECT_SOURCE_DIR}/src/curve25519/decaf_tables.c 101 | DEPENDS decaf_gen_tables_curve25519 102 | COMMENT "Generating code for curve25519/decaf_tables.c" 103 | ) 104 | -------------------------------------------------------------------------------- /src/generator/ed448goldilocks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | # p448 field 8 | add_custom_command( 9 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=field --guard=p448/f_field.h --item=p448 -o ${GSOURCE_PATH}/c/p448/f_field.h ${PROJECT_SOURCE_DIR}/src/per_field/f_field.tmpl.h 10 | 11 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_field/f_field.tmpl.h 12 | OUTPUT ${GSOURCE_PATH}/c/p448/f_field.h 13 | COMMENT "Generating code for p448/f_field.h" 14 | ) 15 | 16 | add_custom_command( 17 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=field --guard=p448/f_generic.c --item=p448 -o ${GSOURCE_PATH}/c/p448/f_generic.c ${PROJECT_SOURCE_DIR}/src/per_field/f_generic.tmpl.c 18 | 19 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_field/f_generic.tmpl.c 20 | OUTPUT ${GSOURCE_PATH}/c/p448/f_generic.c 21 | COMMENT "Generating code for p448/f_generic.c" 22 | ) 23 | 24 | add_custom_target(generatorP448 DEPENDS 25 | generatorCommonCode 26 | ${GSOURCE_PATH}/c/p448/f_field.h 27 | ${GSOURCE_PATH}/c/p448/f_generic.c 28 | ) 29 | 30 | # ed448goldilocks 31 | add_custom_command( 32 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=ed448goldilocks/scalar.c -o ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c ${PROJECT_SOURCE_DIR}/src/per_curve/scalar.tmpl.c 33 | 34 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/scalar.tmpl.c 35 | OUTPUT ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c 36 | COMMENT "Generating code for ed448goldilocks/scalar.c" 37 | ) 38 | 39 | add_custom_command( 40 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=ed448goldilocks/decaf.c -o ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c ${PROJECT_SOURCE_DIR}/src/per_curve/decaf.tmpl.c 41 | 42 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/decaf.tmpl.c 43 | OUTPUT ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c 44 | COMMENT "Generating code for ed448goldilocks/decaf.c" 45 | ) 46 | 47 | add_custom_command( 48 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=ed448goldilocks/elligator.c -o ${GSOURCE_PATH}/c/ed448goldilocks/elligator.c ${PROJECT_SOURCE_DIR}/src/per_curve/elligator.tmpl.c 49 | 50 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/elligator.tmpl.c 51 | OUTPUT ${GSOURCE_PATH}/c/ed448goldilocks/elligator.c 52 | COMMENT "Generating code for ed448goldilocks/elligator.c" 53 | ) 54 | 55 | add_custom_command( 56 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=ed448goldilocks/eddsa.c -o ${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.c 57 | 58 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.c 59 | OUTPUT ${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c 60 | COMMENT "Generating code for ed448goldilocks/eddsa.c" 61 | ) 62 | 63 | add_custom_command( 64 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=ed448goldilocks/decaf_gen_tables.c -o ${GSOURCE_PATH}/c/ed448goldilocks/decaf_gen_tables.c ${PROJECT_SOURCE_DIR}/src/per_curve/decaf_gen_tables.tmpl.c 65 | 66 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/decaf_gen_tables.tmpl.c 67 | OUTPUT ${GSOURCE_PATH}/c/ed448goldilocks/decaf_gen_tables.c 68 | COMMENT "Generating code for ed448goldilocks/decaf_gen_tables.c" 69 | ) 70 | 71 | add_custom_command( 72 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=decaf/point_448.hxx -o ${GSOURCE_PATH}/include/decaf/point_448.hxx ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.hxx 73 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.hxx 74 | OUTPUT ${GSOURCE_PATH}/include/decaf/point_448.hxx 75 | COMMENT "Generating code for include/decaf/point_448.hxx" 76 | ) 77 | 78 | add_custom_command( 79 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=decaf/ed448.hxx -o ${GSOURCE_PATH}/include/decaf/ed448.hxx ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.hxx 80 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.hxx 81 | OUTPUT ${GSOURCE_PATH}/include/decaf/ed448.hxx 82 | COMMENT "Generating code for include/decaf/ed448.hxx" 83 | ) 84 | 85 | 86 | add_custom_target(generatorEd448goldilocks DEPENDS 87 | generatorP448 88 | ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c 89 | ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c 90 | ${GSOURCE_PATH}/c/ed448goldilocks/elligator.c 91 | ${GSOURCE_PATH}/c/ed448goldilocks/eddsa.c 92 | ${GSOURCE_PATH}/include/decaf/point_448.hxx 93 | ${GSOURCE_PATH}/include/decaf/ed448.hxx 94 | ) 95 | include_directories( 96 | ${PROJECT_SOURCE_DIR}/src/p448 97 | ${GSOURCE_PATH}/c/p448 98 | ${PROJECT_SOURCE_DIR}/src/p448/${TARGET_ARCH_DIR_P448} 99 | ) 100 | 101 | add_executable(decaf_gen_tables_ed448goldilocks EXCLUDE_FROM_ALL ${GSOURCE_PATH}/c/ed448goldilocks/decaf_gen_tables.c 102 | ${GSOURCE_PATH}/c/ed448goldilocks/decaf.c 103 | ${GSOURCE_PATH}/c/ed448goldilocks/scalar.c 104 | ${PROJECT_SOURCE_DIR}/src/utils.c 105 | $) 106 | 107 | add_custom_target(decaf_tables_ed448goldilocks 108 | COMMAND decaf_gen_tables_ed448goldilocks > ${PROJECT_SOURCE_DIR}/src/ed448goldilocks/decaf_tables.c 109 | DEPENDS decaf_gen_tables_ed448goldilocks 110 | COMMENT "Generating code for ed448goldilocks/decaf_tables.c" 111 | ) 112 | -------------------------------------------------------------------------------- /src/per_curve/elligator.tmpl.c: -------------------------------------------------------------------------------- 1 | /** @brief Elligator high-level functions. */ 2 | 3 | #include "word.h" 4 | #include "field.h" 5 | #include 6 | 7 | /* Template stuff */ 8 | #define API_NS(_id) $(c_ns)_##_id 9 | #define point_t API_NS(point_t) 10 | #define IMAGINE_TWIST $(imagine_twist) 11 | #define COFACTOR $(cofactor) 12 | static const int EDWARDS_D = $(d); 13 | 14 | #define RISTRETTO_FACTOR $(C_NS)_RISTRETTO_FACTOR 15 | extern const gf RISTRETTO_FACTOR; 16 | 17 | /* End of template stuff */ 18 | extern mask_t API_NS(deisogenize) ( 19 | gf_s *__restrict__ s, 20 | gf_s *__restrict__ inv_el_sum, 21 | gf_s *__restrict__ inv_el_m1, 22 | const point_t p, 23 | mask_t toggle_hibit_s, 24 | mask_t toggle_altx, 25 | mask_t toggle_rotation 26 | ); 27 | 28 | void API_NS(point_from_hash_nonuniform) ( 29 | point_t p, 30 | const unsigned char ser[SER_BYTES] 31 | ) { 32 | gf r0,r,a,b,c,N,e; 33 | const uint8_t mask = (uint8_t)(0xFE<<($((gf_bits-1)%8))); 34 | ignore_result(gf_deserialize(r0,ser,0,mask)); 35 | gf_strong_reduce(r0); 36 | gf_sqr(a,r0); 37 | gf_mul_qnr(r,a); 38 | 39 | /* Compute D@c := (dr+a-d)(dr-ar-d) with a=1 */ 40 | gf_sub(a,r,ONE); 41 | gf_mulw(b,a,EDWARDS_D); /* dr-d */ 42 | gf_add(a,b,ONE); 43 | gf_sub(b,b,r); 44 | gf_mul(c,a,b); 45 | 46 | /* compute N := (r+1)(a-2d) */ 47 | gf_add(a,r,ONE); 48 | gf_mulw(N,a,1-2*EDWARDS_D); 49 | 50 | /* e = +-sqrt(1/ND) or +-r0 * sqrt(qnr/ND) */ 51 | gf_mul(a,c,N); 52 | mask_t square = gf_isr(b,a); 53 | gf_cond_sel(c,r0,ONE,square); /* r? = square ? 1 : r0 */ 54 | gf_mul(e,b,c); 55 | 56 | /* s@a = +-|N.e| */ 57 | gf_mul(a,N,e); 58 | gf_cond_neg(a,gf_lobit(a) ^ ~square); 59 | 60 | /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ 61 | gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ 62 | gf_sqr(b,c); 63 | gf_sub(e,r,ONE); 64 | gf_mul(c,b,e); 65 | gf_mul(b,c,N); 66 | gf_cond_neg(b,square); 67 | gf_sub(b,b,ONE); 68 | 69 | /* isogenize */ 70 | #if IMAGINE_TWIST 71 | gf_mul(c,a,SQRT_MINUS_ONE); 72 | gf_copy(a,c); 73 | #endif 74 | 75 | gf_sqr(c,a); /* s^2 */ 76 | gf_add(a,a,a); /* 2s */ 77 | gf_add(e,c,ONE); 78 | gf_mul(p->t,a,e); /* 2s(1+s^2) */ 79 | gf_mul(p->x,a,b); /* 2st */ 80 | gf_sub(a,ONE,c); 81 | gf_mul(p->y,e,a); /* (1+s^2)(1-s^2) */ 82 | gf_mul(p->z,a,b); /* (1-s^2)t */ 83 | 84 | assert(API_NS(point_valid)(p)); 85 | } 86 | 87 | void API_NS(point_from_hash_uniform) ( 88 | point_t pt, 89 | const unsigned char hashed_data[2*SER_BYTES] 90 | ) { 91 | point_t pt2; 92 | API_NS(point_from_hash_nonuniform)(pt,hashed_data); 93 | API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]); 94 | API_NS(point_add)(pt,pt,pt2); 95 | } 96 | 97 | /* Elligator_onto: 98 | * Make elligator-inverse onto at the cost of roughly halving the success probability. 99 | * Currently no effect for curves with field size 1 bit mod 8 (where the top bit 100 | * is chopped off). FUTURE MAGIC: automatic at least for brainpool-style curves; support 101 | * log p == 1 mod 8 brainpool curves maybe? 102 | */ 103 | #define MAX(A,B) (((A)>(B)) ? (A) : (B)) 104 | 105 | decaf_error_t 106 | API_NS(invert_elligator_nonuniform) ( 107 | unsigned char recovered_hash[SER_BYTES], 108 | const point_t p, 109 | uint32_t hint_ 110 | ) { 111 | mask_t hint = hint_; 112 | mask_t sgn_s = -(hint & 1), 113 | sgn_altx = -(hint>>1 & 1), 114 | sgn_r0 = -(hint>>2 & 1), 115 | /* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0, 116 | * change this mask extraction. 117 | */ 118 | sgn_ed_T = -(hint>>3 & 1); 119 | gf a,b,c; 120 | API_NS(deisogenize)(a,b,c,p,sgn_s,sgn_altx,sgn_ed_T); 121 | 122 | mask_t is_identity = gf_eq(p->t,ZERO); 123 | #if COFACTOR==4 124 | gf_cond_sel(b,b,ONE,is_identity & sgn_altx); 125 | gf_cond_sel(c,c,ONE,is_identity & sgn_s &~ sgn_altx); 126 | #elif IMAGINE_TWIST 127 | /* Terrible, terrible special casing due to lots of 0/0 is deisogenize 128 | * Basically we need to generate -D and +- i*RISTRETTO_FACTOR 129 | */ 130 | gf_mul_i(a,RISTRETTO_FACTOR); 131 | gf_cond_sel(b,b,ONE,is_identity); 132 | gf_cond_neg(a,sgn_altx); 133 | gf_cond_sel(c,c,a,is_identity & sgn_ed_T); 134 | gf_cond_sel(c,c,ZERO,is_identity & ~sgn_ed_T); 135 | gf_mulw(a,ONE,-EDWARDS_D); 136 | gf_cond_sel(c,c,a,is_identity & ~sgn_ed_T &~ sgn_altx); 137 | #else 138 | #error "Different special-casing goes here!" 139 | #endif 140 | 141 | #if IMAGINE_TWIST 142 | gf_mulw(a,b,-EDWARDS_D); 143 | #else 144 | gf_mulw(a,b,EDWARDS_D-1); 145 | #endif 146 | gf_add(b,a,b); 147 | gf_sub(a,a,c); 148 | gf_add(b,b,c); 149 | gf_cond_swap(a,b,sgn_s); 150 | gf_mul_qnr(c,b); 151 | gf_mul(b,c,a); 152 | mask_t succ = gf_isr(c,b); 153 | succ |= gf_eq(b,ZERO); 154 | gf_mul(b,c,a); 155 | 156 | #if $(gf_bits) == 8*SER_BYTES + 1 /* p521. */ 157 | #error "this won't work because it needs to adjust high bit, not low bit" 158 | sgn_r0 = 0; 159 | #endif 160 | 161 | gf_cond_neg(b, sgn_r0^gf_lobit(b)); 162 | /* Eliminate duplicate values for identity ... */ 163 | succ &= ~(gf_eq(b,ZERO) & (sgn_r0 | sgn_s)); 164 | // #if COFACTOR == 8 165 | // succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */ 166 | // #endif 167 | 168 | #if $(gf_bits) == 8*SER_BYTES + 1 /* p521 */ 169 | gf_serialize(recovered_hash,b,0); 170 | #else 171 | gf_serialize(recovered_hash,b,1); 172 | #endif 173 | #if $(gf_bits%8) 174 | #if COFACTOR==8 175 | recovered_hash[SER_BYTES-1] ^= (hint>>4)<<$(gf_bits%8); 176 | #else 177 | recovered_hash[SER_BYTES-1] ^= (hint>>3)<<$(gf_bits%8); 178 | #endif 179 | #endif 180 | return decaf_succeed_if(mask_to_bool(succ)); 181 | } 182 | 183 | decaf_error_t 184 | API_NS(invert_elligator_uniform) ( 185 | unsigned char partial_hash[2*SER_BYTES], 186 | const point_t p, 187 | uint32_t hint 188 | ) { 189 | point_t pt2; 190 | API_NS(point_from_hash_nonuniform)(pt2,&partial_hash[SER_BYTES]); 191 | API_NS(point_sub)(pt2,p,pt2); 192 | return API_NS(invert_elligator_nonuniform)(partial_hash,pt2,hint); 193 | } 194 | -------------------------------------------------------------------------------- /src/spongerng.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file spongerng.c 4 | * @copyright 5 | * Copyright (c) 2015-2017 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief Spongerng instances (STROBE removed) 9 | * @warning The SpongeRNG code isn't stable. Future versions are likely to 10 | * have different outputs. Of course, this only matters in deterministic mode. 11 | */ 12 | 13 | #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ 14 | #include 15 | #include 16 | #include 17 | 18 | #include "keccak_internal.h" 19 | #include 20 | 21 | /* to open and read from /dev/urandom */ 22 | #include 23 | #include 24 | #include 25 | #if defined(_MSC_VER) 26 | # include 27 | #include 28 | typedef SSIZE_T ssize_t; 29 | #else 30 | # include 31 | #endif 32 | 33 | /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */ 34 | static void get_cpu_entropy(uint8_t *entropy, size_t len) { 35 | # if (defined(__i386__) || defined(__x86_64__)) 36 | static char tested = 0, have_rdrand = 0; 37 | if (!tested) { 38 | uint32_t a,b,c,d; 39 | #if defined(__i386__) && defined(__PIC__) 40 | /* Don't clobber ebx. The compiler doesn't like when when __PIC__ */ 41 | __asm__("mov %%ebx, %[not_ebx]\n\t" 42 | "cpuid\n\t" 43 | "xchg %%ebx, %[not_ebx]" : "=a"(a), [not_ebx]"=r"(b), "=c"(c), "=d"(d) : "0"(1)); 44 | #elif defined(__x86_64__) && defined(__PIC__) 45 | /* Don't clobber rbx. The compiler doesn't like when when __PIC__ */ 46 | uint64_t b64; 47 | __asm__("mov %%rbx, %[not_rbx]\n\t" 48 | "cpuid\n\t" 49 | "xchg %%rbx, %[not_rbx]" : "=a"(a), [not_rbx]"=r"(b64), "=c"(c), "=d"(d) : "0"(1)); 50 | b = b64; 51 | #else 52 | __asm__("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1)); 53 | #endif 54 | (void)a; (void)b; (void)d; 55 | have_rdrand = (c>>30)&1; 56 | tested = 1; 57 | } 58 | 59 | if (have_rdrand) { 60 | # if defined(__x86_64__) 61 | uint64_t out, a=0, *eo = (uint64_t *)entropy; 62 | # elif defined(__i386__) 63 | uint32_t out, a=0, *eo = (uint32_t *)entropy; 64 | #endif 65 | len /= sizeof(out); 66 | 67 | uint32_t tries; 68 | for (tries = 100+len; tries && len; len--, eo++) { 69 | for (a = 0; tries && !a; tries--) { 70 | __asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" ); 71 | } 72 | *eo ^= out; 73 | } 74 | } else if (len>=8) { 75 | #ifndef __has_builtin 76 | #define __has_builtin(X) 0 77 | #endif 78 | #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter) 79 | *(uint64_t*) entropy ^= __builtin_readcyclecounter(); 80 | #elif defined(__x86_64__) 81 | uint32_t lobits, hibits; 82 | __asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits)); 83 | *(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32)); 84 | #elif defined(__i386__) 85 | uint64_t __value; 86 | __asm__ __volatile__ ("rdtsc" : "=A"(__value)); 87 | *(uint64_t*) entropy ^= __value; 88 | #endif 89 | } 90 | 91 | #else 92 | (void) entropy; 93 | (void) len; 94 | #endif 95 | } 96 | 97 | void decaf_spongerng_next ( 98 | decaf_keccak_prng_t prng, 99 | uint8_t * __restrict__ out, 100 | size_t len 101 | ) { 102 | if (prng->sponge->params->remaining) { 103 | /* nondet */ 104 | uint8_t cpu_entropy[32] = {0}; 105 | get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy)); 106 | decaf_spongerng_stir(prng,cpu_entropy,sizeof(cpu_entropy)); 107 | decaf_bzero(cpu_entropy,sizeof(cpu_entropy)); 108 | } 109 | 110 | uint8_t lenx[8]; 111 | size_t len1 = len; 112 | for (unsigned i=0; i>= 8; 115 | } 116 | decaf_sha3_update(prng->sponge,lenx,sizeof(lenx)); 117 | decaf_sha3_output(prng->sponge,out,len); 118 | 119 | const uint8_t nope; 120 | decaf_spongerng_stir(prng,&nope,0); 121 | } 122 | 123 | void decaf_spongerng_stir ( 124 | decaf_keccak_prng_t prng, 125 | const uint8_t * __restrict__ in, 126 | size_t len 127 | ) { 128 | uint8_t seed[32]; 129 | decaf_sha3_output(prng->sponge,seed,sizeof(seed)); 130 | uint8_t nondet = prng->sponge->params->remaining; 131 | 132 | decaf_sha3_reset(prng->sponge); 133 | decaf_sha3_update(prng->sponge,seed,sizeof(seed)); 134 | decaf_sha3_update(prng->sponge,in,len); 135 | 136 | prng->sponge->params->remaining = nondet; 137 | decaf_bzero(seed,sizeof(seed)); 138 | } 139 | 140 | void decaf_spongerng_init_from_buffer ( 141 | decaf_keccak_prng_t prng, 142 | const uint8_t * __restrict__ in, 143 | size_t len, 144 | int deterministic 145 | ) { 146 | decaf_sha3_init(prng->sponge,&DECAF_SHAKE256_params_s); 147 | prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ 148 | decaf_spongerng_stir(prng, in, len); 149 | } 150 | 151 | decaf_error_t decaf_spongerng_init_from_file ( 152 | decaf_keccak_prng_t prng, 153 | const char *file, 154 | size_t len, 155 | int deterministic 156 | ) { 157 | decaf_sha3_init(prng->sponge,&DECAF_SHAKE256_params_s); 158 | prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */ 159 | if (!len) return DECAF_FAILURE; 160 | 161 | int fd = open(file, O_RDONLY); 162 | if (fd < 0) return DECAF_FAILURE; 163 | 164 | uint8_t buffer[128]; 165 | while (len) { 166 | ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len); 167 | if (red <= 0) { 168 | close(fd); 169 | return DECAF_FAILURE; 170 | } 171 | decaf_sha3_update(prng->sponge,buffer,red); 172 | len -= red; 173 | }; 174 | close(fd); 175 | const uint8_t nope; 176 | decaf_spongerng_stir(prng,&nope,0); 177 | 178 | return DECAF_SUCCESS; 179 | } 180 | 181 | decaf_error_t decaf_spongerng_init_from_dev_urandom ( 182 | decaf_keccak_prng_t decaf_sponge 183 | ) { 184 | return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0); 185 | } 186 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Decaf elliptic curve library 2 | 3 | The libdecaf library is for elliptic curve research and practical application. 4 | It currently supports Ed448-Goldilocks and Curve25519. 5 | 6 | The goals of this library are: 7 | 8 | * Implementing the X25519, X448 key exchange protocols (RFC 7748). 9 | * Implementing the Ed25519 and EdDSA-Ed448 signature schemes (RFC 8032). 10 | * Providing a platform for research and development of advanced cryptographic schemes using twisted Edwards curves. 11 | 12 | This library is intended for developers who have experience with 13 | cryptography. It doesn't (yet?) include documentation on how to use 14 | digital signatures or key exchange securely. Consult your local 15 | cryptographer for advice. 16 | 17 | ## Mailing lists 18 | 19 | Because this is new software, please expect it to have bugs, perhaps 20 | even critical security bugs. If you are using it, please sign up for 21 | updates: 22 | 23 | * Security-critical announcements (very low volume, God willing): 24 | decaf-security@googlegroups.com, join at https://groups.google.com/forum/#!forum/decaf-security 25 | * New version announcements (low volume): 26 | decaf-announce@googlegroups.com, join at https://groups.google.com/forum/#!forum/decaf-annonuce 27 | * Library discussion (potentially more volume): 28 | decaf-discuss@googlegroups.com, join at https://groups.google.com/forum/#!forum/decaf-discuss 29 | 30 | ## General elliptic curve operations. 31 | 32 | This is a multi-purpose elliptic curve library. There is a C library, 33 | and a set of C++ wrapper headers. The C++ code consists entirely of 34 | inline calls, and has no compiled component. 35 | 36 | The library implements a fairly complete suite of operations on the 37 | supported curves: 38 | 39 | * Point and scalar serialization and deserialization. 40 | * Point addition, subtraction, doubling, and equality. 41 | * Point multiplication by scalars. Accelerated double- and dual-scalar multiply. 42 | * Scalar addition, subtraction, multiplication, division, and equality. 43 | * Construction of precomputed tables from points. Precomputed scalarmul. 44 | * Hashing to the curve with an Elligator variant. Inverse of elligator for steganography. These are useful for advanced protocols such as password-authenticated key exchange (PAKE) and verifiable random functions (VRFs). 45 | 46 | Internally, the library uses twisted Edwards curves with the "decaf" 47 | and "ristretto" technique to remove the curve's cofactor of 4 or 8. 48 | The upshot is that systems using the "decaf" interface will be using 49 | a prime-order group, which mitigates one of the few disadvantages of 50 | Edwards curves. However, this means that it is not able to implement 51 | systems which care about cofactor information. 52 | 53 | The goal of this library is not only to follow best practices, but to 54 | make it easier for clients of the library to follow best practices. 55 | With a few well-marked exceptions, the functions in this library should 56 | be strongly constant-time: they do not allow secret data to flow to 57 | array indices, nor to control decisions except for a final failure 58 | check. Furthermore, the C++ wrapping uses RAII to automatically clear 59 | sensitive data, and has interfaces designed to prevent certain mistakes. 60 | 61 | ## CFRG cryptosystems. 62 | 63 | The library additionally supports two cryptosystems defined by the 64 | Crypto Forum Research Group (CFRG): the X448/X25519 Diffie-Hellman 65 | functions (RFC 7748), and the EdDSA signature scheme (RFC 8032). 66 | Future versions might support additional operations on these curves, 67 | such as precomputed signature verification. 68 | 69 | ## Symmetric crypto and hashing 70 | 71 | The Decaf library doesn't implement much symmetric crypto, but it does 72 | contain the hash functions required by the CFRG cryptosystems: SHA512, 73 | SHA-3 and SHAKE. 74 | 75 | ## Internals 76 | 77 | The "decaf" technique is described in https://eprint.iacr.org/2015/673 78 | While the title of that paper is "removing cofactors through point 79 | compression", it might be more accurate to say "through quotients and 80 | isogenies". The internal representation of points is as "even" elements 81 | of a twisted Edwards curve with a=-1. Using this subgroup removes a 82 | factor of 2 from the cofactor. The remaining factor of 2 or 4 is 83 | removed with a quotient group: any two points which differ by an element 84 | of the 2- or 4-torsion subgroup are considered equal to each other. 85 | 86 | When a point is written out to wire format, it is converted (by isogeny) 87 | to a Jacobi quartic curve, which is halfway between an Edwards curve 88 | and a Montgomery curve. One of the 4 or 8 equivalent points on the 89 | Jacobi quartic is chosen (it is "distinguished" according to certain 90 | criteria, such as having a positive x-coordinate). The x-coordinate of 91 | this point is written out. The y-coordinate is not written out, but the 92 | decoder knows which of the two possible y-coordinates is correct because 93 | of the distinguishing rules. See the paper for more details. 94 | 95 | As of v0.9.4, libdecaf uses the "Ristretto" variant of this encoding. 96 | See https://www.ristretto.group for details, once that site is up. 97 | 98 | ## Build and Install 99 | 100 | cmake -DCMAKE_INSTALL_PREFIX= 101 | make 102 | make test 103 | make install 104 | 105 | Most C source code is generated through a python script during the build. 106 | Some files holding tables are generated in one more step building an 107 | executable to generate them. They are thus stored in the source tree to help 108 | cross-compilation. The build script update them when their dependencies 109 | are modified, to build only these files: 110 | 111 | make decaf_tables 112 | 113 | Doxygen generated documentation is located in ./doc directory in the 114 | binary tree after running 115 | 116 | make doc 117 | 118 | ## Licensing 119 | 120 | Most of the source files here are by Mike Hamburg. Those files are (c) 121 | 2014-2017 Cryptography Research, Inc (a division of Rambus). All of these 122 | files are usable under the MIT license contained in LICENSE.txt. 123 | 124 | ## Caveats 125 | 126 | As mentioned in the license, there is absolutely NO WARRANTY on any of this 127 | code. This code might well have security-critical bugs despite my best efforts. 128 | 129 | I've attempted to protect against timing attacks and invalid point attacks, 130 | but as of yet I've made no attempt to protect against power analysis. 131 | 132 | ## Cross-compiling with mingw 133 | 134 | Due to some alignment errors we cannot use `-O2`, and due to cross-compiling we 135 | need to make sure ARCHFLAGS is unset. Try `OFLAGS='' ARCHFLAGS='' make win`. 136 | 137 | The final library is not built - but for my use-case (statically linking the .o 138 | files into my lib) that is not necessary - fixes welcome. 139 | -------------------------------------------------------------------------------- /_aux/ristretto/ristretto.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | 3 | \usepackage{amsmath,amsthm,amsfonts,amssymb,xspace,graphicx,url,stmaryrd,parskip} 4 | 5 | \newtheorem{lemma}{Lemma} 6 | 7 | \newcommand\todo[1]{\textbf{[[TODO: #1]]}\xspace} 8 | \def\F{\ensuremath{\mathbb{F}}} 9 | \def\G{\ensuremath{\mathbb{G}}} 10 | \def\Z{\ensuremath{\mathbb{Z}}} 11 | \def\O{\ensuremath{O}} 12 | 13 | \begin{document} 14 | \title{The Ristretto and Cortado elliptic curve groups} 15 | \author{Mike Hamburg\thanks{Rambus Security Division}} 16 | \maketitle 17 | 18 | \begin{abstract} 19 | \end{abstract} 20 | 21 | \section{Introduction} 22 | \section{Definitions and notation} 23 | 24 | Let the symbol $\bot$ denote failure. 25 | 26 | \subsection{Field elements} 27 | Let \F\ be a finite field of prime order $p$. For an element $x\in\F$, let $\text{res}(x)$ be the integer representative of $x\in[0,p-1]$. We call an element $x\in\F$ \textit{negative} if $\text{res}(x)$ is odd. Call an element in \F\ \textit{square} if it is a quadratic residue, i.e.\ if there exists $\sqrt{x}\in\F$ such that $\sqrt{x}^2=x$. There will in general be two such square roots; let the notation $\sqrt{x}$ mean the unique non-negative square root of $x$. If $p\equiv1\pmod 4$, then \F\ contains an element $i := \sqrt{-1}$. 28 | 29 | Let $\ell := \lceil \log_{2^8} p\rceil$. Each $x\in\F$ has a unique \textit{little-endian byte representation}, namely the sequence 30 | $$ 31 | \text{\F\_to\_bytes}(x) := \llbracket b_i\rrbracket_{i=0}^{\l-1} \ \text{where}\ b_i\in[0,255]\text{\ and\ }\sum_{i=0}^{\l-1} 2^{8i} \cdot b_i = \text{res}(x) 32 | $$ 33 | \todo{bytes to \F} 34 | 35 | \subsection{Groups} 36 | For an abelian group \G\ with identity \O, let $n\G$ denote the subgroup of $\G$ which are of the form $n\cdot g$ for some $g\in\G$. Let $\G_n$ denote the $n$-torsion group of \G, namely the subgroup $\{g\in\G : n\cdot g = O\}$. 37 | 38 | \subsection{Edwards curves} 39 | We will work with twisted Edwards elliptic curves of the form 40 | % 41 | $$E_{a,d} : y^2 + a\cdot x^2 = 1 + d\cdot x^2\cdot y^2$$ 42 | % 43 | where $x,y\in\F$. Twisted Edwards curves curves have a group law 44 | $$(x_1,y_1) + (x_2,y_2) := 45 | \left( 46 | \frac{x_1 y_2 + x_2 y_1}{1+d x_1 x_2 y_1 y_2}, 47 | \frac{y_1 y_2 - a x_1 x_2}{1-d x_1 x_2 y_1 y_2} 48 | \right) 49 | $$ 50 | with identity point $\O := (0,1)$ and group inverse operation $$-(x,y) = (-x,y)$$ 51 | The group law is called \textit{complete} if is produces the correct answer (rather than e.g.\ $0/0$) for all points on the curve. The above formulas are complete when $d$ and $ad$ are nonsquare in \F, which implies that $a$ is square. When these conditions hold, we also say that the curve itself is complete. 52 | 53 | Let the number of points on the curve be $$\#E_{a,d} = h\cdot q$$ where $q$ is prime and $h\in\{4,8\}$. We call $h$ the \textit{cofactor}. 54 | 55 | For $P = (x,y)\in E$, we can define the \textit{projective homogeneous form} of $P$ as $(X,Y,Z)$ with $Z\neq 0$ and $$(x,y) = (X/Z,Y/Z)$$ and the \textit{extended homogeneous form} as $(X,Y,Z,T)$ where additionally $XY=ZT$. Extended homogeneous form is popular because it supports simple and efficient complete addition formulas~\cite{hisil}. 56 | 57 | \subsection{Montgomery curves} 58 | 59 | When $a-d$ is square in \F, the twisted Edwards curve $E_{a,d}$ is isomorphic to the Montgomery curve 60 | $$v^2 = u\cdot\left(u^2 + 2\cdot\frac{a+d}{a-d}\cdot u + 1\right)$$ 61 | by the map 62 | $$(u,v) = \left(\frac{1+y}{1-y},\ \ \frac{1+y}{1-y}\cdot\frac1x\cdot\frac{2}{\sqrt{a-d}}\right)$$ 63 | with inverse 64 | $$(x,y) = \left(\frac{u}{v}\cdot\frac{\sqrt{a-d}}{2},\ \ \frac{u-1}{u+1}\right)$$ 65 | 66 | If $M = (u,v)$ is a point on the Montgomery curve, then the $u$-coordinate of $2M$ is $(u^2-1)^2 / (4v^2)$ is necessarily square. It follows that if $(x,y)$ is a point on $E_{a,d}$, and $a-d$ is square, then $(1+y)/(1-y)$ is also square. 67 | 68 | Likewhise, when $d-a$ is square in \F, $E_{a,d}$ is isomorphic to the Montgomery curve 69 | $$v^2 = u\cdot\left(u^2 - 2\cdot\frac{a+d}{a-d}\cdot u + 1\right)$$ 70 | by the map 71 | $$(u,v) = \left(\frac{y+1}{y-1},\ \ \frac{y+1}{y-1}\cdot\frac1x\cdot\frac{2}{\sqrt{d-a}}\right)$$ 72 | with inverse 73 | $$(x,y) = \left(\frac{u}{v}\cdot\frac{\sqrt{d-a}}{2},\ \ \frac{1+u}{1-u}\right)$$ 74 | 75 | \section{Lemmas} 76 | First, we characterize the 2-torsion and 4-torsion groups.\\ 77 | \begin{lemma}\label{lemma:tors} 78 | Let $E_{a,d}$ be a complete Edwards curve. Its 2-torsion subgroup is generated by $(0,-1)$. The 4-torsion subgroup is generated by $(1/\sqrt{a},0)$. 79 | 80 | Adding the 2-torsion generator to $(x,y)$ produces $(-x,-y)$. Adding the 4-torsion generator $(1/\sqrt{a},0)$ produces $(y/\sqrt{a},-x\cdot\sqrt{a})$ 81 | \end{lemma} 82 | \begin{proof} 83 | Inspection. 84 | \end{proof} 85 | 86 | \begin{lemma}\label{lemma:line} 87 | Let $E_{a,d}$ be a complete twisted Edwards curve over \F, and $P_1 = (x_1,y_1)$ be any point on it. Then there are exactly two points $P_2 = (x_2,y_2)$ satisfying $x_1 y_2 = x_2 y_1$, namely $P_1$ itself and $(-x_1,-y_1)$. That is, there are either 0 or 2 points on any line through the origin. 88 | \end{lemma} 89 | \begin{proof} 90 | Plugging into the group operation gives 91 | $$x_1 y_2 = x_2 y_1 \Longleftrightarrow P_1-P_2 = (0,y_3)$$ 92 | for some $y_3$. Plugging $x=0$ into the curve equation gives $y=\pm1$, the 2-torsion points. Adding back, we have $P_2 = P_1 + (0,\pm1) = (\pm x_1, \pm y_1)$ as claimed. 93 | \end{proof} 94 | 95 | \begin{lemma}\label{lemma:dma} 96 | If $E_{a,d}$ is a complete Edwards curve, then $a^2-ad$ is square in \F\ (and thus $a-d$ is square in \F) if and only if the cofactor of $E_{a,d}$ is divisible by 8. 97 | \end{lemma} 98 | \begin{proof} 99 | Doubling an 8-torsion generator $(x,y)$ should produce a 4-torsion generator, i.e.\ a point with $y=0$. From the doubling formula, this happens precisely when $y^2=ax^2$, or $2ax^2=1+adx^4$. This has roots in \F\ if and only if its discriminant $4a^2-4ad$ is square, so that $a^2-ad$ is square. 100 | \end{proof} 101 | 102 | \begin{lemma}\label{lemma:sqrt} 103 | If $(x_2,y_2) = 2\cdot(x_1,y_1)$ is an even point in $E_{a,d}$, then $(1-ax_2^2)$ is a quadratic residue in \F. \todo{$(y_2^2-1)$}. 104 | \end{lemma} 105 | \begin{proof} 106 | The doubling formula has $$x_2 = \frac{2x_1 y_1}{y_1^2+ax_1^2}$$ 107 | so that $$1-ax_2^2 = \left(\frac{y_1^2-ax_1^2}{y_1^2+ax_1^2}\right)^2$$ 108 | is a quadratic residue. Now for any point $(x,y)\in E_{a,d}$, we have 109 | $$(y^2-1)\cdot(1-ax^2) 110 | = y^2+ax^2-1-ax^2y^2 111 | = (d-a)x^2y^2 112 | $$ 113 | which is a quadratic residue by Lemma~\ref{lemma:dma}. 114 | \end{proof} 115 | 116 | \section{The Espresso groups} 117 | Let $E$ be a complete twisted Edwards curve with $a\in\{\pm1\}$ and cofactor $4$ or $8$. We describe the \textit{Espresso} group $\G(E)$ as 118 | $$\text{Espresso}(E) := 2E / E_{h/2}$$ 119 | This group has prime order $q$. 120 | \subsection{Group law} 121 | The group law on $\text{Espresso}(E)$ is the same as that on $E$. 122 | \subsection{Equality} 123 | Two elements $P_1 := (x_1,y_1)$ and $P_2 := (x_2,y_2)$ in $\text{Espresso}(E)$ are equal if they differ by an element of $E_{h/2}$. 124 | 125 | If $h=4$, the points are equal if $P_1-P_2\in E_2$. By Lemma~\ref{lemma:line}, this is equivalent to $$x_1 y_2 = x_2 y_1$$ 126 | 127 | If $h=8$, the points are equal if $P_1-P_2\in E_4$. By Lemmas~\ref{lemma:tors} and~\ref{lemma:line}, this is equivalent to $$x_1 y_2 = x_2 y_1\text{\ \ or\ \ }x_1 x_2 = -a y_1 y_2$$ 128 | 129 | These equations are homogeneous, so they may be evaluated in projective homogeneous form with $X_i$ and $Y_i$ in place of $x_i$ and $y_i$ 130 | 131 | \subsection{Encoding} 132 | We now describe how to encode a point $P = (x,y)$ to bytes. The requirements of encoding are that 133 | \begin{itemize} 134 | \item Any point $P\in2E$ can be encoded. 135 | \item Two points $P,Q$ have the same encoding if and only if $P-Q\in E_{h/2}$. 136 | \end{itemize} 137 | 138 | When $h=4$, we encode a point as $\sqrt{a(y-1)/(y+1)}$ 139 | 140 | \end{document} -------------------------------------------------------------------------------- /src/generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # CMakeLists.txt 3 | # 4 | # Released under the MIT License. See LICENSE.txt for license information. 5 | # 6 | ############################################################################ 7 | # global include files 8 | add_custom_command( 9 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=global --guard=decaf.h -o ${GSOURCE_PATH}/include/decaf.h ${PROJECT_SOURCE_DIR}/src/public_include/decaf.tmpl.h 10 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/public_include/decaf.tmpl.h 11 | OUTPUT ${GSOURCE_PATH}/include/decaf.h 12 | COMMENT "Generating code for include/decaf.h" 13 | ) 14 | 15 | add_custom_command( 16 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=global --guard=decaf/eddsa.hxx -o ${GSOURCE_PATH}/include/decaf/eddsa.hxx ${PROJECT_SOURCE_DIR}/src/public_include/decaf/eddsa.tmpl.hxx 17 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/public_include/decaf/eddsa.tmpl.hxx 18 | OUTPUT ${GSOURCE_PATH}/include/decaf/eddsa.hxx 19 | COMMENT "Generating code for include/decaf/eddsa.hxx" 20 | ) 21 | 22 | add_custom_command( 23 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=global --guard=decaf.hxx -o ${GSOURCE_PATH}/include/decaf.hxx ${PROJECT_SOURCE_DIR}/src/public_include/decaf.tmpl.hxx 24 | 25 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/public_include/decaf.tmpl.hxx 26 | OUTPUT ${GSOURCE_PATH}/include/decaf.hxx 27 | COMMENT "Generating code for include/decaf.hxx" 28 | ) 29 | 30 | add_custom_command( 31 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=global --guard=decaf/crypto.hxx -o ${GSOURCE_PATH}/c/decaf/crypto.hxx ${PROJECT_SOURCE_DIR}/src/include/decaf/crypto.tmpl.hxx 32 | 33 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/include/decaf/crypto.tmpl.hxx 34 | OUTPUT ${GSOURCE_PATH}/c/decaf/crypto.hxx 35 | COMMENT "Generating code for decaf/crypto.hxx" 36 | ) 37 | 38 | # copying 39 | add_custom_command( 40 | COMMAND ${CMAKE_COMMAND} -E copy 41 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/common.h 42 | ${GSOURCE_PATH}/include/decaf/common.h 43 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/common.h 44 | OUTPUT ${GSOURCE_PATH}/include/decaf/common.h 45 | ) 46 | 47 | add_custom_command( 48 | COMMAND ${CMAKE_COMMAND} -E copy 49 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/sha512.hxx 50 | ${GSOURCE_PATH}/include/decaf/sha512.hxx 51 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/sha512.hxx 52 | OUTPUT ${GSOURCE_PATH}/include/decaf/sha512.hxx 53 | ) 54 | 55 | add_custom_command( 56 | COMMAND ${CMAKE_COMMAND} -E copy 57 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/spongerng.h 58 | ${GSOURCE_PATH}/include/decaf/spongerng.h 59 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/spongerng.h 60 | OUTPUT ${GSOURCE_PATH}/include/decaf/spongerng.h 61 | ) 62 | 63 | add_custom_command( 64 | COMMAND ${CMAKE_COMMAND} -E copy 65 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/shake.hxx 66 | ${GSOURCE_PATH}/include/decaf/shake.hxx 67 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/shake.hxx 68 | OUTPUT ${GSOURCE_PATH}/include/decaf/shake.hxx 69 | ) 70 | 71 | add_custom_command( 72 | COMMAND ${CMAKE_COMMAND} -E copy 73 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/shake.h 74 | ${GSOURCE_PATH}/include/decaf/shake.h 75 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/shake.h 76 | OUTPUT ${GSOURCE_PATH}/include/decaf/shake.h 77 | ) 78 | 79 | add_custom_command( 80 | COMMAND ${CMAKE_COMMAND} -E copy 81 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/spongerng.hxx 82 | ${GSOURCE_PATH}/include/decaf/spongerng.hxx 83 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/spongerng.hxx 84 | OUTPUT ${GSOURCE_PATH}/include/decaf/spongerng.hxx 85 | ) 86 | add_custom_command( 87 | COMMAND ${CMAKE_COMMAND} -E copy 88 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/secure_buffer.hxx 89 | ${GSOURCE_PATH}/include/decaf/secure_buffer.hxx 90 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/secure_buffer.hxx 91 | OUTPUT ${GSOURCE_PATH}/include/decaf/secure_buffer.hxx 92 | ) 93 | add_custom_command( 94 | COMMAND ${CMAKE_COMMAND} -E copy 95 | ${PROJECT_SOURCE_DIR}/src/public_include/decaf/sha512.h 96 | ${GSOURCE_PATH}/include/decaf/sha512.h 97 | DEPENDS ${PROJECT_SOURCE_DIR}/src/public_include/decaf/sha512.h 98 | OUTPUT ${GSOURCE_PATH}/include/decaf/sha512.h 99 | ) 100 | 101 | 102 | #these files shall be part of generatorCurve25519 and generatorEd448goldilocks targets but they are both included through decaf.h in a source file 103 | add_custom_command( 104 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=decaf/point_255.h -o ${GSOURCE_PATH}/include/decaf/point_255.h ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.h 105 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.h 106 | OUTPUT ${GSOURCE_PATH}/include/decaf/point_255.h 107 | COMMENT "Generating code for decaf/point_255.h" 108 | ) 109 | 110 | add_custom_command( 111 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=curve25519 --guard=decaf/ed255.h -o ${GSOURCE_PATH}/include/decaf/ed255.h ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.h 112 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.h 113 | OUTPUT ${GSOURCE_PATH}/include/decaf/ed255.h 114 | COMMENT "Generating code for decaf/ed255.h" 115 | ) 116 | 117 | add_custom_command( 118 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=decaf/point_448.h -o ${GSOURCE_PATH}/include/decaf/point_448.h ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.h 119 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/point.tmpl.h 120 | OUTPUT ${GSOURCE_PATH}/include/decaf/point_448.h 121 | COMMENT "Generating code for decaf/point_448.h" 122 | ) 123 | 124 | add_custom_command( 125 | COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/generator/template.py --per=curve --item=ed448goldilocks --guard=decaf/ed448.h -o ${GSOURCE_PATH}/include/decaf/ed448.h ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.h 126 | DEPENDS ${PROJECT_SOURCE_DIR}/src/generator/template.py ${PROJECT_SOURCE_DIR}/src/per_curve/eddsa.tmpl.h 127 | OUTPUT ${GSOURCE_PATH}/include/decaf/ed448.h 128 | COMMENT "Generating code for decaf/ed448.h" 129 | ) 130 | 131 | 132 | 133 | add_custom_target(generatorCommonCode DEPENDS 134 | ${GSOURCE_PATH}/include/decaf.h 135 | ${GSOURCE_PATH}/include/decaf/eddsa.hxx 136 | ${GSOURCE_PATH}/include/decaf.hxx 137 | ${GSOURCE_PATH}/c/decaf/crypto.hxx 138 | ${GSOURCE_PATH}/include/decaf/common.h 139 | ${GSOURCE_PATH}/include/decaf/sha512.hxx 140 | ${GSOURCE_PATH}/include/decaf/sha512.h 141 | ${GSOURCE_PATH}/include/decaf/shake.hxx 142 | ${GSOURCE_PATH}/include/decaf/shake.h 143 | ${GSOURCE_PATH}/include/decaf/spongerng.hxx 144 | ${GSOURCE_PATH}/include/decaf/spongerng.h 145 | ${GSOURCE_PATH}/include/decaf/secure_buffer.hxx 146 | #these files shall be part of curve25519 and ed448goldilocks targets but they are included through decaf.h in common *.c 147 | ${GSOURCE_PATH}/include/decaf/point_255.h 148 | ${GSOURCE_PATH}/include/decaf/point_448.h 149 | ${GSOURCE_PATH}/include/decaf/ed255.h 150 | ${GSOURCE_PATH}/include/decaf/ed448.h 151 | ) 152 | 153 | add_subdirectory(curve25519) 154 | add_subdirectory(ed448goldilocks) 155 | 156 | add_custom_target(decaf_tables DEPENDS 157 | decaf_tables_curve25519 158 | decaf_tables_ed448goldilocks 159 | ) 160 | 161 | add_custom_target(generatedCode DEPENDS 162 | generatorCommonCode 163 | generatorEd448goldilocks 164 | generatorCurve25519 165 | ) 166 | -------------------------------------------------------------------------------- /src/sha512.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* Based on DJB's crypto_hashblocks/ref implementation. 4 | * Public domain. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | static uint64_t load_bigendian(const uint8_t *x) 12 | { 13 | return 14 | (uint64_t) (x[7]) \ 15 | | (((uint64_t) (x[6])) << 8) \ 16 | | (((uint64_t) (x[5])) << 16) \ 17 | | (((uint64_t) (x[4])) << 24) \ 18 | | (((uint64_t) (x[3])) << 32) \ 19 | | (((uint64_t) (x[2])) << 40) \ 20 | | (((uint64_t) (x[1])) << 48) \ 21 | | (((uint64_t) (x[0])) << 56) 22 | ; 23 | } 24 | 25 | #define SHR(x,c) ((x) >> (c)) 26 | #define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) 27 | 28 | #define Ch(x,y,z) ((x & y) ^ (~x & z)) 29 | #define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) 30 | #define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) 31 | #define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) 32 | #define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7)) 33 | #define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6)) 34 | 35 | #define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; 36 | 37 | #define EXPAND \ 38 | M(w0 ,w14,w9 ,w1 ) \ 39 | M(w1 ,w15,w10,w2 ) \ 40 | M(w2 ,w0 ,w11,w3 ) \ 41 | M(w3 ,w1 ,w12,w4 ) \ 42 | M(w4 ,w2 ,w13,w5 ) \ 43 | M(w5 ,w3 ,w14,w6 ) \ 44 | M(w6 ,w4 ,w15,w7 ) \ 45 | M(w7 ,w5 ,w0 ,w8 ) \ 46 | M(w8 ,w6 ,w1 ,w9 ) \ 47 | M(w9 ,w7 ,w2 ,w10) \ 48 | M(w10,w8 ,w3 ,w11) \ 49 | M(w11,w9 ,w4 ,w12) \ 50 | M(w12,w10,w5 ,w13) \ 51 | M(w13,w11,w6 ,w14) \ 52 | M(w14,w12,w7 ,w15) \ 53 | M(w15,w13,w8 ,w0 ) 54 | 55 | #define F(w,k) \ 56 | T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ 57 | T2 = Sigma0(a) + Maj(a,b,c); \ 58 | h = g; \ 59 | g = f; \ 60 | f = e; \ 61 | e = d + T1; \ 62 | d = c; \ 63 | c = b; \ 64 | b = a; \ 65 | a = T1 + T2; 66 | 67 | static DECAF_NOINLINE void hashblock(decaf_sha512_ctx_t ctx) { 68 | const uint8_t *in = ctx->block; 69 | uint64_t a = ctx->state[0]; 70 | uint64_t b = ctx->state[1]; 71 | uint64_t c = ctx->state[2]; 72 | uint64_t d = ctx->state[3]; 73 | uint64_t e = ctx->state[4]; 74 | uint64_t f = ctx->state[5]; 75 | uint64_t g = ctx->state[6]; 76 | uint64_t h = ctx->state[7]; 77 | uint64_t T1; 78 | uint64_t T2; 79 | 80 | uint64_t w0 = load_bigendian(in + 0); 81 | uint64_t w1 = load_bigendian(in + 8); 82 | uint64_t w2 = load_bigendian(in + 16); 83 | uint64_t w3 = load_bigendian(in + 24); 84 | uint64_t w4 = load_bigendian(in + 32); 85 | uint64_t w5 = load_bigendian(in + 40); 86 | uint64_t w6 = load_bigendian(in + 48); 87 | uint64_t w7 = load_bigendian(in + 56); 88 | uint64_t w8 = load_bigendian(in + 64); 89 | uint64_t w9 = load_bigendian(in + 72); 90 | uint64_t w10 = load_bigendian(in + 80); 91 | uint64_t w11 = load_bigendian(in + 88); 92 | uint64_t w12 = load_bigendian(in + 96); 93 | uint64_t w13 = load_bigendian(in + 104); 94 | uint64_t w14 = load_bigendian(in + 112); 95 | uint64_t w15 = load_bigendian(in + 120); 96 | 97 | F(w0 ,0x428a2f98d728ae22ULL) 98 | F(w1 ,0x7137449123ef65cdULL) 99 | F(w2 ,0xb5c0fbcfec4d3b2fULL) 100 | F(w3 ,0xe9b5dba58189dbbcULL) 101 | F(w4 ,0x3956c25bf348b538ULL) 102 | F(w5 ,0x59f111f1b605d019ULL) 103 | F(w6 ,0x923f82a4af194f9bULL) 104 | F(w7 ,0xab1c5ed5da6d8118ULL) 105 | F(w8 ,0xd807aa98a3030242ULL) 106 | F(w9 ,0x12835b0145706fbeULL) 107 | F(w10,0x243185be4ee4b28cULL) 108 | F(w11,0x550c7dc3d5ffb4e2ULL) 109 | F(w12,0x72be5d74f27b896fULL) 110 | F(w13,0x80deb1fe3b1696b1ULL) 111 | F(w14,0x9bdc06a725c71235ULL) 112 | F(w15,0xc19bf174cf692694ULL) 113 | 114 | EXPAND 115 | 116 | F(w0 ,0xe49b69c19ef14ad2ULL) 117 | F(w1 ,0xefbe4786384f25e3ULL) 118 | F(w2 ,0x0fc19dc68b8cd5b5ULL) 119 | F(w3 ,0x240ca1cc77ac9c65ULL) 120 | F(w4 ,0x2de92c6f592b0275ULL) 121 | F(w5 ,0x4a7484aa6ea6e483ULL) 122 | F(w6 ,0x5cb0a9dcbd41fbd4ULL) 123 | F(w7 ,0x76f988da831153b5ULL) 124 | F(w8 ,0x983e5152ee66dfabULL) 125 | F(w9 ,0xa831c66d2db43210ULL) 126 | F(w10,0xb00327c898fb213fULL) 127 | F(w11,0xbf597fc7beef0ee4ULL) 128 | F(w12,0xc6e00bf33da88fc2ULL) 129 | F(w13,0xd5a79147930aa725ULL) 130 | F(w14,0x06ca6351e003826fULL) 131 | F(w15,0x142929670a0e6e70ULL) 132 | 133 | EXPAND 134 | 135 | F(w0 ,0x27b70a8546d22ffcULL) 136 | F(w1 ,0x2e1b21385c26c926ULL) 137 | F(w2 ,0x4d2c6dfc5ac42aedULL) 138 | F(w3 ,0x53380d139d95b3dfULL) 139 | F(w4 ,0x650a73548baf63deULL) 140 | F(w5 ,0x766a0abb3c77b2a8ULL) 141 | F(w6 ,0x81c2c92e47edaee6ULL) 142 | F(w7 ,0x92722c851482353bULL) 143 | F(w8 ,0xa2bfe8a14cf10364ULL) 144 | F(w9 ,0xa81a664bbc423001ULL) 145 | F(w10,0xc24b8b70d0f89791ULL) 146 | F(w11,0xc76c51a30654be30ULL) 147 | F(w12,0xd192e819d6ef5218ULL) 148 | F(w13,0xd69906245565a910ULL) 149 | F(w14,0xf40e35855771202aULL) 150 | F(w15,0x106aa07032bbd1b8ULL) 151 | 152 | EXPAND 153 | 154 | F(w0 ,0x19a4c116b8d2d0c8ULL) 155 | F(w1 ,0x1e376c085141ab53ULL) 156 | F(w2 ,0x2748774cdf8eeb99ULL) 157 | F(w3 ,0x34b0bcb5e19b48a8ULL) 158 | F(w4 ,0x391c0cb3c5c95a63ULL) 159 | F(w5 ,0x4ed8aa4ae3418acbULL) 160 | F(w6 ,0x5b9cca4f7763e373ULL) 161 | F(w7 ,0x682e6ff3d6b2b8a3ULL) 162 | F(w8 ,0x748f82ee5defb2fcULL) 163 | F(w9 ,0x78a5636f43172f60ULL) 164 | F(w10,0x84c87814a1f0ab72ULL) 165 | F(w11,0x8cc702081a6439ecULL) 166 | F(w12,0x90befffa23631e28ULL) 167 | F(w13,0xa4506cebde82bde9ULL) 168 | F(w14,0xbef9a3f7b2c67915ULL) 169 | F(w15,0xc67178f2e372532bULL) 170 | 171 | EXPAND 172 | 173 | F(w0 ,0xca273eceea26619cULL) 174 | F(w1 ,0xd186b8c721c0c207ULL) 175 | F(w2 ,0xeada7dd6cde0eb1eULL) 176 | F(w3 ,0xf57d4f7fee6ed178ULL) 177 | F(w4 ,0x06f067aa72176fbaULL) 178 | F(w5 ,0x0a637dc5a2c898a6ULL) 179 | F(w6 ,0x113f9804bef90daeULL) 180 | F(w7 ,0x1b710b35131c471bULL) 181 | F(w8 ,0x28db77f523047d84ULL) 182 | F(w9 ,0x32caab7b40c72493ULL) 183 | F(w10,0x3c9ebe0a15c9bebcULL) 184 | F(w11,0x431d67c49c100d4cULL) 185 | F(w12,0x4cc5d4becb3e42b6ULL) 186 | F(w13,0x597f299cfc657e2aULL) 187 | F(w14,0x5fcb6fab3ad6faecULL) 188 | F(w15,0x6c44198c4a475817ULL) 189 | 190 | ctx->state[0] += a; 191 | ctx->state[1] += b; 192 | ctx->state[2] += c; 193 | ctx->state[3] += d; 194 | ctx->state[4] += e; 195 | ctx->state[5] += f; 196 | ctx->state[6] += g; 197 | ctx->state[7] += h; 198 | } 199 | 200 | void decaf_sha512_init(decaf_sha512_ctx_t ctx) { 201 | static const uint64_t iv[8] = { 202 | 0x6a09e667f3bcc908, 203 | 0xbb67ae8584caa73b, 204 | 0x3c6ef372fe94f82b, 205 | 0xa54ff53a5f1d36f1, 206 | 0x510e527fade682d1, 207 | 0x9b05688c2b3e6c1f, 208 | 0x1f83d9abfb41bd6b, 209 | 0x5be0cd19137e2179 210 | }; 211 | memcpy(ctx->state,iv,sizeof(iv)); 212 | memset(ctx->block,0,sizeof(ctx->block)); 213 | ctx->bytes_processed = 0; 214 | } 215 | 216 | void decaf_sha512_update(decaf_sha512_ctx_t ctx, const uint8_t *message, size_t length) { 217 | while (length > 0) { 218 | size_t grab = length, off = ctx->bytes_processed % 128; 219 | if (grab > 128-off) grab = 128-off; 220 | memcpy(&ctx->block[off], message, grab); 221 | 222 | ctx->bytes_processed += grab; 223 | length -= grab; 224 | message += grab; 225 | 226 | if (grab == 128 - off) { 227 | hashblock(ctx); 228 | } 229 | } 230 | } 231 | 232 | void decaf_sha512_final(decaf_sha512_ctx_t ctx, uint8_t *out, size_t length) { 233 | assert(length <= 512/8); 234 | 235 | size_t off = ctx->bytes_processed % 128; 236 | uint64_t bp = ctx->bytes_processed * 8; 237 | ctx->block[off] = 0x80; 238 | memset(&ctx->block[off+1], 0, 128-off-1); 239 | 240 | if (off >= 112) { 241 | hashblock(ctx); 242 | memset(&ctx->block,0,128); 243 | } 244 | 245 | for (size_t i=0; i<8; i++) 246 | ctx->block[120 + i] = bp >> (56 - 8*i); 247 | hashblock(ctx); 248 | 249 | for (size_t i=0; istate[i/8] >> (56 - 8*(i%8)); 251 | } 252 | 253 | decaf_sha512_init(ctx); 254 | } 255 | -------------------------------------------------------------------------------- /src/public_include/decaf/shake.hxx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file decaf/shake.hxx 3 | * @copyright 4 | * Based on CC0 code by David Leon Gil, 2015 \n 5 | * Copyright (c) 2015 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief SHA-3-n and SHAKE-n instances, C++ wrapper. 9 | */ 10 | 11 | #ifndef __DECAF_SHAKE_HXX__ 12 | #define __DECAF_SHAKE_HXX__ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /** @cond internal */ 19 | #if __cplusplus >= 201103L 20 | #define DECAF_NOEXCEPT noexcept 21 | #define DECAF_DELETE = delete 22 | #else 23 | #define DECAF_NOEXCEPT throw() 24 | #define DECAF_DELETE 25 | #endif 26 | /** @endcond */ 27 | 28 | namespace decaf { 29 | 30 | /** 31 | * Hash function derived from Keccak 32 | * FUTURE: throw ProtocolException when hash is misused by calling update() after output(). 33 | */ 34 | class KeccakHash { 35 | protected: 36 | /** @cond internal */ 37 | /** The C-wrapper sponge state */ 38 | decaf_keccak_sponge_t wrapped; 39 | 40 | /** Initialize from parameters */ 41 | inline KeccakHash(const decaf_kparams_s *params) DECAF_NOEXCEPT { decaf_sha3_init(wrapped, params); } 42 | /** @endcond */ 43 | 44 | public: 45 | /** Add more data to running hash */ 46 | inline void update(const uint8_t *__restrict__ in, size_t len) DECAF_NOEXCEPT { decaf_sha3_update(wrapped,in,len); } 47 | 48 | /** Add more data to running hash, C++ version. */ 49 | inline void update(const Block &s) DECAF_NOEXCEPT { decaf_sha3_update(wrapped,s.data(),s.size()); } 50 | 51 | /** Add more data, stream version. */ 52 | inline KeccakHash &operator<<(const Block &s) DECAF_NOEXCEPT { update(s); return *this; } 53 | 54 | /** Same as <<. */ 55 | inline KeccakHash &operator+=(const Block &s) DECAF_NOEXCEPT { return *this << s; } 56 | 57 | /** @brief Output bytes from the sponge. */ 58 | inline SecureBuffer output(size_t len) /*throw(std::bad_alloc, LengthException)*/ { 59 | if (len > max_output_size()) throw LengthException(); 60 | SecureBuffer buffer(len); 61 | if (DECAF_SUCCESS != decaf_sha3_output(wrapped,buffer.data(),len)) { 62 | throw LengthException(); 63 | } 64 | return buffer; 65 | } 66 | 67 | /** @brief Output bytes from the sponge. */ 68 | inline SecureBuffer final(size_t len) /*throw(std::bad_alloc, LengthException)*/ { 69 | if (len > max_output_size()) throw LengthException(); 70 | SecureBuffer buffer(len); 71 | if (DECAF_SUCCESS != decaf_sha3_final(wrapped,buffer.data(),len)) { 72 | throw LengthException(); 73 | } 74 | return buffer; 75 | } 76 | 77 | /** @brief Output bytes from the sponge. Throw LengthException if you've 78 | * output too many bytes from a SHA-3 instance. 79 | */ 80 | inline void output(Buffer b) /*throw(LengthException)*/ { 81 | if (DECAF_SUCCESS != decaf_sha3_output(wrapped,b.data(),b.size())) { 82 | throw LengthException(); 83 | } 84 | } 85 | 86 | /** @brief Output bytes from the sponge and reinitialize it. Throw 87 | * LengthException if you've output too many bytes from a SHA3 instance. 88 | */ 89 | inline void final(Buffer b) /*throw(LengthException)*/ { 90 | if (DECAF_SUCCESS != decaf_sha3_final(wrapped,b.data(),b.size())) { 91 | throw LengthException(); 92 | } 93 | } 94 | 95 | /** @brief Return the sponge's default output size. */ 96 | inline size_t default_output_size() const DECAF_NOEXCEPT { 97 | return decaf_sha3_default_output_bytes(wrapped); 98 | } 99 | 100 | /** @brief Return the sponge's maximum output size. */ 101 | inline size_t max_output_size() const DECAF_NOEXCEPT { 102 | return decaf_sha3_max_output_bytes(wrapped); 103 | } 104 | 105 | /** Output the default number of bytes. */ 106 | inline SecureBuffer output() /*throw(std::bad_alloc,LengthException)*/ { 107 | return output(default_output_size()); 108 | } 109 | 110 | /** Output the default number of bytes, and reset hash. */ 111 | inline SecureBuffer final() /*throw(std::bad_alloc,LengthException)*/ { 112 | return final(default_output_size()); 113 | } 114 | 115 | /** Reset the hash to the empty string */ 116 | inline void reset() DECAF_NOEXCEPT { decaf_sha3_reset(wrapped); } 117 | 118 | /** Destructor zeroizes state */ 119 | inline ~KeccakHash() DECAF_NOEXCEPT { decaf_sha3_destroy(wrapped); } 120 | }; 121 | 122 | /** Fixed-output-length SHA3 */ 123 | template class SHA3 : public KeccakHash { 124 | private: 125 | /** Get the parameter template block for this hash */ 126 | static inline const struct decaf_kparams_s *get_params(); 127 | 128 | public: 129 | /** Number of bytes of output */ 130 | static const size_t MAX_OUTPUT_BYTES = bits/8; 131 | 132 | /** Number of bytes of output */ 133 | static const size_t DEFAULT_OUTPUT_BYTES = bits/8; 134 | 135 | /** Initializer */ 136 | inline SHA3() DECAF_NOEXCEPT : KeccakHash(get_params()) {} 137 | 138 | /** Hash bytes with this SHA3 instance. 139 | * @throw LengthException if nbytes > MAX_OUTPUT_BYTES 140 | */ 141 | static inline SecureBuffer hash(const Block &b, size_t nbytes = MAX_OUTPUT_BYTES) /*throw(std::bad_alloc, LengthException)*/ { 142 | if (nbytes > MAX_OUTPUT_BYTES) { 143 | throw LengthException(); 144 | } 145 | SHA3 s; s += b; return s.output(nbytes); 146 | } 147 | }; 148 | 149 | /** Variable-output-length SHAKE */ 150 | template 151 | class SHAKE : public KeccakHash { 152 | private: 153 | /** Get the parameter template block for this hash */ 154 | static inline const struct decaf_kparams_s *get_params(); 155 | 156 | public: 157 | /** Number of bytes of output */ 158 | #if __cplusplus >= 201103L 159 | static const size_t MAX_OUTPUT_BYTES = SIZE_MAX; 160 | #else 161 | static const size_t MAX_OUTPUT_BYTES = (size_t)-1; 162 | #endif 163 | 164 | /** Default number of bytes to output */ 165 | static const size_t DEFAULT_OUTPUT_BYTES = bits/4; 166 | 167 | /** Initializer */ 168 | inline SHAKE() DECAF_NOEXCEPT : KeccakHash(get_params()) {} 169 | 170 | /** Hash bytes with this SHAKE instance */ 171 | static inline SecureBuffer hash(const Block &b, size_t outlen) /*throw(std::bad_alloc)*/ { 172 | SHAKE s; s += b; return s.output(outlen); 173 | } 174 | }; 175 | 176 | 177 | #if defined _MSC_VER // MSVC does not want tempalte<> syntax, gcc cannot live without it 178 | /** @cond internal */ 179 | inline const struct decaf_kparams_s *SHAKE<128>::get_params() { return &DECAF_SHAKE128_params_s; } 180 | inline const struct decaf_kparams_s *SHAKE<256>::get_params() { return &DECAF_SHAKE256_params_s; } 181 | inline const struct decaf_kparams_s *SHA3<224>::get_params() { return &DECAF_SHA3_224_params_s; } 182 | inline const struct decaf_kparams_s *SHA3<256>::get_params() { return &DECAF_SHA3_256_params_s; } 183 | inline const struct decaf_kparams_s *SHA3<384>::get_params() { return &DECAF_SHA3_384_params_s; } 184 | inline const struct decaf_kparams_s *SHA3<512>::get_params() { return &DECAF_SHA3_512_params_s; } 185 | /** @endcond */ 186 | #else 187 | /** @cond internal */ 188 | template<> inline const struct decaf_kparams_s *SHAKE<128>::get_params() { return &DECAF_SHAKE128_params_s; } 189 | template<> inline const struct decaf_kparams_s *SHAKE<256>::get_params() { return &DECAF_SHAKE256_params_s; } 190 | template<> inline const struct decaf_kparams_s *SHA3<224>::get_params() { return &DECAF_SHA3_224_params_s; } 191 | template<> inline const struct decaf_kparams_s *SHA3<256>::get_params() { return &DECAF_SHA3_256_params_s; } 192 | template<> inline const struct decaf_kparams_s *SHA3<384>::get_params() { return &DECAF_SHA3_384_params_s; } 193 | template<> inline const struct decaf_kparams_s *SHA3<512>::get_params() { return &DECAF_SHA3_512_params_s; } 194 | /** @endcond */ 195 | #endif 196 | 197 | 198 | } /* namespace decaf */ 199 | 200 | #undef DECAF_NOEXCEPT 201 | #undef DECAF_DELETE 202 | 203 | #endif /* __DECAF_SHAKE_HXX__ */ 204 | -------------------------------------------------------------------------------- /src/shake.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @cond internal 3 | * @file shake.c 4 | * @copyright 5 | * Uses public domain code by Mathias Panzenböck \n 6 | * Uses CC0 code by David Leon Gil, 2015 \n 7 | * Copyright (c) 2015 Cryptography Research, Inc. \n 8 | * Released under the MIT License. See LICENSE.txt for license information. 9 | * @author Mike Hamburg 10 | * @brief SHA-3-n and SHAKE-n instances. 11 | * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change. 12 | */ 13 | 14 | #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ 15 | #define _BSD_SOURCE 1 /* for endian */ 16 | #define _DEFAULT_SOURCE 1 /* for endian with glibc 2.20 */ 17 | #include 18 | #include 19 | #include 20 | 21 | #include "portable_endian.h" 22 | #include "keccak_internal.h" 23 | #include 24 | 25 | #define FLAG_ABSORBING 'A' 26 | #define FLAG_SQUEEZING 'Z' 27 | 28 | /** Constants. **/ 29 | static const uint8_t pi[24] = { 30 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 31 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 32 | }; 33 | 34 | #define RC_B(x,n) ((((x##ull)>>n)&1)<<((1<> (64 - s)); 45 | } 46 | 47 | /* Helper macros to unroll the permutation. */ 48 | #define REPEAT5(e) e e e e e 49 | #define FOR51(v, e) v = 0; REPEAT5(e; v += 1;) 50 | #ifndef SHAKE_NO_UNROLL_LOOPS 51 | # define FOR55(v, e) v = 0; REPEAT5(e; v += 5;) 52 | # define REPEAT24(e) e e e e e e e e e e e e e e e e e e e e e e e e 53 | #else 54 | # define FOR55(v, e) for (v=0; v<25; v+= 5) { e; } 55 | # define REPEAT24(e) {int _j=0; for (_j=0; _j<24; _j++) { e }} 56 | #endif 57 | 58 | /*** The Keccak-f[1600] permutation ***/ 59 | void keccakf(kdomain_t state, uint8_t start_round) { 60 | uint64_t* a = state->w; 61 | uint64_t b[5] = {0}, t, u; 62 | uint8_t x, y, i; 63 | 64 | for (i=0; i<25; i++) a[i] = le64toh(a[i]); 65 | 66 | for (i = start_round; i < 24; i++) { 67 | FOR51(x, b[x] = 0; ) 68 | FOR55(y, FOR51(x, b[x] ^= a[x + y]; )) 69 | FOR55(y, FOR51(x, 70 | a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); 71 | )) 72 | // Rho and pi 73 | t = a[1]; 74 | x = y = 0; 75 | REPEAT24(u = a[pi[x]]; y += x+1; a[pi[x]] = rol(t, y % 64); t = u; x++; ) 76 | // Chi 77 | FOR55(y, 78 | FOR51(x, b[x] = a[y + x];) 79 | FOR51(x, a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]);) 80 | ) 81 | // Iota 82 | a[0] ^= RC[i]; 83 | } 84 | 85 | for (i=0; i<25; i++) a[i] = htole64(a[i]); 86 | } 87 | 88 | decaf_error_t decaf_sha3_update ( 89 | struct decaf_keccak_sponge_s * __restrict__ decaf_sponge, 90 | const uint8_t *in, 91 | size_t len 92 | ) { 93 | assert(decaf_sponge->params->position < decaf_sponge->params->rate); 94 | assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); 95 | assert(decaf_sponge->params->flags == FLAG_ABSORBING); 96 | while (len) { 97 | size_t cando = decaf_sponge->params->rate - decaf_sponge->params->position, i; 98 | uint8_t* state = &decaf_sponge->state->b[decaf_sponge->params->position]; 99 | if (cando > len) { 100 | for (i = 0; i < len; i += 1) state[i] ^= in[i]; 101 | decaf_sponge->params->position += len; 102 | break; 103 | } else { 104 | for (i = 0; i < cando; i += 1) state[i] ^= in[i]; 105 | dokeccak(decaf_sponge); 106 | len -= cando; 107 | in += cando; 108 | } 109 | } 110 | return (decaf_sponge->params->flags == FLAG_ABSORBING) ? DECAF_SUCCESS : DECAF_FAILURE; 111 | } 112 | 113 | decaf_error_t decaf_sha3_output ( 114 | decaf_keccak_sponge_t decaf_sponge, 115 | uint8_t * __restrict__ out, 116 | size_t len 117 | ) { 118 | decaf_error_t ret = DECAF_SUCCESS; 119 | assert(decaf_sponge->params->position < decaf_sponge->params->rate); 120 | assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); 121 | 122 | if (decaf_sponge->params->max_out != 0xFF) { 123 | if (decaf_sponge->params->remaining >= len) { 124 | decaf_sponge->params->remaining -= len; 125 | } else { 126 | decaf_sponge->params->remaining = 0; 127 | ret = DECAF_FAILURE; 128 | } 129 | } 130 | 131 | switch (decaf_sponge->params->flags) { 132 | case FLAG_SQUEEZING: break; 133 | case FLAG_ABSORBING: 134 | { 135 | uint8_t* state = decaf_sponge->state->b; 136 | state[decaf_sponge->params->position] ^= decaf_sponge->params->pad; 137 | state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad; 138 | dokeccak(decaf_sponge); 139 | decaf_sponge->params->flags = FLAG_SQUEEZING; 140 | break; 141 | } 142 | default: 143 | assert(0); 144 | } 145 | 146 | while (len) { 147 | size_t cando = decaf_sponge->params->rate - decaf_sponge->params->position; 148 | uint8_t* state = &decaf_sponge->state->b[decaf_sponge->params->position]; 149 | if (cando > len) { 150 | memcpy(out, state, len); 151 | decaf_sponge->params->position += len; 152 | return ret; 153 | } else { 154 | memcpy(out, state, cando); 155 | dokeccak(decaf_sponge); 156 | len -= cando; 157 | out += cando; 158 | } 159 | } 160 | return ret; 161 | } 162 | 163 | decaf_error_t decaf_sha3_final ( 164 | decaf_keccak_sponge_t decaf_sponge, 165 | uint8_t * __restrict__ out, 166 | size_t len 167 | ) { 168 | decaf_error_t ret = decaf_sha3_output(decaf_sponge,out,len); 169 | decaf_sha3_reset(decaf_sponge); 170 | return ret; 171 | } 172 | 173 | void decaf_sha3_reset ( 174 | decaf_keccak_sponge_t decaf_sponge 175 | ) { 176 | decaf_sha3_init(decaf_sponge, decaf_sponge->params); 177 | decaf_sponge->params->flags = FLAG_ABSORBING; 178 | decaf_sponge->params->remaining = decaf_sponge->params->max_out; 179 | } 180 | 181 | void decaf_sha3_destroy (decaf_keccak_sponge_t decaf_sponge) { 182 | decaf_bzero(decaf_sponge, sizeof(decaf_keccak_sponge_t)); 183 | } 184 | 185 | void decaf_sha3_init ( 186 | decaf_keccak_sponge_t decaf_sponge, 187 | const struct decaf_kparams_s *params 188 | ) { 189 | memset(decaf_sponge->state, 0, sizeof(decaf_sponge->state)); 190 | decaf_sponge->params[0] = params[0]; 191 | decaf_sponge->params->position = 0; 192 | } 193 | 194 | decaf_error_t decaf_sha3_hash ( 195 | uint8_t *out, 196 | size_t outlen, 197 | const uint8_t *in, 198 | size_t inlen, 199 | const struct decaf_kparams_s *params 200 | ) { 201 | decaf_keccak_sponge_t decaf_sponge; 202 | decaf_sha3_init(decaf_sponge, params); 203 | decaf_sha3_update(decaf_sponge, in, inlen); 204 | decaf_error_t ret = decaf_sha3_output(decaf_sponge, out, outlen); 205 | decaf_sha3_destroy(decaf_sponge); 206 | return ret; 207 | } 208 | 209 | #define DEFSHAKE(n) \ 210 | const struct decaf_kparams_s DECAF_SHAKE##n##_params_s = \ 211 | { 0, FLAG_ABSORBING, 200-n/4, 0, 0x1f, 0x80, 0xFF, 0xFF }; 212 | 213 | #define DEFSHA3(n) \ 214 | const struct decaf_kparams_s DECAF_SHA3_##n##_params_s = \ 215 | { 0, FLAG_ABSORBING, 200-n/4, 0, 0x06, 0x80, n/8, n/8 }; 216 | 217 | size_t decaf_sha3_default_output_bytes ( 218 | const decaf_keccak_sponge_t s 219 | ) { 220 | return (s->params->max_out == 0xFF) 221 | ? (200-s->params->rate) 222 | : ((200-s->params->rate)/2); 223 | } 224 | 225 | size_t decaf_sha3_max_output_bytes ( 226 | const decaf_keccak_sponge_t s 227 | ) { 228 | return (s->params->max_out == 0xFF) 229 | ? SIZE_MAX 230 | : (size_t)((200-s->params->rate)/2); 231 | } 232 | 233 | DEFSHAKE(128) 234 | DEFSHAKE(256) 235 | DEFSHA3(224) 236 | DEFSHA3(256) 237 | DEFSHA3(384) 238 | DEFSHA3(512) 239 | 240 | /* FUTURE: Keyak instances, etc */ 241 | -------------------------------------------------------------------------------- /src/p448/arch_x86_64/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | void gf_mul (gf_s *__restrict__ cs, const gf as, const gf bs) { 8 | const uint64_t *a = as->limb, *b = bs->limb; 9 | uint64_t *c = cs->limb; 10 | 11 | __uint128_t accum0 = 0, accum1 = 0, accum2; 12 | uint64_t mask = (1ull<<56) - 1; 13 | 14 | uint64_t aa[4] VECTOR_ALIGNED, bb[4] VECTOR_ALIGNED, bbb[4] VECTOR_ALIGNED; 15 | 16 | /* For some reason clang doesn't vectorize this without prompting? */ 17 | unsigned int i; 18 | for (i=0; i>= 56; 53 | accum1 >>= 56; 54 | 55 | mac(&accum0, &aa[1],&bb[3]); 56 | mac(&accum1, &a[5], &b[7]); 57 | mac(&accum0, &aa[2], &bb[2]); 58 | mac(&accum1, &a[6], &b[6]); 59 | mac(&accum0, &aa[3], &bb[1]); 60 | accum1 += accum0; 61 | 62 | accum2 = widemul(&a[0],&b[0]); 63 | accum1 -= accum2; 64 | accum0 += accum2; 65 | 66 | msb(&accum0, &a[1], &b[3]); 67 | msb(&accum0, &a[2], &b[2]); 68 | mac(&accum1, &a[7], &b[5]); 69 | msb(&accum0, &a[3], &b[1]); 70 | mac(&accum1, &aa[0], &bb[0]); 71 | mac(&accum0, &a[4], &b[4]); 72 | 73 | c[0] = ((uint64_t)(accum0)) & mask; 74 | c[4] = ((uint64_t)(accum1)) & mask; 75 | 76 | accum0 >>= 56; 77 | accum1 >>= 56; 78 | 79 | accum2 = widemul(&a[2],&b[7]); 80 | mac(&accum0, &a[6], &bb[3]); 81 | mac(&accum1, &aa[2], &bbb[3]); 82 | 83 | mac(&accum2, &a[3], &b[6]); 84 | mac(&accum0, &a[7], &bb[2]); 85 | mac(&accum1, &aa[3], &bbb[2]); 86 | 87 | mac(&accum2, &a[0],&b[1]); 88 | mac(&accum1, &aa[0], &bb[1]); 89 | mac(&accum0, &a[4], &b[5]); 90 | 91 | mac(&accum2, &a[1], &b[0]); 92 | mac(&accum1, &aa[1], &bb[0]); 93 | mac(&accum0, &a[5], &b[4]); 94 | 95 | accum1 -= accum2; 96 | accum0 += accum2; 97 | 98 | c[1] = ((uint64_t)(accum0)) & mask; 99 | c[5] = ((uint64_t)(accum1)) & mask; 100 | 101 | accum0 >>= 56; 102 | accum1 >>= 56; 103 | 104 | accum2 = widemul(&a[3],&b[7]); 105 | mac(&accum0, &a[7], &bb[3]); 106 | mac(&accum1, &aa[3], &bbb[3]); 107 | 108 | mac(&accum2, &a[0],&b[2]); 109 | mac(&accum1, &aa[0], &bb[2]); 110 | mac(&accum0, &a[4], &b[6]); 111 | 112 | mac(&accum2, &a[1], &b[1]); 113 | mac(&accum1, &aa[1], &bb[1]); 114 | mac(&accum0, &a[5], &b[5]); 115 | 116 | mac(&accum2, &a[2], &b[0]); 117 | mac(&accum1, &aa[2], &bb[0]); 118 | mac(&accum0, &a[6], &b[4]); 119 | 120 | accum1 -= accum2; 121 | accum0 += accum2; 122 | 123 | c[2] = ((uint64_t)(accum0)) & mask; 124 | c[6] = ((uint64_t)(accum1)) & mask; 125 | 126 | accum0 >>= 56; 127 | accum1 >>= 56; 128 | 129 | accum0 += c[3]; 130 | accum1 += c[7]; 131 | c[3] = ((uint64_t)(accum0)) & mask; 132 | c[7] = ((uint64_t)(accum1)) & mask; 133 | 134 | /* we could almost stop here, but it wouldn't be stable, so... */ 135 | 136 | accum0 >>= 56; 137 | accum1 >>= 56; 138 | c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1)); 139 | c[0] += ((uint64_t)(accum1)); 140 | } 141 | 142 | void gf_mulw_unsigned (gf_s *__restrict__ cs, const gf as, uint32_t b) { 143 | const uint64_t *a = as->limb; 144 | uint64_t *c = cs->limb; 145 | 146 | __uint128_t accum0, accum4; 147 | uint64_t mask = (1ull<<56) - 1; 148 | 149 | accum0 = widemul_rm(b, &a[0]); 150 | accum4 = widemul_rm(b, &a[4]); 151 | 152 | c[0] = accum0 & mask; accum0 >>= 56; 153 | c[4] = accum4 & mask; accum4 >>= 56; 154 | 155 | mac_rm(&accum0, b, &a[1]); 156 | mac_rm(&accum4, b, &a[5]); 157 | 158 | c[1] = accum0 & mask; accum0 >>= 56; 159 | c[5] = accum4 & mask; accum4 >>= 56; 160 | 161 | mac_rm(&accum0, b, &a[2]); 162 | mac_rm(&accum4, b, &a[6]); 163 | 164 | c[2] = accum0 & mask; accum0 >>= 56; 165 | c[6] = accum4 & mask; accum4 >>= 56; 166 | 167 | mac_rm(&accum0, b, &a[3]); 168 | mac_rm(&accum4, b, &a[7]); 169 | 170 | c[3] = accum0 & mask; accum0 >>= 56; 171 | c[7] = accum4 & mask; accum4 >>= 56; 172 | 173 | accum0 += accum4 + c[4]; 174 | c[4] = accum0 & mask; 175 | c[5] += accum0 >> 56; 176 | 177 | accum4 += c[0]; 178 | c[0] = accum4 & mask; 179 | c[1] += accum4 >> 56; 180 | } 181 | 182 | void gf_sqr (gf_s *__restrict__ cs, const gf as) { 183 | const uint64_t *a = as->limb; 184 | uint64_t *c = cs->limb; 185 | 186 | __uint128_t accum0 = 0, accum1 = 0, accum2; 187 | uint64_t mask = (1ull<<56) - 1; 188 | 189 | uint64_t aa[4] VECTOR_ALIGNED; 190 | 191 | /* For some reason clang doesn't vectorize this without prompting? */ 192 | unsigned int i; 193 | for (i=0; i>= 55; 212 | accum1 >>= 55; 213 | 214 | mac2(&accum0, &aa[1],&aa[3]); 215 | mac2(&accum1, &a[5], &a[7]); 216 | mac(&accum0, &aa[2], &aa[2]); 217 | accum1 += accum0; 218 | 219 | msb2(&accum0, &a[1], &a[3]); 220 | mac(&accum1, &a[6], &a[6]); 221 | 222 | accum2 = widemul(&a[0],&a[0]); 223 | accum1 -= accum2; 224 | accum0 += accum2; 225 | 226 | msb(&accum0, &a[2], &a[2]); 227 | mac(&accum1, &aa[0], &aa[0]); 228 | mac(&accum0, &a[4], &a[4]); 229 | 230 | c[0] = ((uint64_t)(accum0)) & mask; 231 | c[4] = ((uint64_t)(accum1)) & mask; 232 | 233 | accum0 >>= 56; 234 | accum1 >>= 56; 235 | 236 | accum2 = widemul2(&aa[2],&aa[3]); 237 | msb2(&accum0, &a[2], &a[3]); 238 | mac2(&accum1, &a[6], &a[7]); 239 | 240 | accum1 += accum2; 241 | accum0 += accum2; 242 | 243 | accum2 = widemul2(&a[0],&a[1]); 244 | mac2(&accum1, &aa[0], &aa[1]); 245 | mac2(&accum0, &a[4], &a[5]); 246 | 247 | accum1 -= accum2; 248 | accum0 += accum2; 249 | 250 | c[1] = ((uint64_t)(accum0)) & mask; 251 | c[5] = ((uint64_t)(accum1)) & mask; 252 | 253 | accum0 >>= 56; 254 | accum1 >>= 56; 255 | 256 | accum2 = widemul(&aa[3],&aa[3]); 257 | msb(&accum0, &a[3], &a[3]); 258 | mac(&accum1, &a[7], &a[7]); 259 | 260 | accum1 += accum2; 261 | accum0 += accum2; 262 | 263 | accum2 = widemul2(&a[0],&a[2]); 264 | mac2(&accum1, &aa[0], &aa[2]); 265 | mac2(&accum0, &a[4], &a[6]); 266 | 267 | mac(&accum2, &a[1], &a[1]); 268 | mac(&accum1, &aa[1], &aa[1]); 269 | mac(&accum0, &a[5], &a[5]); 270 | 271 | accum1 -= accum2; 272 | accum0 += accum2; 273 | 274 | c[2] = ((uint64_t)(accum0)) & mask; 275 | c[6] = ((uint64_t)(accum1)) & mask; 276 | 277 | accum0 >>= 56; 278 | accum1 >>= 56; 279 | 280 | accum0 += c[3]; 281 | accum1 += c[7]; 282 | c[3] = ((uint64_t)(accum0)) & mask; 283 | c[7] = ((uint64_t)(accum1)) & mask; 284 | 285 | /* we could almost stop here, but it wouldn't be stable, so... */ 286 | 287 | accum0 >>= 56; 288 | accum1 >>= 56; 289 | c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1)); 290 | c[0] += ((uint64_t)(accum1)); 291 | } 292 | -------------------------------------------------------------------------------- /_aux/attic/p480/arch_x86_64/f_impl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014 Cryptography Research, Inc. 2 | * Released under the MIT License. See LICENSE.txt for license information. 3 | */ 4 | 5 | #include "f_field.h" 6 | 7 | void gf_mul (gf *__restrict__ cs, const gf *as, const gf *bs) { 8 | const uint64_t *a = as->limb, *b = bs->limb; 9 | uint64_t *c = cs->limb; 10 | 11 | __uint128_t accum0 = 0, accum1 = 0, accum2; 12 | uint64_t mask = (1ull<<60) - 1; 13 | 14 | uint64_t aa[4] __attribute__((aligned(32))), bb[4] __attribute__((aligned(32))), bbb[4] __attribute__((aligned(32))); 15 | 16 | /* For some reason clang doesn't vectorize this without prompting? */ 17 | unsigned int i; 18 | for (i=0; i>= 60; 53 | accum1 >>= 60; 54 | 55 | mac(&accum0, &aa[1],&bb[3]); 56 | mac(&accum1, &a[5], &b[7]); 57 | mac(&accum0, &aa[2], &bb[2]); 58 | mac(&accum1, &a[6], &b[6]); 59 | mac(&accum0, &aa[3], &bb[1]); 60 | accum1 += accum0; 61 | 62 | accum2 = widemul(&a[0],&b[0]); 63 | accum1 -= accum2; 64 | accum0 += accum2; 65 | 66 | msb(&accum0, &a[1], &b[3]); 67 | msb(&accum0, &a[2], &b[2]); 68 | mac(&accum1, &a[7], &b[5]); 69 | msb(&accum0, &a[3], &b[1]); 70 | mac(&accum1, &aa[0], &bb[0]); 71 | mac(&accum0, &a[4], &b[4]); 72 | 73 | c[0] = ((uint64_t)(accum0)) & mask; 74 | c[4] = ((uint64_t)(accum1)) & mask; 75 | 76 | accum0 >>= 60; 77 | accum1 >>= 60; 78 | 79 | accum2 = widemul(&a[2],&b[7]); 80 | mac(&accum0, &a[6], &bb[3]); 81 | mac(&accum1, &aa[2], &bbb[3]); 82 | 83 | mac(&accum2, &a[3], &b[6]); 84 | mac(&accum0, &a[7], &bb[2]); 85 | mac(&accum1, &aa[3], &bbb[2]); 86 | 87 | mac(&accum2, &a[0],&b[1]); 88 | mac(&accum1, &aa[0], &bb[1]); 89 | mac(&accum0, &a[4], &b[5]); 90 | 91 | mac(&accum2, &a[1], &b[0]); 92 | mac(&accum1, &aa[1], &bb[0]); 93 | mac(&accum0, &a[5], &b[4]); 94 | 95 | accum1 -= accum2; 96 | accum0 += accum2; 97 | 98 | c[1] = ((uint64_t)(accum0)) & mask; 99 | c[5] = ((uint64_t)(accum1)) & mask; 100 | 101 | accum0 >>= 60; 102 | accum1 >>= 60; 103 | 104 | accum2 = widemul(&a[3],&b[7]); 105 | mac(&accum0, &a[7], &bb[3]); 106 | mac(&accum1, &aa[3], &bbb[3]); 107 | 108 | mac(&accum2, &a[0],&b[2]); 109 | mac(&accum1, &aa[0], &bb[2]); 110 | mac(&accum0, &a[4], &b[6]); 111 | 112 | mac(&accum2, &a[1], &b[1]); 113 | mac(&accum1, &aa[1], &bb[1]); 114 | mac(&accum0, &a[5], &b[5]); 115 | 116 | mac(&accum2, &a[2], &b[0]); 117 | mac(&accum1, &aa[2], &bb[0]); 118 | mac(&accum0, &a[6], &b[4]); 119 | 120 | accum1 -= accum2; 121 | accum0 += accum2; 122 | 123 | c[2] = ((uint64_t)(accum0)) & mask; 124 | c[6] = ((uint64_t)(accum1)) & mask; 125 | 126 | accum0 >>= 60; 127 | accum1 >>= 60; 128 | 129 | accum0 += c[3]; 130 | accum1 += c[7]; 131 | c[3] = ((uint64_t)(accum0)) & mask; 132 | c[7] = ((uint64_t)(accum1)) & mask; 133 | 134 | /* we could almost stop here, but it wouldn't be stable, so... */ 135 | 136 | accum0 >>= 60; 137 | accum1 >>= 60; 138 | c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1)); 139 | c[0] += ((uint64_t)(accum1)); 140 | } 141 | 142 | void gf_mulw (gf *__restrict__ cs, const gf *as, uint64_t b) { 143 | const uint64_t *a = as->limb; 144 | uint64_t *c = cs->limb; 145 | 146 | __uint128_t accum0, accum4; 147 | uint64_t mask = (1ull<<60) - 1; 148 | 149 | accum0 = widemul_rm(b, &a[0]); 150 | accum4 = widemul_rm(b, &a[4]); 151 | 152 | c[0] = accum0 & mask; accum0 >>= 60; 153 | c[4] = accum4 & mask; accum4 >>= 60; 154 | 155 | mac_rm(&accum0, b, &a[1]); 156 | mac_rm(&accum4, b, &a[5]); 157 | 158 | c[1] = accum0 & mask; accum0 >>= 60; 159 | c[5] = accum4 & mask; accum4 >>= 60; 160 | 161 | mac_rm(&accum0, b, &a[2]); 162 | mac_rm(&accum4, b, &a[6]); 163 | 164 | c[2] = accum0 & mask; accum0 >>= 60; 165 | c[6] = accum4 & mask; accum4 >>= 60; 166 | 167 | mac_rm(&accum0, b, &a[3]); 168 | mac_rm(&accum4, b, &a[7]); 169 | 170 | c[3] = accum0 & mask; accum0 >>= 60; 171 | c[7] = accum4 & mask; accum4 >>= 60; 172 | 173 | accum0 += accum4 + c[4]; 174 | c[4] = accum0 & mask; 175 | c[5] += accum0 >> 60; 176 | 177 | accum4 += c[0]; 178 | c[0] = accum4 & mask; 179 | c[1] += accum4 >> 60; 180 | } 181 | 182 | void gf_sqr (gf *__restrict__ cs, const gf *as) { 183 | const uint64_t *a = as->limb; 184 | uint64_t *c = cs->limb; 185 | 186 | __uint128_t accum0 = 0, accum1 = 0, accum2; 187 | uint64_t mask = (1ull<<60) - 1; 188 | 189 | uint64_t aa[4] __attribute__((aligned(32))); 190 | 191 | /* For some reason clang doesn't vectorize this without prompting? */ 192 | unsigned int i; 193 | for (i=0; i>= 59; 212 | accum1 >>= 59; 213 | 214 | mac2(&accum0, &aa[1],&aa[3]); 215 | mac2(&accum1, &a[5], &a[7]); 216 | mac(&accum0, &aa[2], &aa[2]); 217 | accum1 += accum0; 218 | 219 | msb2(&accum0, &a[1], &a[3]); 220 | mac(&accum1, &a[6], &a[6]); 221 | 222 | accum2 = widemul(&a[0],&a[0]); 223 | accum1 -= accum2; 224 | accum0 += accum2; 225 | 226 | msb(&accum0, &a[2], &a[2]); 227 | mac(&accum1, &aa[0], &aa[0]); 228 | mac(&accum0, &a[4], &a[4]); 229 | 230 | c[0] = ((uint64_t)(accum0)) & mask; 231 | c[4] = ((uint64_t)(accum1)) & mask; 232 | 233 | accum0 >>= 60; 234 | accum1 >>= 60; 235 | 236 | accum2 = widemul2(&aa[2],&aa[3]); 237 | msb2(&accum0, &a[2], &a[3]); 238 | mac2(&accum1, &a[6], &a[7]); 239 | 240 | accum1 += accum2; 241 | accum0 += accum2; 242 | 243 | accum2 = widemul2(&a[0],&a[1]); 244 | mac2(&accum1, &aa[0], &aa[1]); 245 | mac2(&accum0, &a[4], &a[5]); 246 | 247 | accum1 -= accum2; 248 | accum0 += accum2; 249 | 250 | c[1] = ((uint64_t)(accum0)) & mask; 251 | c[5] = ((uint64_t)(accum1)) & mask; 252 | 253 | accum0 >>= 60; 254 | accum1 >>= 60; 255 | 256 | accum2 = widemul(&aa[3],&aa[3]); 257 | msb(&accum0, &a[3], &a[3]); 258 | mac(&accum1, &a[7], &a[7]); 259 | 260 | accum1 += accum2; 261 | accum0 += accum2; 262 | 263 | accum2 = widemul2(&a[0],&a[2]); 264 | mac2(&accum1, &aa[0], &aa[2]); 265 | mac2(&accum0, &a[4], &a[6]); 266 | 267 | mac(&accum2, &a[1], &a[1]); 268 | mac(&accum1, &aa[1], &aa[1]); 269 | mac(&accum0, &a[5], &a[5]); 270 | 271 | accum1 -= accum2; 272 | accum0 += accum2; 273 | 274 | c[2] = ((uint64_t)(accum0)) & mask; 275 | c[6] = ((uint64_t)(accum1)) & mask; 276 | 277 | accum0 >>= 60; 278 | accum1 >>= 60; 279 | 280 | accum0 += c[3]; 281 | accum1 += c[7]; 282 | c[3] = ((uint64_t)(accum0)) & mask; 283 | c[7] = ((uint64_t)(accum1)) & mask; 284 | 285 | /* we could almost stop here, but it wouldn't be stable, so... */ 286 | 287 | accum0 >>= 60; 288 | accum1 >>= 60; 289 | c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1)); 290 | c[0] += ((uint64_t)(accum1)); 291 | } 292 | -------------------------------------------------------------------------------- /test/ristretto.cxx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ristretto.cxx 3 | * @author Mike Hamburg 4 | * 5 | * @copyright 6 | * Copyright (c) 2015 Cryptography Research, Inc. \n 7 | * Released under the MIT License. See LICENSE.txt for license information. 8 | * 9 | * @brief Ristretto implementation widget 10 | */ 11 | 12 | #include 13 | #include 14 | using namespace decaf; 15 | 16 | static inline int hexi(char c) { 17 | if (c >= '0' && c <= '9') return c-'0'; 18 | if (c >= 'a' && c <= 'f') return c-'a'+0xa; 19 | if (c >= 'A' && c <= 'F') return c-'A'+0xa; 20 | return -1; 21 | } 22 | 23 | static int parsehex(uint8_t *out, size_t sizeof_out, const char *hex) { 24 | size_t l = strlen(hex); 25 | if (l%2 != 0) { 26 | fprintf(stderr,"String should be hex, but has odd length\n: %s\n", hex); 27 | return -1; 28 | } else if (l/2 > sizeof_out) { 29 | fprintf(stderr,"Argument is too long: %s\n", hex); 30 | return -1; 31 | } 32 | 33 | memset(out,0,sizeof_out); 34 | int ret1,ret2; 35 | for (size_t i=0; i 0; in++,sizeof_in--) { 48 | printf("%02x",*in); 49 | } 50 | } 51 | 52 | 53 | static int g_argc = 0; 54 | static char **g_argv = NULL; 55 | static int error = 0; 56 | static int done = 0; 57 | 58 | static void usage() { 59 | const char *me=g_argv[0]; 60 | if (!me) me = "ristretto"; 61 | for (unsigned i=0; g_argv[0][i]; i++) { 62 | if (g_argv[0][i] == '/' && g_argv[0][i+1] != 0 && g_argv[0][i+1] != '/') { 63 | me = &g_argv[0][i]; 64 | } 65 | } 66 | 67 | fprintf(stderr,"Usage: %s [points] [operations] ...\n", me); 68 | fprintf(stderr," -b 255|448: Set which group to use (sometimes inferred from lengths)\n"); 69 | fprintf(stderr," -E: Display output as Elligator inverses\n"); 70 | fprintf(stderr," -D: Display output in EdDSA format (times clearing ratio)\n"); 71 | fprintf(stderr," -R: Display raw xyzt\n"); 72 | fprintf(stderr," -C: Display output in X[25519|448] format\n"); 73 | fprintf(stderr," -H: ... divide by encoding ratio first\n"); 74 | fprintf(stderr,"\n"); 75 | fprintf(stderr," Ways to create points:\n"); 76 | fprintf(stderr," [hex]: Point from point data as hex\n"); 77 | fprintf(stderr," -e [hex]: Create point by hashing to curve using elligator\n"); 78 | fprintf(stderr," base: Base point of curve\n"); 79 | fprintf(stderr," identity: Identity point of curve\n"); 80 | fprintf(stderr,"\n"); 81 | fprintf(stderr," Operations:\n"); 82 | fprintf(stderr," -n [point]: negative of point\n"); 83 | fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n"); 84 | fprintf(stderr," [point] + [point]: Add two points\n"); 85 | fprintf(stderr,"\n"); 86 | fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n"); 87 | fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n"); 88 | fprintf(stderr," It's only for debugging!\n"); 89 | fprintf(stderr,"\n"); 90 | 91 | exit(-2); 92 | } 93 | 94 | template class Run { 95 | public: 96 | static void run() { 97 | uint8_t tmp[Group::Point::SER_BYTES]; 98 | typename Group::Point a,b; 99 | typename Group::Scalar s; 100 | bool plus=false, empty=true, elligator=false, mul=false, scalar=false, div=false, torque=false, 101 | scalarempty=true, neg=false, einv=false, like_eddsa=false, like_x=false, decoeff=false, raw=false; 102 | if (done || error) return; 103 | for (int i=1; i(); 212 | if (!done) usage(); 213 | return (error<0) ? -error : error; 214 | } 215 | --------------------------------------------------------------------------------