You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by km...@apache.org on 2019/02/08 08:06:31 UTC
[incubator-milagro-crypto] 01/15: Initial commit
This is an automated email from the ASF dual-hosted git repository.
kmccusker pushed a commit to branch update-code
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto.git
commit 6e5eaaffd6ca71e4c0f501a314e684e505a3abd3
Author: Vladislav Mitov <vl...@gmail.com>
AuthorDate: Thu Mar 10 15:13:17 2016 +0200
Initial commit
---
.gitignore | 8 +
AMCL.pdf | Bin 0 -> 79790 bytes
CMakeLists.txt | 179 ++
LICENSE | 202 ++
NOTICE | 5 +
README.md | 42 +
bigtobig.cpp | 292 +++
bngen.cpp | 511 ++++
bower.json | 47 +
c/CMakeLists.txt | 218 ++
c/DLLDefines.h | 49 +
c/aes.c | 620 +++++
c/amcl.h.in | 2510 ++++++++++++++++++++
c/amcl_.h | 2501 +++++++++++++++++++
c/big.c | 1210 ++++++++++
c/build_ec | 24 +
c/build_ec.bat | 24 +
c/build_pair | 28 +
c/build_pair.bat | 28 +
c/build_pair_ms.bat | 28 +
c/ecdh.c | 576 +++++
c/ecdh.h | 204 ++
c/ecp.c | 1091 +++++++++
c/ecp2.c | 666 ++++++
c/ff.c | 1050 ++++++++
c/fp.c | 559 +++++
c/fp12.c | 688 ++++++
c/fp2.c | 421 ++++
c/fp4.c | 636 +++++
c/gcm.c | 368 +++
c/hash.c | 171 ++
c/maxstack.c | 62 +
c/mpin.c | 1115 +++++++++
c/mpin.h | 364 +++
c/oct.c | 388 +++
c/pair.c | 652 +++++
c/rand.c | 161 ++
c/readme.txt | 62 +
c/rom.c | 852 +++++++
c/rsa.c | 304 +++
c/rsa.h | 96 +
c/testecdh.c | 175 ++
c/testecm.c | 124 +
c/testmpin.c | 273 +++
c/testrsa.c | 79 +
c/tests/CMakeLists.txt | 67 +
c/tests/config.h.in | 2 +
c/tests/test_ecdh.c | 168 ++
c/tests/test_ecm.c | 118 +
c/tests/test_mpin.c | 257 ++
c/tests/test_mpin_bad_pin.c | 268 +++
c/tests/test_mpin_bad_token.c | 268 +++
c/tests/test_mpin_expired_tp.c | 262 ++
c/tests/test_mpin_good.c | 274 +++
c/tests/test_mpin_random.c | 314 +++
c/tests/test_mpin_sign.c | 335 +++
c/tests/test_mpin_tp.c | 281 +++
c/tests/test_mpinfull.c | 298 +++
c/tests/test_mpinfull_random.c | 344 +++
c/tests/test_rsa.c | 82 +
c/tests/test_version.c | 35 +
c/utils.c | 97 +
c/utils.h | 30 +
c/version.c | 32 +
c/version.h | 30 +
cmake_uninstall.cmake.in | 23 +
cs/AES.cs | 531 +++++
cs/BIG.cs | 1145 +++++++++
cs/DBIG.cs | 374 +++
cs/ECDH.cs | 778 ++++++
cs/ECP.cs | 1216 ++++++++++
cs/ECP2.cs | 771 ++++++
cs/FF.cs | 1084 +++++++++
cs/FP.cs | 368 +++
cs/FP12.cs | 769 ++++++
cs/FP2.cs | 428 ++++
cs/FP4.cs | 633 +++++
cs/GCM.cs | 500 ++++
cs/HASH.cs | 240 ++
cs/MPIN.cs | 916 +++++++
cs/PAIR.cs | 586 +++++
cs/RAND.cs | 200 ++
cs/ROM.cs | 434 ++++
cs/RSA.cs | 443 ++++
cs/RectangularArrays.cs | 29 +
cs/StringHelperClass.cs | 90 +
cs/TestECDH.cs | 210 ++
cs/TestECM.cs | 141 ++
cs/TestMPIN.cs | 298 +++
cs/TestRSA.cs | 72 +
cs/readme.txt | 30 +
data/icon.bmp | Bin 0 -> 129738 bytes
data/icon.ico | Bin 0 -> 133982 bytes
docs/AMCL.dox | 266 +++
docs/CMakeLists.txt | 11 +
docs/Doxyfile.in | 1795 ++++++++++++++
docs/README.txt | 16 +
ecgen.cpp | 340 +++
go/readme.txt | 28 +
go/src/github.com/miracl/amcl-cgo/crypto.go | 649 +++++
go/src/github.com/miracl/amcl-cgo/crypto_test.go | 768 ++++++
go/src/github.com/miracl/amcl-go/AES.go | 634 +++++
go/src/github.com/miracl/amcl-go/BIG.go | 956 ++++++++
go/src/github.com/miracl/amcl-go/DBIG.go | 260 ++
go/src/github.com/miracl/amcl-go/ECDH.go | 657 +++++
go/src/github.com/miracl/amcl-go/ECP.go | 1076 +++++++++
go/src/github.com/miracl/amcl-go/ECP2.go | 672 ++++++
go/src/github.com/miracl/amcl-go/FF.go | 926 ++++++++
go/src/github.com/miracl/amcl-go/FP.go | 288 +++
go/src/github.com/miracl/amcl-go/FP12.go | 654 +++++
go/src/github.com/miracl/amcl-go/FP2.go | 324 +++
go/src/github.com/miracl/amcl-go/FP4.go | 522 ++++
go/src/github.com/miracl/amcl-go/GCM.go | 472 ++++
go/src/github.com/miracl/amcl-go/HASH.go | 215 ++
go/src/github.com/miracl/amcl-go/MPIN.go | 807 +++++++
go/src/github.com/miracl/amcl-go/MPIN_test.go | 898 +++++++
go/src/github.com/miracl/amcl-go/PAIR.go | 541 +++++
go/src/github.com/miracl/amcl-go/RAND.go | 187 ++
go/src/github.com/miracl/amcl-go/ROM.go | 353 +++
go/src/github.com/miracl/amcl-go/RSA.go | 373 +++
go/src/github.com/miracl/amcl-go/UTILS.go | 45 +
go/src/github.com/miracl/amcl-go/UTILS_test.go | 71 +
go/src/github.com/miracl/amcl-go/crypto.go | 191 ++
go/src/github.com/miracl/amcl-go/crypto_test.go | 872 +++++++
go/src/github.com/miracl/examples-cgo/mpin.go | 221 ++
go/src/github.com/miracl/examples-cgo/mpinfull.go | 290 +++
go/src/github.com/miracl/examples-cgo/timempin.go | 84 +
go/src/github.com/miracl/examples-go/ecdh.go | 180 ++
.../miracl/examples-go/generateRandom.go | 48 +
go/src/github.com/miracl/examples-go/mpin.go | 248 ++
.../github.com/miracl/examples-go/mpinTwoPass.go | 207 ++
go/src/github.com/miracl/examples-go/mpinfull.go | 269 +++
.../github.com/miracl/examples-go/mpinfullWrap.go | 293 +++
go/src/github.com/miracl/examples-go/otp.go | 48 +
go/src/github.com/miracl/examples-go/pbkdf2.go | 88 +
go/src/github.com/miracl/examples-go/rsa.go | 71 +
go/src/github.com/miracl/examples-go/timempin.go | 96 +
.../github.com/miracl/examples-go/timempinWrap.go | 84 +
java/AES.java | 648 +++++
java/BIG.java | 919 +++++++
java/DBIG.java | 286 +++
java/ECDH.java | 531 +++++
java/ECP.java | 920 +++++++
java/ECP2.java | 623 +++++
java/FF.java | 974 ++++++++
java/FP.java | 327 +++
java/FP12.java | 643 +++++
java/FP2.java | 389 +++
java/FP4.java | 583 +++++
java/GCM.java | 374 +++
java/HASH.java | 215 ++
java/MPIN.java | 746 ++++++
java/PAIR.java | 539 +++++
java/RAND.java | 161 ++
java/ROM.java | 385 +++
java/RSA.java | 318 +++
java/TestECDH.java | 175 ++
java/TestECM.java | 126 +
java/TestMPIN.java | 262 ++
java/TestRSA.java | 66 +
java/readme.txt | 32 +
java64/AES.java | 648 +++++
java64/BIG.java | 902 +++++++
java64/DBIG.java | 307 +++
java64/ECDH.java | 528 ++++
java64/ECP.java | 929 ++++++++
java64/ECP2.java | 626 +++++
java64/FF.java | 974 ++++++++
java64/FP.java | 324 +++
java64/FP12.java | 640 +++++
java64/FP2.java | 391 +++
java64/FP4.java | 585 +++++
java64/GCM.java | 374 +++
java64/HASH.java | 215 ++
java64/MPIN.java | 746 ++++++
java64/PAIR.java | 537 +++++
java64/RAND.java | 161 ++
java64/ROM.java | 381 +++
java64/RSA.java | 319 +++
java64/TestECDH.java | 175 ++
java64/TestECM.java | 126 +
java64/TestMPIN.java | 263 ++
java64/TestRSA.java | 66 +
java64/readme.txt | 32 +
js/AES.js | 424 ++++
js/BIG.js | 953 ++++++++
js/DBIG.js | 248 ++
js/ECDH.js | 537 +++++
js/ECP.js | 898 +++++++
js/ECP2.js | 604 +++++
js/FF.js | 928 ++++++++
js/FP.js | 329 +++
js/FP12.js | 558 +++++
js/FP2.js | 321 +++
js/FP4.js | 501 ++++
js/GCM.js | 304 +++
js/HASH.js | 174 ++
js/MPIN.js | 794 +++++++
js/MPINAuth.js | 518 ++++
js/PAIR.js | 506 ++++
js/RAND.js | 148 ++
js/ROM.js | 596 +++++
js/RSA.js | 331 +++
js/TestECDH.html | 137 ++
js/TestECM.html | 95 +
js/TestMPIN.html | 310 +++
js/TestRSA.html | 78 +
js/readme.txt | 28 +
js/tests/MPIN.js | 799 +++++++
js/tests/README.txt | 111 +
js/tests/TestMPIN.js | 151 ++
js/tests/TestMPINAuth.js | 161 ++
js/tests/TestMPINAuthOnePass.js | 149 ++
js/tests/config.js_local | 41 +
js/tests/config.js_qa | 41 +
js/tests/find_duplicates.py | 40 +
js/tests/genVectorFixed.py | 260 ++
js/tests/genVectors.py | 416 ++++
js/tests/genVectorsOnePass.py | 412 ++++
js/tests/getClientSecret.js | 112 +
js/tests/getTimePermit.js | 115 +
js/tests/run_headless_tests.sh | 63 +
js/tests/run_js_tests.sh | 69 +
js/tests/test_add_shares.js | 92 +
js/tests/test_bad_PIN_AJAX.js | 388 +++
js/tests/test_bad_PIN_WS.js | 326 +++
js/tests/test_good_PIN_AJAX.js | 387 +++
js/tests/test_good_PIN_WS.js | 325 +++
js/tests/test_onepass.js | 97 +
js/tests/test_pass1.js | 87 +
js/tests/test_pass2.js | 82 +
js/tests/test_randomX.js | 100 +
js/tests/test_sha256.js | 94 +
js/tests/test_token.js | 75 +
linux.md | 55 +
mac.md | 56 +
pythonCFFI/CMakeLists.txt | 44 +
pythonCFFI/README.md | 11 +
pythonCFFI/TestMPIN.py | 326 +++
pythonCFFI/TestMPINBNCX.py | 584 +++++
pythonCFFI/TestMPINInstall.py | 703 ++++++
pythonCFFI/TimeMPIN.py | 331 +++
pythonCFFI/TimeMPINFull.py | 444 ++++
pythonCFFI/mpin.py | 555 +++++
swift/TestECDH.swift | 164 ++
swift/TestECM.swift | 112 +
swift/TestMPIN.swift | 253 ++
swift/TestRSA.swift | 78 +
swift/aes.swift | 586 +++++
swift/big.swift | 920 +++++++
swift/dbig.swift | 222 ++
swift/ecdh.swift | 531 +++++
swift/ecp.swift | 923 +++++++
swift/ecp2.swift | 614 +++++
swift/ff.swift | 918 +++++++
swift/fp.swift | 290 +++
swift/fp12.swift | 581 +++++
swift/fp2.swift | 329 +++
swift/fp4.swift | 513 ++++
swift/gcm.swift | 314 +++
swift/hash.swift | 188 ++
swift/main.swift | 30 +
swift/mpin.swift | 728 ++++++
swift/pair.swift | 501 ++++
swift/rand.swift | 131 +
swift/readme.txt | 45 +
swift/rom.swift | 296 +++
swift/rsa.swift | 323 +++
testVectors/mpin/BNCX.json | 1 +
testVectors/mpin/BNCXOnePass.json | 1 +
windows.md | 70 +
271 files changed, 102203 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3220875
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+release
+*.o
+*.a
+*.o.d
+*.so
+*.pyc
+*.class
+*~
diff --git a/AMCL.pdf b/AMCL.pdf
new file mode 100644
index 0000000..4393fe2
Binary files /dev/null and b/AMCL.pdf differ
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..73c0bde
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,179 @@
+cmake_minimum_required (VERSION 2.8)
+project (AMCL)
+enable_testing()
+
+set(AMCL_VERSION_MAJOR "1")
+set(AMCL_VERSION_MINOR "0")
+set(AMCL_VERSION_PATCH "0")
+set(PROJECT_VERSION "${AMCL_VERSION_MAJOR}.${AMCL_VERSION_MINOR}.${AMCL_VERSION_PATCH}")
+message(STATUS "PROJECT_VERSION='${PROJECT_VERSION}'")
+message(STATUS "Generator - ${CMAKE_GENERATOR}")
+
+# Add options for build
+option (BUILD_SHARED_LIBS "Build Shared Libraries" ON)
+option (BUILD_PYTHON "Build Python" ON)
+option (BUILD_MPIN "Build MPIN" ON)
+option (BUILD_DOXYGEN "Build Doxygen" ON)
+option (USE_PATENTS "Use alleged patents" ON)
+
+# Allow the developer to select if Dynamic or Static libraries are built
+# Set the default LIB_TYPE variable to STATIC
+SET (LIB_TYPE STATIC)
+IF (BUILD_SHARED_LIBS)
+ # User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
+ SET (LIB_TYPE SHARED)
+ENDIF (BUILD_SHARED_LIBS)
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ # Mac OS X specific code
+ set(OS "Mac OS X")
+ # MACOSX_RPATH
+ cmake_policy(SET CMP0042 NEW)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ # Linux specific code
+ set(OS "Linux")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ # Windows specific code
+ set(OS "Windows")
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+
+# Select word length
+set(WORD_LENGTH "32" CACHE STRING "Word length. See amcl.h.in for explanation")
+set(Word_Length_Values "16;32;64")
+set_property(CACHE WORD_LENGTH PROPERTY STRINGS ${Word_Length_Values})
+message(STATUS "WORD_LENGTH='${WORD_LENGTH}'")
+
+# Select Field
+set(FIELD_CHOICE "BNCX" CACHE STRING "Choice of Field. See amcl.h.in for explanation")
+set(Field_Values "BN;BNCX;BNT;BNT2;NIST;C25519;BRAINPOOL;ANSSI;MF254;MS255;MF256;MS256")
+set_property(CACHE FIELD_CHOICE PROPERTY STRINGS ${Field_Values})
+message(STATUS "FIELD_CHOICE='${FIELD_CHOICE}'")
+
+# Select Curve type
+set(CURVE_TYPE "WEIERSTRASS" CACHE STRING "Choice of Curve. See amcl.h.in for explanation")
+set(Curve_Values "WEIERSTRASS;EDWARDS;MONTGOMERY")
+set_property(CACHE CURVE_TYPE PROPERTY STRINGS ${Curve_Values})
+message(STATUS "CURVE_TYPE='${CURVE_TYPE}'")
+
+# configure amcl header file to pass CMake settings
+# to the source code
+configure_file (
+ "${PROJECT_SOURCE_DIR}/c/amcl.h.in"
+ "${PROJECT_BINARY_DIR}/c/amcl.h"
+ )
+
+if(NOT(FIELD_CHOICE MATCHES "BN"))
+ message(STATUS "Field choice prevents MPIN being built")
+ set(BUILD_MPIN OFF)
+endif(NOT(FIELD_CHOICE MATCHES "BN"))
+
+# test configuration
+if(BUILD_MPIN)
+ set(MPIN_TIME_PERMIT_TESTS 10 CACHE STRING "Number of days in the future to test M-PIN time permits")
+ set(MPIN_RANDOM_TESTS 10 CACHE STRING "Number of random M-PIN tests")
+ message(STATUS "MPIN_TIME_PERMIT_TESTS=${MPIN_TIME_PERMIT_TESTS}")
+ message(STATUS "MPIN_RANDOM_TESTS=${MPIN_RANDOM_TESTS}")
+ # Configure test variables
+ configure_file (
+ "${PROJECT_SOURCE_DIR}/c/tests/config.h.in"
+ "${PROJECT_BINARY_DIR}/c/tests/config.h"
+ )
+endif(BUILD_MPIN)
+
+# Set a default build type if none was specified
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ message(STATUS "Setting build type to 'Release' as none was specified.")
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
+ # Set the possible values of build type for cmake-gui
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+endif()
+
+# Add subdirectories
+add_subdirectory (c)
+
+# Only build Python for shared libs
+if (NOT BUILD_SHARED_LIBS)
+ set(BUILD_PYTHON OFF)
+endif (NOT BUILD_SHARED_LIBS)
+
+if (BUILD_PYTHON)
+ message(STATUS "Build Python CFFI")
+ execute_process (COMMAND python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process (COMMAND python -c "from distutils.sysconfig import get_python_lib; from os.path import dirname; print dirname(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_LIB OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if((FIELD_CHOICE STREQUAL "BNCX") AND BUILD_MPIN)
+ file(COPY "${PROJECT_SOURCE_DIR}/testVectors/mpin/BNCX.json" DESTINATION "${PROJECT_BINARY_DIR}/pythonCFFI")
+ file(RENAME "${PROJECT_BINARY_DIR}/pythonCFFI/BNCX.json" "${PROJECT_BINARY_DIR}/pythonCFFI/MPINTestVectors.json")
+ endif((FIELD_CHOICE STREQUAL "BNCX") AND BUILD_MPIN)
+ add_subdirectory (pythonCFFI)
+endif (BUILD_PYTHON)
+
+# Build Documentation
+if (BUILD_DOXYGEN)
+ find_package(Doxygen QUIET)
+ if(DOXYGEN_FOUND)
+ add_subdirectory (docs)
+ else(DOXYGEN_FOUND)
+ message(STATUS "Doxygen not found. Documentation will not be built.")
+ endif(DOXYGEN_FOUND)
+endif (BUILD_DOXYGEN)
+
+# uninstall target
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+
+add_custom_target(uninstall
+ COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+
+# Build a CPack driven installer package
+include (InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+set(CPACK_PACKAGE_VERSION "${AMCL_VERSION_MAJOR}.${AMCL_VERSION_MINOR}.${AMCL_VERSION_PATCH}")
+set(CPACK_PACKAGE_NAME "AMCL")
+set(CPACK_PACKAGE_RELEASE 1)
+set(CPACK_PACKAGE_CONTACT "support@miracl.com")
+set(CPACK_PACKAGE_VENDOR "MIRACL")
+if (BUILD_PYTHON)
+ set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.7.0")
+endif (BUILD_PYTHON)
+set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ # Linux specific code
+ set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
+ # Prevents CPack from generating file conflicts
+ set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}")
+ list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/bin")
+ list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/include")
+ list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}/lib")
+ list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON_SITE_LIB}")
+ list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${PYTHON_SITE_PACKAGES}")
+ set(CPACK_GENERATOR "RPM")
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ # Windows specific code
+ set(CPACK_PACKAGE_INSTALL_DIRECTORY "AMCL")
+ set(CPACK_NSIS_MODIFY_PATH ON)
+ set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/data\\\\icon.bmp")
+ set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/data\\\\icon.ico")
+ set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/data\\\\icon.ico")
+ set(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.miracl.com")
+ set(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.miracl.com")
+ set(CPACK_NSIS_CONTACT "support@miracl.com")
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ # Mac OS X specific code
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+include (CPack)
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..19efef5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2016 MIRACL UK Ltd
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..434d2bb
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Milagro Crypto Libraries
+Copyright 2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7282e43
--- /dev/null
+++ b/README.md
@@ -0,0 +1,42 @@
+<h2>AMCL</h2>
+
+<p>This directory contains the source code for the AMCL Library.</p>
+
+<p>The directory structure is as follows</p>
+
+<dl>
+ <dt>./c</dt>
+ <dd>- C Source code</dd>
+ <dt>./js</dt>
+ <dd>- JavaScript code</dd>
+ <dt>./java</dt>
+ <dd>- JAVA code</dd>
+ <dt>./java64</dt>
+ <dd>- JAVA code optimal for a 64-bit Virtual Machine</dd>
+ <dt>./go</dt>
+ <dd>- GO code</dd>
+ <dt>./swift</dt>
+ <dd>- swift code</dd>
+ <dt>./cs</dt>
+ <dd>- C# code</dd>
+ <dt>./pythonCFFI</dt>
+ <dd>- Python code that accesses the C library via the CFFI module</dd>
+ <dt>./testVectors</dt>
+ <dd>- Test Vectors</dd>
+ <dt>./docs</dt>
+ <dd>- Documentation</dd>
+</dl>
+
+<h2>Build Instructions</h2>
+
+<p>AMCL is a standards compliant C library with no external dependencies. It
+can be built using the <a href="http://www.cmake.org">CMake</a> build system.
+In order to use the Python wrappers <a href="https://cffi.readthedocs.org/en/release-0.8/">CFFI</a> is also
+required. There are instructions provided for both Linux and Windows based systems.</p>
+
+<p>Instructions for the Linux build are in ./linux.md</p>
+
+<p>Instructions for the Mac OS build are in ./mac.md</p>
+
+<p>Instructions for the Windows build are in ./windows.md</p>
+
diff --git a/bigtobig.cpp b/bigtobig.cpp
new file mode 100755
index 0000000..730b790
--- /dev/null
+++ b/bigtobig.cpp
@@ -0,0 +1,292 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+//
+// Program to convert from Big to AMCL BIG format
+// cl /O2 bigtobig.cpp big.cpp miracl.lib
+// gcc -O2 bigtobig.cpp big.cpp miracl.a -o bigtobig
+//
+//
+
+#include <iostream>
+#include "zzn.h"
+
+using namespace std;
+
+Miracl precision=100;
+
+// Code to parse formula in command line
+// This code isn't mine, but its public domain
+// Shamefully I forget the source
+//
+// NOTE: It may be necessary on some platforms to change the operators * and #
+//
+
+#if defined(unix)
+#define TIMES '.'
+#define RAISE '^'
+#else
+#define TIMES '*'
+#define RAISE '#'
+#endif
+
+Big tt;
+static char *ss;
+
+void eval_power (Big& oldn,Big& n,char op)
+{
+ if (op) n=pow(oldn,toint(n)); // power(oldn,size(n),n,n);
+}
+
+void eval_product (Big& oldn,Big& n,char op)
+{
+ switch (op)
+ {
+ case TIMES:
+ n*=oldn;
+ break;
+ case '/':
+ n=oldn/n;
+ break;
+ case '%':
+ n=oldn%n;
+ }
+}
+
+void eval_sum (Big& oldn,Big& n,char op)
+{
+ switch (op)
+ {
+ case '+':
+ n+=oldn;
+ break;
+ case '-':
+ n=oldn-n;
+ }
+}
+
+void eval (void)
+{
+ Big oldn[3];
+ Big n;
+ int i;
+ char oldop[3];
+ char op;
+ char minus;
+ for (i=0;i<3;i++)
+ {
+ oldop[i]=0;
+ }
+LOOP:
+ while (*ss==' ')
+ ss++;
+ if (*ss=='-') /* Unary minus */
+ {
+ ss++;
+ minus=1;
+ }
+ else
+ minus=0;
+ while (*ss==' ')
+ ss++;
+ if (*ss=='(' || *ss=='[' || *ss=='{') /* Number is subexpression */
+ {
+ ss++;
+ eval ();
+ n=tt;
+ }
+ else /* Number is decimal value */
+ {
+ for (i=0;ss[i]>='0' && ss[i]<='9';i++)
+ ;
+ if (!i) /* No digits found */
+ {
+ cout << "Error - invalid number" << endl;
+ exit (20);
+ }
+ op=ss[i];
+ ss[i]=0;
+ n=atoi(ss);
+ ss+=i;
+ *ss=op;
+ }
+ if (minus) n=-n;
+ do
+ op=*ss++;
+ while (op==' ');
+ if (op==0 || op==')' || op==']' || op=='}')
+ {
+ eval_power (oldn[2],n,oldop[2]);
+ eval_product (oldn[1],n,oldop[1]);
+ eval_sum (oldn[0],n,oldop[0]);
+ tt=n;
+ return;
+ }
+ else
+ {
+ if (op==RAISE)
+ {
+ eval_power (oldn[2],n,oldop[2]);
+ oldn[2]=n;
+ oldop[2]=RAISE;
+ }
+ else
+ {
+ if (op==TIMES || op=='/' || op=='%')
+ {
+ eval_power (oldn[2],n,oldop[2]);
+ oldop[2]=0;
+ eval_product (oldn[1],n,oldop[1]);
+ oldn[1]=n;
+ oldop[1]=op;
+ }
+ else
+ {
+ if (op=='+' || op=='-')
+ {
+ eval_power (oldn[2],n,oldop[2]);
+ oldop[2]=0;
+ eval_product (oldn[1],n,oldop[1]);
+ oldop[1]=0;
+ eval_sum (oldn[0],n,oldop[0]);
+ oldn[0]=n;
+ oldop[0]=op;
+ }
+ else /* Error - invalid operator */
+ {
+ cout << "Error - invalid operator" << endl;
+ exit (20);
+ }
+ }
+ }
+ }
+ goto LOOP;
+}
+
+void output(int w,Big t,Big m)
+{
+ Big y=t;
+
+ for (int i=0;i<w;i++)
+ {
+ cout << "0x" << y%m ;
+ if (i<w-1) cout << ",";
+ y/=m;
+ }
+ cout << endl;
+}
+
+int main(int argc, char **argv)
+{
+ int i,ip,chunk,basebits;
+ Big n,m;
+ BOOL gotP,gotA,gotB;
+ int Base;
+ miracl *mip=&precision;
+ argv++; argc--;
+ if (argc<1)
+ {
+ cout << "Program converts from Big to BIG" << endl;
+ cout << "bigtobig <big number> <chunk>> <basebits>" << endl;
+ cout << "OR" << endl;
+ cout << "bigtobig <formula for big number> <chunk>> <basebits>" << endl;
+#if defined(unix)
+ cout << "e.g. bigtobig -f 2^255-19 32 29" << endl;
+#else
+ cout << "e.g. bigtobig -f 2#255-19 32 29" << endl;
+#endif
+ cout << "To input Big number in Hex, precede with -h" << endl;
+ return 0;
+ }
+
+ ip=0;
+ gprime(1000);
+ gotP=gotA=gotB=FALSE;
+ n=0;
+ Base=10;
+ while (ip<argc)
+ {
+ if (!gotP && strcmp(argv[ip],"-f")==0)
+ {
+ ip++;
+ if (!gotP && ip<argc)
+ {
+
+ ss=argv[ip++];
+ tt=0;
+ eval();
+ n=tt;
+ gotP=TRUE;
+ continue;
+ }
+ else
+ {
+ cout << "Error in command line" << endl;
+ return 0;
+ }
+ }
+
+
+ if (strcmp(argv[ip],"-h")==0)
+ {
+ ip++;
+ Base=16;
+ continue;
+ }
+
+ if (!gotP)
+ {
+ mip->IOBASE=Base;
+ n=argv[ip++];
+ mip->IOBASE=10;
+ gotP=TRUE;
+ continue;
+ }
+ if (!gotA)
+ {
+ mip->IOBASE=Base;
+ chunk=atoi(argv[ip++]);
+ gotA=TRUE;
+ continue;
+ }
+ if (!gotB)
+ {
+ mip->IOBASE=Base;
+ basebits=atoi(argv[ip++]);
+ gotB=TRUE;
+ continue;
+ }
+ cout << "Error in command line" << endl;
+ return 0;
+ }
+ if (!gotP || !gotA || !gotB)
+ {
+ cout << "Error in command line" << endl;
+ return 0;
+ }
+
+ mip->IOBASE=16;
+
+ m=pow((Big)2,basebits);
+
+ output(1+bits(n)/basebits,n,m);
+
+ return 0;
+}
+
diff --git a/bngen.cpp b/bngen.cpp
new file mode 100755
index 0000000..f59d6f8
--- /dev/null
+++ b/bngen.cpp
@@ -0,0 +1,511 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* BNGEN - Helper MIRACL program to generate constants for BN curve
+
+(MINGW build)
+
+g++ -O3 bngen.cpp big.cpp zzn.cpp zzn2.cpp ecn2.cpp miracl.a -o bngen.exe
+
+This ONLY works for D-type curves of the form y^2=x^3+2, with a negative x parameter, and x=3 mod 4
+
+*/
+
+#include <iostream>
+#include "big.h"
+#include "zzn2.h"
+#include "ecn2.h"
+
+using namespace std;
+
+Miracl precision(20,0);
+
+
+/* set d=0 for c, d=1 to include leading zeros, d=2 for JS-type square brackets, d=3 for L (for long) appended */
+void output(int d,int w,Big t,Big m)
+{
+ Big y=t;
+
+ if (d!=2) cout << "{";
+ else cout << "[";
+ for (int i=0;i<w;i++)
+ {
+ cout << "0x" << y%m;
+ y/=m;
+ if ((y==0 && (d==0 || d==2)) || i==w-1) break;
+ if (d==3) cout << "L,";
+ else cout << ",";
+ }
+ if (d!=2)
+ {
+ if (d==3) cout << "L}";
+ else cout << "}";
+ }
+ else cout << "]";
+}
+
+
+void q_power_frobenius(ECn2 &A,ZZn2 &F)
+{
+// Fast multiplication of A by q (for Trace-Zero group members only)
+ ZZn2 x,y,z,w,r;
+
+ A.get(x,y);
+
+ w=F*F;
+ r=F;
+
+ if (get_mip()->TWIST==MR_SEXTIC_M) r=inverse(F); // could be precalculated
+ if (get_mip()->TWIST==MR_SEXTIC_D) r=F;
+
+ w=r*r;
+ x=w*conj(x);
+ y=r*w*conj(y);
+
+ A.set(x,y);
+}
+
+//
+// Faster Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez
+//
+
+void cofactor(ECn2& S,ZZn2 &F,Big& x)
+{
+ ECn2 T,K;
+ T=S;
+ T*=-x;
+ T.norm();
+ K=(T+T)+T;
+ K.norm();
+ q_power_frobenius(K,F);
+ q_power_frobenius(S,F); q_power_frobenius(S,F); q_power_frobenius(S,F);
+ S+=T; S+=K;
+ q_power_frobenius(T,F); q_power_frobenius(T,F);
+ S+=T;
+ S.norm();
+}
+
+
+void set_frobenius_constant(ZZn2 &X)
+{
+ Big p=get_modulus();
+ switch (get_mip()->pmod8)
+ {
+ case 5:
+ X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2
+ break;
+ case 3: // = (1+sqrt(-1))^(p-1)/2
+ X.set((Big)1,(Big)1);
+ break;
+ case 7:
+ X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2
+ default: break;
+ }
+ X=pow(X,(p-1)/6);
+}
+
+int main()
+{
+ miracl *mip=&precision;
+ Big p,q,R,cru;
+ Big m,x,y,w,t,c,n,r,a,b,gx,gy,D,xa,xb,ya,yb;
+ ZZn2 X;
+ ECn2 Q;
+ ZZn2 Xa,Ya;
+ int i;
+ int CHUNK[4]={16,32,64,32};
+ int WORDS[4]={20,9,5,11};//{20,9,5};
+ int BITS[4]={13,29,56,24};//{13,29,56};
+
+ mip->IOBASE=16;
+
+/* Set BN value x which determines curve - note that x is assumed to be negative */
+
+// x=(char *)"6000000000101041"; // for full 256-bit GT_STRONG parameter
+// x=(char *)"4080000000000001"; // Fast but not not GT_STRONG parameter
+
+ x=(char *)"4000020100608205"; // G2 and GT-Strong parameter
+ x=(char *)"4000000003C012B1"; // MIRACL's GT_STRONG parameter
+ x=(char *)"4080000000000001"; // Nogami's fast parameter
+ x=(char *)"4000806000004081"; // Best GT_STRONG parameter
+
+ p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1;
+ ecurve((Big)0,(Big)2,p,MR_AFFINE);
+ mip->TWIST=MR_SEXTIC_D;
+
+ cout << "/* AMCL - ROM C file for BN curve - Weierstrass Only */" << endl << endl;
+
+ cout << "#define MBITS " << bits(p) << endl;
+ cout << "#define MOD8 " << p%8 << endl;
+ cout << endl;
+ cout << "const int CURVE_A=0;" << endl;
+ for (i=0;i<3;i++)
+ {
+ cout << "#if CHUNK==" << CHUNK[i] << endl << endl;
+ m=pow((Big)2,BITS[i]);
+
+
+ cout << "const chunk MConst=0x" << inverse(m-p%m,m) << ";" << endl;
+
+ cout << "const BIG Modulus="; output(0,WORDS[i],p,m); cout << ";" << endl;
+ t=6*x*x+1;
+ q=p+1-t;
+ cout << "const BIG CURVE_Order="; output(0,WORDS[i],q,m); cout << ";" << endl;
+ cout << "const BIG CURVE_B={0x2};" << endl;
+
+ R=pow((Big)2,WORDS[i]*BITS[i]);
+ // cout << "const BIG Monty=";output(0,WORDS[i],inverse(R,p),m); cout << ";" << endl;
+
+ cout << "const BIG CURVE_Bnx="; output(0,WORDS[i],x,m); cout << ";" << endl;
+
+ cru=(18*pow(x,3)-18*x*x+9*x-2);
+ cout << "const BIG CURVE_Cru="; output(0,WORDS[i],cru,m); cout << ";" << endl;
+
+ set_frobenius_constant(X);
+
+ X.get(a,b);
+ cout << "const BIG CURVE_Fra="; output(0,WORDS[i],a,m); cout << ";" << endl;
+ cout << "const BIG CURVE_Frb="; output(0,WORDS[i],b,m); cout << ";" << endl;
+
+ Xa.set((ZZn)0,(ZZn)-1);
+ Ya.set((ZZn)1,ZZn(0));
+ Q.set(Xa,Ya);
+
+ cofactor(Q,X,x);
+
+ Q.get(Xa,Ya);
+ Xa.get(a,b);
+ cout << "const BIG CURVE_Pxa="; output(0,WORDS[i],a,m); cout << ";" << endl;
+ cout << "const BIG CURVE_Pxb="; output(0,WORDS[i],b,m); cout << ";" << endl;
+ Ya.get(a,b);
+ cout << "const BIG CURVE_Pya="; output(0,WORDS[i],a,m); cout << ";" << endl;
+ cout << "const BIG CURVE_Pyb="; output(0,WORDS[i],b,m); cout << ";" << endl;
+
+// Q*=q;
+// cout << "Q= " << Q << endl;
+
+ cout << "const BIG CURVE_Gx="; output(0,WORDS[i],p-1,m); cout << ";" << endl;
+ cout << "const BIG CURVE_Gy="; output(0,WORDS[i],(Big)1,m); cout << ";" << endl;
+
+ cout << "const BIG CURVE_W[2]={"; output(0,WORDS[i],6*x*x-4*x+1,m);cout << ","; output(0,WORDS[i],(2*x-1),m); cout << "};" << endl;
+ cout << "const BIG CURVE_SB[2][2]={"; cout << "{"; output(0,WORDS[i],6*x*x-2*x,m); cout << ","; output(0,WORDS[i],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(0,WORDS[i],(2*x-1),m); cout << ","; output(0,WORDS[i],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
+
+ cout << "const BIG CURVE_WB[4]={"; output(0,WORDS[i],2*x*x-3*x+1,m); cout << ","; output(0,WORDS[i],12*x*x*x-8*x*x+x,m);
+ cout << ","; output(0,WORDS[i],6*x*x*x-4*x*x+x,m); cout << ","; output(0,WORDS[i],2*x*x-x,m); cout << "};" << endl;
+
+ cout << "const BIG CURVE_BB[4][4]={";
+ cout << "{";
+ output(0,WORDS[i],q-x+1,m);
+ cout << ","; output(0,WORDS[i],q-x,m);
+ cout << ","; output(0,WORDS[i],q-x,m);
+ cout << ","; output(0,WORDS[i],2*x,m);
+ cout << "}";
+
+ cout << ","; cout << "{";output(0,WORDS[i],2*x-1,m);
+ cout << ","; output(0,WORDS[i],q-x,m);
+ cout << ","; output(0,WORDS[i],q-x+1,m);
+ cout << ","; output(0,WORDS[i],q-x,m);
+ cout << "}";
+ cout << ","; cout << "{"; output(0,WORDS[i],2*x,m);
+ cout << ","; output(0,WORDS[i],2*x-1,m);
+ cout << ","; output(0,WORDS[i],2*x-1,m);
+ cout << ","; output(0,WORDS[i],2*x-1,m);
+ cout << "}";
+
+ cout << ","; cout << "{"; output(0,WORDS[i],x+1,m);
+ cout << ","; output(0,WORDS[i],4*x-2,m);
+ cout << ","; output(0,WORDS[i],q-2*x-1,m);
+ cout << ","; output(0,WORDS[i],x+1,m);
+ cout << "}";
+ cout << "};" << endl;
+
+ cout << "#endif" << endl << endl;
+
+ }
+
+ cout << endl;
+ cout << "Cut here -----------------------------------------------------------" << endl;
+ cout << "/* AMCL - ROM Java file for 32-bit VM and BN curve - Weierstrass Only */" << endl << endl;
+
+ cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
+ cout << "public static final int MOD8= " << p%8 << ";" << endl;
+ cout << endl;
+ cout << "public static final int MODTYPE=NOT_SPECIAL;" << endl;
+ m=pow((Big)2,BITS[1]);
+
+
+ cout << "public static final int[] Modulus= "; output(1,WORDS[1],p,m); cout << ";" << endl;
+ R=pow((Big)2,WORDS[1]*BITS[1]);
+// cout << "public static final int[] Monty=";output(1,WORDS[1],inverse(R,p),m); cout << ";" << endl;
+ cout << "public static final int MConst=0x" << inverse(m-p%m,m) << ";" << endl;
+ cout << endl;
+ cout << "public static final int CURVETYPE=WEIERSTRASS;" << endl;
+
+
+ cout << "public static final int CURVE_A = 0;" << endl;
+ cout << "public static final int[] CURVE_B = {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};" << endl;
+ t=6*x*x+1;
+ q=p+1-t;
+ cout << "public static final int[] CURVE_Order="; output(1,WORDS[1],q,m); cout << ";" << endl;
+
+
+ cout << "public static final int[] CURVE_Bnx="; output(1,WORDS[1],x,m); cout << ";" << endl;
+
+ cru=(18*pow(x,3)-18*x*x+9*x-2);
+ cout << "public static final int[] CURVE_Cru="; output(1,WORDS[1],cru,m); cout << ";" << endl;
+
+ set_frobenius_constant(X);
+
+ X.get(a,b);
+ cout << "public static final int[] CURVE_Fra="; output(1,WORDS[1],a,m); cout << ";" << endl;
+ cout << "public static final int[] CURVE_Frb="; output(1,WORDS[1],b,m); cout << ";" << endl;
+
+ Xa.set((ZZn)0,(ZZn)-1);
+ Ya.set((ZZn)1,ZZn(0));
+ Q.set(Xa,Ya);
+
+ cofactor(Q,X,x);
+
+ Q.get(Xa,Ya);
+ Xa.get(a,b);
+ cout << "public static final int[] CURVE_Pxa="; output(1,WORDS[1],a,m); cout << ";" << endl;
+ cout << "public static final int[] CURVE_Pxb="; output(1,WORDS[1],b,m); cout << ";" << endl;
+ Ya.get(a,b);
+ cout << "public static final int[] CURVE_Pya="; output(1,WORDS[1],a,m); cout << ";" << endl;
+ cout << "public static final int[] CURVE_Pyb="; output(1,WORDS[1],b,m); cout << ";" << endl;
+
+// Q*=q;
+// cout << "Q= " << Q << endl;
+
+ cout << "public static final int[] CURVE_Gx ="; output(1,WORDS[1],p-1,m); cout << ";" << endl;
+ cout << "public static final int[] CURVE_Gy ="; output(1,WORDS[1],(Big)1,m); cout << ";" << endl;
+
+ cout << "public static final int[][] CURVE_W={"; output(1,WORDS[1],6*x*x-4*x+1,m);cout << ","; output(1,WORDS[1],(2*x-1),m); cout << "};" << endl;
+ cout << "public static final int[][][] CURVE_SB={"; cout << "{"; output(1,WORDS[1],6*x*x-2*x,m); cout << ","; output(1,WORDS[1],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(1,WORDS[1],(2*x-1),m); cout << ","; output(1,WORDS[1],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
+
+ cout << "public static final int[][] CURVE_WB={"; output(1,WORDS[1],2*x*x-3*x+1,m); cout << ","; output(1,WORDS[1],12*x*x*x-8*x*x+x,m);
+ cout << ","; output(1,WORDS[1],6*x*x*x-4*x*x+x,m); cout << ","; output(1,WORDS[1],2*x*x-x,m); cout << "};" << endl;
+
+ cout << "public static final int[][][] CURVE_BB={";
+ cout << "{";
+ output(1,WORDS[1],q-x+1,m);
+ cout << ","; output(1,WORDS[1],q-x,m);
+ cout << ","; output(1,WORDS[1],q-x,m);
+ cout << ","; output(1,WORDS[1],2*x,m);
+ cout << "}";
+
+ cout << ","; cout << "{";output(1,WORDS[1],2*x-1,m);
+ cout << ","; output(1,WORDS[1],q-x,m);
+ cout << ","; output(1,WORDS[1],q-x+1,m);
+ cout << ","; output(1,WORDS[1],q-x,m);
+ cout << "}";
+ cout << ","; cout << "{"; output(1,WORDS[1],2*x,m);
+ cout << ","; output(1,WORDS[1],2*x-1,m);
+ cout << ","; output(1,WORDS[1],2*x-1,m);
+ cout << ","; output(1,WORDS[1],2*x-1,m);
+ cout << "}";
+
+ cout << ","; cout << "{"; output(1,WORDS[1],x+1,m);
+ cout << ","; output(1,WORDS[1],4*x-2,m);
+ cout << ","; output(1,WORDS[1],q-2*x-1,m);
+ cout << ","; output(1,WORDS[1],x+1,m);
+ cout << "}";
+ cout << "};" << endl;
+
+
+ cout << endl;
+ cout << "Cut here -----------------------------------------------------------" << endl;
+ cout << "/* AMCL - ROM Java file for 64-bit VM and BN curve - Weierstrass Only */" << endl << endl;
+
+ cout << "public static final int MODBITS= " << bits(p) << ";" << endl;
+ cout << "public static final int MOD8= " << p%8 << ";" << endl;
+ cout << endl;
+ cout << "public static final int MODTYPE=NOT_SPECIAL;" << endl;
+ m=pow((Big)2,BITS[2]);
+
+
+ cout << "public static final long[] Modulus= "; output(3,WORDS[2],p,m); cout << ";" << endl;
+ R=pow((Big)2,WORDS[2]*BITS[2]);
+// cout << "public static final long[] Monty=";output(3,WORDS[2],inverse(R,p),m); cout << ";" << endl;
+ cout << "public static final long MConst=0x" << inverse(m-p%m,m) << "L;" << endl;
+ cout << endl;
+ cout << "public static final int CURVETYPE=WEIERSTRASS;" << endl;
+
+
+ cout << "public static final int CURVE_A = 0;" << endl;
+ cout << "public static final long[] CURVE_B = {0x2L,0x0L,0x0L,0x0L,0x0L};" << endl;
+ t=6*x*x+1;
+ q=p+1-t;
+ cout << "public static final long[] CURVE_Order="; output(3,WORDS[2],q,m); cout << ";" << endl;
+
+
+ cout << "public static final long[] CURVE_Bnx="; output(3,WORDS[2],x,m); cout << ";" << endl;
+
+ cru=(18*pow(x,3)-18*x*x+9*x-2);
+ cout << "public static final long[] CURVE_Cru="; output(3,WORDS[2],cru,m); cout << ";" << endl;
+
+ set_frobenius_constant(X);
+
+ X.get(a,b);
+ cout << "public static final long[] CURVE_Fra="; output(3,WORDS[2],a,m); cout << ";" << endl;
+ cout << "public static final long[] CURVE_Frb="; output(3,WORDS[2],b,m); cout << ";" << endl;
+
+ Xa.set((ZZn)0,(ZZn)-1);
+ Ya.set((ZZn)1,ZZn(0));
+ Q.set(Xa,Ya);
+
+ cofactor(Q,X,x);
+
+ Q.get(Xa,Ya);
+ Xa.get(a,b);
+ cout << "public static final long[] CURVE_Pxa="; output(3,WORDS[2],a,m); cout << ";" << endl;
+ cout << "public static final long[] CURVE_Pxb="; output(3,WORDS[2],b,m); cout << ";" << endl;
+ Ya.get(a,b);
+ cout << "public static final long[] CURVE_Pya="; output(3,WORDS[2],a,m); cout << ";" << endl;
+ cout << "public static final long[] CURVE_Pyb="; output(3,WORDS[2],b,m); cout << ";" << endl;
+
+// Q*=q;
+// cout << "Q= " << Q << endl;
+
+ cout << "public static final long[] CURVE_Gx ="; output(3,WORDS[2],p-1,m); cout << ";" << endl;
+ cout << "public static final long[] CURVE_Gy ="; output(3,WORDS[2],(Big)1,m); cout << ";" << endl;
+
+ cout << "public static final long[][] CURVE_W={"; output(3,WORDS[2],6*x*x-4*x+1,m);cout << ","; output(3,WORDS[2],(2*x-1),m); cout << "};" << endl;
+ cout << "public static final long[][][] CURVE_SB={"; cout << "{"; output(3,WORDS[2],6*x*x-2*x,m); cout << ","; output(3,WORDS[2],(2*x-1),m); cout << "}";cout << ","; cout << "{"; output(3,WORDS[2],(2*x-1),m); cout << ","; output(3,WORDS[2],q-(6*x*x-4*x+1),m); cout << "}"; cout << "};" << endl;
+
+ cout << "public static final long[][] CURVE_WB={"; output(3,WORDS[2],2*x*x-3*x+1,m); cout << ","; output(3,WORDS[2],12*x*x*x-8*x*x+x,m);
+ cout << ","; output(3,WORDS[2],6*x*x*x-4*x*x+x,m); cout << ","; output(3,WORDS[2],2*x*x-x,m); cout << "};" << endl;
+
+ cout << "public static final long[][][] CURVE_BB={";
+ cout << "{";
+ output(3,WORDS[2],q-x+1,m);
+ cout << ","; output(3,WORDS[2],q-x,m);
+ cout << ","; output(3,WORDS[2],q-x,m);
+ cout << ","; output(3,WORDS[2],2*x,m);
+ cout << "}";
+
+ cout << ","; cout << "{";output(3,WORDS[2],2*x-1,m);
+ cout << ","; output(3,WORDS[2],q-x,m);
+ cout << ","; output(3,WORDS[2],q-x+1,m);
+ cout << ","; output(3,WORDS[2],q-x,m);
+ cout << "}";
+ cout << ","; cout << "{"; output(3,WORDS[2],2*x,m);
+ cout << ","; output(3,WORDS[2],2*x-1,m);
+ cout << ","; output(3,WORDS[2],2*x-1,m);
+ cout << ","; output(3,WORDS[2],2*x-1,m);
+ cout << "}";
+
+ cout << ","; cout << "{"; output(3,WORDS[2],x+1,m);
+ cout << ","; output(3,WORDS[2],4*x-2,m);
+ cout << ","; output(3,WORDS[2],q-2*x-1,m);
+ cout << ","; output(3,WORDS[2],x+1,m);
+ cout << "}";
+ cout << "};" << endl;
+
+
+
+ cout << endl;
+ cout << "Cut here -----------------------------------------------------------" << endl;
+ cout << "/* AMCL - ROM Javascript file for BN curve - Weierstrass Only */" << endl << endl;
+
+ cout << "MODBITS: " << bits(p) << "," << endl;
+ cout << "MOD8: " << p%8 << "," << endl;
+ cout << endl;
+ cout << "MODTYPE:0," << endl;
+ m=pow((Big)2,BITS[3]);
+
+
+ cout << "Modulus: "; output(2,WORDS[3],p,m); cout << "," << endl;
+ R=pow((Big)2,WORDS[3]*BITS[3]);
+// cout << "Monty:";output(2,WORDS[3],inverse(R,p),m); cout << "," << endl;
+ cout << "MConst:0x" << inverse(m-p%m,m) << "," << endl;
+ cout << endl;
+ cout << "CURVETYPE:0," << endl;
+
+
+ cout << "CURVE_A : 0," << endl;
+ cout << "CURVE_B : [0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]," << endl;
+ t=6*x*x+1;
+ q=p+1-t;
+ cout << "CURVE_Order:"; output(2,WORDS[3],q,m); cout << "," << endl;
+
+
+ cout << "CURVE_Bnx:"; output(2,WORDS[3],x,m); cout << "," << endl;
+
+ cru=(18*pow(x,3)-18*x*x+9*x-2);
+ cout << "CURVE_Cru:"; output(2,WORDS[3],cru,m); cout << "," << endl;
+
+ set_frobenius_constant(X);
+
+ X.get(a,b);
+ cout << "CURVE_Fra:"; output(2,WORDS[3],a,m); cout << "," << endl;
+ cout << "CURVE_Frb:"; output(2,WORDS[3],b,m); cout << "," << endl;
+
+ Xa.set((ZZn)0,(ZZn)-1);
+ Ya.set((ZZn)1,ZZn(0));
+ Q.set(Xa,Ya);
+
+ cofactor(Q,X,x);
+
+ Q.get(Xa,Ya);
+ Xa.get(a,b);
+ cout << "CURVE_Pxa:"; output(2,WORDS[3],a,m); cout << "," << endl;
+ cout << "CURVE_Pxb:"; output(2,WORDS[3],b,m); cout << "," << endl;
+ Ya.get(a,b);
+ cout << "CURVE_Pya:"; output(2,WORDS[3],a,m); cout << "," << endl;
+ cout << "CURVE_Pyb:"; output(2,WORDS[3],b,m); cout << "," << endl;
+
+// Q*=q;
+// cout << "Q= " << Q << endl;
+
+ cout << "CURVE_Gx :"; output(2,WORDS[3],p-1,m); cout << "," << endl;
+ cout << "CURVE_Gy :"; output(2,WORDS[3],(Big)1,m); cout << "," << endl;
+
+ cout << "CURVE_W:["; output(2,WORDS[3],6*x*x-4*x+1,m);cout << ","; output(2,WORDS[3],(2*x-1),m); cout << "]," << endl;
+ cout << "CURVE_SB:["; cout << "["; output(2,WORDS[3],6*x*x-2*x,m); cout << ","; output(2,WORDS[3],(2*x-1),m); cout << "]";cout << ","; cout << "["; output(2,WORDS[3],(2*x-1),m); cout << ","; output(2,WORDS[3],q-(6*x*x-4*x+1),m); cout << "]"; cout << "]," << endl;
+
+ cout << "CURVE_WB:["; output(2,WORDS[3],2*x*x-3*x+1,m); cout << ","; output(2,WORDS[3],12*x*x*x-8*x*x+x,m);
+ cout << ","; output(2,WORDS[3],6*x*x*x-4*x*x+x,m); cout << ","; output(2,WORDS[3],2*x*x-x,m); cout << "]," << endl;
+
+ cout << "CURVE_BB:[";
+ cout << "[";
+ output(2,WORDS[3],q-x+1,m);
+ cout << ","; output(2,WORDS[3],q-x,m);
+ cout << ","; output(2,WORDS[3],q-x,m);
+ cout << ","; output(2,WORDS[3],2*x,m);
+ cout << "]";
+
+ cout << ","; cout << "[";output(2,WORDS[3],2*x-1,m);
+ cout << ","; output(2,WORDS[3],q-x,m);
+ cout << ","; output(2,WORDS[3],q-x+1,m);
+ cout << ","; output(2,WORDS[3],q-x,m);
+ cout << "]";
+ cout << ","; cout << "["; output(2,WORDS[3],2*x,m);
+ cout << ","; output(2,WORDS[3],2*x-1,m);
+ cout << ","; output(2,WORDS[3],2*x-1,m);
+ cout << ","; output(2,WORDS[3],2*x-1,m);
+ cout << "]";
+
+ cout << ","; cout << "["; output(2,WORDS[3],x+1,m);
+ cout << ","; output(2,WORDS[3],4*x-2,m);
+ cout << ","; output(2,WORDS[3],q-2*x-1,m);
+ cout << ","; output(2,WORDS[3],x+1,m);
+ cout << "]";
+ cout << "]," << endl;
+}
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..9a388dc
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,47 @@
+{
+ "name": "clint",
+ "description": "AMCL cryptography js library",
+ "authors": [
+ "MIRACL Crypto Labs."
+ ],
+ "main": [
+ "js/DBIG.js",
+ "js/BIG.js",
+ "js/FP.js",
+ "js/ROM.js",
+ "js/HASH.js",
+ "js/RAND.js",
+ "js/AES.js",
+ "js/GPM.js",
+ "js/ECP.js",
+ "js/FP2.js",
+ "js/ECP2.js",
+ "js/FP4.js",
+ "js/FP12.js",
+ "js/PAIR.js",
+ "js/MPIN.js",
+ "js/MPINAuth.js"
+ ],
+ "ignore": [
+ "**/.*",
+ "c",
+ "data",
+ "docs",
+ "java",
+ "java64",
+ "pythonCFFI",
+ "swift",
+ "testVectors",
+ "*.*",
+ "!*.json",
+ "js/tests",
+ "js/*.html",
+ "js/*.txt"
+ ],
+ "keywords": [
+ "JS",
+ "front-end",
+ "AMCL"
+ ],
+ "homepage": "http://miracl.com"
+}
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
new file mode 100644
index 0000000..50270fb
--- /dev/null
+++ b/c/CMakeLists.txt
@@ -0,0 +1,218 @@
+# Create AMCL library and examples
+
+# add the binary tree directory to the search path for include files and linking
+include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+link_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+
+# post build: mv amcl_.h amcl.h
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/amcl.h")
+ file(RENAME amcl.h amcl_.h)
+endif()
+file(COPY DLLDefines.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+
+set(SOURCES_AMCL
+big.c
+fp.c
+ecp.c
+hash.c
+rand.c
+aes.c
+gcm.c
+oct.c
+rom.c
+fp2.c
+ecp2.c
+fp4.c
+fp12.c
+ff.c)
+
+# Build AMCL
+add_library(amcl ${LIB_TYPE} ${SOURCES_AMCL} version.c)
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ if(BUILD_SHARED_LIBS)
+ message(STATUS "Build shared libs")
+ target_link_libraries (amcl libm.so)
+ else()
+ message(STATUS "Build static libs")
+ target_link_libraries (amcl libm.a)
+ endif(BUILD_SHARED_LIBS)
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+# Build libmpin
+if(BUILD_MPIN)
+ add_library(mpin ${LIB_TYPE} pair.c mpin.c utils.c)
+ target_link_libraries (mpin amcl)
+ add_executable (testmpin testmpin.c)
+ target_link_libraries (testmpin mpin)
+endif(BUILD_MPIN)
+
+
+# Copy built libs to c/tests which allows testing without
+# having to install the libs.
+if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ message(STATUS "Copy libamcl.dll to c/tests for testing")
+ add_custom_command(
+ TARGET amcl
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dll" "${PROJECT_BINARY_DIR}/c/tests/")
+
+ if(BUILD_MPIN)
+ message(STATUS "Copy libmpin.dll to c/tests for testing")
+ add_custom_command(
+ TARGET mpin
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dll" "${PROJECT_BINARY_DIR}/c/tests/")
+ endif(BUILD_MPIN)
+
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+
+# Copy built libs to pythonCFFI which allows testing without
+# having to install the libs.
+if (BUILD_PYTHON AND BUILD_SHARED_LIBS)
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+ if(BUILD_MPIN)
+ message(STATUS "Copy libmpin.so to pythonCFFI for testing")
+ add_custom_command(
+ TARGET mpin
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.so" "${PROJECT_BINARY_DIR}/pythonCFFI/")
+ endif(BUILD_MPIN)
+
+ endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ message(STATUS "Copy libamcl.dll to pythonCFFI for testing")
+ add_custom_command(
+ TARGET amcl
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dll" "${PROJECT_BINARY_DIR}/pythonCFFI/")
+
+ if(BUILD_MPIN)
+ message(STATUS "Copy libmpin.dll to pythonCFFI for testing")
+ add_custom_command(
+ TARGET mpin
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dll" "${PROJECT_BINARY_DIR}/pythonCFFI/")
+ endif(BUILD_MPIN)
+
+ endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+ message(STATUS "Copy libamcl.dylib to pythonCFFI for testing")
+ add_custom_command(
+ TARGET amcl
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libamcl.dylib" "${PROJECT_BINARY_DIR}/pythonCFFI/")
+
+ if(BUILD_MPIN)
+ message(STATUS "Copy libmpin.dylib to pythonCFFI for testing")
+ add_custom_command(
+ TARGET mpin
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/libmpin.dylib" "${PROJECT_BINARY_DIR}/pythonCFFI/")
+ endif(BUILD_MPIN)
+
+ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+
+endif (BUILD_PYTHON AND BUILD_SHARED_LIBS)
+
+# Example programs
+add_executable (testecm testecm.c ecdh.c)
+add_executable (testecdh testecdh.c ecdh.c)
+add_executable (testrsa testrsa.c rsa.c)
+target_link_libraries (testecm amcl)
+target_link_libraries (testecdh amcl)
+target_link_libraries (testrsa amcl)
+
+add_subdirectory (tests)
+
+# Install libs and headers
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ install(DIRECTORY DESTINATION include/amcl DIRECTORY_PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_WRITE GROUP_READ
+ WORLD_WRITE WORLD_READ WORLD_EXECUTE)
+ install (TARGETS amcl DESTINATION lib PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+
+ if(BUILD_MPIN)
+ install (TARGETS mpin DESTINATION lib PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ endif(BUILD_MPIN)
+
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ # Windows specific code
+ install (TARGETS amcl DESTINATION lib)
+ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION lib)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION lib)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION lib)
+
+ if(BUILD_MPIN)
+ install (TARGETS mpin DESTINATION lib)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION lib)
+ endif(BUILD_MPIN)
+
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ # Mac OS X specific code
+ install(DIRECTORY DESTINATION include/amcl DIRECTORY_PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_WRITE GROUP_READ
+ WORLD_WRITE WORLD_READ WORLD_EXECUTE)
+ install (TARGETS amcl DESTINATION lib PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amcl.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/DLLDefines.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+
+ if(BUILD_MPIN)
+ install (TARGETS mpin DESTINATION lib PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/mpin.h DESTINATION include/amcl PERMISSIONS
+ OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+ endif(BUILD_MPIN)
+
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
diff --git a/c/DLLDefines.h b/c/DLLDefines.h
new file mode 100755
index 0000000..57655f3
--- /dev/null
+++ b/c/DLLDefines.h
@@ -0,0 +1,49 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* Use with Visual Studio Compiler for building Shared libraries */
+#ifndef _DLLDEFINES_H_
+#define _DLLDEFINES_H_
+
+/* Cmake will define sok_EXPORTS and mpin_EXPORTS on Windows when it
+configures to build a shared library. If you are going to use
+another build system on windows or create the visual studio
+projects by hand you need to define sok_EXPORTS and mpin_EXPORTS when
+building a DLL on windows. */
+/* #define sok_EXPORTS */
+/* #define mpin_EXPORTS */
+
+
+#if defined (_MSC_VER)
+
+ #define DLL_EXPORT extern
+/* This code does not work with cl */
+/* #if defined(sok_EXPORTS) || defined(mpin_EXPORTS) */
+/* #define DLL_EXPORT __declspec(dllexport) */
+/* #else */
+/* #define DLL_EXPORT __declspec(dllimport) */
+/* #endif /\* sok_EXPORTS || mpin_EXPORTS *\/ */
+
+#else /* defined (_WIN32) */
+
+ #define DLL_EXPORT extern
+
+#endif
+
+#endif /* _DLLDEFINES_H_ */
diff --git a/c/aes.c b/c/aes.c
new file mode 100755
index 0000000..d9360e9
--- /dev/null
+++ b/c/aes.c
@@ -0,0 +1,620 @@
+/*
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+/*
+ * Implementation of the NIST Advanced Ecryption Standard
+ *
+ * SU=m, SU is Stack Usage
+ */
+
+#include <stdlib.h>
+#include "amcl.h"
+
+/* this is fixed */
+#define NB 4
+#define ROUNDS 10
+
+/* Rotates 32-bit word left by 1, 2 or 3 byte */
+
+#define ROTL8(x) (((x)<<8)|((x)>>24))
+#define ROTL16(x) (((x)<<16)|((x)>>16))
+#define ROTL24(x) (((x)<<24)|((x)>>8))
+
+static const uchar InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
+
+static const uchar ptab[]=
+{1,3,5,15,17,51,85,255,26,46,114,150,161,248,19,53,
+95,225,56,72,216,115,149,164,247,2,6,10,30,34,102,170,
+229,52,92,228,55,89,235,38,106,190,217,112,144,171,230,49,
+83,245,4,12,20,60,68,204,79,209,104,184,211,110,178,205,
+76,212,103,169,224,59,77,215,98,166,241,8,24,40,120,136,
+131,158,185,208,107,189,220,127,129,152,179,206,73,219,118,154,
+181,196,87,249,16,48,80,240,11,29,39,105,187,214,97,163,
+254,25,43,125,135,146,173,236,47,113,147,174,233,32,96,160,
+251,22,58,78,210,109,183,194,93,231,50,86,250,21,63,65,
+195,94,226,61,71,201,64,192,91,237,44,116,156,191,218,117,
+159,186,213,100,172,239,42,126,130,157,188,223,122,142,137,128,
+155,182,193,88,232,35,101,175,234,37,111,177,200,67,197,84,
+252,31,33,99,165,244,7,9,27,45,119,153,176,203,70,202,
+69,207,74,222,121,139,134,145,168,227,62,66,198,81,243,14,
+18,54,90,238,41,123,141,140,143,138,133,148,167,242,13,23,
+57,75,221,124,132,151,162,253,28,36,108,180,199,82,246,1};
+
+static const uchar ltab[]=
+{0,255,25,1,50,2,26,198,75,199,27,104,51,238,223,3,
+100,4,224,14,52,141,129,239,76,113,8,200,248,105,28,193,
+125,194,29,181,249,185,39,106,77,228,166,114,154,201,9,120,
+101,47,138,5,33,15,225,36,18,240,130,69,53,147,218,142,
+150,143,219,189,54,208,206,148,19,92,210,241,64,70,131,56,
+102,221,253,48,191,6,139,98,179,37,226,152,34,136,145,16,
+126,110,72,195,163,182,30,66,58,107,40,84,250,133,61,186,
+43,121,10,21,155,159,94,202,78,212,172,229,243,115,167,87,
+175,88,168,80,244,234,214,116,79,174,233,213,231,230,173,232,
+44,215,117,122,235,22,11,245,89,203,95,176,156,169,81,160,
+127,12,246,111,23,196,73,236,216,67,31,45,164,118,123,183,
+204,187,62,90,251,96,177,134,59,82,161,108,170,85,41,157,
+151,178,135,144,97,190,220,252,188,149,207,205,55,63,91,209,
+83,57,132,60,65,162,109,71,20,42,158,93,86,242,211,171,
+68,17,146,217,35,32,46,137,180,124,184,38,119,153,227,165,
+103,74,237,222,197,49,254,24,13,99,140,128,192,247,112,7};
+
+static const uchar fbsub[]=
+{99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,
+202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,
+183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,
+4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,
+9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,
+83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,
+208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,
+81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,
+205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,
+96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,
+224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,
+231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,
+186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,
+112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,
+225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,
+140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22};
+
+static const uchar rbsub[]=
+{82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,
+124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,
+84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,
+8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,
+114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,
+108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,
+144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,
+208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,
+58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,
+150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,
+71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,
+252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,
+31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,
+96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,
+160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,
+23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125};
+
+static const unsign32 rco[]=
+{1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47};
+
+static const unsign32 ftable[]=
+{0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6,
+0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56,
+0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f,
+0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb,
+0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453,
+0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c,
+0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551,
+0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a,
+0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637,
+0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df,
+0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d,
+0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b,
+0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd,
+0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1,
+0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d,
+0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85,
+0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a,
+0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe,
+0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d,
+0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1,
+0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5,
+0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3,
+0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755,
+0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6,
+0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54,
+0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428,
+0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264,
+0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8,
+0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531,
+0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda,
+0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac,
+0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810,
+0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657,
+0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e,
+0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c,
+0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c,
+0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199,
+0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122,
+0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c,
+0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5,
+0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7,
+0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e,
+0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c};
+
+static const unsign32 rtable[]=
+{0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f,
+0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5,
+0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25,
+0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b,
+0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458,
+0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927,
+0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5,
+0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9,
+0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72,
+0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3,
+0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7,
+0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4,
+0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040,
+0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d,
+0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6,
+0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879,
+0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32,
+0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36,
+0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793,
+0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c,
+0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2,
+0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3,
+0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb,
+0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684,
+0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc,
+0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947,
+0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9,
+0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f,
+0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890,
+0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf,
+0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e,
+0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef,
+0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a,
+0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733,
+0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43,
+0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546,
+0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92,
+0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb,
+0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255,
+0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478,
+0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc,
+0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664,
+0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0};
+
+#define MR_TOBYTE(x) ((uchar)((x)))
+
+static unsign32 pack(const uchar *b)
+{ /* pack bytes into a 32-bit Word */
+ return ((unsign32)b[3]<<24)|((unsign32)b[2]<<16)|((unsign32)b[1]<<8)|(unsign32)b[0];
+}
+
+static void unpack(unsign32 a,uchar *b)
+{ /* unpack bytes from a word */
+ b[0]=MR_TOBYTE(a);
+ b[1]=MR_TOBYTE(a>>8);
+ b[2]=MR_TOBYTE(a>>16);
+ b[3]=MR_TOBYTE(a>>24);
+}
+
+/* SU= 8 */
+static uchar bmul(uchar x,uchar y)
+{ /* x.y= AntiLog(Log(x) + Log(y)) */
+ if (x && y) return ptab[(ltab[x]+ltab[y])%255];
+ else return 0;
+}
+
+static unsign32 SubByte(unsign32 a)
+{
+ uchar b[4];
+ unpack(a,b);
+ b[0]=fbsub[b[0]];
+ b[1]=fbsub[b[1]];
+ b[2]=fbsub[b[2]];
+ b[3]=fbsub[b[3]];
+ return pack(b);
+}
+
+/* SU= 16 */
+static uchar product(unsign32 x,unsign32 y)
+{ /* dot product of two 4-byte arrays */
+ uchar xb[4],yb[4];
+ unpack(x,xb);
+ unpack(y,yb);
+ return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
+}
+
+static unsign32 InvMixCol(unsign32 x)
+{ /* matrix Multiplication */
+ unsign32 y,m;
+ uchar b[4];
+
+ m=pack(InCo);
+ b[3]=product(m,x);
+ m=ROTL24(m);
+ b[2]=product(m,x);
+ m=ROTL24(m);
+ b[1]=product(m,x);
+ m=ROTL24(m);
+ b[0]=product(m,x);
+ y=pack(b);
+ return y;
+}
+
+/* SU= 8 */
+/* reset cipher */
+void AES_reset(aes *a,int mode,char *iv)
+{ /* reset mode, or reset iv */
+ int i;
+ a->mode=mode;
+ for (i=0;i<4*NB;i++)
+ a->f[i]=0;
+ if (mode!=ECB && iv!=NULL)
+ {
+ for (i=0;i<4*NB;i++)
+ a->f[i]=iv[i];
+ }
+}
+
+void AES_getreg(aes *a,char *ir)
+{
+ int i;
+ for (i=0;i<4*NB;i++) ir[i]=a->f[i];
+}
+
+/* SU= 72 */
+/* Initialise cipher */
+void AES_init(aes* a,int mode,char *key,char *iv)
+{ /* Key=16 bytes */
+ /* Key Scheduler. Create expanded encryption key */
+ int i,j,k,N,nk;
+ unsign32 CipherKey[4];
+
+ nk=4;
+
+ AES_reset(a,mode,iv);
+
+ N=NB*(ROUNDS+1);
+
+ for (i=j=0;i<nk;i++,j+=4)
+ {
+ CipherKey[i]=pack((uchar *)&key[j]);
+ }
+ for (i=0;i<nk;i++) a->fkey[i]=CipherKey[i];
+ for (j=nk,k=0;j<N;j+=nk,k++)
+ {
+ a->fkey[j]=a->fkey[j-nk]^SubByte(ROTL24(a->fkey[j-1]))^rco[k];
+
+ for (i=1;i<nk && (i+j)<N;i++)
+ a->fkey[i+j]=a->fkey[i+j-nk]^a->fkey[i+j-1];
+
+ }
+ /* now for the expanded decrypt key in reverse order */
+
+ for (j=0;j<NB;j++) a->rkey[j+N-NB]=a->fkey[j];
+ for (i=NB;i<N-NB;i+=NB)
+ {
+ k=N-NB-i;
+ for (j=0;j<NB;j++) a->rkey[k+j]=InvMixCol(a->fkey[i+j]);
+ }
+ for (j=N-NB;j<N;j++) a->rkey[j-N+NB]=a->fkey[j];
+
+}
+
+/* SU= 80 */
+/* Encrypt a single block */
+void AES_ecb_encrypt(aes *a,uchar *buff)
+{
+ int i,j,k;
+ unsign32 p[4],q[4],*x,*y,*t;
+
+ for (i=j=0;i<NB;i++,j+=4)
+ {
+ p[i]=pack((uchar *)&buff[j]);
+ p[i]^=a->fkey[i];
+ }
+
+ k=NB;
+ x=p; y=q;
+
+/* State alternates between x and y */
+ for (i=1;i<ROUNDS;i++)
+ {
+
+ y[0]=a->fkey[k]^ftable[MR_TOBYTE(x[0])]^
+ ROTL8(ftable[MR_TOBYTE(x[1]>>8)])^
+ ROTL16(ftable[MR_TOBYTE(x[2]>>16)])^
+ ROTL24(ftable[x[3]>>24]);
+ y[1]=a->fkey[k+1]^ftable[MR_TOBYTE(x[1])]^
+ ROTL8(ftable[MR_TOBYTE(x[2]>>8)])^
+ ROTL16(ftable[MR_TOBYTE(x[3]>>16)])^
+ ROTL24(ftable[x[0]>>24]);
+ y[2]=a->fkey[k+2]^ftable[MR_TOBYTE(x[2])]^
+ ROTL8(ftable[MR_TOBYTE(x[3]>>8)])^
+ ROTL16(ftable[MR_TOBYTE(x[0]>>16)])^
+ ROTL24(ftable[x[1]>>24]);
+ y[3]=a->fkey[k+3]^ftable[MR_TOBYTE(x[3])]^
+ ROTL8(ftable[MR_TOBYTE(x[0]>>8)])^
+ ROTL16(ftable[MR_TOBYTE(x[1]>>16)])^
+ ROTL24(ftable[x[2]>>24]);
+
+ k+=4;
+ t=x; x=y; y=t; /* swap pointers */
+ }
+
+/* Last Round */
+
+ y[0]=a->fkey[k]^(unsign32)fbsub[MR_TOBYTE(x[0])]^
+ ROTL8((unsign32)fbsub[MR_TOBYTE(x[1]>>8)])^
+ ROTL16((unsign32)fbsub[MR_TOBYTE(x[2]>>16)])^
+ ROTL24((unsign32)fbsub[x[3]>>24]);
+ y[1]=a->fkey[k+1]^(unsign32)fbsub[MR_TOBYTE(x[1])]^
+ ROTL8((unsign32)fbsub[MR_TOBYTE(x[2]>>8)])^
+ ROTL16((unsign32)fbsub[MR_TOBYTE(x[3]>>16)])^
+ ROTL24((unsign32)fbsub[x[0]>>24]);
+ y[2]=a->fkey[k+2]^(unsign32)fbsub[MR_TOBYTE(x[2])]^
+ ROTL8((unsign32)fbsub[MR_TOBYTE(x[3]>>8)])^
+ ROTL16((unsign32)fbsub[MR_TOBYTE(x[0]>>16)])^
+ ROTL24((unsign32)fbsub[x[1]>>24]);
+ y[3]=a->fkey[k+3]^(unsign32)fbsub[MR_TOBYTE(x[3])]^
+ ROTL8((unsign32)fbsub[MR_TOBYTE(x[0]>>8)])^
+ ROTL16((unsign32)fbsub[MR_TOBYTE(x[1]>>16)])^
+ ROTL24((unsign32)fbsub[x[2]>>24]);
+
+ for (i=j=0;i<NB;i++,j+=4)
+ {
+ unpack(y[i],(uchar *)&buff[j]);
+ x[i]=y[i]=0; /* clean up stack */
+ }
+}
+
+/* SU= 80 */
+/* Decrypt a single block */
+void AES_ecb_decrypt(aes *a,uchar *buff)
+{
+ int i,j,k;
+ unsign32 p[4],q[4],*x,*y,*t;
+
+ for (i=j=0;i<NB;i++,j+=4)
+ {
+ p[i]=pack((uchar *)&buff[j]);
+ p[i]^=a->rkey[i];
+ }
+
+ k=NB;
+ x=p; y=q;
+
+/* State alternates between x and y */
+ for (i=1;i<ROUNDS;i++)
+ { /* Nr is number of rounds. May be odd. */
+
+ y[0]=a->rkey[k]^rtable[MR_TOBYTE(x[0])]^
+ ROTL8(rtable[MR_TOBYTE(x[3]>>8)])^
+ ROTL16(rtable[MR_TOBYTE(x[2]>>16)])^
+ ROTL24(rtable[x[1]>>24]);
+ y[1]=a->rkey[k+1]^rtable[MR_TOBYTE(x[1])]^
+ ROTL8(rtable[MR_TOBYTE(x[0]>>8)])^
+ ROTL16(rtable[MR_TOBYTE(x[3]>>16)])^
+ ROTL24(rtable[x[2]>>24]);
+ y[2]=a->rkey[k+2]^rtable[MR_TOBYTE(x[2])]^
+ ROTL8(rtable[MR_TOBYTE(x[1]>>8)])^
+ ROTL16(rtable[MR_TOBYTE(x[0]>>16)])^
+ ROTL24(rtable[x[3]>>24]);
+ y[3]=a->rkey[k+3]^rtable[MR_TOBYTE(x[3])]^
+ ROTL8(rtable[MR_TOBYTE(x[2]>>8)])^
+ ROTL16(rtable[MR_TOBYTE(x[1]>>16)])^
+ ROTL24(rtable[x[0]>>24]);
+
+ k+=4;
+ t=x; x=y; y=t; /* swap pointers */
+ }
+
+
+/* Last Round */
+ y[0]=a->rkey[k]^(unsign32)rbsub[MR_TOBYTE(x[0])]^
+ ROTL8((unsign32)rbsub[MR_TOBYTE(x[3]>>8)])^
+ ROTL16((unsign32)rbsub[MR_TOBYTE(x[2]>>16)])^
+ ROTL24((unsign32)rbsub[x[1]>>24]);
+ y[1]=a->rkey[k+1]^(unsign32)rbsub[MR_TOBYTE(x[1])]^
+ ROTL8((unsign32)rbsub[MR_TOBYTE(x[0]>>8)])^
+ ROTL16((unsign32)rbsub[MR_TOBYTE(x[3]>>16)])^
+ ROTL24((unsign32)rbsub[x[2]>>24]);
+ y[2]=a->rkey[k+2]^(unsign32)rbsub[MR_TOBYTE(x[2])]^
+ ROTL8((unsign32)rbsub[MR_TOBYTE(x[1]>>8)])^
+ ROTL16((unsign32)rbsub[MR_TOBYTE(x[0]>>16)])^
+ ROTL24((unsign32)rbsub[x[3]>>24]);
+ y[3]=a->rkey[k+3]^(unsign32)rbsub[MR_TOBYTE(x[3])]^
+ ROTL8((unsign32)rbsub[MR_TOBYTE(x[2]>>8)])^
+ ROTL16((unsign32)rbsub[MR_TOBYTE(x[1]>>16)])^
+ ROTL24((unsign32)rbsub[x[0]>>24]);
+
+ for (i=j=0;i<NB;i++,j+=4)
+ {
+ unpack(y[i],(uchar *)&buff[j]);
+ x[i]=y[i]=0; /* clean up stack */
+ }
+
+}
+
+/* SU= 40 */
+/* Encrypt using selected mode of operation */
+unsign32 AES_encrypt(aes* a,char *buff)
+{
+ int j,bytes;
+ char st[16];
+ unsign32 fell_off;
+
+/* Supported Modes of Operation */
+
+ fell_off=0;
+ switch (a->mode)
+ {
+ case ECB:
+ AES_ecb_encrypt(a,(uchar *)buff);
+ return 0;
+ case CBC:
+ for (j=0;j<4*NB;j++) buff[j]^=a->f[j];
+ AES_ecb_encrypt(a,(uchar *)buff);
+ for (j=0;j<4*NB;j++) a->f[j]=buff[j];
+ return 0;
+
+ case CFB1:
+ case CFB2:
+ case CFB4:
+ bytes=a->mode-CFB1+1;
+ for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|a->f[j];
+ for (j=0;j<4*NB;j++) st[j]=a->f[j];
+ for (j=bytes;j<4*NB;j++) a->f[j-bytes]=a->f[j];
+ AES_ecb_encrypt(a,(uchar *)st);
+ for (j=0;j<bytes;j++)
+ {
+ buff[j]^=st[j];
+ a->f[16-bytes+j]=buff[j];
+ }
+ return fell_off;
+
+ case OFB1:
+ case OFB2:
+ case OFB4:
+ case OFB8:
+ case OFB16:
+
+ bytes=a->mode-OFB1+1;
+ AES_ecb_encrypt(a,(uchar *)(a->f));
+ for (j=0;j<bytes;j++) buff[j]^=a->f[j];
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/* SU= 40 */
+/* Decrypt using selected mode of operation */
+unsign32 AES_decrypt(aes *a,char *buff)
+{
+ int j,bytes;
+ char st[16];
+ unsign32 fell_off;
+
+ /* Supported modes of operation */
+ fell_off=0;
+ switch (a->mode)
+ {
+ case ECB:
+ AES_ecb_decrypt(a,(uchar *)buff);
+ return 0;
+ case CBC:
+ for (j=0;j<4*NB;j++)
+ {
+ st[j]=a->f[j];
+ a->f[j]=buff[j];
+ }
+ AES_ecb_decrypt(a,(uchar *)buff);
+ for (j=0;j<4*NB;j++)
+ {
+ buff[j]^=st[j];
+ st[j]=0;
+ }
+ return 0;
+ case CFB1:
+ case CFB2:
+ case CFB4:
+ bytes=a->mode-CFB1+1;
+ for (j=0;j<bytes;j++) fell_off=(fell_off<<8)|a->f[j];
+ for (j=0;j<4*NB;j++) st[j]=a->f[j];
+ for (j=bytes;j<4*NB;j++) a->f[j-bytes]=a->f[j];
+ AES_ecb_encrypt(a,(uchar *)st);
+ for (j=0;j<bytes;j++)
+ {
+ a->f[16-bytes+j]=buff[j];
+ buff[j]^=st[j];
+ }
+ return fell_off;
+ case OFB1:
+ case OFB2:
+ case OFB4:
+ case OFB8:
+ case OFB16:
+ bytes=a->mode-OFB1+1;
+ AES_ecb_encrypt(a,(uchar *)(a->f));
+ for (j=0;j<bytes;j++) buff[j]^=a->f[j];
+ return 0;
+
+
+ default:
+ return 0;
+ }
+}
+
+/* Clean up and delete left-overs */
+void AES_end(aes *a)
+{ /* clean up */
+ int i;
+ for (i=0;i<NB*(ROUNDS+1);i++)
+ a->fkey[i]=a->rkey[i]=0;
+ for (i=0;i<4*NB;i++)
+ a->f[i]=0;
+}
+
+/*
+int main()
+{
+ int i;
+ aes a;
+ unsign32 t;
+ uchar x,y;
+
+ char key[16];
+ char block[16];
+ char iv[16];
+ for (i=0;i<16;i++) key[i]=0;
+ key[0]=1;
+ for (i=0;i<16;i++) iv[i]=i;
+ for (i=0;i<16;i++) block[i]=i;
+
+ AES_init(&a,CBC,key,iv);
+
+ printf("Plain= ");
+ for (i=0;i<16;i++) printf("%02x",block[i]);
+ printf("\n");
+ AES_encrypt(&a,block);
+ printf("Encrypt= ");
+ for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+ printf("\n");
+ AES_reset(&a,CBC,iv);
+ AES_decrypt(&a,block);
+ printf("Decrypt= ");
+ for (i=0;i<16;i++) printf("%02x",(uchar)block[i]);
+ printf("\n");
+
+ AES_end(&a);
+
+ return 0;
+}
+
+*/
+
diff --git a/c/amcl.h.in b/c/amcl.h.in
new file mode 100755
index 0000000..d9e7b37
--- /dev/null
+++ b/c/amcl.h.in
@@ -0,0 +1,2510 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* AMCL header file */
+/* Designed for AES-128 security, 254-256 bit elliptic curves and BN curves for pairings */
+/* Each "limb" of a big number occupies at most (n-3) bits of an n-bit computer word. The most significant word must have at least 4 extra unused bits */
+/* For n=64, use 5 words, use 56 bits per limb, leaving at least 24 unused MSBs 5*56-256 */
+/* For n=32, use 9 words, use 29 bits per limb, leaving at least 5 unused MSBs 9*29-256 */
+/* For n=16, use 20 words, use 13 bits per limb, leaving at least 4 unused MSBs 20*13-256 */
+
+/**
+ * @file amcl.h.in
+ * @author Mike Scott and kealan McCusker
+ * @date 19th May 2015
+ * @brief Main Header File
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "DLLDefines.h"
+
+#define AMCL_VERSION_MAJOR @AMCL_VERSION_MAJOR@
+#define AMCL_VERSION_MINOR @AMCL_VERSION_MINOR@
+#define AMCL_VERSION_PATCH @AMCL_VERSION_PATCH@
+#define OS "@OS@"
+#cmakedefine USE_PATENTS
+
+/* Support for C99? Note for GCC need to explicitly include -std=c99 in command line */
+
+#if __STDC_VERSION__ >= 199901L
+/* C99 code */
+#define C99
+#else
+/* Not C99 code */
+#endif
+
+#ifndef C99 /* You are on your own! These are for Microsoft C */
+#define sign32 __int32 /**< 32-bit signed integer */
+#define sign8 signed char /**< 8-bit signed integer */
+#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
+#else
+#include <stdint.h>
+#define sign8 int8_t /**< 8-bit signed integer */
+#define sign32 int32_t /**< 32-bit signed integer */
+#define unsign32 uint32_t /**< 32-bit unsigned integer */
+#endif
+
+/* modulus types */
+
+#define NOT_SPECIAL 0 /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1 /**< Pseudo-mersenne modulus of form $2^n-c$ */
+#define MONTGOMERY_FRIENDLY 3 /**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$ */
+
+/* curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve */
+#define EDWARDS 1 /**< Edwards or Twisted Edwards curve */
+#define MONTGOMERY 2 /**< Montgomery form curve */
+
+/* Elliptic curves are defined over prime fields */
+/* Here are some popular EC prime fields for which I have prepared curves. Feel free to specify your own. */
+
+#define NIST 0 /**< For the NIST 256-bit standard curve - WEIERSTRASS only */
+#define C25519 1 /**< Bernstein's Modulus 2^255-19 - EDWARDS or MONTGOMERY only */
+#define BRAINPOOL 2 /**< For Brainpool 256-bit curve - WEIERSTRASS only */
+#define ANSSI 3 /**< For French 256-bit standard curve - WEIERSTRASS only */
+#define MF254 4 /**< For NUMS curves from Bos et al - 254-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS255 5 /**< For NUMS curve - 255-bit pseudo-mersenne modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MF256 6 /**< For NUMS curve - 256-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS256 7 /**< For NUMS curve - 256-bit pseudo-merseene modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+
+#define BN 100 /**< Standard Nogami BN curve - fastest. Modulus built from t=-0x4080000000000001 - WEIERSTRASS only */
+#define BNCX 101 /**< Our MIRACL BN curve. Modulus built from t=-0x4000000003C012B1 - WEIERSTRASS only */
+#define BNT 102 /**< GT_Strong BN curve. Modulus built from t=-0x4000806000004081 - WEIERSTRASS only */
+#define BNT2 103 /**< G2 and GT-Strong BN curve. Modulus built from t=-0x4000020100608205 - WEIERSTRASS only */
+
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture and choose modulus and curve ***/
+
+#define CHUNK @WORD_LENGTH@ /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#define CHOICE @FIELD_CHOICE@ /**< Current choice of Field */
+#define FIELD_CHOICE "@FIELD_CHOICE@"
+/* For some moduli only WEIERSTRASS curves are supported. For others there is a choice of WEIERSTRASS, EDWARDS or MONTGOMERY curves. See above. */
+#define CURVETYPE @CURVE_TYPE@ /**< Note that not all curve types are supported - see above */
+
+/* Actual curve parameters associated with these choices can be found in rom.c */
+#define CURVE_TYPE "@CURVE_TYPE@"
+
+/* These next options only apply for pairings */
+#ifdef USE_PATENTS
+ #define USE_GLV /**< Note this method is patented (GLV), so maybe you want to comment this out */
+ #define USE_GS_G2 /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+#endif
+#define USE_GS_GT /**< Not patented, so probably always use this */
+
+/* Finite field support - for RSA, DH etc. */
+#define FF_BITS 2048 /**< Finite Field Size in bits - must be 256.2^n */
+
+/* For debugging Only.
+#define DEBUG_REDUCE
+#define DEBUG_NORM
+#define GET_STATS
+*/
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+
+#if CHOICE>=BN /* Its a BN curve */
+#define MBITS 254 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE>BN
+#define GT_STRONG /**< Using a GT-Strong BN curve */
+#endif
+
+#if CHOICE==NIST
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE==C25519
+#define MBITS 255 /**< Number of bits in Modulus */
+#define MOD8 5 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+#if CHOICE==BRAINPOOL
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE==ANSSI
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+/**< NUMS curve from Bos et al. paper */
+
+#if CHOICE==MF254
+#define MBITS 254 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE MONTGOMERY_FRIENDLY /**< Modulus type */
+#endif
+
+#if CHOICE==MF256
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE MONTGOMERY_FRIENDLY /**< Modulus type */
+#endif
+
+#if CHOICE==MS255
+#define MBITS 255 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+#if CHOICE==MS256
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+
+#define FFLEN (FF_BITS/256) /**< RSA public key bytes */
+#define HFLEN (FFLEN/2) /**< Useful for half-size RSA private key operations */
+
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+#if CHUNK==16
+#define NLEN 20 /**< Number of words in BIG. */
+#define BASEBITS 13 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int16 /**< C type corresponding to word length */
+#define dchunk __int32 /**< Always define double length chunk type if available */
+#else
+#define chunk int16_t /**< C type corresponding to word length */
+#define dchunk int32_t /**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 32
+#define NLEN 9 /**< Number of words in BIG. */
+#define BASEBITS 29 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int32 /**< C type corresponding to word length */
+#define dchunk __int64 /**< Always define double length chunk type if available */
+#else
+#define chunk int32_t /**< C type corresponding to word length */
+#define dchunk int64_t /**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 64
+#define NLEN 5 /**< Number of words in BIG. */
+#define BASEBITS 56 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int64 /**< C type corresponding to word length */
+ /**< Note - no 128-bit type available */
+#else
+#define chunk int64_t /**< C type corresponding to word length */
+#ifdef __GNUC__
+#define dchunk __int128 /**< Always define double length chunk type if available - GCC supports 128 bit type ??? */
+#endif
+#endif
+#endif
+
+/* Don't mess with anything below this line */
+
+#ifdef GET_STATS
+extern int tsqr,rsqr,tmul,rmul;
+extern int tadd,radd,tneg,rneg;
+extern int tdadd,rdadd,tdneg,rdneg;
+#endif
+
+#define DCHUNK 2*CHUNK /**< Number of bits in double-length type */
+#define DNLEN 2*NLEN /**< double length required for products of BIGs */
+
+#ifdef dchunk
+#define COMBA /**< Use COMBA method for faster BN muls, sqrs and reductions */
+#endif
+
+#define CHUNK_BITS 8*sizeof(chunk) /**< Number of bits in a chunk */
+
+#ifdef DEBUG_NORM /* Add an extra location to track chunk extension */
+typedef chunk BIG[NLEN+1]; /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN+1]; /**< Define type DBIG as array of chunks */
+#else
+typedef chunk BIG[NLEN]; /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN]; /**< Define type DBIG as array of chunks */
+#endif
+
+#define HBITS (BASEBITS/2) /**< Number of bits in number base divided by 2 */
+#define HBITS1 ((BASEBITS+1)/2) /**< Number of bits in number base plus 1 divided by 2 */
+#define HDIFF (HBITS1-HBITS) /**< Will be either 0 or 1, depending if number of bits in number base is even or odd */
+
+#define MASK (((chunk)1<<BASEBITS)-1) /**< Mask = 2^BASEBITS-1 */
+#define HMASK (((chunk)1<<HBITS)-1) /**< Mask = 2^HBITS-1 */
+#define HMASK1 (((chunk)1<<HBITS1)-1) /**< Mask = 2^HBITS1-1 */
+
+#define MODBITS MBITS /**< Number of bits in Modulus for selected curve */
+#define MODBYTES 32 /**< Number of bytes in Modulus */
+#define MB (MBITS%BASEBITS) /**< Number of bits in modulus mod number of bits in number base */
+#define TBITS (MBITS%BASEBITS) /**< Number of active bits in top word */
+#define TMASK (((chunk)1<<(MBITS%BASEBITS))-1) /**< Mask for active bits in top word */
+#define NEXCESS (1<<(CHUNK-BASEBITS-1)) /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
+#define FEXCESS ((chunk)1<<(BASEBITS*NLEN-MBITS)) /**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by more than this before reduction */
+#define OMASK ((chunk)(-1)<<(MBITS%BASEBITS)) /**< for masking out overflow bits */
+
+/* catch field excesses */
+#define EXCESS(a) ((a[NLEN-1]&OMASK)>>(MB)) /**< Field Excess */
+
+/* Field Params - see rom.c */
+extern const BIG Modulus; /**< Actual Modulus set in rom.c */
+extern const chunk MConst; /**< Montgomery only - 1/p mod 2^BASEBITS */
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A; /**< Elliptic curve A parameter */
+extern const BIG CURVE_B; /**< Elliptic curve B parameter */
+extern const BIG CURVE_Order; /**< Elliptic curve group order */
+
+/* Generator point on G1 */
+extern const BIG CURVE_Gx; /**< x-coordinate of generator point in group G1 */
+extern const BIG CURVE_Gy; /**< y-coordinate of generator point in group G1 */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+extern const BIG CURVE_Bnx; /**< BN curve x parameter */
+
+extern const BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const BIG CURVE_Fra; /**< real part of BN curve Frobenius Constant */
+extern const BIG CURVE_Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+
+extern const BIG CURVE_W[2]; /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_WB[4]; /**< BN curve constant for GS decomposition */
+extern const BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Structures */
+
+/**
+ @brief ECP structure - Elliptic Curve Point over base field
+*/
+
+typedef struct {
+#if CURVETYPE!=EDWARDS
+int inf; /**< Infinity Flag - not needed for Edwards representation */
+#endif
+BIG x; /**< x-coordinate of point */
+#if CURVETYPE!=MONTGOMERY
+BIG y; /**< y-coordinate of point. Not needed for Montgomery representation */
+#endif
+BIG z; /**< z-coordinate of point */
+} ECP;
+
+/**
+ @brief FP2 Structure - quadratic extension field
+*/
+
+typedef struct {
+BIG a; /**< real part of FP2 */
+BIG b; /**< imaginary part of FP2 */
+} FP2;
+
+/**
+ @brief FP4 Structure - towered over two FP2
+*/
+
+typedef struct {
+FP2 a; /**< real part of FP4 */
+FP2 b; /**< imaginary part of FP4 */
+} FP4;
+
+/**
+ @brief FP12 Structure - towered over three FP4
+*/
+
+typedef struct {
+FP4 a; /**< first part of FP12 */
+FP4 b; /**< second part of FP12 */
+FP4 c; /**< third part of FP12 */
+} FP12;
+
+/**
+ @brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct {
+int inf; /**< Infinity Flag */
+FP2 x; /**< x-coordinate of point */
+FP2 y; /**< y-coordinate of point */
+FP2 z; /**< z-coordinate of point */
+} ECP2;
+
+/**
+ @brief SHA256 hash function instance
+*/
+
+typedef struct {
+unsign32 length[2]; /**< 64-bit input length */
+unsign32 h[8]; /**< Internal state */
+unsign32 w[64]; /**< Internal state */
+} hash;
+
+/* Symmetric Encryption AES structure */
+
+#define ECB 0 /**< Electronic Code Book */
+#define CBC 1 /**< Cipher Block Chaining */
+#define CFB1 2 /**< Cipher Feedback - 1 byte */
+#define CFB2 3 /**< Cipher Feedback - 2 bytes */
+#define CFB4 5 /**< Cipher Feedback - 4 bytes */
+#define OFB1 14 /**< Output Feedback - 1 byte */
+#define OFB2 15 /**< Output Feedback - 2 bytes */
+#define OFB4 17 /**< Output Feedback - 4 bytes */
+#define OFB8 21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+
+#define uchar unsigned char /**< Unsigned char */
+
+/**
+ @brief AES instance
+*/
+
+
+typedef struct {
+int mode; /**< AES mode of operation */
+unsign32 fkey[44]; /**< subkeys for encrypton */
+unsign32 rkey[44]; /**< subkeys for decrypton */
+char f[16]; /**< buffer for chaining vector */
+} aes;
+
+/* AES-GCM suppport. */
+
+#define GCM_ACCEPTING_HEADER 0 /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1 /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3 /**< GCM status */
+#define GCM_ENCRYPTING 0 /**< GCM mode */
+#define GCM_DECRYPTING 1 /**< GCM mode */
+
+
+/**
+ @brief GCM mode instance, using AES internally
+*/
+
+typedef struct {
+unsign32 table[128][4]; /**< 2k byte table */
+uchar stateX[16]; /**< GCM Internal State */
+uchar Y_0[16]; /**< GCM Internal State */
+unsign32 lenA[2]; /**< GCM 64-bit length of header */
+unsign32 lenC[2]; /**< GCM 64-bit length of ciphertext */
+int status; /**< GCM Status */
+aes a; /**< Internal Instance of AES cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK 21 /**< PRNG constant */
+#define NJ 6 /**< PRNG constant */
+#define NV 8 /**< PRNG constant */
+
+
+/**
+ @brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct {
+unsign32 ira[NK]; /**< random number array */
+int rndptr; /**< pointer into array */
+unsign32 borrow; /**< borrow as a result of subtraction */
+int pool_ptr; /**< pointer into random pool */
+char pool[32]; /**< random pool */
+} csprng;
+
+
+/**
+ @brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+ int len; /**< length in bytes */
+ int max; /**< max length allowed - enforce truncation */
+ char *val; /**< byte array */
+} octet;
+
+/**
+ @brief Integer Factorisation Public Key
+*/
+
+typedef struct
+{
+ sign32 e; /**< RSA exponent (typically 65537) */
+ BIG n[FFLEN]; /**< An array of BIGs to store public key */
+} rsa_public_key;
+
+/**
+ @brief Integer Factorisation Private Key
+*/
+
+typedef struct
+{
+ BIG p[FFLEN/2]; /**< secret prime p */
+ BIG q[FFLEN/2]; /**< secret prime q */
+ BIG dp[FFLEN/2]; /**< decrypting exponent mod (p-1) */
+ BIG dq[FFLEN/2]; /**< decrypting exponent mod (q-1) */
+ BIG c[FFLEN/2]; /**< 1/p mod q */
+} rsa_private_key;
+
+/*
+
+Note that a normalised BIG consists of digits mod 2^BASEBITS
+However BIG digits may be "extended" up to 2^(WORDLENGTH-1).
+
+BIGs in extended form may need to be normalised before certain
+operations.
+
+A BIG may be "reduced" to be less that the Modulus, or it
+may be "unreduced" and allowed to grow greater than the
+Modulus.
+
+Normalisation is quite fast. Reduction involves conditional branches,
+which can be regarded as significant "speed bumps". We try to
+delay reductions as much as possible. Reductions may also involve
+side channel leakage, so delaying and batching them
+hopefully disguises internal operations.
+
+*/
+
+/* BIG number prototypes */
+
+/** @brief Calculates a*b+c+*d
+ *
+ Calculate partial product of a.b, add in carry c, and add total to d
+ @param a multiplier
+ @param b multiplicand
+ @param c carry
+ @param d pointer to accumulated bottom half of result
+ @return top half of result
+ */
+extern chunk muladd(chunk a,chunk b,chunk c,chunk *d);
+/** @brief Tests for BIG equal to zero
+ *
+ @param x a BIG number
+ @return 1 if zero, else returns 0
+ */
+extern int BIG_iszilch(BIG x);
+/** @brief Tests for DBIG equal to zero
+ *
+ @param x a DBIG number
+ @return 1 if zero, else returns 0
+ */
+extern int BIG_diszilch(DBIG x);
+/** @brief Outputs a BIG number to the console
+ *
+ @param x a BIG number
+ */
+extern void BIG_output(BIG x);
+/** @brief Outputs a BIG number to the console in raw form (for debugging)
+ *
+ @param x a BIG number
+ */
+extern void BIG_rawoutput(BIG x);
+/** @brief Conditional constant time swap of two BIG numbers
+ *
+ Conditionally swaps parameters in constant time (without branching)
+ @param x a BIG number
+ @param y another BIG number
+ @param s swap takes place if not equal to 0
+ */
+extern void BIG_cswap(BIG x,BIG y,int s);
+/** @brief Conditional copy of BIG number
+ *
+ Conditionally copies second parameter to the first (without branching)
+ @param x a BIG number
+ @param y another BIG number
+ @param s copy takes place if not equal to 0
+ */
+extern void BIG_cmove(BIG x,BIG y,int s);
+/** @brief Convert from BIG number to byte array
+ *
+ @param a byte array
+ @param x BIG number
+ */
+extern void BIG_toBytes(char *a,BIG x);
+/** @brief Convert to BIG number from byte array
+ *
+ @param x BIG number
+ @param a byte array
+ */
+extern void BIG_fromBytes(BIG x,char *a);
+/** @brief Outputs a DBIG number to the console
+ *
+ @param x a DBIG number
+ */
+extern void BIG_doutput(DBIG x);
+/** @brief Copy BIG from Read-Only Memory to a BIG
+ *
+ @param x BIG number
+ @param y BIG number in ROM
+ */
+extern void BIG_rcopy(BIG x,const BIG y);
+/** @brief Copy BIG to another BIG
+ *
+ @param x BIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_copy(BIG x,BIG y);
+/** @brief Copy DBIG to another DBIG
+ *
+ @param x DBIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_dcopy(DBIG x,DBIG y);
+/** @brief Copy BIG to upper half of DBIG
+ *
+ @param x DBIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_dsucopy(DBIG x,BIG y);
+/** @brief Copy BIG to lower half of DBIG
+ *
+ @param x DBIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_dscopy(DBIG x,BIG y);
+/** @brief Copy lower half of DBIG to a BIG
+ *
+ @param x BIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_sdcopy(BIG x,DBIG y);
+/** @brief Copy upper half of DBIG to a BIG
+ *
+ @param x BIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_sducopy(BIG x,DBIG y);
+/** @brief Set BIG to zero
+ *
+ @param x BIG number to be set to zero
+ */
+extern void BIG_zero(BIG x);
+/** @brief Set DBIG to zero
+ *
+ @param x DBIG number to be set to zero
+ */
+extern void BIG_dzero(DBIG x);
+/** @brief Set BIG to one (unity)
+ *
+ @param x BIG number to be set to one.
+ */
+extern void BIG_one(BIG x);
+/** @brief Set BIG to inverse mod 2^256
+ *
+ @param x BIG number to be inverted
+ */
+extern void BIG_invmod2m(BIG x);
+/** @brief Set BIG to sum of two BIGs - output not normalised
+ *
+ @param x BIG number, sum of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_add(BIG x,BIG y,BIG z);
+/** @brief Increment BIG by a small integer - output not normalised
+ *
+ @param x BIG number to be incremented
+ @param i integer
+ */
+extern void BIG_inc(BIG x,int i);
+/** @brief Set BIG to difference of two BIGs
+ *
+ @param x BIG number, difference of other two - output not normalised
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_sub(BIG x,BIG y,BIG z);
+/** @brief Decrement BIG by a small integer - output not normalised
+ *
+ @param x BIG number to be decremented
+ @param i integer
+ */
+extern void BIG_dec(BIG x,int i);
+/** @brief Set DBIG to difference of two DBIGs
+ *
+ @param x DBIG number, difference of other two - output not normalised
+ @param y DBIG number
+ @param z DBIG number
+ */
+extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
+/** @brief Multiply BIG by a small integer - output not normalised
+ *
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ */
+extern void BIG_imul(BIG x,BIG y,int i);
+/** @brief Multiply BIG by not-so-small small integer - output normalised
+ *
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ @return Overflowing bits
+ */
+extern chunk BIG_pmul(BIG x,BIG y,int i);
+/** @brief Divide BIG by 3 - output normalised
+ *
+ @param x BIG number
+ @return Remainder
+ */
+extern int BIG_div3(BIG x);
+/** @brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
+ *
+ @param x DBIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ */
+extern void BIG_pxmul(DBIG x,BIG y,int i);
+/** @brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
+ *
+ @param x DBIG number, product of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_mul(DBIG x,BIG y,BIG z);
+/** @brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
+ *
+ Note that the product must fit into a BIG, and x must be distinct from y and z
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_smul(BIG x,BIG y,BIG z);
+/** @brief Square BIG resulting in a DBIG - input normalised and output normalised
+ *
+ @param x DBIG number, square of a BIG
+ @param y BIG number to be squared
+ */
+extern void BIG_sqr(DBIG x,BIG y);
+/** @brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
+ *
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_shl(BIG x,int s);
+/** @brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+ *
+ The number of bits to be shifted must be less than BASEBITS
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ @return Overflow bits
+ */
+extern chunk BIG_fshl(BIG x,int s);
+/** @brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
+ *
+ @param x DBIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_dshl(DBIG x,int s);
+/** @brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
+ *
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_shr(BIG x,int s);
+/** @brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+ *
+ The number of bits to be shifted must be less than BASEBITS
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ @return Shifted out bits
+ */
+extern chunk BIG_fshr(BIG x,int s);
+/** @brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
+ *
+ @param x DBIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_dshr(DBIG x,int s);
+/** @brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
+ *
+ Internal function. The value of s must be approximately in the middle of the DBIG.
+ Typically used to extract z mod 2^MODBITS and z/2^MODBITS
+ @param x BIG number, top half of z
+ @param y BIG number, bottom half of z
+ @param z DBIG number to be split in two.
+ @param s Bit position at which to split
+ */
+extern void BIG_split(BIG x,BIG y,DBIG z,int s);
+/** @brief Normalizes a BIG number - output normalised
+ *
+ All digits of the input BIG are reduced mod 2^BASEBITS
+ @param x BIG number to be normalised
+ */
+extern chunk BIG_norm(BIG x);
+/** @brief Normalizes a DBIG number - output normalised
+ *
+ All digits of the input DBIG are reduced mod 2^BASEBITS
+ @param x DBIG number to be normalised
+ */
+extern void BIG_dnorm(DBIG x);
+/** @brief Compares two BIG numbers. Inputs must be normalised externally
+ *
+ @param x first BIG number to be compared
+ @param y second BIG number to be compared
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_comp(BIG x,BIG y);
+/** @brief Compares two DBIG numbers. Inputs must be normalised externally
+ *
+ @param x first DBIG number to be compared
+ @param y second DBIG number to be compared
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_dcomp(DBIG x,DBIG y);
+/** @brief Calculate number of bits in a BIG - output normalised
+ *
+ @param x BIG number
+ @return Number of bits in x
+ */
+extern int BIG_nbits(BIG x);
+/** @brief Calculate number of bits in a DBIG - output normalised
+ *
+ @param x DBIG number
+ @return Number of bits in x
+ */
+extern int BIG_dnbits(DBIG x);
+/** @brief Reduce x mod n - input and output normalised
+ *
+ Slow but rarely used
+ @param x BIG number to be reduced mod n
+ @param n The modulus
+ */
+extern void BIG_mod(BIG x,BIG n);
+/** @brief Divide x by n - output normalised
+ *
+ Slow but rarely used
+ @param x BIG number to be divided by n
+ @param n The Divisor
+ */
+extern void BIG_sdiv(BIG x,BIG n);
+/** @brief x=y mod n - output normalised
+ *
+ Slow but rarely used. y is destroyed.
+ @param x BIG number, on exit = y mod n
+ @param y DBIG number
+ @param n Modulus
+ */
+extern void BIG_dmod(BIG x,DBIG y,BIG n);
+/** @brief x=y/n - output normalised
+ *
+ Slow but rarely used. y is destroyed.
+ @param x BIG number, on exit = y/n
+ @param y DBIG number
+ @param n Modulus
+ */
+extern void BIG_ddiv(BIG x,DBIG y,BIG n);
+/** @brief return parity of BIG, that is the least significant bit
+ *
+ @param x BIG number
+ @return 0 or 1
+ */
+extern int BIG_parity(BIG x);
+/** @brief return i-th of BIG
+ *
+ @param x BIG number
+ @param i the bit of x to be returned
+ @return 0 or 1
+ */
+extern int BIG_bit(BIG x,int i);
+/** @brief return least significant bits of a BIG
+ *
+ @param x BIG number
+ @param n number of bits to return. Assumed to be less than BASEBITS.
+ @return least significant n bits as an integer
+ */
+extern int BIG_lastbits(BIG x,int n);
+/** @brief Create a random BIG from a random number generator
+ *
+ Assumes that the random number generator has been suitably initialised
+ @param x BIG number, on exit a random number
+ @param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_random(BIG x,csprng *r);
+/** @brief Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
+ *
+ Assumes that the random number generator has been suitably initialised
+ @param x BIG number, on exit a random number
+ @param n The modulus
+ @param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_randomnum(BIG x,BIG n,csprng *r);
+/** @brief return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
+ *
+ Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
+ @param x BIG number
+ @param x3 BIG number, three times x
+ @param i bit position
+ @param nbs pointer to integer returning number of bits processed
+ @param nzs pointer to integer returning number of trailing 0s
+ @return + or - 1, 3 or 5
+ */
+extern int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs);
+/** @brief Calculate x=y*z mod n
+ *
+ Slow method for modular multiplication
+ @param x BIG number, on exit = y*z mod n
+ @param y BIG number
+ @param z BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
+/** @brief Calculate x=y/z mod n
+ *
+ Slow method for modular division
+ @param x BIG number, on exit = y/z mod n
+ @param y BIG number
+ @param z BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
+/** @brief Calculate x=y^2 mod n
+ *
+ Slow method for modular squaring
+ @param x BIG number, on exit = y^2 mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modsqr(BIG x,BIG y,BIG n);
+/** @brief Calculate x=-y mod n
+ *
+ Modular negation
+ @param x BIG number, on exit = -y mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modneg(BIG x,BIG y,BIG n);
+/** @brief Calculate jacobi Symbol (x/y)
+ *
+ @param x BIG number
+ @param y BIG number
+ @return Jacobi symbol, -1,0 or 1
+ */
+extern int BIG_jacobi(BIG x,BIG y);
+/** @brief Calculate x=1/y mod n
+ *
+ Modular Inversion - This is slow. Uses binary method.
+ @param x BIG number, on exit = 1/y mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_invmodp(BIG x,BIG y,BIG n);
+
+
+
+/* FP prototypes */
+
+/** @brief Tests for BIG equal to zero mod Modulus
+ *
+ @param x BIG number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP_iszilch(BIG x);
+/** @brief Converts from BIG integer to n-residue form mod Modulus
+ *
+ @param x BIG number to be converted
+ */
+extern void FP_nres(BIG x);
+/** @brief Converts from n-residue form back to BIG integer form
+ *
+ @param x BIG number to be converted
+ */
+extern void FP_redc(BIG x);
+/** @brief Sets BIG to representation of unity in n-residue form
+ *
+ @param x BIG number to be set equal to unity.
+ */
+extern void FP_one(BIG x);
+/** @brief Reduces DBIG to BIG exploiting special form of the modulus
+ *
+ This function comes in different flavours depending on the form of Modulus that is currently in use.
+ @param x BIG number, on exit = y mod Modulus
+ @param y DBIG number to be reduced
+ */
+extern void FP_mod(BIG x,DBIG y);
+/** @brief Fast Modular multiplication of two BIGs in n-residue form, mod Modulus
+ *
+ Uses appropriate fast modular reduction method
+ @param x BIG number, on exit the modular product = y*z mod Modulus
+ @param y BIG number, the multiplicand
+ @param z BIG number, the multiplier
+ */
+extern void FP_mul(BIG x,BIG y,BIG z);
+/** @brief Fast Modular multiplication of a BIG in n-residue form, by a small integer, mod Modulus
+ *
+ @param x BIG number, on exit the modular product = y*i mod Modulus
+ @param y BIG number, the multiplicand
+ @param i a small number, the multiplier
+ */
+extern void FP_imul(BIG x,BIG y,int i);
+/** @brief Fast Modular squaring of a BIG in n-residue form, mod Modulus
+ *
+ Uses appropriate fast modular reduction method
+ @param x BIG number, on exit the modular product = y^2 mod Modulus
+ @param y BIG number, the number to be squared
+
+ */
+extern void FP_sqr(BIG x,BIG y);
+/** @brief Modular addition of two BIGs in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit the modular sum = y+z mod Modulus
+ @param y BIG number
+ @param z BIG number
+ */
+extern void FP_add(BIG x,BIG y,BIG z);
+/** @brief Modular subtraction of two BIGs in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit the modular difference = y-z mod Modulus
+ @param y BIG number
+ @param z BIG number
+ */
+extern void FP_sub(BIG x,BIG y,BIG z);
+/** @brief Modular division by 2 of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit =y/2 mod Modulus
+ @param y BIG number
+ */
+extern void FP_div2(BIG x,BIG y);
+/** @brief Fast Modular exponentiation of a BIG in n-residue form, to the power of a BIG, mod Modulus
+ *
+ @param x BIG number, on exit = y^z mod Modulus
+ @param y BIG number
+ @param z Big number exponent
+ */
+extern void FP_pow(BIG x,BIG y,BIG z);
+/** @brief Fast Modular square root of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = sqrt(y) mod Modulus
+ @param y BIG number, the number whose square root is calculated
+
+ */
+extern void FP_sqrt(BIG x,BIG y);
+/** @brief Modular negation of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = -y mod Modulus
+ @param y BIG number
+ */
+extern void FP_neg(BIG x,BIG y);
+/** @brief Outputs a BIG number that is in n-residue form to the console
+ *
+ Converts from n-residue form before output
+ @param x a BIG number
+ */
+extern void FP_output(BIG x);
+/** @brief Outputs a BIG number that is in n-residue form to the console, in raw form
+ *
+ Converts from n-residue form before output
+ @param x a BIG number
+ */
+extern void FP_rawoutput(BIG x);
+/** @brief Reduces possibly unreduced BIG mod Modulus
+ *
+ @param x BIG number, on exit reduced mod Modulus
+ */
+extern void FP_reduce(BIG x);
+/** @brief Tests for BIG a quadratic residue mod Modulus
+ *
+ @param x BIG number to be tested
+ @return 1 if quadratic residue, else returns 0 if quadratic non-residue
+ */
+extern int FP_qr(BIG x);
+/** @brief Modular inverse of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = 1/y mod Modulus
+ @param y BIG number
+ */
+extern void FP_inv(BIG x,BIG y);
+
+
+/* FP2 prototypes */
+
+/** @brief Tests for FP2 equal to zero
+ *
+ @param x FP2 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP2_iszilch(FP2 *x);
+/** @brief Conditional copy of FP2 number
+ *
+ Conditionally copies second parameter to the first (without branching)
+ @param x FP2 instance, set to y if s!=0
+ @param y another FP2 instance
+ @param s copy only takes place if not equal to 0
+ */
+extern void FP2_cmove(FP2 *x,FP2 *y,int s);
+/** @brief Tests for FP2 equal to one
+ *
+ @param x FP2 instance to be tested
+ @return 1 if x=1, else returns 0
+ */
+extern int FP2_isunity(FP2 *x);
+/** @brief Tests for equality of two FP2s
+ *
+ @param x FP2 instance to be compared
+ @param y FP2 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP2_equals(FP2 *x,FP2 *y);
+/** @brief Initialise FP2 from two BIGs in n-residue form
+ *
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ @param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_FPs(FP2 *x,BIG a,BIG b);
+/** @brief Initialise FP2 from two BIG integers
+ *
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ @param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_BIGs(FP2 *x,BIG a,BIG b);
+/** @brief Initialise FP2 from single BIG in n-residue form
+ *
+ Imaginary part is set to zero
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ */
+extern void FP2_from_FP(FP2 *x,BIG a);
+/** @brief Initialise FP2 from single BIG
+ *
+ Imaginary part is set to zero
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ */
+extern void FP2_from_BIG(FP2 *x,BIG a);
+/** @brief Copy FP2 to another FP2
+ *
+ @param x FP2 instance, on exit = y
+ @param y FP2 instance to be copied
+ */
+extern void FP2_copy(FP2 *x,FP2 *y);
+/** @brief Set FP2 to zero
+ *
+ @param x FP2 instance to be set to zero
+ */
+extern void FP2_zero(FP2 *x);
+/** @brief Set FP2 to unity
+ *
+ @param x FP2 instance to be set to one
+ */
+extern void FP2_one(FP2 *x);
+/** @brief Negation of FP2
+ *
+ @param x FP2 instance, on exit = -y
+ @param y FP2 instance
+ */
+extern void FP2_neg(FP2 *x,FP2 *y);
+/** @brief Conjugation of FP2
+ *
+ If y=(a,b) on exit x=(a,-b)
+ @param x FP2 instance, on exit = conj(y)
+ @param y FP2 instance
+ */
+extern void FP2_conj(FP2 *x,FP2 *y);
+/** @brief addition of two FP2s
+ *
+ @param x FP2 instance, on exit = y+z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
+/** @brief subtraction of two FP2s
+ *
+ @param x FP2 instance, on exit = y-z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
+/** @brief Multiplication of an FP2 by an n-residue
+ *
+ @param x FP2 instance, on exit = y*b
+ @param y FP2 instance
+ @param b BIG n-residue
+ */
+extern void FP2_pmul(FP2 *x,FP2 *y,BIG b);
+/** @brief Multiplication of an FP2 by a small integer
+ *
+ @param x FP2 instance, on exit = y*i
+ @param y FP2 instance
+ @param i an integer
+ */
+extern void FP2_imul(FP2 *x,FP2 *y,int i);
+/** @brief Squaring an FP2
+ *
+ @param x FP2 instance, on exit = y^2
+ @param y FP2 instance
+ */
+extern void FP2_sqr(FP2 *x,FP2 *y);
+/** @brief Multiplication of two FP2s
+ *
+ @param x FP2 instance, on exit = y*z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
+/** @brief Formats and outputs an FP2 to the console
+ *
+ @param x FP2 instance
+ */
+extern void FP2_output(FP2 *x);
+/** @brief Formats and outputs an FP2 to the console in raw form (for debugging)
+ *
+ @param x FP2 instance
+ */
+extern void FP2_rawoutput(FP2 *x);
+/** @brief Inverting an FP2
+ *
+ @param x FP2 instance, on exit = 1/y
+ @param y FP2 instance
+ */
+extern void FP2_inv(FP2 *x,FP2 *y);
+/** @brief Divide an FP2 by 2
+ *
+ @param x FP2 instance, on exit = y/2
+ @param y FP2 instance
+ */
+extern void FP2_div2(FP2 *x,FP2 *y);
+/** @brief Multiply an FP2 by (1+sqrt(-1))
+ *
+ Note that (1+sqrt(-1)) is irreducible for FP4
+ @param x FP2 instance, on exit = x*(1+sqrt(-1))
+ */
+extern void FP2_mul_ip(FP2 *x);
+/** @brief Divide an FP2 by (1+sqrt(-1))
+ *
+ Note that (1+sqrt(-1)) is irreducible for FP4
+ @param x FP2 instance, on exit = x/(1+sqrt(-1))
+ */
+extern void FP2_div_ip(FP2 *x);
+/** @brief Normalises the components of an FP2
+ *
+ @param x FP2 instance to be normalised
+ */
+extern void FP2_norm(FP2 *x);
+/** @brief Reduces all components of possibly unreduced FP2 mod Modulus
+ *
+ @param x FP2 instance, on exit reduced mod Modulus
+ */
+extern void FP2_reduce(FP2 *x);
+/** @brief Raises an FP2 to the power of a BIG
+ *
+ @param x FP2 instance, on exit = y^b
+ @param y FP2 instance
+ @param b BIG number
+ */
+extern void FP2_pow(FP2 *x,FP2 *y,BIG b);
+/** @brief Square root of an FP2
+ *
+ @param x FP2 instance, on exit = sqrt(y)
+ @param y FP2 instance
+ */
+extern int FP2_sqrt(FP2 *x,FP2 *y);
+
+
+
+/* ECP E(Fp) prototypes */
+/** @brief Tests for ECP point equal to infinity
+ *
+ @param P ECP point to be tested
+ @return 1 if infinity, else returns 0
+ */
+extern int ECP_isinf(ECP *P);
+/** @brief Tests for equality of two ECPs
+ *
+ @param P ECP instance to be compared
+ @param Q ECP instance to be compared
+ @return 1 if P=Q, else returns 0
+ */
+extern int ECP_equals(ECP *P,ECP *Q);
+/** @brief Copy ECP point to another ECP point
+ *
+ @param P ECP instance, on exit = Q
+ @param Q ECP instance to be copied
+ */
+extern void ECP_copy(ECP *P,ECP *Q);
+/** @brief Negation of an ECP point
+ *
+ @param P ECP instance, on exit = -P
+ */
+extern void ECP_neg(ECP *P);
+/** @brief Set ECP to point-at-infinity
+ *
+ @param P ECP instance to be set to infinity
+ */
+extern void ECP_inf(ECP *P);
+/** @brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+ Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
+ Used internally.
+ @param r BIG n-residue value of f(x)
+ @param x BIG n-residue x
+ */
+extern void ECP_rhs(BIG r,BIG x);
+/** @brief Set ECP to point(x,y) given just x and sign of y
+ *
+ Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
+ The correct y value (plus or minus) is selected given its sign s.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @param s an integer representing the "sign" of y, in fact its least significant bit.
+ */
+extern int ECP_setx(ECP *P,BIG x,int s);
+
+#if CURVETYPE==MONTGOMERY
+/** @brief Set ECP to point(x,[y]) given x
+ *
+ Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x);
+/** @brief Extract x coordinate of an ECP point P
+ *
+ @param x BIG on exit = x coordinate of point
+ @param P ECP instance (x,[y])
+ @return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP_get(BIG x,ECP *P);
+/** @brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
+ *
+ Differential addition of points on a Montgomery curve
+ @param P ECP instance, on exit =P+Q
+ @param Q ECP instance to be added to P
+ @param D Difference between P and Q
+ */
+extern void ECP_add(ECP *P,ECP *Q,ECP *D);
+#else
+/** @brief Set ECP to point(x,y) given x and y
+ *
+ Point P set to infinity if no such point on the curve.
+ @param P ECP instance to be set (x,y)
+ @param x BIG x coordinate of point
+ @param y BIG y coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x,BIG y);
+/** @brief Extract x and y coordinates of an ECP point P
+ *
+ If x=y, returns only x
+ @param x BIG on exit = x coordinate of point
+ @param y BIG on exit = y coordinate of point (unless x=y)
+ @param P ECP instance (x,y)
+ @return sign of y, or -1 if P is point-at-infinity
+ */
+extern int ECP_get(BIG x,BIG y,ECP *P);
+/** @brief Adds ECP instance Q to ECP instance P
+ *
+ @param P ECP instance, on exit =P+Q
+ @param Q ECP instance to be added to P
+ */
+extern void ECP_add(ECP *P,ECP *Q);
+/** @brief Subtracts ECP instance Q from ECP instance P
+ *
+ @param P ECP instance, on exit =P-Q
+ @param Q ECP instance to be subtracted from P
+ */
+extern void ECP_sub(ECP *P,ECP *Q);
+#endif
+/** @brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+ @param P ECP instance to be converted to affine form
+ */
+extern void ECP_affine(ECP *P);
+/** @brief Formats and outputs an ECP point to the console, in projective coordinates
+ *
+ @param P ECP instance to be printed
+ */
+extern void ECP_outputxyz(ECP *P);
+/** @brief Formats and outputs an ECP point to the console, converted to affine coordinates
+ *
+ @param P ECP instance to be printed
+ */
+extern void ECP_output(ECP * P);
+/** @brief Formats and outputs an ECP point to an octet string
+ *
+ The octet string is created in the standard form 04|x|y, except for Montgomery curve in which case it is 06|x
+ Here x (and y) are the x and y coordinates in big-endian base 256 form.
+ @param S output octet string
+ @param P ECP instance to be converted to an octet string
+ */
+extern void ECP_toOctet(octet *S,ECP *P);
+/** @brief Creates an ECP point from an octet string
+ *
+ The octet string is in the standard form 0x04|x|y, except for Montgomery curve in which case it is 0x06|x
+ Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+ @param P ECP instance to be created from the octet string
+ @param S input octet string
+ return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP_fromOctet(ECP *P,octet *S);
+/** @brief Doubles an ECP instance P
+ *
+ @param P ECP instance, on exit =2*P
+ */
+extern void ECP_dbl(ECP *P);
+/** @brief Multiplies an ECP instance P by a small integer, side-channel resistant
+ *
+ @param P ECP instance, on exit =i*P
+ @param i small integer multiplier
+ @param b maximum number of bits in multiplier
+ */
+extern void ECP_pinmul(ECP *P,int i,int b);
+/** @brief Multiplies an ECP instance P by a BIG, side-channel resistant
+ *
+ Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
+ @param P ECP instance, on exit =b*P
+ @param b BIG number multiplier
+
+ */
+extern void ECP_mul(ECP *P,BIG b);
+/** @brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
+ *
+ @param P ECP instance, on exit =e*P+f*Q
+ @param Q ECP instance
+ @param e BIG number multiplier
+ @param f BIG number multiplier
+ */
+extern void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f);
+
+
+
+/* ECP2 E(Fp2) prototypes */
+/** @brief Tests for ECP2 point equal to infinity
+ *
+ @param P ECP2 point to be tested
+ @return 1 if infinity, else returns 0
+ */
+extern int ECP2_isinf(ECP2 *P);
+/** @brief Copy ECP2 point to another ECP2 point
+ *
+ @param P ECP2 instance, on exit = Q
+ @param Q ECP2 instance to be copied
+ */
+extern void ECP2_copy(ECP2 *P,ECP2 *Q);
+/** @brief Set ECP2 to point-at-infinity
+ *
+ @param P ECP2 instance to be set to infinity
+ */
+extern void ECP2_inf(ECP2 *P);
+/** @brief Tests for equality of two ECP2s
+ *
+ @param P ECP2 instance to be compared
+ @param Q ECP2 instance to be compared
+ @return 1 if P=Q, else returns 0
+ */
+extern int ECP2_equals(ECP2 *P,ECP2 *Q);
+/** @brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+ @param P ECP2 instance to be converted to affine form
+ */
+extern void ECP2_affine(ECP2 *P);
+/** @brief Extract x and y coordinates of an ECP2 point P
+ *
+ If x=y, returns only x
+ @param x FP2 on exit = x coordinate of point
+ @param y FP2 on exit = y coordinate of point (unless x=y)
+ @param P ECP2 instance (x,y)
+ @return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP2_get(FP2 *x,FP2 *y,ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
+ *
+ @param P ECP2 instance to be printed
+ */
+extern void ECP2_output(ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to the console, in projective coordinates
+ *
+ @param P ECP2 instance to be printed
+ */
+extern void ECP2_outputxyz(ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to an octet string
+ *
+ The octet string is created in the form x|y.
+ Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+ @param S output octet string
+ @param P ECP2 instance to be converted to an octet string
+ */
+extern void ECP2_toOctet(octet *S,ECP2 *P);
+/** @brief Creates an ECP2 point from an octet string
+ *
+ The octet string is in the form x|y
+ The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+ @param P ECP2 instance to be created from the octet string
+ @param S input octet string
+ return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP2_fromOctet(ECP2 *P,octet *S);
+/** @brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+ Function f(x)=x^3+Ax+B
+ Used internally.
+ @param r FP2 value of f(x)
+ @param x FP2 instance
+ */
+extern void ECP2_rhs(FP2 *r,FP2 *x);
+/** @brief Set ECP2 to point(x,y) given x and y
+ *
+ Point P set to infinity if no such point on the curve.
+ @param P ECP2 instance to be set (x,y)
+ @param x FP2 x coordinate of point
+ @param y FP2 y coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP2_set(ECP2 *P,FP2 *x,FP2 *y);
+/** @brief Set ECP to point(x,[y]) given x
+ *
+ Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP2_setx(ECP2 *P,FP2 *x);
+/** @brief Negation of an ECP2 point
+ *
+ @param P ECP2 instance, on exit = -P
+ */
+extern void ECP2_neg(ECP2 *P);
+/** @brief Doubles an ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =2*P
+ */
+extern int ECP2_dbl(ECP2 *P);
+/** @brief Adds ECP2 instance Q to ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =P+Q
+ @param Q ECP2 instance to be added to P
+ */
+extern int ECP2_add(ECP2 *P,ECP2 *Q);
+/** @brief Subtracts ECP instance Q from ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =P-Q
+ @param Q ECP2 instance to be subtracted from P
+ */
+extern void ECP2_sub(ECP2 *P,ECP2 *Q);
+/** @brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
+ *
+ Uses fixed sized windows.
+ @param P ECP2 instance, on exit =b*P
+ @param b BIG number multiplier
+
+ */
+extern void ECP2_mul(ECP2 *P,BIG b);
+/** @brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
+ *
+ Fast point multiplication using Frobenius
+ @param P ECP2 instance, on exit = p*P
+ @param f FP2 precalculated Frobenius constant
+
+ */
+extern void ECP2_frob(ECP2 *P,FP2 *f);
+/** @brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ *
+ @param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ @param Q ECP2 array of 4 points
+ @param b BIG array of 4 multipliers
+ */
+extern void ECP2_mul4(ECP2 *P,ECP2 *Q,BIG *b);
+
+
+
+/* FP4 prototypes */
+/** @brief Tests for FP4 equal to zero
+ *
+ @param x FP4 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP4_iszilch(FP4 *x);
+/** @brief Tests for FP4 equal to unity
+ *
+ @param x FP4 number to be tested
+ @return 1 if unity, else returns 0
+ */
+extern int FP4_isunity(FP4 *x);
+/** @brief Tests for equality of two FP4s
+ *
+ @param x FP4 instance to be compared
+ @param y FP4 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP4_equals(FP4 *x,FP4 *y);
+/** @brief Tests for FP4 having only a real part and no imaginary part
+ *
+ @param x FP4 number to be tested
+ @return 1 if real, else returns 0
+ */
+extern int FP4_isreal(FP4 *x);
+/** @brief Initialise FP4 from two FP2s
+ *
+ @param x FP4 instance to be initialised
+ @param a FP2 to form real part of FP4
+ @param b FP2 to form imaginary part of FP4
+ */
+extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
+/** @brief Initialise FP4 from single FP2
+ *
+ Imaginary part is set to zero
+ @param x FP4 instance to be initialised
+ @param a FP2 to form real part of FP4
+ */
+extern void FP4_from_FP2(FP4 *x,FP2 *a);
+/** @brief Copy FP4 to another FP4
+ *
+ @param x FP4 instance, on exit = y
+ @param y FP4 instance to be copied
+ */
+extern void FP4_copy(FP4 *x,FP4 *y);
+/** @brief Set FP4 to zero
+ *
+ @param x FP4 instance to be set to zero
+ */
+extern void FP4_zero(FP4 *x);
+/** @brief Set FP4 to unity
+ *
+ @param x FP4 instance to be set to one
+ */
+extern void FP4_one(FP4 *x);
+/** @brief Negation of FP4
+ *
+ @param x FP4 instance, on exit = -y
+ @param y FP4 instance
+ */
+extern void FP4_neg(FP4 *x,FP4 *y);
+/** @brief Conjugation of FP4
+ *
+ If y=(a,b) on exit x=(a,-b)
+ @param x FP4 instance, on exit = conj(y)
+ @param y FP4 instance
+ */
+extern void FP4_conj(FP4 *x,FP4 *y);
+/** @brief Negative conjugation of FP4
+ *
+ If y=(a,b) on exit x=(-a,b)
+ @param x FP4 instance, on exit = -conj(y)
+ @param y FP4 instance
+ */
+extern void FP4_nconj(FP4 *x,FP4 *y);
+/** @brief addition of two FP4s
+ *
+ @param x FP4 instance, on exit = y+z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
+/** @brief subtraction of two FP4s
+ *
+ @param x FP4 instance, on exit = y-z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
+/** @brief Multiplication of an FP4 by an FP2
+ *
+ @param x FP4 instance, on exit = y*a
+ @param y FP4 instance
+ @param a FP2 multiplier
+ */
+extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
+/** @brief Multiplication of an FP4 by a small integer
+ *
+ @param x FP4 instance, on exit = y*i
+ @param y FP4 instance
+ @param i an integer
+ */
+extern void FP4_imul(FP4 *x,FP4 *y,int i);
+/** @brief Squaring an FP4
+ *
+ @param x FP4 instance, on exit = y^2
+ @param y FP4 instance
+ */
+extern void FP4_sqr(FP4 *x,FP4 *y);
+/** @brief Multiplication of two FP4s
+ *
+ @param x FP4 instance, on exit = y*z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
+/** @brief Inverting an FP4
+ *
+ @param x FP4 instance, on exit = 1/y
+ @param y FP4 instance
+ */
+extern void FP4_inv(FP4 *x,FP4 *y);
+/** @brief Formats and outputs an FP4 to the console
+ *
+ @param x FP4 instance to be printed
+ */
+extern void FP4_output(FP4 *x);
+/** @brief Formats and outputs an FP4 to the console in raw form (for debugging)
+ *
+ @param x FP4 instance to be printed
+ */
+extern void FP4_rawoutput(FP4 *x);
+/** @brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+ @param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP4_times_i(FP4 *x);
+/** @brief Normalises the components of an FP4
+ *
+ @param x FP4 instance to be normalised
+ */
+extern void FP4_norm(FP4 *x);
+/** @brief Reduces all components of possibly unreduced FP4 mod Modulus
+ *
+ @param x FP4 instance, on exit reduced mod Modulus
+ */
+extern void FP4_reduce(FP4 *x);
+/** @brief Raises an FP4 to the power of a BIG
+ *
+ @param x FP4 instance, on exit = y^b
+ @param y FP4 instance
+ @param b BIG number
+ */
+extern void FP4_pow(FP4 *x,FP4 *y,BIG b);
+/** @brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
+ *
+ @param x FP4 instance, on exit = x^p
+ @param f FP2 precalculated Frobenius constant
+ */
+extern void FP4_frob(FP4 *x,FP2 *f);
+/** @brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+ @param r FP4 instance, on exit = w*x-conj(x)*y+z
+ @param w FP4 instance
+ @param x FP4 instance
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
+/** @brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+ @param r FP4 instance, on exit = x^2-2*conj(x)
+ @param x FP4 instance
+ */
+extern void FP4_xtr_D(FP4 *r,FP4 *x);
+/** @brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
+ *
+ XTR single exponentiation
+ @param r FP4 instance, on exit = trace(w^b)
+ @param x FP4 instance, trace of an FP12 w
+ @param b BIG number
+ */
+extern void FP4_xtr_pow(FP4 *r,FP4 *x,BIG b);
+/** @brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
+ *
+ XTR double exponentiation
+ Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+ @param r FP4 instance, on exit = trace(c^a.d^b)
+ @param c FP4 instance, trace of an FP12
+ @param d FP4 instance, trace of an FP12
+ @param e FP4 instance, trace of an FP12
+ @param f FP4 instance, trace of an FP12
+ @param a BIG number
+ @param b BIG number
+ */
+extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,BIG a,BIG b);
+
+
+
+/* FP12 prototypes */
+/** @brief Tests for FP12 equal to zero
+ *
+ @param x FP12 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP12_iszilch(FP12 *x);
+/** @brief Tests for FP12 equal to unity
+ *
+ @param x FP12 number to be tested
+ @return 1 if unity, else returns 0
+ */
+extern int FP12_isunity(FP12 *x);
+/** @brief Copy FP12 to another FP12
+ *
+ @param x FP12 instance, on exit = y
+ @param y FP12 instance to be copied
+ */
+extern void FP12_copy(FP12 *x,FP12 *y);
+/** @brief Set FP12 to unity
+ *
+ @param x FP12 instance to be set to one
+ */
+extern void FP12_one(FP12 *x);
+/** @brief Tests for equality of two FP12s
+ *
+ @param x FP12 instance to be compared
+ @param y FP12 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP12_equals(FP12 *x,FP12 *y);
+/** @brief Conjugation of FP12
+ *
+ If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
+ @param x FP12 instance, on exit = conj(y)
+ @param y FP12 instance
+ */
+extern void FP12_conj(FP12 *x,FP12 *y);
+/** @brief Initialise FP12 from single FP4
+ *
+ Sets first FP4 component of an FP12, other components set to zero
+ @param x FP12 instance to be initialised
+ @param a FP4 to form first part of FP4
+ */
+extern void FP12_from_FP4(FP12 *x,FP4 *a);
+/** @brief Initialise FP12 from three FP4s
+ *
+ @param x FP12 instance to be initialised
+ @param a FP4 to form first part of FP12
+ @param b FP4 to form second part of FP12
+ @param c FP4 to form third part of FP12
+ */
+extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
+/** @brief Fast Squaring of an FP12 in "unitary" form
+ *
+ @param x FP12 instance, on exit = y^2
+ @param y FP4 instance, must be unitary
+ */
+extern void FP12_usqr(FP12 *x,FP12 *y);
+/** @brief Squaring an FP12
+ *
+ @param x FP12 instance, on exit = y^2
+ @param y FP12 instance
+ */
+extern void FP12_sqr(FP12 *x,FP12 *y);
+/** @brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+ *
+ Here the multiplier has a special form that can be exploited
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, of special form
+ */
+extern void FP12_smul(FP12 *x,FP12 *y);
+/** @brief Multiplication of two FP12s
+ *
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, the multiplier
+ */
+extern void FP12_mul(FP12 *x,FP12 *y);
+/** @brief Inverting an FP12
+ *
+ @param x FP12 instance, on exit = 1/y
+ @param y FP12 instance
+ */
+extern void FP12_inv(FP12 *x,FP12 *y);
+/** @brief Raises an FP12 to the power of a BIG
+ *
+ @param r FP12 instance, on exit = y^b
+ @param x FP12 instance
+ @param b BIG number
+ */
+extern void FP12_pow(FP12 *r,FP12 *x,BIG b);
+/** @brief Raises an FP12 instance x to a small integer power, side-channel resistant
+ *
+ @param x ECP instance, on exit = x^i
+ @param i small integer exponent
+ @param b maximum number of bits in exponent
+ */
+extern void FP12_pinpow(FP12 *x,int i,int b);
+/** @brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
+ *
+ @param r ECP instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
+ @param x FP12 array with 4 FP12s
+ @param b BIG array of 4 exponents
+ */
+extern void FP12_pow4(FP12 *r,FP12 *x,BIG *b);
+/** @brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
+ *
+ @param x FP12 instance, on exit = x^p
+ @param f FP2 precalculated Frobenius constant
+ */
+extern void FP12_frob(FP12 *x,FP2 *f);
+/** @brief Reduces all components of possibly unreduced FP12 mod Modulus
+ *
+ @param x FP12 instance, on exit reduced mod Modulus
+ */
+extern void FP12_reduce(FP12 *x);
+/** @brief Normalises the components of an FP12
+ *
+ @param x FP12 instance to be normalised
+ */
+extern void FP12_norm(FP12 *x);
+/** @brief Formats and outputs an FP12 to the console
+ *
+ @param x FP12 instance to be printed
+ */
+extern void FP12_output(FP12 *x);
+/** @brief Formats and outputs an FP12 instance to an octet string
+ *
+ Serializes the components of an FP12 to big-endian base 256 form.
+ @param S output octet string
+ @param x FP12 instance to be converted to an octet string
+ */
+extern void FP12_toOctet(octet *S,FP12 *x);
+/** @brief Creates an FP12 instance from an octet string
+ *
+ De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
+ @param x FP12 instance to be created from an octet string
+ @param S input octet string
+
+ */
+extern void FP12_fromOctet(FP12 *x,octet *S);
+/** @brief Calculate the trace of an FP12
+ *
+ @param t FP4 trace of x, on exit = tr(x)
+ @param x FP12 instance
+
+ */
+extern void FP12_trace(FP4 *t,FP12 *x);
+
+
+
+/* Pairing function prototypes */
+/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+ @param r FP12 result of the pairing calculation e(P,Q)
+ @param P ECP2 instance, an element of G2
+ @param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q);
+/** @brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+ Faster than calculating two separate pairings
+ @param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+ @param P ECP2 instance, an element of G2
+ @param Q ECP instance, an element of G1
+ @param R ECP2 instance, an element of G2
+ @param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
+/** @brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+ Here p is the internal modulus, and r is the group order
+ @param x FP12, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(FP12 *x);
+/** @brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+ May exploit endomorphism for speed.
+ @param Q ECP member of G1.
+ @param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,BIG b);
+/** @brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+ May exploit endomorphism for speed.
+ @param P ECP2 member of G1.
+ @param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP2 *P,BIG b);
+/** @brief Fast raising of a member of GT to a BIG power
+ *
+ May exploit endomorphism for speed.
+ @param x FP12 member of GT.
+ @param b BIG exponent
+
+ */
+extern void PAIR_GTpow(FP12 *x,BIG b);
+/** @brief Tests FP12 for membership of GT
+ *
+ @param x FP12 instance
+ @return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(FP12 *x);
+
+
+
+/* Finite Field Prototypes */
+/** @brief Copy one FF element of given length to another
+ *
+ @param x FF instance to be copied to, on exit = y
+ @param y FF instance to be copied from
+ @param n size of FF in BIGs
+
+ */
+extern void FF_copy(BIG *x,BIG *y,int n);
+/** @brief Initialize an FF element of given length from a 32-bit integer m
+ *
+ @param x FF instance to be copied to, on exit = m
+ @param m integer
+ @param n size of FF in BIGs
+ */
+extern void FF_init(BIG *x,sign32 m,int n);
+/** @brief Set FF element of given size to zero
+ *
+ @param x FF instance to be set to zero
+ @param n size of FF in BIGs
+ */
+extern void FF_zero(BIG *x,int n);
+/** @brief Tests for FF element equal to zero
+ *
+ @param x FF number to be tested
+ @param n size of FF in BIGs
+ @return 1 if zero, else returns 0
+ */
+extern int FF_iszilch(BIG *x,int n);
+/** @brief return parity of an FF, that is the least significant bit
+ *
+ @param x FF number
+ @return 0 or 1
+ */
+extern int FF_parity(BIG *x);
+/** @brief return least significant m bits of an FF
+ *
+ @param x FF number
+ @param m number of bits to return. Assumed to be less than BASEBITS.
+ @return least significant n bits as an integer
+ */
+extern int FF_lastbits(BIG *x,int m);
+/** @brief Set FF element of given size to unity
+ *
+ @param x FF instance to be set to unity
+ @param n size of FF in BIGs
+ */
+extern void FF_one(BIG *x,int n);
+/** @brief Compares two FF numbers. Inputs must be normalised externally
+ *
+ @param x first FF number to be compared
+ @param y second FF number to be compared
+ @param n size of FF in BIGs
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int FF_comp(BIG *x,BIG *y,int n);
+/** @brief addition of two FFs
+ *
+ @param x FF instance, on exit = y+z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_add(BIG *x,BIG *y,BIG *z,int n);
+/** @brief subtraction of two FFs
+ *
+ @param x FF instance, on exit = y-z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_sub(BIG *x,BIG *y,BIG *z,int n);
+/** @brief increment an FF by an integer,and normalise
+ *
+ @param x FF instance, on exit = x+m
+ @param m an integer to be added to x
+ @param n size of FF in BIGs
+ */
+extern void FF_inc(BIG *x,int m,int n);
+/** @brief Decrement an FF by an integer,and normalise
+ *
+ @param x FF instance, on exit = x-m
+ @param m an integer to be subtracted from x
+ @param n size of FF in BIGs
+ */
+extern void FF_dec(BIG *x,int m,int n);
+/** @brief Normalises the components of an FF
+ *
+ @param x FF instance to be normalised
+ @param n size of FF in BIGs
+ */
+extern void FF_norm(BIG *x,int n);
+/** @brief Shift left an FF by 1 bit
+ *
+ @param x FF instance to be shifted left
+ @param n size of FF in BIGs
+ */
+extern void FF_shl(BIG *x,int n);
+/** @brief Shift right an FF by 1 bit
+ *
+ @param x FF instance to be shifted right
+ @param n size of FF in BIGs
+ */
+extern void FF_shr(BIG *x,int n);
+/** @brief Formats and outputs an FF to the console
+ *
+ @param x FF instance to be printed
+ @param n size of FF in BIGs
+ */
+extern void FF_output(BIG *x,int n);
+/** @brief Formats and outputs an FF instance to an octet string
+ *
+ Converts an FF to big-endian base 256 form.
+ @param S output octet string
+ @param x FF instance to be converted to an octet string
+ @param n size of FF in BIGs
+ */
+extern void FF_toOctet(octet *S,BIG *x,int n);
+/** @brief Populates an FF instance from an octet string
+ *
+ Creates FF from big-endian base 256 form.
+ @param x FF instance to be created from an octet string
+ @param S input octet string
+ @param n size of FF in BIGs
+ */
+extern void FF_fromOctet(BIG *x,octet *S,int n);
+/** @brief Multiplication of two FFs
+ *
+ Uses Karatsuba method internally
+ @param x FF instance, on exit = y*z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_mul(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Reduce FF mod a modulus
+ *
+ This is slow
+ @param x FF instance to be reduced mod m - on exit = x mod m
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_mod(BIG *x,BIG *m,int n);
+/** @brief Square an FF
+ *
+ Uses Karatsuba method internally
+ @param x FF instance, on exit = y^2
+ @param y FF instance to be squared
+ @param n size of FF in BIGs
+ */
+extern void FF_sqr(BIG *x,BIG *y,int n);
+/** @brief Reduces a double-length FF with respect to a given modulus
+ *
+ This is slow
+ @param x FF instance, on exit = y mod z
+ @param y FF instance, of double length 2*n
+ @param z FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_dmod(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Invert an FF mod a prime modulus
+ *
+ @param x FF instance, on exit = 1/y mod z
+ @param y FF instance
+ @param z FF prime modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_invmodp(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Create an FF from a random number generator
+ *
+ @param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ */
+extern void FF_random(BIG *x,csprng *R,int n);
+/** @brief Create a random FF less than a given modulus from a random number generator
+ *
+ @param x FF instance, on exit x is a random number < y
+ @param y FF instance, the modulus
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ */
+extern void FF_randomnum(BIG *x,BIG *y,csprng *R,int n);
+/** @brief Calculate r=x^e mod m, side channel resistant
+ *
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e FF exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_skpow(BIG *r,BIG *x,BIG * e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m, side channel resistant
+ *
+ For short BIG exponent
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e BIG exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_skspow(BIG *r,BIG *x,BIG e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m
+ *
+ For very short integer exponent
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e integer exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_power(BIG *r,BIG *x,int e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m
+ *
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e FF exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_pow(BIG *r,BIG *x,BIG *e,BIG *m,int n);
+/** @brief Test if an FF has factor in common with integer s
+ *
+ @param x FF instance to be tested
+ @param s the supplied integer
+ @param n size of FF in BIGs
+ @return 1 if gcd(x,s)!=1, else return 0
+ */
+extern int FF_cfactor(BIG *x,sign32 s,int n);
+/** @brief Test if an FF is prime
+ *
+ Uses Miller-Rabin Method
+ @param x FF instance to be tested
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ @return 1 if x is (almost certainly) prime, else return 0
+ */
+extern int FF_prime(BIG *x,csprng *R,int n);
+/** @brief Calculate r=x^e.y^f mod m
+ *
+ @param r FF instance, on exit = x^e.y^f mod p
+ @param x FF instance
+ @param e BIG exponent
+ @param y FF instance
+ @param f BIG exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_pow2(BIG *r,BIG *x,BIG e,BIG *y,BIG f,BIG *m,int n);
+
+
+/* Octet string handlers */
+/** @brief Formats and outputs an octet to the console in hex
+ *
+ @param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/** @brief Formats and outputs an octet to the console as a character string
+ *
+ @param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/** @brief Wipe clean an octet
+ *
+ @param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/** @brief Compare two octets
+ *
+ @param O first Octet to be compared
+ @param P second Octet to be compared
+ @return 1 if equal, else 0
+ */
+extern int OCT_comp(octet *O,octet *P);
+/** @brief Compare first n bytes of two octets
+ *
+ @param O first Octet to be compared
+ @param P second Octet to be compared
+ @param n number of bytes to compare
+ @return 1 if equal, else 0
+ */
+extern int OCT_ncomp(octet *O,octet *P,int n);
+/** @brief Join from a C string to end of an octet
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/** @brief Join bytes to end of an octet
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param s bytes to be joined to end of octet
+ @param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/** @brief Join single byte to end of an octet, repeated n times
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param b byte to be joined to end of octet
+ @param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/** @brief Join one octet to the end of another
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/** @brief XOR common bytes of a pair of Octets
+ *
+ @param O Octet - on exit = O xor P
+ @param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/** @brief reset Octet to zero length
+ *
+ @param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/** @brief Pad out an Octet to the given length
+ *
+ Padding is done by inserting leading zeros, so abcd becomes 00abcd
+ @param O Octet to be padded
+ @param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/** @brief Convert an Octet to printable base64 number
+ *
+ @param b zero terminated byte array to take base64 conversion
+ @param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/** @brief Populate an Octet from base64 number
+ *
+ @param O Octet to be populated
+ @param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/** @brief Copy one Octet into another
+ *
+ @param O Octet to be copied to
+ @param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/** @brief XOR every byte of an octet with input m
+ *
+ @param O Octet
+ @param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/** @brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
+ *
+ @param O Octet to be chopped
+ @param P new Octet to be created
+ @param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/** @brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+ Typically n is 4 for a 32-bit integer
+ @param O Octet to be appended to
+ @param m integer to be appended to O
+ @param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/** @brief Create an Octet from bytes taken from a random number generator
+ *
+ Truncates if there is no room
+ @param O Octet to be populated
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/** @brief Shifts Octet left by n bytes
+ *
+ Leftmost bytes disappear
+ @param O Octet to be shifted
+ @param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/** @brief Convert an Octet to printable hex number
+ *
+ @param dst hex value
+ @param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/** @brief Convert an Octet to string
+ *
+ @param dst string value
+ @param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+/* Hash function */
+/** @brief Initialise an instance of SHA256
+ *
+ @param H an instance SHA256
+ */
+extern void HASH_init(hash *H);
+/** @brief Add a byte to the hash
+ *
+ @param H an instance SHA256
+ @param b byte to be included in hash
+ */
+extern void HASH_process(hash *H,int b);
+/** @brief Generate 32-byte hash
+ *
+ @param H an instance SHA256
+ @param h is the output 32-byte hash
+ */
+extern void HASH_hash(hash *H,char *h);
+
+
+
+/* AES functions */
+/** @brief Reset AES mode or IV
+ *
+ @param A an instance of the AES
+ @param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+ @param iv the new Initialisation Vector
+ */
+extern void AES_reset(aes *A,int m,char *iv);
+/** @brief Extract chaining vector from AES instance
+ *
+ @param A an instance of the AES
+ @param f the extracted chaining vector
+ */
+extern void AES_getreg(aes *A,char * f);
+/** @brief Initialise an instance of AES and its mode of operation
+ *
+ @param A an instance AES
+ @param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+ @param k the AES key as an array of 16 bytes
+ @param iv the Initialisation Vector
+ */
+extern void AES_init(aes *A,int m,char *k,char *iv);
+/** @brief Encrypt a single 16 byte block in ECB mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(aes *A,uchar * b);
+/** @brief Decrypt a single 16 byte block in ECB mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(aes *A,uchar * b);
+/** @brief Encrypt a single 16 byte block in active mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(aes *A,char *b );
+/** @brief Decrypt a single 16 byte block in active mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+ @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(aes *A,char *b);
+/** @brief Clean up after application of AES
+ *
+ @param A an instance of the AES
+ */
+extern void AES_end(aes *A);
+
+
+/* AES-GCM functions */
+/** @brief Initialise an instance of AES-GCM mode
+ *
+ @param G an instance AES-GCM
+ @param k the AES key as an array of 16 bytes
+ @param n the number of bytes in the Initialisation Vector (IV)
+ @param iv the IV
+ */
+extern void GCM_init(gcm *G,char *k,int n,char *iv);
+/** @brief Add header (material to be authenticated but not encrypted)
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param b is the header material to be added
+ @param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/** @brief Add plaintext and extract ciphertext
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param c is the ciphertext generated
+ @param p is the plaintext material to be added
+ @param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/** @brief Add ciphertext and extract plaintext
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param p is the plaintext generated
+ @param c is the ciphertext material to be added
+ @param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/** @brief Finish off and extract authentication tag (HMAC)
+ *
+ @param G is an active instance AES-GCM
+ @param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/** @brief Seed a random number generator from an array of bytes
+ *
+ The provided seed should be truly random
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n the number of seed bytes provided
+ @param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/** @brief Delete all internal state of a random number generator
+ *
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ */
+extern void RAND_clean(csprng *R);
+/** @brief Return a random byte from a random number generator
+ *
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+#endif
diff --git a/c/amcl_.h b/c/amcl_.h
new file mode 100755
index 0000000..cb9cd58
--- /dev/null
+++ b/c/amcl_.h
@@ -0,0 +1,2501 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* AMCL header file */
+/* Designed for AES-128 security, 254-256 bit elliptic curves and BN curves for pairings */
+/* Each "limb" of a big number occupies at most (n-3) bits of an n-bit computer word. The most significant word must have at least 4 extra unused bits */
+/* For n=64, use 5 words, use 56 bits per limb, leaving at least 24 unused MSBs 5*56-256 */
+/* For n=32, use 9 words, use 29 bits per limb, leaving at least 5 unused MSBs 9*29-256 */
+/* For n=16, use 20 words, use 13 bits per limb, leaving at least 4 unused MSBs 20*13-256 */
+
+/**
+ * @file amcl_.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 19th May 2015
+ * @brief Main Header File
+ *
+ * Allows some user configuration
+ * defines structures
+ * declares functions
+ *
+ */
+
+
+/* NOTE: There is only one user configurable section in this header - see below */
+
+#ifndef AMCL_H
+#define AMCL_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "DLLDefines.h"
+
+/* Support for C99? Note for GCC need to explicitly include -std=c99 in command line */
+
+#if __STDC_VERSION__ >= 199901L
+/* C99 code */
+#define C99
+#else
+/* Not C99 code */
+#endif
+
+#ifndef C99 /* You are on your own! These are for Microsoft C */
+#define sign32 __int32 /**< 32-bit signed integer */
+#define sign8 signed char /**< 8-bit signed integer */
+#define unsign32 unsigned __int32 /**< 32-bit unsigned integer */
+#else
+#include <stdint.h>
+#define sign8 int8_t /**< 8-bit signed integer */
+#define sign32 int32_t /**< 32-bit signed integer */
+#define unsign32 uint32_t /**< 32-bit unsigned integer */
+#endif
+
+/* modulus types */
+
+#define NOT_SPECIAL 0 /**< Modulus of no exploitable form */
+#define PSEUDO_MERSENNE 1 /**< Pseudo-mersenne modulus of form $2^n-c$ */
+#define MONTGOMERY_FRIENDLY 3 /**< Montgomery Friendly modulus of form $2^a(2^b-c)-1$ */
+
+/* curve types */
+
+#define WEIERSTRASS 0 /**< Short Weierstrass form curve */
+#define EDWARDS 1 /**< Edwards or Twisted Edwards curve */
+#define MONTGOMERY 2 /**< Montgomery form curve */
+
+/* Elliptic curves are defined over prime fields */
+/* Here are some popular EC prime fields for which I have prepared curves. Feel free to specify your own. */
+
+#define NIST 0 /**< For the NIST 256-bit standard curve - WEIERSTRASS only */
+#define C25519 1 /**< Bernstein's Modulus 2^255-19 - EDWARDS or MONTGOMERY only */
+#define BRAINPOOL 2 /**< For Brainpool 256-bit curve - WEIERSTRASS only */
+#define ANSSI 3 /**< For French 256-bit standard curve - WEIERSTRASS only */
+#define MF254 4 /**< For NUMS curves from Bos et al - 254-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS255 5 /**< For NUMS curve - 255-bit pseudo-mersenne modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MF256 6 /**< For NUMS curve - 256-bit Montgomery friendly modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+#define MS256 7 /**< For NUMS curve - 256-bit pseudo-merseene modulus - WEIERSTRASS or EDWARDS or MONTGOMERY */
+
+#define BN 100 /**< Standard Nogami BN curve - fastest. Modulus built from t=-0x4080000000000001 - WEIERSTRASS only */
+#define BNCX 101 /**< Our MIRACL BN curve. Modulus built from t=-0x4000000003C012B1 - WEIERSTRASS only */
+#define BNT 102 /**< GT_Strong BN curve. Modulus built from t=-0x4000806000004081 - WEIERSTRASS only */
+#define BNT2 103 /**< G2 and GT-Strong BN curve. Modulus built from t=-0x4000020100608205 - WEIERSTRASS only */
+
+
+/*** START OF USER CONFIGURABLE SECTION - set architecture and choose modulus and curve ***/
+
+#define CHUNK 32 /**< size of chunk in bits = wordlength of computer = 16, 32 or 64. Note not all curve options are supported on 16-bit processors - see rom.c */
+#define CHOICE BNCX /**< Current choice of Field */
+/* For some moduli only WEIERSTRASS curves are supported. For others there is a choice of WEIERSTRASS, EDWARDS or MONTGOMERY curves. See above. */
+#define CURVETYPE WEIERSTRASS /**< Note that not all curve types are supported - see above */
+
+/* Actual curve parameters associated with these choices can be found in rom.c */
+
+/* These next options only apply for pairings */
+#define USE_GLV /**< Note this method is patented (GLV), so maybe you want to comment this out */
+#define USE_GS_G2 /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+#define USE_GS_GT /**< Not patented, so probably always use this */
+
+/* Finite field support - for RSA, DH etc. */
+#define FF_BITS 2048 /**< Finite Field Size in bits - must be 256.2^n */
+
+/* For debugging Only.
+#define DEBUG_REDUCE
+#define DEBUG_NORM
+#define GET_STATS
+*/
+
+/*** END OF USER CONFIGURABLE SECTION ***/
+
+
+#if CHOICE>=BN /* Its a BN curve */
+#define MBITS 254 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE>BN
+#define GT_STRONG /**< Using a GT-Strong BN curve */
+#endif
+
+#if CHOICE==NIST
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE==C25519
+#define MBITS 255 /**< Number of bits in Modulus */
+#define MOD8 5 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+#if CHOICE==BRAINPOOL
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+#if CHOICE==ANSSI
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE NOT_SPECIAL /**< Modulus type */
+#endif
+
+/**< NUMS curve from Bos et al. paper */
+
+#if CHOICE==MF254
+#define MBITS 254 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE MONTGOMERY_FRIENDLY /**< Modulus type */
+#endif
+
+#if CHOICE==MF256
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 7 /**< Modulus mod 8 */
+#define MODTYPE MONTGOMERY_FRIENDLY /**< Modulus type */
+#endif
+
+#if CHOICE==MS255
+#define MBITS 255 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+#if CHOICE==MS256
+#define MBITS 256 /**< Number of bits in Modulus */
+#define MOD8 3 /**< Modulus mod 8 */
+#define MODTYPE PSEUDO_MERSENNE /**< Modulus type */
+#endif
+
+
+#define FFLEN (FF_BITS/256) /**< RSA public key bytes */
+#define HFLEN (FFLEN/2) /**< Useful for half-size RSA private key operations */
+
+/* This next is probably OK, but may need changing for non-C99-standard environments */
+
+#if CHUNK==16
+#define NLEN 20 /**< Number of words in BIG. */
+#define BASEBITS 13 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int16 /**< C type corresponding to word length */
+#define dchunk __int32 /**< Always define double length chunk type if available */
+#else
+#define chunk int16_t /**< C type corresponding to word length */
+#define dchunk int32_t /**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 32
+#define NLEN 9 /**< Number of words in BIG. */
+#define BASEBITS 29 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int32 /**< C type corresponding to word length */
+#define dchunk __int64 /**< Always define double length chunk type if available */
+#else
+#define chunk int32_t /**< C type corresponding to word length */
+#define dchunk int64_t /**< Always define double length chunk type if available */
+#endif
+#endif
+
+#if CHUNK == 64
+#define NLEN 5 /**< Number of words in BIG. */
+#define BASEBITS 56 /**< Numbers represented to base 2*BASEBITS */
+#ifndef C99
+#define chunk __int64 /**< C type corresponding to word length */
+ /**< Note - no 128-bit type available */
+#else
+#define chunk int64_t /**< C type corresponding to word length */
+#ifdef __GNUC__
+#define dchunk __int128 /**< Always define double length chunk type if available - GCC supports 128 bit type ??? */
+#endif
+#endif
+#endif
+
+/* Don't mess with anything below this line */
+
+#ifdef GET_STATS
+extern int tsqr,rsqr,tmul,rmul;
+extern int tadd,radd,tneg,rneg;
+extern int tdadd,rdadd,tdneg,rdneg;
+#endif
+
+#define DCHUNK 2*CHUNK /**< Number of bits in double-length type */
+#define DNLEN 2*NLEN /**< double length required for products of BIGs */
+
+#ifdef dchunk
+#define COMBA /**< Use COMBA method for faster BN muls, sqrs and reductions */
+#endif
+
+#define CHUNK_BITS 8*sizeof(chunk) /**< Number of bits in a chunk */
+
+#ifdef DEBUG_NORM /* Add an extra location to track chunk extension */
+typedef chunk BIG[NLEN+1]; /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN+1]; /**< Define type DBIG as array of chunks */
+#else
+typedef chunk BIG[NLEN]; /**< Define type BIG as array of chunks */
+typedef chunk DBIG[DNLEN]; /**< Define type DBIG as array of chunks */
+#endif
+
+#define HBITS (BASEBITS/2) /**< Number of bits in number base divided by 2 */
+#define HBITS1 ((BASEBITS+1)/2) /**< Number of bits in number base plus 1 divided by 2 */
+#define HDIFF (HBITS1-HBITS) /**< Will be either 0 or 1, depending if number of bits in number base is even or odd */
+
+#define MASK (((chunk)1<<BASEBITS)-1) /**< Mask = 2^BASEBITS-1 */
+#define HMASK (((chunk)1<<HBITS)-1) /**< Mask = 2^HBITS-1 */
+#define HMASK1 (((chunk)1<<HBITS1)-1) /**< Mask = 2^HBITS1-1 */
+
+#define MODBITS MBITS /**< Number of bits in Modulus for selected curve */
+#define MODBYTES 32 /**< Number of bytes in Modulus */
+#define MB (MBITS%BASEBITS) /**< Number of bits in modulus mod number of bits in number base */
+#define TBITS (MBITS%BASEBITS) /**< Number of active bits in top word */
+#define TMASK (((chunk)1<<(MBITS%BASEBITS))-1) /**< Mask for active bits in top word */
+#define NEXCESS (1<<(CHUNK-BASEBITS-1)) /**< 2^(CHUNK-BASEBITS-1) - digit cannot be multiplied by more than this before normalisation */
+#define FEXCESS ((chunk)1<<(BASEBITS*NLEN-MBITS)) /**< 2^(BASEBITS*NLEN-MODBITS) - normalised BIG can be multiplied by more than this before reduction */
+#define OMASK ((chunk)(-1)<<(MBITS%BASEBITS)) /**< for masking out overflow bits */
+
+/* catch field excesses */
+#define EXCESS(a) ((a[NLEN-1]&OMASK)>>(MB)) /**< Field Excess */
+
+/* Field Params - see rom.c */
+extern const BIG Modulus; /**< Actual Modulus set in rom.c */
+extern const chunk MConst; /**< Montgomery only - 1/p mod 2^BASEBITS */
+
+/* Curve Params - see rom.c */
+extern const int CURVE_A; /**< Elliptic curve A parameter */
+extern const BIG CURVE_B; /**< Elliptic curve B parameter */
+extern const BIG CURVE_Order; /**< Elliptic curve group order */
+
+/* Generator point on G1 */
+extern const BIG CURVE_Gx; /**< x-coordinate of generator point in group G1 */
+extern const BIG CURVE_Gy; /**< y-coordinate of generator point in group G1 */
+
+/* For Pairings only */
+
+/* Generator point on G2 */
+extern const BIG CURVE_Pxa; /**< real part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pxb; /**< imaginary part of x-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pya; /**< real part of y-coordinate of generator point in group G2 */
+extern const BIG CURVE_Pyb; /**< imaginary part of y-coordinate of generator point in group G2 */
+
+extern const BIG CURVE_Bnx; /**< BN curve x parameter */
+
+extern const BIG CURVE_Cru; /**< BN curve Cube Root of Unity */
+
+extern const BIG CURVE_Fra; /**< real part of BN curve Frobenius Constant */
+extern const BIG CURVE_Frb; /**< imaginary part of BN curve Frobenius Constant */
+
+
+extern const BIG CURVE_W[2]; /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_SB[2][2]; /**< BN curve constant for GLV decomposition */
+extern const BIG CURVE_WB[4]; /**< BN curve constant for GS decomposition */
+extern const BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
+
+/* Structures */
+
+/**
+ @brief ECP structure - Elliptic Curve Point over base field
+*/
+
+typedef struct {
+#if CURVETYPE!=EDWARDS
+int inf; /**< Infinity Flag - not needed for Edwards representation */
+#endif
+BIG x; /**< x-coordinate of point */
+#if CURVETYPE!=MONTGOMERY
+BIG y; /**< y-coordinate of point. Not needed for Montgomery representation */
+#endif
+BIG z; /**< z-coordinate of point */
+} ECP;
+
+/**
+ @brief FP2 Structure - quadratic extension field
+*/
+
+typedef struct {
+BIG a; /**< real part of FP2 */
+BIG b; /**< imaginary part of FP2 */
+} FP2;
+
+/**
+ @brief FP4 Structure - towered over two FP2
+*/
+
+typedef struct {
+FP2 a; /**< real part of FP4 */
+FP2 b; /**< imaginary part of FP4 */
+} FP4;
+
+/**
+ @brief FP12 Structure - towered over three FP4
+*/
+
+typedef struct {
+FP4 a; /**< first part of FP12 */
+FP4 b; /**< second part of FP12 */
+FP4 c; /**< third part of FP12 */
+} FP12;
+
+/**
+ @brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
+*/
+
+typedef struct {
+int inf; /**< Infinity Flag */
+FP2 x; /**< x-coordinate of point */
+FP2 y; /**< y-coordinate of point */
+FP2 z; /**< z-coordinate of point */
+} ECP2;
+
+/**
+ @brief SHA256 hash function instance
+*/
+
+typedef struct {
+unsign32 length[2]; /**< 64-bit input length */
+unsign32 h[8]; /**< Internal state */
+unsign32 w[64]; /**< Internal state */
+} hash;
+
+/* Symmetric Encryption AES structure */
+
+#define ECB 0 /**< Electronic Code Book */
+#define CBC 1 /**< Cipher Block Chaining */
+#define CFB1 2 /**< Cipher Feedback - 1 byte */
+#define CFB2 3 /**< Cipher Feedback - 2 bytes */
+#define CFB4 5 /**< Cipher Feedback - 4 bytes */
+#define OFB1 14 /**< Output Feedback - 1 byte */
+#define OFB2 15 /**< Output Feedback - 2 bytes */
+#define OFB4 17 /**< Output Feedback - 4 bytes */
+#define OFB8 21 /**< Output Feedback - 8 bytes */
+#define OFB16 29 /**< Output Feedback - 16 bytes */
+
+#define uchar unsigned char /**< Unsigned char */
+
+/**
+ @brief AES instance
+*/
+
+
+typedef struct {
+int mode; /**< AES mode of operation */
+unsign32 fkey[44]; /**< subkeys for encrypton */
+unsign32 rkey[44]; /**< subkeys for decrypton */
+char f[16]; /**< buffer for chaining vector */
+} aes;
+
+/* AES-GCM suppport. */
+
+#define GCM_ACCEPTING_HEADER 0 /**< GCM status */
+#define GCM_ACCEPTING_CIPHER 1 /**< GCM status */
+#define GCM_NOT_ACCEPTING_MORE 2 /**< GCM status */
+#define GCM_FINISHED 3 /**< GCM status */
+#define GCM_ENCRYPTING 0 /**< GCM mode */
+#define GCM_DECRYPTING 1 /**< GCM mode */
+
+
+/**
+ @brief GCM mode instance, using AES internally
+*/
+
+typedef struct {
+unsign32 table[128][4]; /**< 2k byte table */
+uchar stateX[16]; /**< GCM Internal State */
+uchar Y_0[16]; /**< GCM Internal State */
+unsign32 lenA[2]; /**< GCM 64-bit length of header */
+unsign32 lenC[2]; /**< GCM 64-bit length of ciphertext */
+int status; /**< GCM Status */
+aes a; /**< Internal Instance of AES cipher */
+} gcm;
+
+/* Marsaglia & Zaman Random number generator constants */
+
+#define NK 21 /**< PRNG constant */
+#define NJ 6 /**< PRNG constant */
+#define NV 8 /**< PRNG constant */
+
+
+/**
+ @brief Cryptographically secure pseudo-random number generator instance
+*/
+
+typedef struct {
+unsign32 ira[NK]; /**< random number array */
+int rndptr; /**< pointer into array */
+unsign32 borrow; /**< borrow as a result of subtraction */
+int pool_ptr; /**< pointer into random pool */
+char pool[32]; /**< random pool */
+} csprng;
+
+
+/**
+ @brief Portable representation of a big positive number
+*/
+
+typedef struct
+{
+ int len; /**< length in bytes */
+ int max; /**< max length allowed - enforce truncation */
+ char *val; /**< byte array */
+} octet;
+
+/**
+ @brief Integer Factorisation Public Key
+*/
+
+typedef struct
+{
+ sign32 e; /**< RSA exponent (typically 65537) */
+ BIG n[FFLEN]; /**< An array of BIGs to store public key */
+} rsa_public_key;
+
+/**
+ @brief Integer Factorisation Private Key
+*/
+
+typedef struct
+{
+ BIG p[FFLEN/2]; /**< secret prime p */
+ BIG q[FFLEN/2]; /**< secret prime q */
+ BIG dp[FFLEN/2]; /**< decrypting exponent mod (p-1) */
+ BIG dq[FFLEN/2]; /**< decrypting exponent mod (q-1) */
+ BIG c[FFLEN/2]; /**< 1/p mod q */
+} rsa_private_key;
+
+/*
+
+Note that a normalised BIG consists of digits mod 2^BASEBITS
+However BIG digits may be "extended" up to 2^(WORDLENGTH-1).
+
+BIGs in extended form may need to be normalised before certain
+operations.
+
+A BIG may be "reduced" to be less that the Modulus, or it
+may be "unreduced" and allowed to grow greater than the
+Modulus.
+
+Normalisation is quite fast. Reduction involves conditional branches,
+which can be regarded as significant "speed bumps". We try to
+delay reductions as much as possible. Reductions may also involve
+side channel leakage, so delaying and batching them
+hopefully disguises internal operations.
+
+*/
+
+/* BIG number prototypes */
+
+/** @brief Calculates a*b+c+*d
+ *
+ Calculate partial product of a.b, add in carry c, and add total to d
+ @param a multiplier
+ @param b multiplicand
+ @param c carry
+ @param d pointer to accumulated bottom half of result
+ @return top half of result
+ */
+extern chunk muladd(chunk a,chunk b,chunk c,chunk *d);
+/** @brief Tests for BIG equal to zero
+ *
+ @param x a BIG number
+ @return 1 if zero, else returns 0
+ */
+extern int BIG_iszilch(BIG x);
+/** @brief Tests for DBIG equal to zero
+ *
+ @param x a DBIG number
+ @return 1 if zero, else returns 0
+ */
+extern int BIG_diszilch(DBIG x);
+/** @brief Outputs a BIG number to the console
+ *
+ @param x a BIG number
+ */
+extern void BIG_output(BIG x);
+/** @brief Outputs a BIG number to the console in raw form (for debugging)
+ *
+ @param x a BIG number
+ */
+extern void BIG_rawoutput(BIG x);
+/** @brief Conditional constant time swap of two BIG numbers
+ *
+ Conditionally swaps parameters in constant time (without branching)
+ @param x a BIG number
+ @param y another BIG number
+ @param s swap takes place if not equal to 0
+ */
+extern void BIG_cswap(BIG x,BIG y,int s);
+/** @brief Conditional copy of BIG number
+ *
+ Conditionally copies second parameter to the first (without branching)
+ @param x a BIG number
+ @param y another BIG number
+ @param s copy takes place if not equal to 0
+ */
+extern void BIG_cmove(BIG x,BIG y,int s);
+/** @brief Convert from BIG number to byte array
+ *
+ @param a byte array
+ @param x BIG number
+ */
+extern void BIG_toBytes(char *a,BIG x);
+/** @brief Convert to BIG number from byte array
+ *
+ @param x BIG number
+ @param a byte array
+ */
+extern void BIG_fromBytes(BIG x,char *a);
+/** @brief Outputs a DBIG number to the console
+ *
+ @param x a DBIG number
+ */
+extern void BIG_doutput(DBIG x);
+/** @brief Copy BIG from Read-Only Memory to a BIG
+ *
+ @param x BIG number
+ @param y BIG number in ROM
+ */
+extern void BIG_rcopy(BIG x,const BIG y);
+/** @brief Copy BIG to another BIG
+ *
+ @param x BIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_copy(BIG x,BIG y);
+/** @brief Copy DBIG to another DBIG
+ *
+ @param x DBIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_dcopy(DBIG x,DBIG y);
+/** @brief Copy BIG to upper half of DBIG
+ *
+ @param x DBIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_dsucopy(DBIG x,BIG y);
+/** @brief Copy BIG to lower half of DBIG
+ *
+ @param x DBIG number
+ @param y BIG number to be copied
+ */
+extern void BIG_dscopy(DBIG x,BIG y);
+/** @brief Copy lower half of DBIG to a BIG
+ *
+ @param x BIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_sdcopy(BIG x,DBIG y);
+/** @brief Copy upper half of DBIG to a BIG
+ *
+ @param x BIG number
+ @param y DBIG number to be copied
+ */
+extern void BIG_sducopy(BIG x,DBIG y);
+/** @brief Set BIG to zero
+ *
+ @param x BIG number to be set to zero
+ */
+extern void BIG_zero(BIG x);
+/** @brief Set DBIG to zero
+ *
+ @param x DBIG number to be set to zero
+ */
+extern void BIG_dzero(DBIG x);
+/** @brief Set BIG to one (unity)
+ *
+ @param x BIG number to be set to one.
+ */
+extern void BIG_one(BIG x);
+/** @brief Set BIG to inverse mod 2^256
+ *
+ @param x BIG number to be inverted
+ */
+extern void BIG_invmod2m(BIG x);
+/** @brief Set BIG to sum of two BIGs - output not normalised
+ *
+ @param x BIG number, sum of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_add(BIG x,BIG y,BIG z);
+/** @brief Increment BIG by a small integer - output not normalised
+ *
+ @param x BIG number to be incremented
+ @param i integer
+ */
+extern void BIG_inc(BIG x,int i);
+/** @brief Set BIG to difference of two BIGs
+ *
+ @param x BIG number, difference of other two - output not normalised
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_sub(BIG x,BIG y,BIG z);
+/** @brief Decrement BIG by a small integer - output not normalised
+ *
+ @param x BIG number to be decremented
+ @param i integer
+ */
+extern void BIG_dec(BIG x,int i);
+/** @brief Set DBIG to difference of two DBIGs
+ *
+ @param x DBIG number, difference of other two - output not normalised
+ @param y DBIG number
+ @param z DBIG number
+ */
+extern void BIG_dsub(DBIG x,DBIG y,DBIG z);
+/** @brief Multiply BIG by a small integer - output not normalised
+ *
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ */
+extern void BIG_imul(BIG x,BIG y,int i);
+/** @brief Multiply BIG by not-so-small small integer - output normalised
+ *
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ @return Overflowing bits
+ */
+extern chunk BIG_pmul(BIG x,BIG y,int i);
+/** @brief Divide BIG by 3 - output normalised
+ *
+ @param x BIG number
+ @return Remainder
+ */
+extern int BIG_div3(BIG x);
+/** @brief Multiply BIG by even bigger small integer resulting in a DBIG - output normalised
+ *
+ @param x DBIG number, product of other two
+ @param y BIG number
+ @param i small integer
+ */
+extern void BIG_pxmul(DBIG x,BIG y,int i);
+/** @brief Multiply BIG by another BIG resulting in DBIG - inputs normalised and output normalised
+ *
+ @param x DBIG number, product of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_mul(DBIG x,BIG y,BIG z);
+/** @brief Multiply BIG by another BIG resulting in another BIG - inputs normalised and output normalised
+ *
+ Note that the product must fit into a BIG, and x must be distinct from y and z
+ @param x BIG number, product of other two
+ @param y BIG number
+ @param z BIG number
+ */
+extern void BIG_smul(BIG x,BIG y,BIG z);
+/** @brief Square BIG resulting in a DBIG - input normalised and output normalised
+ *
+ @param x DBIG number, square of a BIG
+ @param y BIG number to be squared
+ */
+extern void BIG_sqr(DBIG x,BIG y);
+/** @brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
+ *
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_shl(BIG x,int s);
+/** @brief Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+ *
+ The number of bits to be shifted must be less than BASEBITS
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ @return Overflow bits
+ */
+extern chunk BIG_fshl(BIG x,int s);
+/** @brief Shifts a DBIG left by any number of bits - input must be normalised, output normalised
+ *
+ @param x DBIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_dshl(DBIG x,int s);
+/** @brief Shifts a BIG right by any number of bits - input must be normalised, output normalised
+ *
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_shr(BIG x,int s);
+/** @brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+ *
+ The number of bits to be shifted must be less than BASEBITS
+ @param x BIG number to be shifted
+ @param s Number of bits to shift
+ @return Shifted out bits
+ */
+extern chunk BIG_fshr(BIG x,int s);
+/** @brief Shifts a DBIG right by any number of bits - input must be normalised, output normalised
+ *
+ @param x DBIG number to be shifted
+ @param s Number of bits to shift
+ */
+extern void BIG_dshr(DBIG x,int s);
+/** @brief Splits a DBIG into two BIGs - input must be normalised, outputs normalised
+ *
+ Internal function. The value of s must be approximately in the middle of the DBIG.
+ Typically used to extract z mod 2^MODBITS and z/2^MODBITS
+ @param x BIG number, top half of z
+ @param y BIG number, bottom half of z
+ @param z DBIG number to be split in two.
+ @param s Bit position at which to split
+ */
+extern void BIG_split(BIG x,BIG y,DBIG z,int s);
+/** @brief Normalizes a BIG number - output normalised
+ *
+ All digits of the input BIG are reduced mod 2^BASEBITS
+ @param x BIG number to be normalised
+ */
+extern chunk BIG_norm(BIG x);
+/** @brief Normalizes a DBIG number - output normalised
+ *
+ All digits of the input DBIG are reduced mod 2^BASEBITS
+ @param x DBIG number to be normalised
+ */
+extern void BIG_dnorm(DBIG x);
+/** @brief Compares two BIG numbers. Inputs must be normalised externally
+ *
+ @param x first BIG number to be compared
+ @param y second BIG number to be compared
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_comp(BIG x,BIG y);
+/** @brief Compares two DBIG numbers. Inputs must be normalised externally
+ *
+ @param x first DBIG number to be compared
+ @param y second DBIG number to be compared
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int BIG_dcomp(DBIG x,DBIG y);
+/** @brief Calculate number of bits in a BIG - output normalised
+ *
+ @param x BIG number
+ @return Number of bits in x
+ */
+extern int BIG_nbits(BIG x);
+/** @brief Calculate number of bits in a DBIG - output normalised
+ *
+ @param x DBIG number
+ @return Number of bits in x
+ */
+extern int BIG_dnbits(DBIG x);
+/** @brief Reduce x mod n - input and output normalised
+ *
+ Slow but rarely used
+ @param x BIG number to be reduced mod n
+ @param n The modulus
+ */
+extern void BIG_mod(BIG x,BIG n);
+/** @brief Divide x by n - output normalised
+ *
+ Slow but rarely used
+ @param x BIG number to be divided by n
+ @param n The Divisor
+ */
+extern void BIG_sdiv(BIG x,BIG n);
+/** @brief x=y mod n - output normalised
+ *
+ Slow but rarely used. y is destroyed.
+ @param x BIG number, on exit = y mod n
+ @param y DBIG number
+ @param n Modulus
+ */
+extern void BIG_dmod(BIG x,DBIG y,BIG n);
+/** @brief x=y/n - output normalised
+ *
+ Slow but rarely used. y is destroyed.
+ @param x BIG number, on exit = y/n
+ @param y DBIG number
+ @param n Modulus
+ */
+extern void BIG_ddiv(BIG x,DBIG y,BIG n);
+/** @brief return parity of BIG, that is the least significant bit
+ *
+ @param x BIG number
+ @return 0 or 1
+ */
+extern int BIG_parity(BIG x);
+/** @brief return i-th of BIG
+ *
+ @param x BIG number
+ @param i the bit of x to be returned
+ @return 0 or 1
+ */
+extern int BIG_bit(BIG x,int i);
+/** @brief return least significant bits of a BIG
+ *
+ @param x BIG number
+ @param n number of bits to return. Assumed to be less than BASEBITS.
+ @return least significant n bits as an integer
+ */
+extern int BIG_lastbits(BIG x,int n);
+/** @brief Create a random BIG from a random number generator
+ *
+ Assumes that the random number generator has been suitably initialised
+ @param x BIG number, on exit a random number
+ @param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_random(BIG x,csprng *r);
+/** @brief Create an unbiased random BIG from a random number generator, reduced with respect to a modulus
+ *
+ Assumes that the random number generator has been suitably initialised
+ @param x BIG number, on exit a random number
+ @param n The modulus
+ @param r A pointer to a Cryptographically Secure Random Number Generator
+ */
+extern void BIG_randomnum(BIG x,BIG n,csprng *r);
+/** @brief return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised
+ *
+ Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any
+ @param x BIG number
+ @param x3 BIG number, three times x
+ @param i bit position
+ @param nbs pointer to integer returning number of bits processed
+ @param nzs pointer to integer returning number of trailing 0s
+ @return + or - 1, 3 or 5
+ */
+extern int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs);
+/** @brief Calculate x=y*z mod n
+ *
+ Slow method for modular multiplication
+ @param x BIG number, on exit = y*z mod n
+ @param y BIG number
+ @param z BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modmul(BIG x,BIG y,BIG z,BIG n);
+/** @brief Calculate x=y/z mod n
+ *
+ Slow method for modular division
+ @param x BIG number, on exit = y/z mod n
+ @param y BIG number
+ @param z BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_moddiv(BIG x,BIG y,BIG z,BIG n);
+/** @brief Calculate x=y^2 mod n
+ *
+ Slow method for modular squaring
+ @param x BIG number, on exit = y^2 mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modsqr(BIG x,BIG y,BIG n);
+/** @brief Calculate x=-y mod n
+ *
+ Modular negation
+ @param x BIG number, on exit = -y mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_modneg(BIG x,BIG y,BIG n);
+/** @brief Calculate jacobi Symbol (x/y)
+ *
+ @param x BIG number
+ @param y BIG number
+ @return Jacobi symbol, -1,0 or 1
+ */
+extern int BIG_jacobi(BIG x,BIG y);
+/** @brief Calculate x=1/y mod n
+ *
+ Modular Inversion - This is slow. Uses binary method.
+ @param x BIG number, on exit = 1/y mod n
+ @param y BIG number
+ @param n The BIG Modulus
+ */
+extern void BIG_invmodp(BIG x,BIG y,BIG n);
+
+
+
+/* FP prototypes */
+
+/** @brief Tests for BIG equal to zero mod Modulus
+ *
+ @param x BIG number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP_iszilch(BIG x);
+/** @brief Converts from BIG integer to n-residue form mod Modulus
+ *
+ @param x BIG number to be converted
+ */
+extern void FP_nres(BIG x);
+/** @brief Converts from n-residue form back to BIG integer form
+ *
+ @param x BIG number to be converted
+ */
+extern void FP_redc(BIG x);
+/** @brief Sets BIG to representation of unity in n-residue form
+ *
+ @param x BIG number to be set equal to unity.
+ */
+extern void FP_one(BIG x);
+/** @brief Reduces DBIG to BIG exploiting special form of the modulus
+ *
+ This function comes in different flavours depending on the form of Modulus that is currently in use.
+ @param x BIG number, on exit = y mod Modulus
+ @param y DBIG number to be reduced
+ */
+extern void FP_mod(BIG x,DBIG y);
+/** @brief Fast Modular multiplication of two BIGs in n-residue form, mod Modulus
+ *
+ Uses appropriate fast modular reduction method
+ @param x BIG number, on exit the modular product = y*z mod Modulus
+ @param y BIG number, the multiplicand
+ @param z BIG number, the multiplier
+ */
+extern void FP_mul(BIG x,BIG y,BIG z);
+/** @brief Fast Modular multiplication of a BIG in n-residue form, by a small integer, mod Modulus
+ *
+ @param x BIG number, on exit the modular product = y*i mod Modulus
+ @param y BIG number, the multiplicand
+ @param i a small number, the multiplier
+ */
+extern void FP_imul(BIG x,BIG y,int i);
+/** @brief Fast Modular squaring of a BIG in n-residue form, mod Modulus
+ *
+ Uses appropriate fast modular reduction method
+ @param x BIG number, on exit the modular product = y^2 mod Modulus
+ @param y BIG number, the number to be squared
+
+ */
+extern void FP_sqr(BIG x,BIG y);
+/** @brief Modular addition of two BIGs in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit the modular sum = y+z mod Modulus
+ @param y BIG number
+ @param z BIG number
+ */
+extern void FP_add(BIG x,BIG y,BIG z);
+/** @brief Modular subtraction of two BIGs in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit the modular difference = y-z mod Modulus
+ @param y BIG number
+ @param z BIG number
+ */
+extern void FP_sub(BIG x,BIG y,BIG z);
+/** @brief Modular division by 2 of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit =y/2 mod Modulus
+ @param y BIG number
+ */
+extern void FP_div2(BIG x,BIG y);
+/** @brief Fast Modular exponentiation of a BIG in n-residue form, to the power of a BIG, mod Modulus
+ *
+ @param x BIG number, on exit = y^z mod Modulus
+ @param y BIG number
+ @param z Big number exponent
+ */
+extern void FP_pow(BIG x,BIG y,BIG z);
+/** @brief Fast Modular square root of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = sqrt(y) mod Modulus
+ @param y BIG number, the number whose square root is calculated
+
+ */
+extern void FP_sqrt(BIG x,BIG y);
+/** @brief Modular negation of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = -y mod Modulus
+ @param y BIG number
+ */
+extern void FP_neg(BIG x,BIG y);
+/** @brief Outputs a BIG number that is in n-residue form to the console
+ *
+ Converts from n-residue form before output
+ @param x a BIG number
+ */
+extern void FP_output(BIG x);
+/** @brief Outputs a BIG number that is in n-residue form to the console, in raw form
+ *
+ Converts from n-residue form before output
+ @param x a BIG number
+ */
+extern void FP_rawoutput(BIG x);
+/** @brief Reduces possibly unreduced BIG mod Modulus
+ *
+ @param x BIG number, on exit reduced mod Modulus
+ */
+extern void FP_reduce(BIG x);
+/** @brief Tests for BIG a quadratic residue mod Modulus
+ *
+ @param x BIG number to be tested
+ @return 1 if quadratic residue, else returns 0 if quadratic non-residue
+ */
+extern int FP_qr(BIG x);
+/** @brief Modular inverse of a BIG in n-residue form, mod Modulus
+ *
+ @param x BIG number, on exit = 1/y mod Modulus
+ @param y BIG number
+ */
+extern void FP_inv(BIG x,BIG y);
+
+
+/* FP2 prototypes */
+
+/** @brief Tests for FP2 equal to zero
+ *
+ @param x FP2 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP2_iszilch(FP2 *x);
+/** @brief Conditional copy of FP2 number
+ *
+ Conditionally copies second parameter to the first (without branching)
+ @param x FP2 instance, set to y if s!=0
+ @param y another FP2 instance
+ @param s copy only takes place if not equal to 0
+ */
+extern void FP2_cmove(FP2 *x,FP2 *y,int s);
+/** @brief Tests for FP2 equal to one
+ *
+ @param x FP2 instance to be tested
+ @return 1 if x=1, else returns 0
+ */
+extern int FP2_isunity(FP2 *x);
+/** @brief Tests for equality of two FP2s
+ *
+ @param x FP2 instance to be compared
+ @param y FP2 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP2_equals(FP2 *x,FP2 *y);
+/** @brief Initialise FP2 from two BIGs in n-residue form
+ *
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ @param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_FPs(FP2 *x,BIG a,BIG b);
+/** @brief Initialise FP2 from two BIG integers
+ *
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ @param b BIG to form imaginary part of FP2
+ */
+extern void FP2_from_BIGs(FP2 *x,BIG a,BIG b);
+/** @brief Initialise FP2 from single BIG in n-residue form
+ *
+ Imaginary part is set to zero
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ */
+extern void FP2_from_FP(FP2 *x,BIG a);
+/** @brief Initialise FP2 from single BIG
+ *
+ Imaginary part is set to zero
+ @param x FP2 instance to be initialised
+ @param a BIG to form real part of FP2
+ */
+extern void FP2_from_BIG(FP2 *x,BIG a);
+/** @brief Copy FP2 to another FP2
+ *
+ @param x FP2 instance, on exit = y
+ @param y FP2 instance to be copied
+ */
+extern void FP2_copy(FP2 *x,FP2 *y);
+/** @brief Set FP2 to zero
+ *
+ @param x FP2 instance to be set to zero
+ */
+extern void FP2_zero(FP2 *x);
+/** @brief Set FP2 to unity
+ *
+ @param x FP2 instance to be set to one
+ */
+extern void FP2_one(FP2 *x);
+/** @brief Negation of FP2
+ *
+ @param x FP2 instance, on exit = -y
+ @param y FP2 instance
+ */
+extern void FP2_neg(FP2 *x,FP2 *y);
+/** @brief Conjugation of FP2
+ *
+ If y=(a,b) on exit x=(a,-b)
+ @param x FP2 instance, on exit = conj(y)
+ @param y FP2 instance
+ */
+extern void FP2_conj(FP2 *x,FP2 *y);
+/** @brief addition of two FP2s
+ *
+ @param x FP2 instance, on exit = y+z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_add(FP2 *x,FP2 *y,FP2 *z);
+/** @brief subtraction of two FP2s
+ *
+ @param x FP2 instance, on exit = y-z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_sub(FP2 *x,FP2 *y,FP2 *z);
+/** @brief Multiplication of an FP2 by an n-residue
+ *
+ @param x FP2 instance, on exit = y*b
+ @param y FP2 instance
+ @param b BIG n-residue
+ */
+extern void FP2_pmul(FP2 *x,FP2 *y,BIG b);
+/** @brief Multiplication of an FP2 by a small integer
+ *
+ @param x FP2 instance, on exit = y*i
+ @param y FP2 instance
+ @param i an integer
+ */
+extern void FP2_imul(FP2 *x,FP2 *y,int i);
+/** @brief Squaring an FP2
+ *
+ @param x FP2 instance, on exit = y^2
+ @param y FP2 instance
+ */
+extern void FP2_sqr(FP2 *x,FP2 *y);
+/** @brief Multiplication of two FP2s
+ *
+ @param x FP2 instance, on exit = y*z
+ @param y FP2 instance
+ @param z FP2 instance
+ */
+extern void FP2_mul(FP2 *x,FP2 *y,FP2 *z);
+/** @brief Formats and outputs an FP2 to the console
+ *
+ @param x FP2 instance
+ */
+extern void FP2_output(FP2 *x);
+/** @brief Formats and outputs an FP2 to the console in raw form (for debugging)
+ *
+ @param x FP2 instance
+ */
+extern void FP2_rawoutput(FP2 *x);
+/** @brief Inverting an FP2
+ *
+ @param x FP2 instance, on exit = 1/y
+ @param y FP2 instance
+ */
+extern void FP2_inv(FP2 *x,FP2 *y);
+/** @brief Divide an FP2 by 2
+ *
+ @param x FP2 instance, on exit = y/2
+ @param y FP2 instance
+ */
+extern void FP2_div2(FP2 *x,FP2 *y);
+/** @brief Multiply an FP2 by (1+sqrt(-1))
+ *
+ Note that (1+sqrt(-1)) is irreducible for FP4
+ @param x FP2 instance, on exit = x*(1+sqrt(-1))
+ */
+extern void FP2_mul_ip(FP2 *x);
+/** @brief Divide an FP2 by (1+sqrt(-1))
+ *
+ Note that (1+sqrt(-1)) is irreducible for FP4
+ @param x FP2 instance, on exit = x/(1+sqrt(-1))
+ */
+extern void FP2_div_ip(FP2 *x);
+/** @brief Normalises the components of an FP2
+ *
+ @param x FP2 instance to be normalised
+ */
+extern void FP2_norm(FP2 *x);
+/** @brief Reduces all components of possibly unreduced FP2 mod Modulus
+ *
+ @param x FP2 instance, on exit reduced mod Modulus
+ */
+extern void FP2_reduce(FP2 *x);
+/** @brief Raises an FP2 to the power of a BIG
+ *
+ @param x FP2 instance, on exit = y^b
+ @param y FP2 instance
+ @param b BIG number
+ */
+extern void FP2_pow(FP2 *x,FP2 *y,BIG b);
+/** @brief Square root of an FP2
+ *
+ @param x FP2 instance, on exit = sqrt(y)
+ @param y FP2 instance
+ */
+extern int FP2_sqrt(FP2 *x,FP2 *y);
+
+
+
+/* ECP E(Fp) prototypes */
+/** @brief Tests for ECP point equal to infinity
+ *
+ @param P ECP point to be tested
+ @return 1 if infinity, else returns 0
+ */
+extern int ECP_isinf(ECP *P);
+/** @brief Tests for equality of two ECPs
+ *
+ @param P ECP instance to be compared
+ @param Q ECP instance to be compared
+ @return 1 if P=Q, else returns 0
+ */
+extern int ECP_equals(ECP *P,ECP *Q);
+/** @brief Copy ECP point to another ECP point
+ *
+ @param P ECP instance, on exit = Q
+ @param Q ECP instance to be copied
+ */
+extern void ECP_copy(ECP *P,ECP *Q);
+/** @brief Negation of an ECP point
+ *
+ @param P ECP instance, on exit = -P
+ */
+extern void ECP_neg(ECP *P);
+/** @brief Set ECP to point-at-infinity
+ *
+ @param P ECP instance to be set to infinity
+ */
+extern void ECP_inf(ECP *P);
+/** @brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+ Function f(x) depends on form of elliptic curve, Weierstrass, Edwards or Montgomery.
+ Used internally.
+ @param r BIG n-residue value of f(x)
+ @param x BIG n-residue x
+ */
+extern void ECP_rhs(BIG r,BIG x);
+/** @brief Set ECP to point(x,y) given just x and sign of y
+ *
+ Point P set to infinity if no such point on the curve. If x is on the curve then y is calculated from the curve equation.
+ The correct y value (plus or minus) is selected given its sign s.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @param s an integer representing the "sign" of y, in fact its least significant bit.
+ */
+extern int ECP_setx(ECP *P,BIG x,int s);
+
+#if CURVETYPE==MONTGOMERY
+/** @brief Set ECP to point(x,[y]) given x
+ *
+ Point P set to infinity if no such point on the curve. Note that y coordinate is not needed.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x);
+/** @brief Extract x coordinate of an ECP point P
+ *
+ @param x BIG on exit = x coordinate of point
+ @param P ECP instance (x,[y])
+ @return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP_get(BIG x,ECP *P);
+/** @brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
+ *
+ Differential addition of points on a Montgomery curve
+ @param P ECP instance, on exit =P+Q
+ @param Q ECP instance to be added to P
+ @param D Difference between P and Q
+ */
+extern void ECP_add(ECP *P,ECP *Q,ECP *D);
+#else
+/** @brief Set ECP to point(x,y) given x and y
+ *
+ Point P set to infinity if no such point on the curve.
+ @param P ECP instance to be set (x,y)
+ @param x BIG x coordinate of point
+ @param y BIG y coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP_set(ECP *P,BIG x,BIG y);
+/** @brief Extract x and y coordinates of an ECP point P
+ *
+ If x=y, returns only x
+ @param x BIG on exit = x coordinate of point
+ @param y BIG on exit = y coordinate of point (unless x=y)
+ @param P ECP instance (x,y)
+ @return sign of y, or -1 if P is point-at-infinity
+ */
+extern int ECP_get(BIG x,BIG y,ECP *P);
+/** @brief Adds ECP instance Q to ECP instance P
+ *
+ @param P ECP instance, on exit =P+Q
+ @param Q ECP instance to be added to P
+ */
+extern void ECP_add(ECP *P,ECP *Q);
+/** @brief Subtracts ECP instance Q from ECP instance P
+ *
+ @param P ECP instance, on exit =P-Q
+ @param Q ECP instance to be subtracted from P
+ */
+extern void ECP_sub(ECP *P,ECP *Q);
+#endif
+/** @brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+ @param P ECP instance to be converted to affine form
+ */
+extern void ECP_affine(ECP *P);
+/** @brief Formats and outputs an ECP point to the console, in projective coordinates
+ *
+ @param P ECP instance to be printed
+ */
+extern void ECP_outputxyz(ECP *P);
+/** @brief Formats and outputs an ECP point to the console, converted to affine coordinates
+ *
+ @param P ECP instance to be printed
+ */
+extern void ECP_output(ECP * P);
+/** @brief Formats and outputs an ECP point to an octet string
+ *
+ The octet string is created in the standard form 04|x|y, except for Montgomery curve in which case it is 06|x
+ Here x (and y) are the x and y coordinates in big-endian base 256 form.
+ @param S output octet string
+ @param P ECP instance to be converted to an octet string
+ */
+extern void ECP_toOctet(octet *S,ECP *P);
+/** @brief Creates an ECP point from an octet string
+ *
+ The octet string is in the standard form 0x04|x|y, except for Montgomery curve in which case it is 0x06|x
+ Here x (and y) are the x and y coordinates in left justified big-endian base 256 form.
+ @param P ECP instance to be created from the octet string
+ @param S input octet string
+ return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP_fromOctet(ECP *P,octet *S);
+/** @brief Doubles an ECP instance P
+ *
+ @param P ECP instance, on exit =2*P
+ */
+extern void ECP_dbl(ECP *P);
+/** @brief Multiplies an ECP instance P by a small integer, side-channel resistant
+ *
+ @param P ECP instance, on exit =i*P
+ @param i small integer multiplier
+ @param b maximum number of bits in multiplier
+ */
+extern void ECP_pinmul(ECP *P,int i,int b);
+/** @brief Multiplies an ECP instance P by a BIG, side-channel resistant
+ *
+ Uses Montgomery ladder for Montgomery curves, otherwise fixed sized windows.
+ @param P ECP instance, on exit =b*P
+ @param b BIG number multiplier
+
+ */
+extern void ECP_mul(ECP *P,BIG b);
+/** @brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
+ *
+ @param P ECP instance, on exit =e*P+f*Q
+ @param Q ECP instance
+ @param e BIG number multiplier
+ @param f BIG number multiplier
+ */
+extern void ECP_mul2(ECP *P,ECP *Q,BIG e,BIG f);
+
+
+
+/* ECP2 E(Fp2) prototypes */
+/** @brief Tests for ECP2 point equal to infinity
+ *
+ @param P ECP2 point to be tested
+ @return 1 if infinity, else returns 0
+ */
+extern int ECP2_isinf(ECP2 *P);
+/** @brief Copy ECP2 point to another ECP2 point
+ *
+ @param P ECP2 instance, on exit = Q
+ @param Q ECP2 instance to be copied
+ */
+extern void ECP2_copy(ECP2 *P,ECP2 *Q);
+/** @brief Set ECP2 to point-at-infinity
+ *
+ @param P ECP2 instance to be set to infinity
+ */
+extern void ECP2_inf(ECP2 *P);
+/** @brief Tests for equality of two ECP2s
+ *
+ @param P ECP2 instance to be compared
+ @param Q ECP2 instance to be compared
+ @return 1 if P=Q, else returns 0
+ */
+extern int ECP2_equals(ECP2 *P,ECP2 *Q);
+/** @brief Converts an ECP2 point from Projective (x,y,z) coordinates to affine (x,y) coordinates
+ *
+ @param P ECP2 instance to be converted to affine form
+ */
+extern void ECP2_affine(ECP2 *P);
+/** @brief Extract x and y coordinates of an ECP2 point P
+ *
+ If x=y, returns only x
+ @param x FP2 on exit = x coordinate of point
+ @param y FP2 on exit = y coordinate of point (unless x=y)
+ @param P ECP2 instance (x,y)
+ @return -1 if P is point-at-infinity, else 0
+ */
+extern int ECP2_get(FP2 *x,FP2 *y,ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to the console, converted to affine coordinates
+ *
+ @param P ECP2 instance to be printed
+ */
+extern void ECP2_output(ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to the console, in projective coordinates
+ *
+ @param P ECP2 instance to be printed
+ */
+extern void ECP2_outputxyz(ECP2 *P);
+/** @brief Formats and outputs an ECP2 point to an octet string
+ *
+ The octet string is created in the form x|y.
+ Convert the real and imaginary parts of the x and y coordinates to big-endian base 256 form.
+ @param S output octet string
+ @param P ECP2 instance to be converted to an octet string
+ */
+extern void ECP2_toOctet(octet *S,ECP2 *P);
+/** @brief Creates an ECP2 point from an octet string
+ *
+ The octet string is in the form x|y
+ The real and imaginary parts of the x and y coordinates are in big-endian base 256 form.
+ @param P ECP2 instance to be created from the octet string
+ @param S input octet string
+ return 1 if octet string corresponds to a point on the curve, else 0
+ */
+extern int ECP2_fromOctet(ECP2 *P,octet *S);
+/** @brief Calculate Right Hand Side of curve equation y^2=f(x)
+ *
+ Function f(x)=x^3+Ax+B
+ Used internally.
+ @param r FP2 value of f(x)
+ @param x FP2 instance
+ */
+extern void ECP2_rhs(FP2 *r,FP2 *x);
+/** @brief Set ECP2 to point(x,y) given x and y
+ *
+ Point P set to infinity if no such point on the curve.
+ @param P ECP2 instance to be set (x,y)
+ @param x FP2 x coordinate of point
+ @param y FP2 y coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP2_set(ECP2 *P,FP2 *x,FP2 *y);
+/** @brief Set ECP to point(x,[y]) given x
+ *
+ Point P set to infinity if no such point on the curve. Otherwise y coordinate is calculated from x.
+ @param P ECP instance to be set (x,[y])
+ @param x BIG x coordinate of point
+ @return 1 if point exists, else 0
+ */
+extern int ECP2_setx(ECP2 *P,FP2 *x);
+/** @brief Negation of an ECP2 point
+ *
+ @param P ECP2 instance, on exit = -P
+ */
+extern void ECP2_neg(ECP2 *P);
+/** @brief Doubles an ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =2*P
+ */
+extern int ECP2_dbl(ECP2 *P);
+/** @brief Adds ECP2 instance Q to ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =P+Q
+ @param Q ECP2 instance to be added to P
+ */
+extern int ECP2_add(ECP2 *P,ECP2 *Q);
+/** @brief Subtracts ECP instance Q from ECP2 instance P
+ *
+ @param P ECP2 instance, on exit =P-Q
+ @param Q ECP2 instance to be subtracted from P
+ */
+extern void ECP2_sub(ECP2 *P,ECP2 *Q);
+/** @brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
+ *
+ Uses fixed sized windows.
+ @param P ECP2 instance, on exit =b*P
+ @param b BIG number multiplier
+
+ */
+extern void ECP2_mul(ECP2 *P,BIG b);
+/** @brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
+ *
+ Fast point multiplication using Frobenius
+ @param P ECP2 instance, on exit = p*P
+ @param f FP2 precalculated Frobenius constant
+
+ */
+extern void ECP2_frob(ECP2 *P,FP2 *f);
+/** @brief Calculates P=b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ *
+ @param P ECP2 instance, on exit = b[0]*Q[0]+b[1]*Q[1]+b[2]*Q[2]+b[3]*Q[3]
+ @param Q ECP2 array of 4 points
+ @param b BIG array of 4 multipliers
+ */
+extern void ECP2_mul4(ECP2 *P,ECP2 *Q,BIG *b);
+
+
+
+/* FP4 prototypes */
+/** @brief Tests for FP4 equal to zero
+ *
+ @param x FP4 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP4_iszilch(FP4 *x);
+/** @brief Tests for FP4 equal to unity
+ *
+ @param x FP4 number to be tested
+ @return 1 if unity, else returns 0
+ */
+extern int FP4_isunity(FP4 *x);
+/** @brief Tests for equality of two FP4s
+ *
+ @param x FP4 instance to be compared
+ @param y FP4 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP4_equals(FP4 *x,FP4 *y);
+/** @brief Tests for FP4 having only a real part and no imaginary part
+ *
+ @param x FP4 number to be tested
+ @return 1 if real, else returns 0
+ */
+extern int FP4_isreal(FP4 *x);
+/** @brief Initialise FP4 from two FP2s
+ *
+ @param x FP4 instance to be initialised
+ @param a FP2 to form real part of FP4
+ @param b FP2 to form imaginary part of FP4
+ */
+extern void FP4_from_FP2s(FP4 *x,FP2 *a,FP2 *b);
+/** @brief Initialise FP4 from single FP2
+ *
+ Imaginary part is set to zero
+ @param x FP4 instance to be initialised
+ @param a FP2 to form real part of FP4
+ */
+extern void FP4_from_FP2(FP4 *x,FP2 *a);
+/** @brief Copy FP4 to another FP4
+ *
+ @param x FP4 instance, on exit = y
+ @param y FP4 instance to be copied
+ */
+extern void FP4_copy(FP4 *x,FP4 *y);
+/** @brief Set FP4 to zero
+ *
+ @param x FP4 instance to be set to zero
+ */
+extern void FP4_zero(FP4 *x);
+/** @brief Set FP4 to unity
+ *
+ @param x FP4 instance to be set to one
+ */
+extern void FP4_one(FP4 *x);
+/** @brief Negation of FP4
+ *
+ @param x FP4 instance, on exit = -y
+ @param y FP4 instance
+ */
+extern void FP4_neg(FP4 *x,FP4 *y);
+/** @brief Conjugation of FP4
+ *
+ If y=(a,b) on exit x=(a,-b)
+ @param x FP4 instance, on exit = conj(y)
+ @param y FP4 instance
+ */
+extern void FP4_conj(FP4 *x,FP4 *y);
+/** @brief Negative conjugation of FP4
+ *
+ If y=(a,b) on exit x=(-a,b)
+ @param x FP4 instance, on exit = -conj(y)
+ @param y FP4 instance
+ */
+extern void FP4_nconj(FP4 *x,FP4 *y);
+/** @brief addition of two FP4s
+ *
+ @param x FP4 instance, on exit = y+z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_add(FP4 *x,FP4 *y,FP4 *z);
+/** @brief subtraction of two FP4s
+ *
+ @param x FP4 instance, on exit = y-z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_sub(FP4 *x,FP4 *y,FP4 *z);
+/** @brief Multiplication of an FP4 by an FP2
+ *
+ @param x FP4 instance, on exit = y*a
+ @param y FP4 instance
+ @param a FP2 multiplier
+ */
+extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
+/** @brief Multiplication of an FP4 by a small integer
+ *
+ @param x FP4 instance, on exit = y*i
+ @param y FP4 instance
+ @param i an integer
+ */
+extern void FP4_imul(FP4 *x,FP4 *y,int i);
+/** @brief Squaring an FP4
+ *
+ @param x FP4 instance, on exit = y^2
+ @param y FP4 instance
+ */
+extern void FP4_sqr(FP4 *x,FP4 *y);
+/** @brief Multiplication of two FP4s
+ *
+ @param x FP4 instance, on exit = y*z
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_mul(FP4 *x,FP4 *y,FP4 *z);
+/** @brief Inverting an FP4
+ *
+ @param x FP4 instance, on exit = 1/y
+ @param y FP4 instance
+ */
+extern void FP4_inv(FP4 *x,FP4 *y);
+/** @brief Formats and outputs an FP4 to the console
+ *
+ @param x FP4 instance to be printed
+ */
+extern void FP4_output(FP4 *x);
+/** @brief Formats and outputs an FP4 to the console in raw form (for debugging)
+ *
+ @param x FP4 instance to be printed
+ */
+extern void FP4_rawoutput(FP4 *x);
+/** @brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+ *
+ @param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
+ */
+extern void FP4_times_i(FP4 *x);
+/** @brief Normalises the components of an FP4
+ *
+ @param x FP4 instance to be normalised
+ */
+extern void FP4_norm(FP4 *x);
+/** @brief Reduces all components of possibly unreduced FP4 mod Modulus
+ *
+ @param x FP4 instance, on exit reduced mod Modulus
+ */
+extern void FP4_reduce(FP4 *x);
+/** @brief Raises an FP4 to the power of a BIG
+ *
+ @param x FP4 instance, on exit = y^b
+ @param y FP4 instance
+ @param b BIG number
+ */
+extern void FP4_pow(FP4 *x,FP4 *y,BIG b);
+/** @brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
+ *
+ @param x FP4 instance, on exit = x^p
+ @param f FP2 precalculated Frobenius constant
+ */
+extern void FP4_frob(FP4 *x,FP2 *f);
+/** @brief Calculates the XTR addition function r=w*x-conj(x)*y+z
+ *
+ @param r FP4 instance, on exit = w*x-conj(x)*y+z
+ @param w FP4 instance
+ @param x FP4 instance
+ @param y FP4 instance
+ @param z FP4 instance
+ */
+extern void FP4_xtr_A(FP4 *r,FP4 *w,FP4 *x,FP4 *y,FP4 *z);
+/** @brief Calculates the XTR doubling function r=x^2-2*conj(x)
+ *
+ @param r FP4 instance, on exit = x^2-2*conj(x)
+ @param x FP4 instance
+ */
+extern void FP4_xtr_D(FP4 *r,FP4 *x);
+/** @brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
+ *
+ XTR single exponentiation
+ @param r FP4 instance, on exit = trace(w^b)
+ @param x FP4 instance, trace of an FP12 w
+ @param b BIG number
+ */
+extern void FP4_xtr_pow(FP4 *r,FP4 *x,BIG b);
+/** @brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
+ *
+ XTR double exponentiation
+ Assumes c=tr(x^m), d=tr(x^n), e=tr(x^(m-n)), f=tr(x^(m-2n))
+ @param r FP4 instance, on exit = trace(c^a.d^b)
+ @param c FP4 instance, trace of an FP12
+ @param d FP4 instance, trace of an FP12
+ @param e FP4 instance, trace of an FP12
+ @param f FP4 instance, trace of an FP12
+ @param a BIG number
+ @param b BIG number
+ */
+extern void FP4_xtr_pow2(FP4 *r,FP4 *c,FP4 *d,FP4 *e,FP4 *f,BIG a,BIG b);
+
+
+
+/* FP12 prototypes */
+/** @brief Tests for FP12 equal to zero
+ *
+ @param x FP12 number to be tested
+ @return 1 if zero, else returns 0
+ */
+extern int FP12_iszilch(FP12 *x);
+/** @brief Tests for FP12 equal to unity
+ *
+ @param x FP12 number to be tested
+ @return 1 if unity, else returns 0
+ */
+extern int FP12_isunity(FP12 *x);
+/** @brief Copy FP12 to another FP12
+ *
+ @param x FP12 instance, on exit = y
+ @param y FP12 instance to be copied
+ */
+extern void FP12_copy(FP12 *x,FP12 *y);
+/** @brief Set FP12 to unity
+ *
+ @param x FP12 instance to be set to one
+ */
+extern void FP12_one(FP12 *x);
+/** @brief Tests for equality of two FP12s
+ *
+ @param x FP12 instance to be compared
+ @param y FP12 instance to be compared
+ @return 1 if x=y, else returns 0
+ */
+extern int FP12_equals(FP12 *x,FP12 *y);
+/** @brief Conjugation of FP12
+ *
+ If y=(a,b,c) (where a,b,c are its three FP4 components) on exit x=(conj(a),-conj(b),conj(c))
+ @param x FP12 instance, on exit = conj(y)
+ @param y FP12 instance
+ */
+extern void FP12_conj(FP12 *x,FP12 *y);
+/** @brief Initialise FP12 from single FP4
+ *
+ Sets first FP4 component of an FP12, other components set to zero
+ @param x FP12 instance to be initialised
+ @param a FP4 to form first part of FP4
+ */
+extern void FP12_from_FP4(FP12 *x,FP4 *a);
+/** @brief Initialise FP12 from three FP4s
+ *
+ @param x FP12 instance to be initialised
+ @param a FP4 to form first part of FP12
+ @param b FP4 to form second part of FP12
+ @param c FP4 to form third part of FP12
+ */
+extern void FP12_from_FP4s(FP12 *x,FP4 *a,FP4* b,FP4 *c);
+/** @brief Fast Squaring of an FP12 in "unitary" form
+ *
+ @param x FP12 instance, on exit = y^2
+ @param y FP4 instance, must be unitary
+ */
+extern void FP12_usqr(FP12 *x,FP12 *y);
+/** @brief Squaring an FP12
+ *
+ @param x FP12 instance, on exit = y^2
+ @param y FP12 instance
+ */
+extern void FP12_sqr(FP12 *x,FP12 *y);
+/** @brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+ *
+ Here the multiplier has a special form that can be exploited
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, of special form
+ */
+extern void FP12_smul(FP12 *x,FP12 *y);
+/** @brief Multiplication of two FP12s
+ *
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, the multiplier
+ */
+extern void FP12_mul(FP12 *x,FP12 *y);
+/** @brief Inverting an FP12
+ *
+ @param x FP12 instance, on exit = 1/y
+ @param y FP12 instance
+ */
+extern void FP12_inv(FP12 *x,FP12 *y);
+/** @brief Raises an FP12 to the power of a BIG
+ *
+ @param r FP12 instance, on exit = y^b
+ @param x FP12 instance
+ @param b BIG number
+ */
+extern void FP12_pow(FP12 *r,FP12 *x,BIG b);
+/** @brief Raises an FP12 instance x to a small integer power, side-channel resistant
+ *
+ @param x ECP instance, on exit = x^i
+ @param i small integer exponent
+ @param b maximum number of bits in exponent
+ */
+extern void FP12_pinpow(FP12 *x,int i,int b);
+/** @brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
+ *
+ @param r ECP instance, on exit = x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3]
+ @param x FP12 array with 4 FP12s
+ @param b BIG array of 4 exponents
+ */
+extern void FP12_pow4(FP12 *r,FP12 *x,BIG *b);
+/** @brief Raises an FP12 to the power of the internal modulus p, using the Frobenius
+ *
+ @param x FP12 instance, on exit = x^p
+ @param f FP2 precalculated Frobenius constant
+ */
+extern void FP12_frob(FP12 *x,FP2 *f);
+/** @brief Reduces all components of possibly unreduced FP12 mod Modulus
+ *
+ @param x FP12 instance, on exit reduced mod Modulus
+ */
+extern void FP12_reduce(FP12 *x);
+/** @brief Normalises the components of an FP12
+ *
+ @param x FP12 instance to be normalised
+ */
+extern void FP12_norm(FP12 *x);
+/** @brief Formats and outputs an FP12 to the console
+ *
+ @param x FP12 instance to be printed
+ */
+extern void FP12_output(FP12 *x);
+/** @brief Formats and outputs an FP12 instance to an octet string
+ *
+ Serializes the components of an FP12 to big-endian base 256 form.
+ @param S output octet string
+ @param x FP12 instance to be converted to an octet string
+ */
+extern void FP12_toOctet(octet *S,FP12 *x);
+/** @brief Creates an FP12 instance from an octet string
+ *
+ De-serializes the components of an FP12 to create an FP12 from big-endian base 256 components.
+ @param x FP12 instance to be created from an octet string
+ @param S input octet string
+
+ */
+extern void FP12_fromOctet(FP12 *x,octet *S);
+/** @brief Calculate the trace of an FP12
+ *
+ @param t FP4 trace of x, on exit = tr(x)
+ @param x FP12 instance
+
+ */
+extern void FP12_trace(FP4 *t,FP12 *x);
+
+
+
+/* Pairing function prototypes */
+/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
+ *
+ @param r FP12 result of the pairing calculation e(P,Q)
+ @param P ECP2 instance, an element of G2
+ @param Q ECP instance, an element of G1
+
+ */
+extern void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q);
+/** @brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+ *
+ Faster than calculating two separate pairings
+ @param r FP12 result of the pairing calculation e(P,Q).e(R,S), an element of GT
+ @param P ECP2 instance, an element of G2
+ @param Q ECP instance, an element of G1
+ @param R ECP2 instance, an element of G2
+ @param S ECP instance, an element of G1
+ */
+extern void PAIR_double_ate(FP12 *r,ECP2 *P,ECP *Q,ECP2 *R,ECP *S);
+/** @brief Final exponentiation of pairing, converts output of Miller loop to element in GT
+ *
+ Here p is the internal modulus, and r is the group order
+ @param x FP12, on exit = x^((p^12-1)/r)
+ */
+extern void PAIR_fexp(FP12 *x);
+/** @brief Fast point multiplication of a member of the group G1 by a BIG number
+ *
+ May exploit endomorphism for speed.
+ @param Q ECP member of G1.
+ @param b BIG multiplier
+
+ */
+extern void PAIR_G1mul(ECP *Q,BIG b);
+/** @brief Fast point multiplication of a member of the group G2 by a BIG number
+ *
+ May exploit endomorphism for speed.
+ @param P ECP2 member of G1.
+ @param b BIG multiplier
+
+ */
+extern void PAIR_G2mul(ECP2 *P,BIG b);
+/** @brief Fast raising of a member of GT to a BIG power
+ *
+ May exploit endomorphism for speed.
+ @param x FP12 member of GT.
+ @param b BIG exponent
+
+ */
+extern void PAIR_GTpow(FP12 *x,BIG b);
+/** @brief Tests FP12 for membership of GT
+ *
+ @param x FP12 instance
+ @return 1 if x is in GT, else return 0
+
+ */
+extern int PAIR_GTmember(FP12 *x);
+
+
+
+/* Finite Field Prototypes */
+/** @brief Copy one FF element of given length to another
+ *
+ @param x FF instance to be copied to, on exit = y
+ @param y FF instance to be copied from
+ @param n size of FF in BIGs
+
+ */
+extern void FF_copy(BIG *x,BIG *y,int n);
+/** @brief Initialize an FF element of given length from a 32-bit integer m
+ *
+ @param x FF instance to be copied to, on exit = m
+ @param m integer
+ @param n size of FF in BIGs
+ */
+extern void FF_init(BIG *x,sign32 m,int n);
+/** @brief Set FF element of given size to zero
+ *
+ @param x FF instance to be set to zero
+ @param n size of FF in BIGs
+ */
+extern void FF_zero(BIG *x,int n);
+/** @brief Tests for FF element equal to zero
+ *
+ @param x FF number to be tested
+ @param n size of FF in BIGs
+ @return 1 if zero, else returns 0
+ */
+extern int FF_iszilch(BIG *x,int n);
+/** @brief return parity of an FF, that is the least significant bit
+ *
+ @param x FF number
+ @return 0 or 1
+ */
+extern int FF_parity(BIG *x);
+/** @brief return least significant m bits of an FF
+ *
+ @param x FF number
+ @param m number of bits to return. Assumed to be less than BASEBITS.
+ @return least significant n bits as an integer
+ */
+extern int FF_lastbits(BIG *x,int m);
+/** @brief Set FF element of given size to unity
+ *
+ @param x FF instance to be set to unity
+ @param n size of FF in BIGs
+ */
+extern void FF_one(BIG *x,int n);
+/** @brief Compares two FF numbers. Inputs must be normalised externally
+ *
+ @param x first FF number to be compared
+ @param y second FF number to be compared
+ @param n size of FF in BIGs
+ @return -1 is x<y, 0 if x=y, 1 if x>y
+ */
+extern int FF_comp(BIG *x,BIG *y,int n);
+/** @brief addition of two FFs
+ *
+ @param x FF instance, on exit = y+z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_add(BIG *x,BIG *y,BIG *z,int n);
+/** @brief subtraction of two FFs
+ *
+ @param x FF instance, on exit = y-z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_sub(BIG *x,BIG *y,BIG *z,int n);
+/** @brief increment an FF by an integer,and normalise
+ *
+ @param x FF instance, on exit = x+m
+ @param m an integer to be added to x
+ @param n size of FF in BIGs
+ */
+extern void FF_inc(BIG *x,int m,int n);
+/** @brief Decrement an FF by an integer,and normalise
+ *
+ @param x FF instance, on exit = x-m
+ @param m an integer to be subtracted from x
+ @param n size of FF in BIGs
+ */
+extern void FF_dec(BIG *x,int m,int n);
+/** @brief Normalises the components of an FF
+ *
+ @param x FF instance to be normalised
+ @param n size of FF in BIGs
+ */
+extern void FF_norm(BIG *x,int n);
+/** @brief Shift left an FF by 1 bit
+ *
+ @param x FF instance to be shifted left
+ @param n size of FF in BIGs
+ */
+extern void FF_shl(BIG *x,int n);
+/** @brief Shift right an FF by 1 bit
+ *
+ @param x FF instance to be shifted right
+ @param n size of FF in BIGs
+ */
+extern void FF_shr(BIG *x,int n);
+/** @brief Formats and outputs an FF to the console
+ *
+ @param x FF instance to be printed
+ @param n size of FF in BIGs
+ */
+extern void FF_output(BIG *x,int n);
+/** @brief Formats and outputs an FF instance to an octet string
+ *
+ Converts an FF to big-endian base 256 form.
+ @param S output octet string
+ @param x FF instance to be converted to an octet string
+ @param n size of FF in BIGs
+ */
+extern void FF_toOctet(octet *S,BIG *x,int n);
+/** @brief Populates an FF instance from an octet string
+ *
+ Creates FF from big-endian base 256 form.
+ @param x FF instance to be created from an octet string
+ @param S input octet string
+ @param n size of FF in BIGs
+ */
+extern void FF_fromOctet(BIG *x,octet *S,int n);
+/** @brief Multiplication of two FFs
+ *
+ Uses Karatsuba method internally
+ @param x FF instance, on exit = y*z
+ @param y FF instance
+ @param z FF instance
+ @param n size of FF in BIGs
+ */
+extern void FF_mul(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Reduce FF mod a modulus
+ *
+ This is slow
+ @param x FF instance to be reduced mod m - on exit = x mod m
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_mod(BIG *x,BIG *m,int n);
+/** @brief Square an FF
+ *
+ Uses Karatsuba method internally
+ @param x FF instance, on exit = y^2
+ @param y FF instance to be squared
+ @param n size of FF in BIGs
+ */
+extern void FF_sqr(BIG *x,BIG *y,int n);
+/** @brief Reduces a double-length FF with respect to a given modulus
+ *
+ This is slow
+ @param x FF instance, on exit = y mod z
+ @param y FF instance, of double length 2*n
+ @param z FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_dmod(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Invert an FF mod a prime modulus
+ *
+ @param x FF instance, on exit = 1/y mod z
+ @param y FF instance
+ @param z FF prime modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_invmodp(BIG *x,BIG *y,BIG *z,int n);
+/** @brief Create an FF from a random number generator
+ *
+ @param x FF instance, on exit x is a random number of length n BIGs with most significant bit a 1
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ */
+extern void FF_random(BIG *x,csprng *R,int n);
+/** @brief Create a random FF less than a given modulus from a random number generator
+ *
+ @param x FF instance, on exit x is a random number < y
+ @param y FF instance, the modulus
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ */
+extern void FF_randomnum(BIG *x,BIG *y,csprng *R,int n);
+/** @brief Calculate r=x^e mod m, side channel resistant
+ *
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e FF exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_skpow(BIG *r,BIG *x,BIG * e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m, side channel resistant
+ *
+ For short BIG exponent
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e BIG exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_skspow(BIG *r,BIG *x,BIG e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m
+ *
+ For very short integer exponent
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e integer exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_power(BIG *r,BIG *x,int e,BIG *m,int n);
+/** @brief Calculate r=x^e mod m
+ *
+ @param r FF instance, on exit = x^e mod p
+ @param x FF instance
+ @param e FF exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_pow(BIG *r,BIG *x,BIG *e,BIG *m,int n);
+/** @brief Test if an FF has factor in common with integer s
+ *
+ @param x FF instance to be tested
+ @param s the supplied integer
+ @param n size of FF in BIGs
+ @return 1 if gcd(x,s)!=1, else return 0
+ */
+extern int FF_cfactor(BIG *x,sign32 s,int n);
+/** @brief Test if an FF is prime
+ *
+ Uses Miller-Rabin Method
+ @param x FF instance to be tested
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n size of FF in BIGs
+ @return 1 if x is (almost certainly) prime, else return 0
+ */
+extern int FF_prime(BIG *x,csprng *R,int n);
+/** @brief Calculate r=x^e.y^f mod m
+ *
+ @param r FF instance, on exit = x^e.y^f mod p
+ @param x FF instance
+ @param e BIG exponent
+ @param y FF instance
+ @param f BIG exponent
+ @param m FF modulus
+ @param n size of FF in BIGs
+ */
+extern void FF_pow2(BIG *r,BIG *x,BIG e,BIG *y,BIG f,BIG *m,int n);
+
+
+/* Octet string handlers */
+/** @brief Formats and outputs an octet to the console in hex
+ *
+ @param O Octet to be output
+ */
+extern void OCT_output(octet *O);
+/** @brief Formats and outputs an octet to the console as a character string
+ *
+ @param O Octet to be output
+ */
+extern void OCT_output_string(octet *O);
+/** @brief Wipe clean an octet
+ *
+ @param O Octet to be cleaned
+ */
+extern void OCT_clear(octet *O);
+/** @brief Compare two octets
+ *
+ @param O first Octet to be compared
+ @param P second Octet to be compared
+ @return 1 if equal, else 0
+ */
+extern int OCT_comp(octet *O,octet *P);
+/** @brief Compare first n bytes of two octets
+ *
+ @param O first Octet to be compared
+ @param P second Octet to be compared
+ @param n number of bytes to compare
+ @return 1 if equal, else 0
+ */
+extern int OCT_ncomp(octet *O,octet *P,int n);
+/** @brief Join from a C string to end of an octet
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param s zero terminated string to be joined to octet
+ */
+extern void OCT_jstring(octet *O,char *s);
+/** @brief Join bytes to end of an octet
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param s bytes to be joined to end of octet
+ @param n number of bytes to join
+ */
+extern void OCT_jbytes(octet *O,char *s,int n);
+/** @brief Join single byte to end of an octet, repeated n times
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param b byte to be joined to end of octet
+ @param n number of times b is to be joined
+ */
+extern void OCT_jbyte(octet *O,int b,int n);
+/** @brief Join one octet to the end of another
+ *
+ Truncates if there is no room
+ @param O Octet to be written to
+ @param P Octet to be joined to the end of O
+ */
+extern void OCT_joctet(octet *O,octet *P);
+/** @brief XOR common bytes of a pair of Octets
+ *
+ @param O Octet - on exit = O xor P
+ @param P Octet to be xored into O
+ */
+extern void OCT_xor(octet *O,octet *P);
+/** @brief reset Octet to zero length
+ *
+ @param O Octet to be emptied
+ */
+extern void OCT_empty(octet *O);
+/** @brief Pad out an Octet to the given length
+ *
+ Padding is done by inserting leading zeros, so abcd becomes 00abcd
+ @param O Octet to be padded
+ @param n new length of Octet
+ */
+extern int OCT_pad(octet *O,int n);
+/** @brief Convert an Octet to printable base64 number
+ *
+ @param b zero terminated byte array to take base64 conversion
+ @param O Octet to be converted
+ */
+extern void OCT_tobase64(char *b,octet *O);
+/** @brief Populate an Octet from base64 number
+ *
+ @param O Octet to be populated
+ @param b zero terminated base64 string
+
+ */
+extern void OCT_frombase64(octet *O,char *b);
+/** @brief Copy one Octet into another
+ *
+ @param O Octet to be copied to
+ @param P Octet to be copied from
+
+ */
+extern void OCT_copy(octet *O,octet *P);
+/** @brief XOR every byte of an octet with input m
+ *
+ @param O Octet
+ @param m byte to be XORed with every byte of O
+
+ */
+extern void OCT_xorbyte(octet *O,int m);
+/** @brief Chops Octet into two, leaving first n bytes in O, moving the rest to P
+ *
+ @param O Octet to be chopped
+ @param P new Octet to be created
+ @param n number of bytes to chop off O
+
+ */
+extern void OCT_chop(octet *O,octet *P,int n);
+/** @brief Join n bytes of integer m to end of Octet O (big endian)
+ *
+ Typically n is 4 for a 32-bit integer
+ @param O Octet to be appended to
+ @param m integer to be appended to O
+ @param n number of bytes in m
+
+ */
+extern void OCT_jint(octet *O,int m,int n);
+/** @brief Create an Octet from bytes taken from a random number generator
+ *
+ Truncates if there is no room
+ @param O Octet to be populated
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n number of bytes to extracted from R
+
+ */
+extern void OCT_rand(octet *O,csprng *R,int n);
+/** @brief Shifts Octet left by n bytes
+ *
+ Leftmost bytes disappear
+ @param O Octet to be shifted
+ @param n number of bytes to shift
+
+ */
+extern void OCT_shl(octet *O,int n);
+/** @brief Convert an Octet to printable hex number
+ *
+ @param dst hex value
+ @param src Octet to be converted
+ */
+extern void OCT_toHex(octet *src,char *dst);
+/** @brief Convert an Octet to string
+ *
+ @param dst string value
+ @param src Octet to be converted
+ */
+extern void OCT_toStr(octet *src,char *dst);
+
+
+
+/* Hash function */
+/** @brief Initialise an instance of SHA256
+ *
+ @param H an instance SHA256
+ */
+extern void HASH_init(hash *H);
+/** @brief Add a byte to the hash
+ *
+ @param H an instance SHA256
+ @param b byte to be included in hash
+ */
+extern void HASH_process(hash *H,int b);
+/** @brief Generate 32-byte hash
+ *
+ @param H an instance SHA256
+ @param h is the output 32-byte hash
+ */
+extern void HASH_hash(hash *H,char *h);
+
+
+
+/* AES functions */
+/** @brief Reset AES mode or IV
+ *
+ @param A an instance of the AES
+ @param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
+ @param iv the new Initialisation Vector
+ */
+extern void AES_reset(aes *A,int m,char *iv);
+/** @brief Extract chaining vector from AES instance
+ *
+ @param A an instance of the AES
+ @param f the extracted chaining vector
+ */
+extern void AES_getreg(aes *A,char * f);
+/** @brief Initialise an instance of AES and its mode of operation
+ *
+ @param A an instance AES
+ @param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+ @param k the AES key as an array of 16 bytes
+ @param iv the Initialisation Vector
+ */
+extern void AES_init(aes *A,int m,char *k,char *iv);
+/** @brief Encrypt a single 16 byte block in ECB mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ */
+extern void AES_ecb_encrypt(aes *A,uchar * b);
+/** @brief Decrypt a single 16 byte block in ECB mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 cipherext bytes, on exit becomes plaintext
+ */
+extern void AES_ecb_decrypt(aes *A,uchar * b);
+/** @brief Encrypt a single 16 byte block in active mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 plaintext bytes, on exit becomes ciphertext
+ @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_encrypt(aes *A,char *b );
+/** @brief Decrypt a single 16 byte block in active mode
+ *
+ @param A an instance of the AES
+ @param b is an array of 16 ciphertext bytes, on exit becomes plaintext
+ @return 0, or overflow bytes from CFB mode
+ */
+extern unsign32 AES_decrypt(aes *A,char *b);
+/** @brief Clean up after application of AES
+ *
+ @param A an instance of the AES
+ */
+extern void AES_end(aes *A);
+
+
+/* AES-GCM functions */
+/** @brief Initialise an instance of AES-GCM mode
+ *
+ @param G an instance AES-GCM
+ @param k the AES key as an array of 16 bytes
+ @param n the number of bytes in the Initialisation Vector (IV)
+ @param iv the IV
+ */
+extern void GCM_init(gcm *G,char *k,int n,char *iv);
+/** @brief Add header (material to be authenticated but not encrypted)
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param b is the header material to be added
+ @param n the number of bytes in the header
+ */
+extern int GCM_add_header(gcm *G,char *b,int n);
+/** @brief Add plaintext and extract ciphertext
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param c is the ciphertext generated
+ @param p is the plaintext material to be added
+ @param n the number of bytes in the plaintext
+ */
+extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
+/** @brief Add ciphertext and extract plaintext
+ *
+ Note that this function can be called any number of times with n a multiple of 16, and then one last time with any value for n
+ @param G an instance AES-GCM
+ @param p is the plaintext generated
+ @param c is the ciphertext material to be added
+ @param n the number of bytes in the ciphertext
+ */
+extern int GCM_add_cipher(gcm *G,char *p,char *c,int n);
+/** @brief Finish off and extract authentication tag (HMAC)
+ *
+ @param G is an active instance AES-GCM
+ @param t is the output 16 byte authentication tag
+ */
+extern void GCM_finish(gcm *G,char *t);
+
+
+
+/* random numbers */
+/** @brief Seed a random number generator from an array of bytes
+ *
+ The provided seed should be truly random
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @param n the number of seed bytes provided
+ @param b an array of seed bytes
+
+ */
+extern void RAND_seed(csprng *R,int n,char *b);
+/** @brief Delete all internal state of a random number generator
+ *
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ */
+extern void RAND_clean(csprng *R);
+/** @brief Return a random byte from a random number generator
+ *
+ @param R an instance of a Cryptographically Secure Random Number Generator
+ @return a random byte
+ */
+extern int RAND_byte(csprng *R);
+
+#endif
diff --git a/c/big.c b/c/big.c
new file mode 100755
index 0000000..b26abc2
--- /dev/null
+++ b/c/big.c
@@ -0,0 +1,1210 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* AMCL basic functions for BIG type */
+/* SU=m, SU is Stack Usage */
+
+#include "amcl.h"
+
+/* Calculates x*y+c+*r */
+
+#ifdef dchunk
+
+/* Method required to calculate x*y+c+r, bottom half in r, top half returned */
+chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+ dchunk prod=(dchunk)x*y+c+*r;
+ *r=(chunk)prod&MASK;
+ return (chunk)(prod>>BASEBITS);
+}
+
+#else
+
+/* No integer type available that can store double the wordlength */
+/* accumulate partial products */
+
+chunk muladd(chunk x,chunk y,chunk c,chunk *r)
+{
+ chunk x0,x1,y0,y1;
+ chunk bot,top,mid,carry;
+ x0=x&HMASK;
+ x1=(x>>HBITS);
+ y0=y&HMASK;
+ y1=(y>>HBITS);
+ bot=x0*y0;
+ top=x1*y1;
+ mid=x0*y1+x1*y0;
+ x0=mid&HMASK1;
+ x1=(mid>>HBITS1);
+ bot+=x0<<HBITS; bot+=*r; bot+=c;
+
+#if HDIFF==1
+ bot+=(top&HDIFF)<<(BASEBITS-1);
+ top>>=HDIFF;
+#endif
+
+ top+=x1;
+ carry=bot>>BASEBITS;
+ bot&=MASK;
+ top+=carry;
+
+ *r=bot;
+ return top;
+}
+
+#endif
+
+/* test a=0? */
+int BIG_iszilch(BIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ if (a[i]!=0) return 0;
+ return 1;
+}
+
+/* test a=0? */
+int BIG_diszilch(DBIG a)
+{
+ int i;
+ for (i=0;i<DNLEN;i++)
+ if (a[i]!=0) return 0;
+ return 1;
+}
+
+/* SU= 56 */
+/* output a */
+void BIG_output(BIG a)
+{
+ BIG b;
+ int i,len;
+ len=BIG_nbits(a);
+ if (len%4==0) len/=4;
+ else {len/=4; len++;}
+ if (len<MODBYTES*2) len=MODBYTES*2;
+
+ for (i=len-1;i>=0;i--)
+ {
+ BIG_copy(b,a);
+ BIG_shr(b,i*4);
+ printf("%01x",(unsigned int) b[0]&15);
+ }
+}
+
+/* SU= 16 */
+void BIG_rawoutput(BIG a)
+{
+ int i;
+ printf("(");
+ for (i=0;i<NLEN-1;i++)
+ printf("%llx,",(long long unsigned int) a[i]);
+ printf("%llx)",(long long unsigned int) a[NLEN-1]);
+}
+
+/* Swap a and b if d=1 */
+void BIG_cswap(BIG a,BIG b,int d)
+{
+ int i;
+ chunk t,c=d;
+ c=~(c-1);
+#ifdef DEBUG_NORM
+ for (i=0;i<=NLEN;i++)
+#else
+ for (i=0;i<NLEN;i++)
+#endif
+ {
+ t=c&(a[i]^b[i]);
+ a[i]^=t;
+ b[i]^=t;
+ }
+}
+
+/* Move b to a if d=1 */
+void BIG_cmove(BIG f,BIG g,int d)
+{
+ int i;
+ chunk b=(chunk)-d;
+#ifdef DEBUG_NORM
+ for (i=0;i<=NLEN;i++)
+#else
+ for (i=0;i<NLEN;i++)
+#endif
+ {
+ f[i]^=(f[i]^g[i])&b;
+ }
+}
+
+/* convert BIG to/from bytes */
+/* SU= 64 */
+void BIG_toBytes(char *b,BIG a)
+{
+ int i;
+ BIG c;
+ BIG_norm(a);
+ BIG_copy(c,a);
+ for (i=MODBYTES-1;i>=0;i--)
+ {
+ b[i]=c[0]&0xff;
+ BIG_fshr(c,8);
+ }
+}
+
+/* SU= 16 */
+void BIG_fromBytes(BIG a,char *b)
+{
+ int i;
+ BIG_zero(a);
+ for (i=0;i<MODBYTES;i++)
+ {
+ BIG_fshl(a,8); a[0]+=(int)(unsigned char)b[i];
+ //BIG_inc(a,(int)(unsigned char)b[i]); BIG_norm(a);
+ }
+#ifdef DEBUG_NORM
+ a[NLEN]=0;
+#endif
+}
+
+/* SU= 88 */
+void BIG_doutput(DBIG a)
+{
+ DBIG b;
+ int i,len;
+ BIG_dnorm(a);
+ len=BIG_dnbits(a);
+ if (len%4==0) len/=4;
+ else {len/=4; len++;}
+
+ for (i=len-1;i>=0;i--)
+ {
+ BIG_dcopy(b,a);
+ BIG_dshr(b,i*4);
+ printf("%01x",(unsigned int) b[0]&15);
+ }
+}
+
+/* Copy b=a */
+void BIG_copy(BIG b,BIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ b[i]=a[i];
+#ifdef DEBUG_NORM
+ b[NLEN]=a[NLEN];
+#endif
+}
+
+/* Copy from ROM b=a */
+void BIG_rcopy(BIG b,const BIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ b[i]=a[i];
+#ifdef DEBUG_NORM
+ b[NLEN]=0;
+#endif
+}
+
+/* double length DBIG copy b=a */
+void BIG_dcopy(DBIG b,DBIG a)
+{
+ int i;
+ for (i=0;i<DNLEN;i++)
+ b[i]=a[i];
+#ifdef DEBUG_NORM
+ b[DNLEN]=a[DNLEN];
+#endif
+}
+
+/* Copy BIG to bottom half of DBIG */
+void BIG_dscopy(DBIG b,BIG a)
+{
+ int i;
+ for (i=0;i<NLEN-1;i++)
+ b[i]=a[i];
+
+ b[NLEN-1]=a[NLEN-1]&MASK; /* top word normalized */
+ b[NLEN]=a[NLEN-1]>>BASEBITS;
+
+ for (i=NLEN+1;i<DNLEN;i++) b[i]=0;
+#ifdef DEBUG_NORM
+ b[DNLEN]=a[NLEN];
+#endif
+}
+
+/* Copy BIG to top half of DBIG */
+void BIG_dsucopy(DBIG b,BIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ b[i]=0;
+ for (i=NLEN;i<DNLEN;i++)
+ b[i]=a[i-NLEN];
+#ifdef DEBUG_NORM
+ b[DNLEN]=a[NLEN];
+#endif
+}
+
+/* Copy bottom half of DBIG to BIG */
+void BIG_sdcopy(BIG b,DBIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ b[i]=a[i];
+#ifdef DEBUG_NORM
+ b[NLEN]=a[DNLEN];
+#endif
+}
+
+/* Copy top half of DBIG to BIG */
+void BIG_sducopy(BIG b,DBIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ b[i]=a[i+NLEN];
+#ifdef DEBUG_NORM
+ b[NLEN]=a[DNLEN];
+#endif
+}
+
+/* Set a=0 */
+void BIG_zero(BIG a)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ a[i]=0;
+#ifdef DEBUG_NORM
+ a[NLEN]=0;
+#endif
+}
+
+void BIG_dzero(DBIG a)
+{
+ int i;
+ for (i=0;i<DNLEN;i++)
+ a[i]=0;
+#ifdef DEBUG_NORM
+ a[DNLEN]=0;
+#endif
+}
+
+/* set a=1 */
+void BIG_one(BIG a)
+{
+ int i;
+ a[0]=1;
+ for (i=1;i<NLEN;i++)
+ a[i]=0;
+#ifdef DEBUG_NORM
+ a[NLEN]=0;
+#endif
+}
+
+
+
+/* Set c=a+b */
+/* SU= 8 */
+void BIG_add(BIG c,BIG a,BIG b)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ c[i]=a[i]+b[i];
+#ifdef DEBUG_NORM
+ c[NLEN]=a[NLEN]+b[NLEN]+1;
+ if (c[NLEN]>=NEXCESS) printf("add problem - digit overflow %d\n",c[NLEN]);
+#endif
+}
+
+/* Set c=c+d */
+void BIG_inc(BIG c,int d)
+{
+ BIG_norm(c);
+ c[0]+=(chunk)d;
+#ifdef DEBUG_NORM
+ c[NLEN]=1;
+#endif
+}
+
+/* Set c=a-b */
+/* SU= 8 */
+void BIG_sub(BIG c,BIG a,BIG b)
+{
+ int i;
+ for (i=0;i<NLEN;i++)
+ c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+ c[NLEN]=a[NLEN]+b[NLEN]+1;
+ if (c[NLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[NLEN]);
+#endif
+}
+
+/* SU= 8 */
+
+void BIG_dsub(DBIG c,DBIG a,DBIG b)
+{
+ int i;
+ for (i=0;i<DNLEN;i++)
+ c[i]=a[i]-b[i];
+#ifdef DEBUG_NORM
+ c[DNLEN]=a[DNLEN]+b[DNLEN]+1;
+ if (c[DNLEN]>=NEXCESS) printf("sub problem - digit overflow %d\n",c[DNLEN]);
+#endif
+}
+
+
+/* Set c=c-1 */
+void BIG_dec(BIG c,int d)
+{
+ BIG_norm(c);
+ c[0]-=(chunk)d;
+#ifdef DEBUG_NORM
+ c[NLEN]=1;
+#endif
+}
+
+/* multiplication r=a*c by c<=NEXCESS */
+void BIG_imul(BIG r,BIG a,int c)
+{
+ int i;
+ for (i=0;i<NLEN;i++) r[i]=a[i]*c;
+#ifdef DEBUG_NORM
+ r[NLEN]=(a[NLEN]+1)*c-1;
+ if (r[NLEN]>=NEXCESS) printf("int mul problem - digit overflow %d\n",r[NLEN]);
+#endif
+}
+
+/* multiplication r=a*c by larger integer - c<=FEXCESS */
+/* SU= 24 */
+chunk BIG_pmul(BIG r,BIG a,int c)
+{
+ int i;
+ chunk ak,carry=0;
+ BIG_norm(a);
+ for (i=0;i<NLEN;i++)
+ {
+ ak=a[i];
+ r[i]=0;
+ carry=muladd(ak,(chunk)c,carry,&r[i]);
+ }
+#ifdef DEBUG_NORM
+ r[NLEN]=0;
+#endif
+ return carry;
+}
+
+/* r/=3 */
+/* SU= 16 */
+int BIG_div3(BIG r)
+{
+ int i;
+ chunk ak,base,carry=0;
+ BIG_norm(r);
+ base=((chunk)1<<BASEBITS);
+ for (i=NLEN-1;i>=0;i--)
+ {
+ ak=(carry*base+r[i]);
+ r[i]=ak/3;
+ carry=ak%3;
+ }
+ return (int)carry;
+}
+
+/* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
+/* SU= 24 */
+void BIG_pxmul(DBIG c,BIG a,int b)
+{
+ int j;
+ chunk carry;
+ BIG_dzero(c);
+ carry=0;
+ for (j=0;j<NLEN;j++)
+ carry=muladd(a[j],(chunk)b,carry,&c[j]);
+ c[NLEN]=carry;
+#ifdef DEBUG_NORM
+ c[DNLEN]=0;
+#endif
+}
+
+/* Set c=a*b */
+/* SU= 72 */
+void BIG_mul(DBIG c,BIG a,BIG b)
+{
+ int i,j;
+ chunk carry;
+#ifdef dchunk
+ dchunk t,co;
+#endif
+
+ BIG_norm(a); /* needed here to prevent overflow from addition of partial products */
+ BIG_norm(b);
+
+/* Faster to Combafy it.. Let the compiler unroll the loops! */
+
+#ifdef COMBA
+
+ t=(dchunk)a[0]*b[0];
+ c[0]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[1]*b[0]+(dchunk)a[0]*b[1]+co;
+ c[1]=(chunk)t&MASK; co=t>>BASEBITS;
+
+ for (j=2;j<NLEN;j++)
+ {
+ t=co; for (i=0;i<=j;i++) t+=(dchunk)a[j-i]*b[i];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+
+ for (j=NLEN;j<DNLEN-2;j++)
+ {
+ t=co; for (i=j-NLEN+1;i<NLEN;i++) t+=(dchunk)a[j-i]*b[i];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+
+ t=(dchunk)a[NLEN-1]*b[NLEN-1]+co;
+ c[DNLEN-2]=(chunk)t&MASK; co=t>>BASEBITS;
+ c[DNLEN-1]=(chunk)co;
+#else
+ BIG_dzero(c);
+ for (i=0;i<NLEN;i++)
+ {
+ carry=0;
+ for (j=0;j<NLEN;j++)
+ carry=muladd(a[i],b[j],carry,&c[i+j]);
+ c[NLEN+i]=carry;
+ }
+#endif
+
+#ifdef DEBUG_NORM
+ c[DNLEN]=0;
+#endif
+}
+
+/* .. if you know the result will fit in a BIG, c must be distinct from a and b */
+/* SU= 40 */
+void BIG_smul(BIG c,BIG a,BIG b)
+{
+ int i,j;
+ chunk carry;
+ BIG_norm(a);
+ BIG_norm(b);
+
+ BIG_zero(c);
+ for (i=0;i<NLEN;i++)
+ {
+ carry=0;
+ for (j=0;j<NLEN;j++)
+ if (i+j<NLEN) carry=muladd(a[i],b[j],carry,&c[i+j]);
+ }
+#ifdef DEBUG_NORM
+ c[NLEN]=0;
+#endif
+
+}
+
+/* Set c=a*a */
+/* SU= 80 */
+void BIG_sqr(DBIG c,BIG a)
+{
+ int i,j;
+ chunk carry;
+#ifdef dchunk
+ dchunk t,co;
+#endif
+
+ BIG_norm(a);
+
+/* Note 2*a[i] in loop below and extra addition */
+
+#ifdef COMBA
+
+ t=(dchunk)a[0]*a[0];
+ c[0]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[1]*a[0]; t+=t; t+=co;
+ c[1]=(chunk)t&MASK; co=t>>BASEBITS;
+
+#if NLEN%2==1
+ for (j=2;j<NLEN-1;j+=2)
+ {
+ t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[j+1]*a[0]; for (i=1;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
+ c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+ j=NLEN-1;
+ t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+
+#else
+ for (j=2;j<NLEN;j+=2)
+ {
+ t=(dchunk)a[j]*a[0]; for (i=1;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[j+1]*a[0]; for (i=1;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
+ c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+
+#endif
+
+#if NLEN%2==1
+ j=NLEN;
+ t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co;
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ for (j=NLEN+1;j<DNLEN-2;j+=2)
+ {
+ t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[NLEN-1]*a[j-NLEN+2]; for (i=j-NLEN+3;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
+ c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+#else
+ for (j=NLEN;j<DNLEN-2;j+=2)
+ {
+ t=(dchunk)a[NLEN-1]*a[j-NLEN+1]; for (i=j-NLEN+2;i<(j+1)/2;i++) t+=(dchunk)a[j-i]*a[i]; t+=t; t+=co; t+=(dchunk)a[j/2]*a[j/2];
+ c[j]=(chunk)t&MASK; co=t>>BASEBITS;
+ t=(dchunk)a[NLEN-1]*a[j-NLEN+2]; for (i=j-NLEN+3;i<(j+2)/2;i++) t+=(dchunk)a[j+1-i]*a[i]; t+=t; t+=co;
+ c[j+1]=(chunk)t&MASK; co=t>>BASEBITS;
+ }
+
+#endif
+
+ t=(dchunk)a[NLEN-1]*a[NLEN-1]+co;
+ c[DNLEN-2]=(chunk)t&MASK; co=t>>BASEBITS;
+ c[DNLEN-1]=(chunk)co;
+
+#else
+ BIG_dzero(c);
+ for (i=0;i<NLEN;i++)
+ {
+ carry=0;
+ for (j=i+1;j<NLEN;j++)
+ carry=muladd(a[i],a[j],carry,&c[i+j]);
+ c[NLEN+i]=carry;
+ }
+
+ for (i=0;i<DNLEN;i++) c[i]*=2;
+
+ for (i=0;i<NLEN;i++)
+ c[2*i+1]+=muladd(a[i],a[i],0,&c[2*i]);
+
+ BIG_dnorm(c);
+#endif
+
+
+#ifdef DEBUG_NORM
+ c[DNLEN]=0;
+#endif
+
+}
+
+/* General shift left of a by n bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_shl(BIG a,int k)
+{
+ int i;
+ int n=k%BASEBITS;
+ int m=k/BASEBITS;
+
+ a[NLEN-1]=((a[NLEN-1-m]<<n))|(a[NLEN-m-2]>>(BASEBITS-n));
+
+ for (i=NLEN-2;i>m;i--)
+ a[i]=((a[i-m]<<n)&MASK)|(a[i-m-1]>>(BASEBITS-n));
+ a[m]=(a[0]<<n)&MASK;
+ for (i=0;i<m;i++) a[i]=0;
+
+}
+
+/* Fast shift left of a by n bits, where n less than a word, Return excess (but store it as well) */
+/* a MUST be normalised */
+/* SU= 16 */
+chunk BIG_fshl(BIG a,int n)
+{
+ int i;
+
+ a[NLEN-1]=((a[NLEN-1]<<n))|(a[NLEN-2]>>(BASEBITS-n)); /* top word not masked */
+ for (i=NLEN-2;i>0;i--)
+ a[i]=((a[i]<<n)&MASK)|(a[i-1]>>(BASEBITS-n));
+ a[0]=(a[0]<<n)&MASK;
+
+ return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* return excess - only used in ff.c */
+}
+
+/* double length left shift of a by k bits - k can be > BASEBITS , a MUST be normalised */
+/* SU= 32 */
+void BIG_dshl(DBIG a,int k)
+{
+ int i;
+ int n=k%BASEBITS;
+ int m=k/BASEBITS;
+
+ a[DNLEN-1]=((a[DNLEN-1-m]<<n))|(a[DNLEN-m-2]>>(BASEBITS-n));
+
+ for (i=DNLEN-2;i>m;i--)
+ a[i]=((a[i-m]<<n)&MASK)|(a[i-m-1]>>(BASEBITS-n));
+ a[m]=(a[0]<<n)&MASK;
+ for (i=0;i<m;i++) a[i]=0;
+
+}
+
+/* General shift rightof a by k bits */
+/* a MUST be normalised */
+/* SU= 32 */
+void BIG_shr(BIG a,int k)
+{
+ int i;
+ int n=k%BASEBITS;
+ int m=k/BASEBITS;
+ for (i=0;i<NLEN-m-1;i++)
+ a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&MASK);
+ a[NLEN-m-1]=a[NLEN-1]>>n;
+ for (i=NLEN-m;i<NLEN;i++) a[i]=0;
+
+}
+
+/* Faster shift right of a by k bits. Return shifted out part */
+/* a MUST be normalised */
+/* SU= 16 */
+chunk BIG_fshr(BIG a,int k)
+{
+ int i;
+ chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
+ for (i=0;i<NLEN-1;i++)
+ a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS-k))&MASK);
+ a[NLEN-1]=a[NLEN-1]>>k;
+ return r;
+}
+
+/* double length right shift of a by k bits - can be > BASEBITS */
+/* SU= 32 */
+void BIG_dshr(DBIG a,int k)
+{
+ int i;
+ int n=k%BASEBITS;
+ int m=k/BASEBITS;
+ for (i=0;i<DNLEN-m-1;i++)
+ a[i]=(a[m+i]>>n)|((a[m+i+1]<<(BASEBITS-n))&MASK);
+ a[DNLEN-m-1]=a[DNLEN-1]>>n;
+ for (i=DNLEN-m;i<DNLEN;i++ ) a[i]=0;
+}
+
+/* Split DBIG d into two BIGs t|b. Split happens at n bits, where n falls into NLEN word */
+/* d MUST be normalised */
+/* SU= 24 */
+void BIG_split(BIG t,BIG b,DBIG d,int n)
+{
+ int i;
+ chunk nw,carry;
+ int m=n%BASEBITS;
+// BIG_dnorm(d);
+
+ for (i=0;i<NLEN-1;i++) b[i]=d[i];
+
+ b[NLEN-1]=d[NLEN-1]&(((chunk)1<<m)-1);
+
+ if (t!=b)
+ {
+ carry=(d[DNLEN-1]<<(BASEBITS-m));
+ for (i=DNLEN-2;i>=NLEN-1;i--)
+ {
+ nw=(d[i]>>m)|carry;
+ carry=(d[i]<<(BASEBITS-m))&MASK;
+ t[i-NLEN+1]=nw;
+ }
+ }
+#ifdef DEBUG_NORM
+ t[NLEN]=0;
+ b[NLEN]=0;
+#endif
+
+}
+
+/* you gotta keep the sign of carry! Look - no branching! */
+/* Note that sign bit is needed to disambiguate between +ve and -ve values */
+/* normalise BIG - force all digits < 2^BASEBITS */
+chunk BIG_norm(BIG a)
+{
+ int i;
+ chunk d,carry=0;
+ for (i=0;i<NLEN-1;i++)
+ {
+ d=a[i]+carry;
+ a[i]=d&MASK;
+ carry=d>>BASEBITS;
+ }
+ a[NLEN-1]=(a[NLEN-1]+carry);
+
+#ifdef DEBUG_NORM
+ a[NLEN]=0;
+#endif
+ return (a[NLEN-1]>>((8*MODBYTES)%BASEBITS)); /* only used in ff.c */
+}
+
+void BIG_dnorm(DBIG a)
+{
+ int i;
+ chunk d,carry=0;;
+ for (i=0;i<DNLEN-1;i++)
+ {
+ d=a[i]+carry;
+ a[i]=d&MASK;
+ carry=d>>BASEBITS;
+ }
+ a[DNLEN-1]=(a[DNLEN-1]+carry);
+#ifdef DEBUG_NORM
+ a[DNLEN]=0;
+#endif
+}
+
+/* Compare a and b. Return 1 for a>b, -1 for a<b, 0 for a==b */
+/* a and b MUST be normalised before call */
+int BIG_comp(BIG a,BIG b)
+{
+ int i;
+ for (i=NLEN-1;i>=0;i--)
+ {
+ if (a[i]==b[i]) continue;
+ if (a[i]>b[i]) return 1;
+ else return -1;
+ }
+ return 0;
+}
+
+int BIG_dcomp(DBIG a,DBIG b)
+{
+ int i;
+ for (i=DNLEN-1;i>=0;i--)
+ {
+ if (a[i]==b[i]) continue;
+ if (a[i]>b[i]) return 1;
+ else return -1;
+ }
+ return 0;
+}
+
+/* return number of bits in a */
+/* SU= 8 */
+int BIG_nbits(BIG a)
+{
+ int bts,k=NLEN-1;
+ chunk c;
+ BIG_norm(a);
+ while (k>=0 && a[k]==0) k--;
+ if (k<0) return 0;
+ bts=BASEBITS*k;
+ c=a[k];
+ while (c!=0) {c/=2; bts++;}
+ return bts;
+}
+
+/* SU= 8 */
+int BIG_dnbits(BIG a)
+{
+ int bts,k=DNLEN-1;
+ chunk c;
+ BIG_dnorm(a);
+ while (a[k]==0 && k>=0) k--;
+ if (k<0) return 0;
+ bts=BASEBITS*k;
+ c=a[k];
+ while (c!=0) {c/=2; bts++;}
+ return bts;
+}
+
+
+/* Set b=b mod c */
+/* SU= 16 */
+void BIG_mod(BIG b,BIG c)
+{
+ int k=0;
+
+ BIG_norm(b);
+ if (BIG_comp(b,c)<0)
+ return;
+ do
+ {
+ BIG_fshl(c,1);
+ k++;
+ } while (BIG_comp(b,c)>=0);
+
+ while (k>0)
+ {
+ BIG_fshr(c,1);
+ if (BIG_comp(b,c)>=0)
+ {
+ BIG_sub(b,b,c);
+ BIG_norm(b);
+ }
+ k--;
+ }
+}
+
+/* Set a=b mod c, b is destroyed. Slow but rarely used. */
+/* SU= 96 */
+void BIG_dmod(BIG a,DBIG b,BIG c)
+{
+ int k=0;
+ DBIG m;
+ BIG_dnorm(b);
+ BIG_dscopy(m,c);
+
+ if (BIG_dcomp(b,m)<0)
+ {
+ BIG_sdcopy(a,b);
+ return;
+ }
+
+ do
+ {
+ BIG_dshl(m,1);
+ k++;
+ } while (BIG_dcomp(b,m)>=0);
+
+ while (k>0)
+ {
+ BIG_dshr(m,1);
+ if (BIG_dcomp(b,m)>=0)
+ {
+ BIG_dsub(b,b,m);
+ BIG_dnorm(b);
+ }
+ k--;
+ }
+ BIG_sdcopy(a,b);
+}
+
+/* Set a=b/c, b is destroyed. Slow but rarely used. */
+/* SU= 136 */
+void BIG_ddiv(BIG a,DBIG b,BIG c)
+{
+ int k=0;
+ DBIG m;
+ BIG e;
+ BIG_dnorm(b);
+ BIG_dscopy(m,c);
+
+ BIG_zero(a);
+ BIG_zero(e); BIG_inc(e,1);
+
+ while (BIG_dcomp(b,m)>=0)
+ {
+ BIG_fshl(e,1);
+ BIG_dshl(m,1);
+ k++;
+ }
+
+ while (k>0)
+ {
+ BIG_dshr(m,1);
+ BIG_fshr(e,1);
+ if (BIG_dcomp(b,m)>=0)
+ {
+ BIG_add(a,a,e);
+ BIG_norm(a);
+ BIG_dsub(b,b,m);
+ BIG_dnorm(b);
+ }
+ k--;
+ }
+}
+
+/* SU= 136 */
+
+void BIG_sdiv(BIG a,BIG c)
+{
+ int k=0;
+ BIG m,e,b;
+ BIG_norm(a);
+ BIG_copy(b,a);
+ BIG_copy(m,c);
+
+ BIG_zero(a);
+ BIG_zero(e); BIG_inc(e,1);
+
+ while (BIG_comp(b,m)>=0)
+ {
+ BIG_fshl(e,1);
+ BIG_fshl(m,1);
+ k++;
+ }
+
+ while (k>0)
+ {
+ BIG_fshr(m,1);
+ BIG_fshr(e,1);
+ if (BIG_comp(b,m)>=0)
+ {
+ BIG_add(a,a,e);
+ BIG_norm(a);
+ BIG_sub(b,b,m);
+ BIG_norm(b);
+ }
+ k--;
+ }
+}
+
+/* return LSB of a */
+int BIG_parity(BIG a)
+{
+ return a[0]%2;
+}
+
+/* return n-th bit of a */
+/* SU= 16 */
+int BIG_bit(BIG a,int n)
+{
+ if (a[n/BASEBITS]&((chunk)1<<(n%BASEBITS))) return 1;
+ else return 0;
+}
+
+/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed.
+nbs is number of bits processed, and nzs is number of trailing 0s detected */
+/* SU= 32 */
+int BIG_nafbits(BIG x,BIG x3,int i,int *nbs,int *nzs)
+{
+ int j,r,nb;
+
+ nb=BIG_bit(x3,i)-BIG_bit(x,i);
+ *nbs=1;
+ *nzs=0;
+ if (nb==0) return 0;
+ if (i==0) return nb;
+
+ if (nb>0) r=1;
+ else r=(-1);
+
+ for (j=i-1;j>0;j--)
+ {
+ (*nbs)++;
+ r*=2;
+ nb=BIG_bit(x3,j)-BIG_bit(x,j);
+ if (nb>0) r+=1;
+ if (nb<0) r-=1;
+ if (abs(r)>5) break;
+ }
+
+ if (r%2!=0 && j!=0)
+ { /* backtrack */
+ if (nb>0) r=(r-1)/2;
+ if (nb<0) r=(r+1)/2;
+ (*nbs)--;
+ }
+
+ while (r%2==0)
+ { /* remove trailing zeros */
+ r/=2;
+ (*nzs)++;
+ (*nbs)--;
+ }
+ return r;
+}
+
+/* return last n bits of a, where n is small < BASEBITS */
+/* SU= 16 */
+int BIG_lastbits(BIG a,int n)
+{
+ int msk=(1<<n)-1;
+ BIG_norm(a);
+ return ((int)a[0])&msk;
+}
+
+/* get 8*MODBYTES size random number */
+void BIG_random(BIG m,csprng *rng)
+{
+ int i,b,j=0,r=0;
+
+ BIG_zero(m);
+/* generate random BIG */
+ for (i=0;i<8*MODBYTES;i++)
+ {
+ if (j==0) r=RAND_byte(rng);
+ else r>>=1;
+ b=r&1;
+ BIG_shl(m,1); m[0]+=b;
+ j++; j&=7;
+ }
+
+#ifdef DEBUG_NORM
+ m[NLEN]=0;
+#endif
+}
+
+/* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
+
+void BIG_randomnum(BIG m,BIG q,csprng *rng)
+{
+ int i,b,j=0,r=0;
+ DBIG d;
+ BIG_dzero(d);
+/* generate random DBIG */
+ for (i=0;i<2*MODBITS;i++)
+ {
+ if (j==0) r=RAND_byte(rng);
+ else r>>=1;
+ b=r&1;
+ BIG_dshl(d,1); d[0]+=b;
+ j++; j&=7;
+ }
+/* reduce modulo a BIG. Removes bias */
+ BIG_dmod(m,d,q);
+#ifdef DEBUG_NORM
+ m[NLEN]=0;
+#endif
+}
+
+/* Set r=a*b mod m */
+/* SU= 96 */
+void BIG_modmul(BIG r,BIG a,BIG b,BIG m)
+{
+ DBIG d;
+ BIG_mod(a,m);
+ BIG_mod(b,m);
+ BIG_mul(d,a,b);
+ BIG_dmod(r,d,m);
+}
+
+/* Set a=a*a mod m */
+/* SU= 88 */
+void BIG_modsqr(BIG r,BIG a,BIG m)
+{
+ DBIG d;
+ BIG_mod(a,m);
+ BIG_sqr(d,a);
+ BIG_dmod(r,d,m);
+}
+
+/* Set r=-a mod m */
+/* SU= 16 */
+void BIG_modneg(BIG r,BIG a,BIG m)
+{
+ BIG_mod(a,m);
+ BIG_sub(r,m,a);
+}
+
+/* Set a=a/b mod m */
+/* SU= 136 */
+void BIG_moddiv(BIG r,BIG a,BIG b,BIG m)
+{
+ DBIG d;
+ BIG z;
+ BIG_mod(a,m);
+ BIG_invmodp(z,b,m);
+ BIG_mul(d,a,z);
+ BIG_dmod(r,d,m);
+}
+
+/* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
+/* SU= 216 */
+int BIG_jacobi(BIG a,BIG p)
+{
+ int n8,k,m=0;
+ BIG t,x,n,zilch,one;
+ BIG_one(one);
+ BIG_zero(zilch);
+ if (BIG_parity(p)==0 || BIG_comp(a,zilch)==0 || BIG_comp(p,one)<=0) return 0;
+ BIG_norm(a);
+ BIG_copy(x,a);
+ BIG_copy(n,p);
+ BIG_mod(x,p);
+
+ while (BIG_comp(n,one)>0)
+ {
+ if (BIG_comp(x,zilch)==0) return 0;
+ n8=BIG_lastbits(n,3);
+ k=0;
+ while (BIG_parity(x)==0)
+ {
+ k++;
+ BIG_shr(x,1);
+ }
+ if (k%2==1) m+=(n8*n8-1)/8;
+ m+=(n8-1)*(BIG_lastbits(x,2)-1)/4;
+ BIG_copy(t,n);
+
+ BIG_mod(t,x);
+ BIG_copy(n,x);
+ BIG_copy(x,t);
+ m%=2;
+
+ }
+ if (m==0) return 1;
+ else return -1;
+}
+
+/* Set r=1/a mod p. Binary method */
+/* SU= 240 */
+void BIG_invmodp(BIG r,BIG a,BIG p)
+{
+ BIG u,v,x1,x2,t,one;
+ BIG_mod(a,p);
+ BIG_copy(u,a);
+ BIG_copy(v,p);
+ BIG_one(one);
+ BIG_copy(x1,one);
+ BIG_zero(x2);
+
+ while (BIG_comp(u,one)!=0 && BIG_comp(v,one)!=0)
+ {
+ while (BIG_parity(u)==0)
+ {
+ BIG_shr(u,1);
+ if (BIG_parity(x1)!=0)
+ {
+ BIG_add(x1,p,x1);
+ BIG_norm(x1);
+ }
+ BIG_shr(x1,1);
+ }
+ while (BIG_parity(v)==0)
+ {
+ BIG_shr(v,1);
+ if (BIG_parity(x2)!=0)
+ {
+ BIG_add(x2,p,x2);
+ BIG_norm(x2);
+ }
+ BIG_shr(x2,1);
+ }
+ if (BIG_comp(u,v)>=0)
+ {
+ BIG_sub(u,u,v);
+ BIG_norm(u);
+ if (BIG_comp(x1,x2)>=0) BIG_sub(x1,x1,x2);
+ else
+ {
+ BIG_sub(t,p,x2);
+ BIG_add(x1,x1,t);
+ }
+ BIG_norm(x1);
+ }
+ else
+ {
+ BIG_sub(v,v,u);
+ BIG_norm(v);
+ if (BIG_comp(x2,x1)>=0) BIG_sub(x2,x2,x1);
+ else
+ {
+ BIG_sub(t,p,x1);
+ BIG_add(x2,x2,t);
+ }
+ BIG_norm(x2);
+ }
+ }
+ if (BIG_comp(u,one)==0)
+ BIG_copy(r,x1);
+ else
+ BIG_copy(r,x2);
+}
diff --git a/c/build_ec b/c/build_ec
new file mode 100644
index 0000000..5b364d0
--- /dev/null
+++ b/c/build_ec
@@ -0,0 +1,24 @@
+cp amcl_.h amcl.h
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 ff.c
+
+rm amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+gcc -std=c99 -O3 testecm.c ecdh.c amcl.a -o testecm
+gcc -std=c99 -O3 testecdh.c ecdh.c amcl.a -o testecdh
+gcc -std=c99 -O3 testrsa.c rsa.c amcl.a -o testrsa
+
+rm amcl.h
+rm *.o
diff --git a/c/build_ec.bat b/c/build_ec.bat
new file mode 100644
index 0000000..c302beb
--- /dev/null
+++ b/c/build_ec.bat
@@ -0,0 +1,24 @@
+copy amcl_.h amcl.h
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 ff.c
+
+del amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o ff.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+gcc -std=c99 -O3 testecm.c ecdh.c amcl.a -o testecm.exe
+gcc -std=c99 -O3 testecdh.c ecdh.c amcl.a -o testecdh.exe
+gcc -std=c99 -O3 testrsa.c rsa.c amcl.a -o testrsa.exe
+
+del amcl.h
+del *.o
diff --git a/c/build_pair b/c/build_pair
new file mode 100644
index 0000000..7232c27
--- /dev/null
+++ b/c/build_pair
@@ -0,0 +1,28 @@
+cp amcl_.h amcl.h
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 fp2.c
+gcc -std=c99 -c -O3 ecp2.c
+gcc -std=c99 -c -O3 fp4.c
+gcc -std=c99 -c -O3 fp12.c
+gcc -std=c99 -c -O3 pair.c
+
+rm amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
+
+gcc -std=c99 -O3 testmpin.c mpin.c amcl.a -o testmpin
+
+rm amcl.h
+rm *.o
diff --git a/c/build_pair.bat b/c/build_pair.bat
new file mode 100644
index 0000000..05d1c24
--- /dev/null
+++ b/c/build_pair.bat
@@ -0,0 +1,28 @@
+copy amcl_.h amcl.h
+
+gcc -std=c99 -c -O3 big.c
+gcc -std=c99 -c -O3 fp.c
+gcc -std=c99 -c -O3 ecp.c
+gcc -std=c99 -c -O3 hash.c
+gcc -std=c99 -c -O3 rand.c
+gcc -std=c99 -c -O3 aes.c
+gcc -std=c99 -c -O3 gcm.c
+gcc -std=c99 -c -O3 oct.c
+gcc -std=c99 -c -O3 rom.c
+
+gcc -std=c99 -c -O3 fp2.c
+gcc -std=c99 -c -O3 ecp2.c
+gcc -std=c99 -c -O3 fp4.c
+gcc -std=c99 -c -O3 fp12.c
+gcc -std=c99 -c -O3 pair.c
+
+del amcl.a
+ar rc amcl.a big.o fp.o ecp.o hash.o
+ar r amcl.a rand.o aes.o gcm.o oct.o rom.o
+
+ar r amcl.a pair.o fp2.o ecp2.o fp4.o fp12.o
+
+gcc -std=c99 -O3 testmpin.c mpin.c amcl.a -o testmpin.exe
+
+del amcl.h
+del *.o
diff --git a/c/build_pair_ms.bat b/c/build_pair_ms.bat
new file mode 100644
index 0000000..96b6234
--- /dev/null
+++ b/c/build_pair_ms.bat
@@ -0,0 +1,28 @@
+copy amcl_.h amcl.h
+
+cl /c /O2 big.c
+cl /c /O2 fp.c
+cl /c /O2 ecp.c
+cl /c /O2 hash.c
+cl /c /O2 rand.c
+cl /c /O2 aes.c
+cl /c /O2 gcm.c
+cl /c /O2 oct.c
+cl /c /O2 rom.c
+cl /c /O2 fp.c
+cl /c /O2 fp2.c
+cl /c /O2 ecp2.c
+cl /c /O2 fp4.c
+cl /c /O2 fp12.c
+cl /c /O2 pair.c
+
+del amcl.lib
+lib /OUT:amcl.lib big.obj fp.obj ecp.obj hash.obj
+lib /OUT:amcl.lib amcl.lib rand.obj aes.obj gcm.obj oct.obj rom.obj
+
+lib /OUT:amcl.lib amcl.lib pair.obj fp2.obj ecp2.obj fp4.obj fp12.obj
+
+cl /O2 testmpin.c mpin.c amcl.lib
+
+del amcl.h
+del *.obj
diff --git a/c/ecdh.c b/c/ecdh.c
new file mode 100755
index 0000000..9d037d0
--- /dev/null
+++ b/c/ecdh.c
@@ -0,0 +1,576 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* ECDH/ECIES/ECDSA Functions - see main program below */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ecdh.h"
+
+#define ROUNDUP(a,b) ((a)-1)/(b)+1
+
+/* general purpose hash function w=hash(p|n|x|y) */
+static void hashit(octet *p,int n,octet *x,octet *y,octet *w)
+{
+ int i,c[4];
+ hash sha;
+ char hh[32];
+
+ HASH_init(&sha);
+ if (p!=NULL)
+ for (i=0;i<p->len;i++) HASH_process(&sha,p->val[i]);
+ if (n>0)
+ {
+ c[0]=(n>>24)&0xff;
+ c[1]=(n>>16)&0xff;
+ c[2]=(n>>8)&0xff;
+ c[3]=(n)&0xff;
+ for (i=0;i<4;i++) HASH_process(&sha,c[i]);
+ }
+ if (x!=NULL)
+ for (i=0;i<x->len;i++) HASH_process(&sha,x->val[i]);
+ if (y!=NULL)
+ for (i=0;i<y->len;i++) HASH_process(&sha,y->val[i]);
+
+
+ HASH_hash(&sha,hh);
+
+ OCT_empty(w);
+ OCT_jbytes(w,hh,32);
+ for (i=0;i<32;i++) hh[i]=0;
+}
+
+/* Hash octet p to octet w */
+void HASH(octet *p,octet *w)
+{
+ hashit(p,-1,NULL,NULL,w);
+}
+
+/* Initialise a Cryptographically Strong Random Number Generator from
+ an octet of raw random data */
+void CREATE_CSPRNG(csprng *RNG,octet *RAW)
+{
+ RAND_seed(RNG,RAW->len,RAW->val);
+}
+
+void KILL_CSPRNG(csprng *RNG)
+{
+ RAND_clean(RNG);
+}
+
+/* Calculate HMAC of m using key k. HMAC is tag of length olen */
+int HMAC(octet *m,octet *k,int olen,octet *tag)
+{
+/* Input is from an octet m *
+ * olen is requested output length in bytes. k is the key *
+ * The output is the calculated tag */
+ int hlen,b;
+ char h[32],k0[64];
+ octet H={0,sizeof(h),h};
+ octet K0={0,sizeof(k0),k0};
+
+ hlen=32; b=64;
+ if (olen<4 || olen>hlen) return 0;
+
+ if (k->len > b) hashit(k,-1,NULL,NULL,&K0);
+ else OCT_copy(&K0,k);
+
+ OCT_jbyte(&K0,0,b-K0.len);
+
+ OCT_xorbyte(&K0,0x36);
+
+ hashit(&K0,-1,m,NULL,&H);
+
+ OCT_xorbyte(&K0,0x6a); /* 0x6a = 0x36 ^ 0x5c */
+ hashit(&K0,-1,&H,NULL,&H);
+
+ OCT_empty(tag);
+ OCT_jbytes(tag,H.val,olen);
+
+ return 1;
+}
+
+/* Key Derivation Functions */
+/* Input octet z */
+/* Output key of length olen */
+/*
+void KDF1(octet *z,int olen,octet *key)
+{
+ char h[32];
+ octet H={0,sizeof(h),h};
+ int counter,cthreshold;
+ int hlen=32;
+
+ OCT_empty(key);
+
+ cthreshold=ROUNDUP(olen,hlen);
+
+ for (counter=0;counter<cthreshold;counter++)
+ {
+ hashit(z,counter,NULL,NULL,&H);
+ if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
+ else OCT_joctet(key,&H);
+ }
+}
+*/
+void KDF2(octet *z,octet *p,int olen,octet *key)
+{
+/* NOTE: the parameter olen is the length of the output k in bytes */
+ char h[32];
+ octet H={0,sizeof(h),h};
+ int counter,cthreshold;
+ int hlen=32;
+
+ OCT_empty(key);
+
+ cthreshold=ROUNDUP(olen,hlen);
+
+ for (counter=1;counter<=cthreshold;counter++)
+ {
+ hashit(z,counter,p,NULL,&H);
+ if (key->len+hlen>olen) OCT_jbytes(key,H.val,olen%hlen);
+ else OCT_joctet(key,&H);
+ }
+}
+
+/* Password based Key Derivation Function */
+/* Input password p, salt s, and repeat count */
+/* Output key of length olen */
+void PBKDF2(octet *p,octet *s,int rep,int olen,octet *key)
+{
+ int i,j,len,d=ROUNDUP(olen,32);
+ char f[EFS],u[EFS];
+ octet F={0,sizeof(f),f};
+ octet U={0,sizeof(u),u};
+ OCT_empty(key);
+
+ for (i=1;i<=d;i++)
+ {
+ len=s->len;
+ OCT_jint(s,i,4);
+ HMAC(s,p,EFS,&F);
+ s->len=len;
+ OCT_copy(&U,&F);
+ for (j=2;j<=rep;j++)
+ {
+ HMAC(&U,p,EFS,&U);
+ OCT_xor(&F,&U);
+ }
+
+ OCT_joctet(key,&F);
+ }
+ OCT_chop(key,NULL,olen);
+}
+
+/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
+void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
+{ /* AES CBC encryption, with Null IV and key k */
+ /* Input is from an octet string m, output is to an octet string c */
+ /* Input is padded as necessary to make up a full final block */
+ aes a;
+ int fin;
+ int i,j,ipt,opt;
+ char buff[16];
+ int padlen;
+
+ OCT_clear(c);
+ if (m->len==0) return;
+ AES_init(&a,CBC,k->val,NULL);
+
+ ipt=opt=0;
+ fin=0;
+ for(;;)
+ {
+ for (i=0;i<16;i++)
+ {
+ if (ipt<m->len) buff[i]=m->val[ipt++];
+ else {fin=1; break;}
+ }
+ if (fin) break;
+ AES_encrypt(&a,buff);
+ for (i=0;i<16;i++)
+ if (opt<c->max) c->val[opt++]=buff[i];
+ }
+
+/* last block, filled up to i-th index */
+
+ padlen=16-i;
+ for (j=i;j<16;j++) buff[j]=padlen;
+ AES_encrypt(&a,buff);
+ for (i=0;i<16;i++)
+ if (opt<c->max) c->val[opt++]=buff[i];
+ AES_end(&a);
+ c->len=opt;
+}
+
+/* decrypts and returns TRUE if all consistent, else returns FALSE */
+int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+{ /* padding is removed */
+ aes a;
+ int i,ipt,opt,ch;
+ char buff[16];
+ int fin,bad;
+ int padlen;
+ ipt=opt=0;
+
+ OCT_clear(m);
+ if (c->len==0) return 1;
+ ch=c->val[ipt++];
+
+ AES_init(&a,CBC,k->val,NULL);
+ fin=0;
+
+ for(;;)
+ {
+ for (i=0;i<16;i++)
+ {
+ buff[i]=ch;
+ if (ipt>=c->len) {fin=1; break;}
+ else ch=c->val[ipt++];
+ }
+ AES_decrypt(&a,buff);
+ if (fin) break;
+ for (i=0;i<16;i++)
+ if (opt<m->max) m->val[opt++]=buff[i];
+ }
+ AES_end(&a);
+ bad=0;
+ padlen=buff[15];
+ if (i!=15 || padlen<1 || padlen>16) bad=1;
+ if (padlen>=2 && padlen<=16)
+ for (i=16-padlen;i<16;i++) if (buff[i]!=padlen) bad=1;
+
+ if (!bad) for (i=0;i<16-padlen;i++)
+ if (opt<m->max) m->val[opt++]=buff[i];
+
+ m->len=opt;
+ if (bad) return 0;
+ return 1;
+}
+
+/* Calculate a public/private EC GF(p) key pair. W=S.G mod EC(p),
+ * where S is the secret key and W is the public key
+ * and G is fixed generator.
+ * If RNG is NULL then the private key is provided externally in S
+ * otherwise it is generated randomly internally */
+int ECP_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
+{
+ BIG r,gx,gy,s;
+ ECP G;
+ int res=0;
+ BIG_rcopy(gx,CURVE_Gx);
+
+#if CURVETYPE!=MONTGOMERY
+ BIG_rcopy(gy,CURVE_Gy);
+ ECP_set(&G,gx,gy);
+#else
+ ECP_set(&G,gx);
+#endif
+
+ BIG_rcopy(r,CURVE_Order);
+ if (RNG!=NULL)
+ BIG_randomnum(s,r,RNG);
+ else
+ {
+ BIG_fromBytes(s,S->val);
+ BIG_mod(s,r);
+ }
+
+ ECP_mul(&G,s);
+#if CURVETYPE!=MONTGOMERY
+ ECP_get(gx,gy,&G);
+#else
+ ECP_get(gx,&G);
+#endif
+ if (RNG!=NULL)
+ {
+ S->len=EGS;
+ BIG_toBytes(S->val,s);
+ }
+#if CURVETYPE!=MONTGOMERY
+ W->len=2*EFS+1; W->val[0]=4;
+ BIG_toBytes(&(W->val[1]),gx);
+ BIG_toBytes(&(W->val[EFS+1]),gy);
+#else
+ W->len=EFS+1; W->val[0]=2;
+ BIG_toBytes(&(W->val[1]),gx);
+#endif
+
+ return res;
+}
+
+/* validate public key. Set full=true for fuller check */
+int ECP_PUBLIC_KEY_VALIDATE(int full,octet *W)
+{
+ BIG q,r,wx,wy;
+ ECP WP;
+ int valid;
+ int res=0;
+
+ BIG_rcopy(q,Modulus);
+ BIG_rcopy(r,CURVE_Order);
+
+ BIG_fromBytes(wx,&(W->val[1]));
+ if (BIG_comp(wx,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#if CURVETYPE!=MONTGOMERY
+ BIG_fromBytes(wy,&(W->val[EFS+1]));
+ if (BIG_comp(wy,q)>=0) res=ECDH_INVALID_PUBLIC_KEY;
+#endif
+ if (res==0)
+ {
+#if CURVETYPE!=MONTGOMERY
+ valid=ECP_set(&WP,wx,wy);
+#else
+ valid=ECP_set(&WP,wx);
+#endif
+ if (!valid || ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+ if (res==0 && full)
+ {
+ ECP_mul(&WP,r);
+ if (!ECP_isinf(&WP)) res=ECDH_INVALID_PUBLIC_KEY;
+ }
+ }
+
+ return res;
+}
+
+/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
+int ECPSVDP_DH(octet *S,octet *WD,octet *Z)
+{
+ BIG r,s,wx,wy;
+ int valid;
+ ECP W;
+ int res=0;
+
+ BIG_fromBytes(s,S->val);
+
+ BIG_fromBytes(wx,&(WD->val[1]));
+#if CURVETYPE!=MONTGOMERY
+ BIG_fromBytes(wy,&(WD->val[EFS+1]));
+ valid=ECP_set(&W,wx,wy);
+#else
+ valid=ECP_set(&W,wx);
+#endif
+ if (!valid) res=ECDH_ERROR;
+ if (res==0)
+ {
+ BIG_rcopy(r,CURVE_Order);
+ BIG_mod(s,r);
+
+ ECP_mul(&W,s);
+ if (ECP_isinf(&W)) res=ECDH_ERROR;
+ else
+ {
+#if CURVETYPE!=MONTGOMERY
+ ECP_get(wx,wx,&W);
+#else
+ ECP_get(wx,&W);
+#endif
+ Z->len=32;
+ BIG_toBytes(Z->val,wx);
+ }
+ }
+ return res;
+}
+
+#if CURVETYPE!=MONTGOMERY
+
+/* IEEE ECDSA Signature, C and D are signature on F using private key S */
+int ECPSP_DSA(csprng *RNG,octet *S,octet *F,octet *C,octet *D)
+{
+ char h[32];
+ octet H={0,sizeof(h),h};
+
+ BIG gx,gy,r,s,f,c,d,u,vx;
+ ECP G,V;
+
+ hashit(F,-1,NULL,NULL,&H);
+
+ BIG_rcopy(gx,CURVE_Gx);
+ BIG_rcopy(gy,CURVE_Gy);
+ BIG_rcopy(r,CURVE_Order);
+
+ BIG_fromBytes(s,S->val);
+ BIG_fromBytes(f,H.val);
+
+ ECP_set(&G,gx,gy);
+
+ do {
+ BIG_randomnum(u,r,RNG);
+ ECP_copy(&V,&G);
+ ECP_mul(&V,u);
+
+ ECP_get(vx,vx,&V);
+
+ BIG_copy(c,vx);
+ BIG_mod(c,r);
+ if (BIG_iszilch(c)) continue;
+
+ BIG_invmodp(u,u,r);
+ BIG_modmul(d,s,c,r);
+
+ BIG_add(d,f,d);
+
+ BIG_modmul(d,u,d,r);
+
+ } while (BIG_iszilch(d));
+
+ C->len=D->len=EGS;
+
+ BIG_toBytes(C->val,c);
+ BIG_toBytes(D->val,d);
+
+ return 0;
+}
+
+/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
+int ECPVP_DSA(octet *W,octet *F, octet *C,octet *D)
+{
+ char h[32];
+ octet H={0,sizeof(h),h};
+
+ BIG r,gx,gy,wx,wy,f,c,d,h2;
+ int res=0;
+ ECP G,WP;
+ int valid;
+
+ hashit(F,-1,NULL,NULL,&H);
+
+ BIG_rcopy(gx,CURVE_Gx);
+ BIG_rcopy(gy,CURVE_Gy);
+ BIG_rcopy(r,CURVE_Order);
+
+ BIG_fromBytes(c,C->val);
+ BIG_fromBytes(d,D->val);
+ BIG_fromBytes(f,H.val);
+
+ if (BIG_iszilch(c) || BIG_comp(c,r)>=0 || BIG_iszilch(d) || BIG_comp(d,r)>=0)
+ res=ECDH_INVALID;
+
+ if (res==0)
+ {
+ BIG_invmodp(d,d,r);
+ BIG_modmul(f,f,d,r);
+ BIG_modmul(h2,c,d,r);
+
+ ECP_set(&G,gx,gy);
+
+ BIG_fromBytes(wx,&(W->val[1]));
+ BIG_fromBytes(wy,&(W->val[EFS+1]));
+
+ valid=ECP_set(&WP,wx,wy);
+
+ if (!valid) res=ECDH_ERROR;
+ else
+ {
+ ECP_mul2(&WP,&G,h2,f);
+
+ if (ECP_isinf(&WP)) res=ECDH_INVALID;
+ else
+ {
+ ECP_get(d,d,&WP);
+ BIG_mod(d,r);
+ if (BIG_comp(d,c)!=0) res=ECDH_INVALID;
+ }
+ }
+ }
+
+ return res;
+}
+
+/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
+void ECP_ECIES_ENCRYPT(octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+{
+
+ int i,len;
+ char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],l2[8],u[EFS];
+ octet Z={0,sizeof(z),z};
+ octet VZ={0,sizeof(vz),vz};
+ octet K={0,sizeof(k),k};
+ octet K1={0,sizeof(k1),k1};
+ octet K2={0,sizeof(k2),k2};
+ octet L2={0,sizeof(l2),l2};
+ octet U={0,sizeof(u),u};
+
+ if (ECP_KEY_PAIR_GENERATE(RNG,&U,V)!=0) return;
+ if (ECPSVDP_DH(&U,W,&Z)!=0) return;
+
+ OCT_copy(&VZ,V);
+ OCT_joctet(&VZ,&Z);
+
+ KDF2(&VZ,P1,EFS,&K);
+
+ K1.len=K2.len=16;
+ for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
+
+ AES_CBC_IV0_ENCRYPT(&K1,M,C);
+
+ OCT_jint(&L2,P2->len,8);
+
+ len=C->len;
+ OCT_joctet(C,P2);
+ OCT_joctet(C,&L2);
+ HMAC(C,&K2,tlen,T);
+ C->len=len;
+}
+
+/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
+int ECP_ECIES_DECRYPT(octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+{
+
+ int i,len;
+ char z[EFS],vz[3*EFS+2],k[32],k1[16],k2[16],l2[8],tag[32];
+ octet Z={0,sizeof(z),z};
+ octet VZ={0,sizeof(vz),vz};
+ octet K={0,sizeof(k),k};
+ octet K1={0,sizeof(k1),k1};
+ octet K2={0,sizeof(k2),k2};
+ octet L2={0,sizeof(l2),l2};
+ octet TAG={0,sizeof(tag),tag};
+
+ if (ECPSVDP_DH(U,V,&Z)!=0) return 0;
+
+ OCT_copy(&VZ,V);
+ OCT_joctet(&VZ,&Z);
+
+ KDF2(&VZ,P1,EFS,&K);
+
+ K1.len=K2.len=16;
+ for (i=0;i<16;i++) {K1.val[i]=K.val[i]; K2.val[i]=K.val[16+i];}
+
+ if (!AES_CBC_IV0_DECRYPT(&K1,C,M)) return 0;
+
+ OCT_jint(&L2,P2->len,8);
+
+ len=C->len;
+ OCT_joctet(C,P2);
+ OCT_joctet(C,&L2);
+ HMAC(C,&K2,T->len,&TAG);
+ C->len=len;
+
+ if (!OCT_comp(T,&TAG)) return 0;
+
+ return 1;
+
+}
+
+#endif
diff --git a/c/ecdh.h b/c/ecdh.h
new file mode 100755
index 0000000..2dfef9b
--- /dev/null
+++ b/c/ecdh.h
@@ -0,0 +1,204 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/**
+ * @file ecdh.h
+ * @author Mike Scott and Kealan McCusker
+ * @date 2nd June 2015
+ * @brief ECDH Header file for implementation of standard EC protocols
+ *
+ * declares functions
+ *
+ */
+
+#ifndef ECDH_H
+#define ECDH_H
+
+#include "amcl.h"
+
+#define EAS 16 /**< Symmetric Key size - 128 bits */
+#define EGS 32 /**< ECC Group Size */
+#define EFS 32 /**< ECC Field Size */
+
+#define ECDH_OK 0 /**< Function completed without error */
+/*#define ECDH_DOMAIN_ERROR -1*/
+#define ECDH_INVALID_PUBLIC_KEY -2 /**< Public Key is Invalid */
+#define ECDH_ERROR -3 /**< ECDH Internal Error */
+#define ECDH_INVALID -4 /**< ECDH Internal Error */
+/*#define ECDH_DOMAIN_NOT_FOUND -5
+#define ECDH_OUT_OF_MEMORY -6
+#define ECDH_DIV_BY_ZERO -7
+#define ECDH_BAD_ASSUMPTION -8*/
+
+/* ECDH Auxiliary Functions */
+
+/** @brief Initialise a random number generator
+ *
+ @param R is a pointer to a cryptographically secure random number generator
+ @param S is an input truly random seed value
+ */
+extern void CREATE_CSPRNG(csprng *R,octet *S);
+/** @brief Kill a random number generator
+ *
+ Deletes all internal state
+ @param R is a pointer to a cryptographically secure random number generator
+ */
+extern void KILL_CSPRNG(csprng *R);
+/** @brief hash an octet into another octet
+ *
+ @param I input octet
+ @param O output octet - H(I)
+ */
+extern void HASH(octet *I,octet *O);
+/** @brief HMAC of message M using key K to create tag of length len in octet tag
+ *
+ IEEE-1363 MAC1 function. Uses SHA256 internally.
+ @param M input message octet
+ @param K input encryption key
+ @param len is output desired length of HMAC tag
+ @param tag is the output HMAC
+ @return 0 for bad parameters, else 1
+ */
+extern int HMAC(octet *M,octet *K,int len,octet *tag);
+
+/*extern void KDF1(octet *,int,octet *);*/
+
+/** @brief Key Derivation Function - generates key K from inputs Z and P
+ *
+ IEEE-1363 KDF2 Key Derivation Function. Uses SHA256 internally.
+ @param Z input octet
+ @param P input key derivation parameters - can be NULL
+ @param len is output desired length of key
+ @param K is the derived key
+ */
+extern void KDF2(octet *Z,octet *P,int len,octet *K);
+/** @brief Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+ *
+ PBKDF2 Password Based Key Derivation Function. Uses SHA256 internally.
+ @param P input password
+ @param S input salt
+ @param rep Number of times to be iterated.
+ @param len is output desired length of key
+ @param K is the derived key
+ */
+extern void PBKDF2(octet *P,octet *S,int rep,int len,octet *K);
+/** @brief AES encrypts a plaintext to a ciphtertext
+ *
+ IEEE-1363 AES_CBC_IV0_ENCRYPT function. Encrypts in CBC mode with a zero IV, padding as necessary to create a full final block.
+ @param K AES key
+ @param P input plaintext octet
+ @param C output ciphertext octet
+ */
+extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
+/** @brief AES encrypts a plaintext to a ciphtertext
+ *
+ IEEE-1363 AES_CBC_IV0_DECRYPT function. Decrypts in CBC mode with a zero IV.
+ @param K AES key
+ @param C input ciphertext octet
+ @param P output plaintext octet
+ @return 0 if bad input, else 1
+ */
+extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
+
+/* ECDH primitives - support functions */
+/** @brief Generate an ECC public/private key pair
+ *
+ @param R is a pointer to a cryptographically secure random number generator
+ @param s the private key, an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+ @param W the output public key, which is s.G, where G is a fixed generator
+ @return 0 or an error code
+ */
+extern int ECP_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
+/** @brief Validate an ECC public key
+ *
+ @param f if = 0 just does some simple checks, else tests that W is of the correct order
+ @param W the input public key to be validated
+ @return 0 if public key is OK, or an error code
+ */
+extern int ECP_PUBLIC_KEY_VALIDATE(int f,octet *W);
+
+/* ECDH primitives */
+
+/** @brief Generate Diffie-Hellman shared key
+ *
+ IEEE-1363 Diffie-Hellman shared secret calculation
+ @param s is the input private key,
+ @param W the input public key of the other party
+ @param K the output shared key, in fact the x-coordinate of s.W
+ @return 0 or an error code
+ */
+extern int ECPSVDP_DH(octet *s,octet *W,octet *K);
+/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
+
+/*#if CURVETYPE!=MONTGOMERY */
+/* ECIES functions */
+/** @brief ECIES Encryption
+ *
+ IEEE-1363 ECIES Encryption
+ @param P1 input Key Derivation parameters
+ @param P2 input Encoding parameters
+ @param R is a pointer to a cryptographically secure random number generator
+ @param W the input public key of the recieving party
+ @param M is the plaintext message to be encrypted
+ @param len the length of the HMAC tag
+ @param V component of the output ciphertext
+ @param C the output ciphertext
+ @param T the output HMAC tag, part of the ciphertext
+ */
+extern void ECP_ECIES_ENCRYPT(octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
+/** @brief ECIES Decryption
+ *
+ IEEE-1363 ECIES Decryption
+ @param P1 input Key Derivation parameters
+ @param P2 input Encoding parameters
+ @param V component of the input ciphertext
+ @param C the input ciphertext
+ @param T the input HMAC tag, part of the ciphertext
+ @param U the input private key for decryption
+ @param M the output plaintext message
+ @return 1 if successful, else 0
+ */
+extern int ECP_ECIES_DECRYPT(octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
+
+/* ECDSA functions */
+/** @brief ECDSA Signature
+ *
+ IEEE-1363 ECDSA Signature
+ @param R is a pointer to a cryptographically secure random number generator
+ @param s the input private signing key
+ @param M the input message to be signed
+ @param c component of the output signature
+ @param d component of the output signature
+
+ */
+extern int ECPSP_DSA(csprng *R,octet *s,octet *M,octet *c,octet *d);
+/** @brief ECDSA Signature Verification
+ *
+ IEEE-1363 ECDSA Signature Verification
+ @param W the input public key
+ @param M the input message
+ @param c component of the input signature
+ @param d component of the input signature
+ @return 0 or an error code
+ */
+extern int ECPVP_DSA(octet *W,octet *M,octet *c,octet *d);
+/*#endif*/
+
+#endif
+
diff --git a/c/ecp.c b/c/ecp.c
new file mode 100755
index 0000000..b7fdd10
--- /dev/null
+++ b/c/ecp.c
@@ -0,0 +1,1091 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+/* AMCL Elliptic Curve Functions */
+/* SU=m, SU is Stack Usage (Weierstrass Curves) */
+
+//#define HAS_MAIN
+
+#include "amcl.h"
+
+/* test for P=O point-at-infinity */
+int ECP_isinf(ECP *P)
+{
+#if CURVETYPE==EDWARDS
+ FP_reduce(P->x);
+ FP_reduce(P->y);
+ FP_reduce(P->z);
+ return (BIG_iszilch(P->x) && BIG_comp(P->y,P->z)==0);
+#else
+ return P->inf;
+#endif
+}
+
+/* Conditional swap of P and Q dependant on d */
+static void ECP_cswap(ECP *P,ECP *Q,int d)
+{
+ BIG_cswap(P->x,Q->x,d);
+#if CURVETYPE!=MONTGOMERY
+ BIG_cswap(P->y,Q->y,d);
+#endif
+ BIG_cswap(P->z,Q->z,d);
+#if CURVETYPE!=EDWARDS
+ d=~(d-1);
+ d=d&(P->inf^Q->inf);
+ P->inf^=d;
+ Q->inf^=d;
+#endif
+}
+
+/* Conditional move Q to P dependant on d */
+static void ECP_cmove(ECP *P,ECP *Q,int d)
+{
+ BIG_cmove(P->x,Q->x,d);
+#if CURVETYPE!=MONTGOMERY
+ BIG_cmove(P->y,Q->y,d);
+#endif
+ BIG_cmove(P->z,Q->z,d);
+#if CURVETYPE!=EDWARDS
+ d=~(d-1);
+ P->inf^=(P->inf^Q->inf)&d;
+#endif
+}
+
+/* return 1 if b==c, no branching */
+static int teq(sign32 b,sign32 c)
+{
+ sign32 x=b^c;
+ x-=1; // if x=0, x now -1
+ return (int)((x>>31)&1);
+}
+
+/* Constant time select from pre-computed table */
+static void ECP_select(ECP *P,ECP W[],sign32 b)
+{
+ ECP MP;
+ sign32 m=b>>31;
+ sign32 babs=(b^m)-m;
+
+ babs=(babs-1)/2;
+
+ ECP_cmove(P,&W[0],teq(babs,0)); // conditional move
+ ECP_cmove(P,&W[1],teq(babs,1));
+ ECP_cmove(P,&W[2],teq(babs,2));
+ ECP_cmove(P,&W[3],teq(babs,3));
+ ECP_cmove(P,&W[4],teq(babs,4));
+ ECP_cmove(P,&W[5],teq(babs,5));
+ ECP_cmove(P,&W[6],teq(babs,6));
+ ECP_cmove(P,&W[7],teq(babs,7));
+
+ ECP_copy(&MP,P);
+ ECP_neg(&MP); // minus P
+ ECP_cmove(P,&MP,(int)(m&1));
+}
+
+/* Test P == Q */
+/* SU=168 */
+int ECP_equals(ECP *P,ECP *Q)
+{
+#if CURVETYPE==WEIERSTRASS
+ BIG pz2,qz2,a,b;
+ if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
+ if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
+
+ FP_sqr(pz2,P->z); FP_sqr(qz2,Q->z);
+
+ FP_mul(a,P->x,qz2);
+ FP_mul(b,Q->x,pz2);
+ FP_reduce(a);
+ FP_reduce(b);
+ if (BIG_comp(a,b)!=0) return 0;
+
+ FP_mul(a,P->y,qz2);
+ FP_mul(a,a,Q->z);
+ FP_mul(b,Q->y,pz2);
+ FP_mul(b,b,P->z);
+ FP_reduce(a);
+ FP_reduce(b);
+ if (BIG_comp(a,b)!=0) return 0;
+ return 1;
+#else
+ BIG a,b;
+ if (ECP_isinf(P) && ECP_isinf(Q)) return 1;
+ if (ECP_isinf(P) || ECP_isinf(Q)) return 0;
+
+ FP_mul(a,P->x,Q->z);
+ FP_mul(b,Q->x,P->z);
+ FP_reduce(a);
+ FP_reduce(b);
+ if (BIG_comp(a,b)!=0) return 0;
+
+#if CURVETYPE==EDWARDS
+ FP_mul(a,P->y,Q->z);
+ FP_mul(b,Q->y,P->z);
+ FP_reduce(a);
+ FP_reduce(b);
+ if (BIG_comp(a,b)!=0) return 0;
+#endif
+
+ return 1;
+#endif
+}
+
+/* Set P=Q */
+/* SU=16 */
+void ECP_copy(ECP *P,ECP *Q)
+{
+#if CURVETYPE!=EDWARDS
+ P->inf=Q->inf;
+#endif
+ BIG_copy(P->x,Q->x);
+#if CURVETYPE!=MONTGOMERY
+ BIG_copy(P->y,Q->y);
+#endif
+ BIG_copy(P->z,Q->z);
+}
+
+/* Set P=-Q */
+#if CURVETYPE!=MONTGOMERY
+/* SU=8 */
+void ECP_neg(ECP *P)
+{
+ if (ECP_isinf(P)) return;
+#if CURVETYPE==WEIERSTRASS
+ FP_neg(P->y,P->y);
+ BIG_norm(P->y);
+#else
+ FP_neg(P->x,P->x);
+ BIG_norm(P->x);
+#endif
+
+}
+#endif
+
+/* Set P=O */
+void ECP_inf(ECP *P)
+{
+#if CURVETYPE==EDWARDS
+ BIG_zero(P->x); FP_one(P->y); FP_one(P->z);
+#else
+ P->inf=1;
+#endif
+}
+
+/* Calculate right Hand Side of curve equation y^2=RHS */
+/* SU=56 */
+void ECP_rhs(BIG v,BIG x)
+{
+#if CURVETYPE==WEIERSTRASS
+/* x^3+Ax+B */
+ BIG t;
+ FP_sqr(t,x);
+ FP_mul(t,t,x);
+
+ if (CURVE_A==-3)
+ {
+ FP_neg(v,x);
+ BIG_norm(v);
+ BIG_imul(v,v,-CURVE_A);
+ BIG_norm(v);
+ FP_add(v,t,v);
+ }
+ else BIG_copy(v,t);
+
+ BIG_rcopy(t,CURVE_B);
+ FP_nres(t);
+ FP_add(v,t,v);
+ FP_reduce(v);
+#endif
+
+#if CURVETYPE==EDWARDS
+/* (Ax^2-1)/(Bx^2-1) */
+ BIG t,m,one;
+ BIG_rcopy(m,Modulus);
+ FP_sqr(v,x);
+ FP_one(one);
+ BIG_rcopy(t,CURVE_B); FP_nres(t);
+ FP_mul(t,v,t); FP_sub(t,t,one);
+ if (CURVE_A==1) FP_sub(v,v,one);
+
+ if (CURVE_A==-1)
+ {
+ FP_add(v,v,one);
+ FP_neg(v,v);
+ }
+ FP_redc(v); FP_redc(t);
+ BIG_moddiv(v,v,t,m);
+ FP_nres(v);
+#endif
+
+#if CURVETYPE==MONTGOMERY
+/* x^3+Ax^2+x */
+ BIG x2,x3;
+ FP_sqr(x2,x);
+ FP_mul(x3,x2,x);
+ BIG_copy(v,x);
+ FP_imul(x2,x2,CURVE_A);
+ FP_add(v,v,x2);
+ FP_add(v,v,x3);
+ FP_reduce(v);
+#endif
+}
+
+/* Set P=(x,y) */
+
+#if CURVETYPE==MONTGOMERY
+
+/* Set P=(x,{y}) */
+
+int ECP_set(ECP *P,BIG x)
+{
+ BIG m,rhs;
+ BIG_rcopy(m,Modulus);
+ BIG_copy(rhs,x);
+ FP_nres(rhs);
+ ECP_rhs(rhs,rhs);
+ FP_redc(rhs);
+
+ if (BIG_jacobi(rhs,m)!=1)
+ {
+ ECP_inf(P);
+ return 0;
+ }
+ P->inf=0;
+ BIG_copy(P->x,x); FP_nres(P->x);
+ FP_one(P->z);
+ return 1;
+}
+
+/* Extract x coordinate as BIG */
+int ECP_get(BIG x,ECP *P)
+{
+ if (ECP_isinf(P)) return -1;
+ ECP_affine(P);
... 94107 lines suppressed ...