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 ...