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 2023/06/29 09:48:18 UTC

[incubator-milagro-crypto-c] branch master updated: Add IETF-compliant BLS and fix many code smells reported by sonarqube

This is an automated email from the ASF dual-hosted git repository.

kmccusker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-c.git


The following commit(s) were added to refs/heads/master by this push:
     new 442ac54  Add IETF-compliant BLS and fix many code smells reported by sonarqube
     new 2f51151  Merge pull request #116 from aadomnqredo/bls_and_more
442ac54 is described below

commit 442ac54dae9173eb3a3e589a03207d3e1e631ac5
Author: Alexandre Adomnicai <al...@qredo.com>
AuthorDate: Wed Jun 28 10:25:23 2023 +0200

    Add IETF-compliant BLS and fix many code smells reported by sonarqube
---
 .gitignore                                  |    5 +
 CMakeLists.txt                              |  118 +-
 Dockerfile                                  |   86 +-
 README.md                                   |   24 +-
 amcl.pc.in                                  |    2 +-
 benchmark/CMakeLists.txt                    |   14 +-
 benchmark/bench.c.in                        |    1 -
 benchmark/benchtest_bls_ZZZ.c.in            |  133 ++
 benchmark/benchtest_ec_ZZZ.c.in             |   27 +-
 benchmark/benchtest_ecdsa_ZZZ.c.in          |  138 ++
 benchmark/benchtest_ff_WWW.c.in             |   41 +-
 benchmark/benchtest_mpin_ZZZ.c.in           |   72 +-
 benchmark/benchtest_paillier.c.in           |   14 +-
 benchmark/benchtest_pair_ZZZ.c.in           |   50 +-
 benchmark/benchtest_rsa_WWW.c.in            |   31 +-
 cmake/AMCLParameters.cmake                  |  118 +-
 doc/Doxyfile                                |    9 -
 examples/CMakeLists.txt                     |    4 +-
 examples/example_bls_ZZZ.c.in               |    4 +-
 examples/example_bls_sss_ZZZ.c.in           |    4 +-
 examples/example_dvs_ZZZ.c.in               |   26 +-
 examples/example_ecdh_ZZZ.c.in              |   37 +-
 examples/example_mpin_ZZZ.c.in              |   68 +-
 examples/example_paillier.c                 |    2 +-
 examples/example_rsa_WWW.c.in               |   17 +-
 include/amcl.h.in                           |  152 +-
 include/arch.h.in                           |   14 +-
 include/big.h.in                            |  108 +-
 include/bls.h.in                            |   14 +-
 include/bls_ietf.h.in                       |  439 ++++
 include/config_curve.h.in                   |    4 +-
 include/ecdh.h.in                           |   17 +-
 include/ecdh_support.h                      |   16 +-
 include/ecp.h.in                            |   47 +-
 include/ecp2.h.in                           |   59 +-
 include/ff.h.in                             |    9 +-
 include/fp.h.in                             |   30 +-
 include/fp12.h.in                           |   36 +-
 include/fp16.h.in                           |    2 +-
 include/fp2.h.in                            |   42 +-
 include/fp4.h.in                            |   50 +-
 include/fp8.h.in                            |    4 +-
 include/hash_to_field.h.in                  |   56 +
 include/mpin.h.in                           |   45 +-
 include/paillier.h                          |   13 +-
 include/pair.h.in                           |   14 +-
 include/pbc_support.h                       |   10 +-
 include/randapi.h                           |    2 +-
 include/rsa.h.in                            |   22 +-
 include/rsa_support.h                       |    6 +-
 include/utils.h                             |    4 +-
 python/CMakeLists.txt                       |    8 +-
 python/run_bls_ZZZ.py.in                    |    1 -
 scripts/build.sh                            |   44 +
 scripts/coverage.sh                         |   25 +
 scripts/delete.sh                           |   20 +
 scripts/docker.sh                           |  111 +
 scripts/format.sh                           |   14 +
 scripts/gitleaks.sh                         |   43 +
 scripts/test.sh                             |   26 +
 src/aes.c                                   |  108 +-
 src/big.c.in                                |  373 ++--
 src/bls.c.in                                |   30 +-
 src/bls_ietf.c.in                           | 1275 +++++++++++
 src/ecdh.c.in                               |   73 +-
 src/ecdh_support.c                          |   75 +-
 src/ecp.c.in                                |  923 ++++----
 src/ecp2.c.in                               |  440 ++--
 src/ecp4.c.in                               |    4 +-
 src/ecp8.c.in                               |    4 +-
 src/ff.c.in                                 |  317 +--
 src/fp.c.in                                 |  218 +-
 src/fp12.c.in                               |  139 +-
 src/fp16.c.in                               |    2 +-
 src/fp2.c.in                                |   71 +-
 src/fp4.c.in                                |   99 +-
 src/fp8.c.in                                |    4 +-
 src/gcm.c                                   |  190 +-
 src/hash.c                                  |  175 +-
 src/hash_to_field.c.in                      |  138 ++
 src/hkdf.c                                  |   94 +
 src/hmac.c                                  |  170 ++
 src/mpin.c.in                               |  197 +-
 src/oct.c                                   |  120 +-
 src/paillier.c                              |   12 +-
 src/pair.c.in                               |  240 ++-
 src/pbc_support.c                           |   31 +-
 src/rand.c                                  |   41 +-
 src/randapi.c                               |    2 +-
 src/rom_iso_BLS381.c                        |  294 +++
 src/rsa.c.in                                |   32 +-
 src/rsa_support.c                           |   58 +-
 src/utils.c                                 |   22 +-
 test/CMakeLists.txt                         |   20 +
 test/test_aes_decrypt.c                     |   20 +-
 test/test_aes_encrypt.c                     |   22 +-
 test/test_big_arithmetics_XXX.c.in          |   20 +-
 test/test_big_consistency_XXX.c.in          |   16 +-
 test/test_bls_ZZZ.c.in                      |    2 +-
 test/test_bls_ietf_ZZZ.c.in                 |  554 +++++
 test/test_bls_ietf_h2c_G1_ZZZ.c.in          |  184 ++
 test/test_bls_ietf_h2c_G2_ZZZ.c.in          |  234 ++
 test/test_bls_sss_ZZZ.c.in                  |    2 +-
 test/test_ecc_ZZZ.c.in                      |   38 +-
 test/test_ecdsa_verify_ZZZ.c.in             |    2 +-
 test/test_ecp2_arithmetics_ZZZ.c.in         |   34 +-
 test/test_ecp_arithmetics_ZZZ.c.in          |   49 +-
 test/test_ff_consistency_WWW.c.in           |   14 +-
 test/test_gcm_decrypt.c                     |   19 +-
 test/test_gcm_encrypt.c                     |   14 +-
 test/test_hash.c                            |   28 +-
 test/test_hkdf.c                            |  217 ++
 test/test_hmac.c                            |  168 ++
 test/test_mpin_ZZZ.c.in                     |   31 +-
 test/test_mpin_bad_pin_ZZZ.c.in             |   34 +-
 test/test_mpin_bad_token_ZZZ.c.in           |   34 +-
 test/test_mpin_dvs_ZZZ.c.in                 |   26 +-
 test/test_mpin_dvs_wrong_pk_ZZZ.c.in        |   28 +-
 test/test_mpin_expired_tp_ZZZ.c.in          |   34 +-
 test/test_mpin_good_ZZZ.c.in                |   34 +-
 test/test_mpin_random_ZZZ.c.in              |   49 +-
 test/test_mpin_sign_ZZZ.c.in                |   35 +-
 test/test_mpin_tp_ZZZ.c.in                  |   43 +-
 test/test_mpin_vectors_ZZZ.c.in             |   52 +-
 test/test_mpinfull_ZZZ.c.in                 |   55 +-
 test/test_mpinfull_onepass_ZZZ.c.in         |   42 +-
 test/test_mpinfull_random_ZZZ.c.in          |   64 +-
 test/test_mpinfull_tp_ZZZ.c.in              |   65 +-
 test/test_octet_consistency.c               |   18 +-
 test/test_output_functions_ZZZ.c.in         |  108 +-
 test/test_paillier_add.c                    |   18 +-
 test/test_paillier_consistency.c            |    5 +-
 test/test_paillier_decrypt.c                |   22 +-
 test/test_paillier_encrypt.c                |   14 +-
 test/test_paillier_keygen.c                 |   24 +-
 test/test_paillier_mult.c                   |   14 +-
 test/test_pair_ZZZ.c.in                     |   39 +-
 test/test_rsa_WWW.c.in                      |   18 +-
 test/test_rsa_sign_WWW_ZZZ.c.in             |    2 +-
 test/test_utils.c                           |    5 +-
 test/test_x509_WWW_ZZZ.c.in                 |   21 +-
 testVectors/bls/bls12-381/bls12_381.rsp     | 3075 +++++++++++++++++++++++++++
 testVectors/bls/bls12-381/hash2curve_G1.rsp |  140 ++
 testVectors/bls/bls12-381/hash2curve_G2.rsp |  250 +++
 testVectors/hkdf/HKDF_SHA256.rsp            |   42 +
 testVectors/hmac/HMAC_SHA256.rsp            | 1581 ++++++++++++++
 146 files changed, 13365 insertions(+), 2837 deletions(-)

diff --git a/.gitignore b/.gitignore
index c1efd00..c40610c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,8 @@
 build
 target
 *~
+.idea
+cmake-build-debug
+qredo-secret-detection-config.toml
+security-ci-cd-templates
+gitleaks_report.json
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1a366f..43fbad1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,7 +54,6 @@ log(PROJECT_VERSION)
 log(CMAKE_GENERATOR)
 
 add_definitions(-DCMAKE)
-
 set(AMCL_VERSION       ${PROJECT_VERSION})
 set(AMCL_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
 set(AMCL_VERSION_MINOR ${PROJECT_VERSION_MINOR})
@@ -69,14 +68,14 @@ if(CMAKE_COMPILER_IS_GNUCC)
 
     if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
-        set(CMAKE_C_FLAGS_ASAN    "-O0 -g3 -fsanitize=address")
+        set(CMAKE_C_FLAGS_ASAN    "-O0 -g3 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fno-strict-overflow")
     else (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
         message(STATUS "GCC 4.8 required to run address sanitizer - please upgrade your installation")
     endif(GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
 
-    set(CMAKE_C_FLAGS_RELEASE     "-O2")
-    set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
-    set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
+    set(CMAKE_C_FLAGS_RELEASE     "-O2 -fno-strict-overflow")
+    set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3 -fno-strict-overflow")
+    set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 -fno-strict-overflow --coverage")
     set(CMAKE_C_FLAGS_CHECK       "-O2 -Werror")
     set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
 endif(CMAKE_COMPILER_IS_GNUCC)
@@ -119,11 +118,13 @@ option(BUILD_MPIN     "Build MPIN"     ON)
 option(BUILD_WCC      "Build WCC"      ON)
 option(BUILD_X509     "BUild X509"     ON)
 option(BUILD_BLS      "Build BLS"      ON)
+option(BUILD_BLS_IETF "Build BLS_IETF" ON)
 option(BUILD_PAILLIER "Build Paillier" OFF)
 log(BUILD_MPIN)
 log(BUILD_WCC)
 log(BUILD_X509)
 log(BUILD_BLS)
+log(BUILD_BLS_IETF)
 log(BUILD_PAILLIER)
 
 option(DEBUG_REDUCE "Print debug message for field reduction" OFF)
@@ -192,6 +193,8 @@ unset(RSL)
 
 add_library(amcl_core
   src/hash.c
+  src/hmac.c
+  src/hkdf.c
   src/rand.c
   src/randapi.c
   src/aes.c
@@ -208,6 +211,9 @@ set_target_properties(amcl_core PROPERTIES
   SOVERSION ${AMCL_SOVERSION}
 )
 
+target_compile_options(amcl_core PUBLIC
+  "$<$<CONFIG:DEBUG>:-DDEBUG>"
+)
 target_include_directories(amcl_core PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
@@ -415,25 +421,40 @@ foreach(curve ${AMCL_CURVE})
   amcl_curve_field(TC "${curve}")
   amcl_curve_field(TF "${curve}")
 
-  amcl_configure_file_curve(include/big.h.in          include/big_${BD}.h          "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/config_big.h.in   include/config_big_${BD}.h   "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/config_field.h.in include/config_field_${TF}.h "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/config_curve.h.in include/config_curve_${TC}.h "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/fp.h.in           include/fp_${TF}.h           "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/ecdh.h.in         include/ecdh_${TC}.h         "${curve}" amcl_curve_${TC}_GEN_HDRS)
-  amcl_configure_file_curve(include/ecp.h.in          include/ecp_${TC}.h          "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/big.h.in           include/big_${BD}.h           "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/config_big.h.in    include/config_big_${BD}.h    "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/config_field.h.in  include/config_field_${TF}.h  "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/config_curve.h.in  include/config_curve_${TC}.h  "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/fp.h.in            include/fp_${TF}.h            "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/ecdh.h.in          include/ecdh_${TC}.h          "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  amcl_configure_file_curve(include/ecp.h.in           include/ecp_${TC}.h           "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  if(TC STREQUAL "BLS381")
+    amcl_configure_file_curve(include/hash_to_field.h.in include/hash_to_field_${TC}.h "${curve}" amcl_curve_${TC}_GEN_HDRS)
+  endif()
 
-  amcl_configure_file_curve(src/big.c.in  src/big_${BD}.c  "${curve}" amcl_curve_${TC}_GEN_SRCS)
-  amcl_configure_file_curve(src/fp.c.in   src/fp_${TF}.c   "${curve}" amcl_curve_${TC}_GEN_SRCS)
-  amcl_configure_file_curve(src/ecp.c.in  src/ecp_${TC}.c  "${curve}" amcl_curve_${TC}_GEN_SRCS)
-  amcl_configure_file_curve(src/ecdh.c.in src/ecdh_${TC}.c "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  amcl_configure_file_curve(src/big.c.in           src/big_${BD}.c           "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  amcl_configure_file_curve(src/fp.c.in            src/fp_${TF}.c            "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  amcl_configure_file_curve(src/ecp.c.in           src/ecp_${TC}.c           "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  amcl_configure_file_curve(src/ecdh.c.in          src/ecdh_${TC}.c          "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  if(TC STREQUAL "BLS381")
+    amcl_configure_file_curve(src/hash_to_field.c.in src/hash_to_field_${TC}.c "${curve}" amcl_curve_${TC}_GEN_SRCS)
+  endif()
 
   message(STATUS "Build libamcl_curve_${TC}")
-  add_library(amcl_curve_${TC}
-    ${amcl_curve_${TC}_GEN_SRCS}
-    src/rom_curve_${TC}.c
-    src/rom_field_${TF}.c
-  )
+  if(TC STREQUAL "BLS381")
+    add_library(amcl_curve_${TC}
+      ${amcl_curve_${TC}_GEN_SRCS}
+      src/rom_curve_${TC}.c
+      src/rom_iso_${TC}.c
+      src/rom_field_${TF}.c
+    )
+  else()
+    add_library(amcl_curve_${TC}
+      ${amcl_curve_${TC}_GEN_SRCS}
+      src/rom_curve_${TC}.c
+      src/rom_field_${TF}.c
+    )
+  endif()
   list(APPEND AMCL_LIBRARIES amcl_curve_${TC})
 
   set_target_properties(amcl_curve_${TC} PROPERTIES
@@ -711,6 +732,55 @@ if(BUILD_BLS)
   endforeach()
 endif()
 
+##################################################
+# AMCL_BLS_IETF Library
+##################################################
+if(BUILD_BLS_IETF)
+  foreach(curve ${AMCL_CURVE})
+    amcl_curve_field(TC "${curve}")
+    amcl_curve_field(CS "${curve}")
+
+    if(TC STREQUAL "BLS381")
+        amcl_configure_file_curve(include/bls_ietf.h.in include/bls_ietf_${TC}.h "${curve}" amcl_bls_ietf_${TC}_GEN_HDRS)
+        amcl_configure_file_curve(src/bls_ietf.c.in     src/bls_ietf_${TC}.c     "${curve}" amcl_bls_ietf_${TC}_GEN_SRCS)
+
+      message(STATUS "Build libamcl_bls_ietf_${TC}")
+      add_library(amcl_bls_ietf_${TC}
+        ${amcl_bls_ietf_${TC}_GEN_SRCS}
+      )
+      list(APPEND AMCL_LIBRARIES amcl_bls_ietf_${TC})
+
+      set_target_properties(amcl_bls_ietf_${TC} PROPERTIES
+        EXPORT_NAME bls_ietf_${TC}
+        VERSION ${AMCL_VERSION}
+        SOVERSION ${AMCL_SOVERSION}
+      )
+
+      target_include_directories(amcl_bls_ietf_${TC} PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+      )
+
+      target_link_libraries(amcl_bls_ietf_${TC} PUBLIC
+        amcl_pairing_${TC}
+      )
+
+      install(TARGETS amcl_bls_ietf_${TC}
+        EXPORT AMCLTargets
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      )
+
+      install(FILES
+        ${amcl_bls_ietf_${TC}_GEN_HDRS}
+        DESTINATION ${INSTALL_INCLUDESUBDIR}
+      )
+    endif(TC STREQUAL "BLS381")
+  endforeach()
+endif()
+
 ##################################################
 # pkgconfig
 ##################################################
@@ -782,8 +852,10 @@ if(BUILD_EXAMPLES)
 endif()
 
 if(BUILD_PYTHON)
-  message(STATUS "Build Python wrappers")
-  add_subdirectory(python)
+  if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "ASan")
+    message(STATUS "Build Python wrappers")
+    add_subdirectory(python)
+  endif()
 endif()
 
 if(BUILD_TESTING)
diff --git a/Dockerfile b/Dockerfile
index 5f4e797..cdd8312 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,24 +1,62 @@
-FROM ubuntu:bionic
-
-RUN dpkg --add-architecture i386
-
-# add repositories cache
-RUN apt-get update -y
-
-# install packages
-RUN apt-get install -y \
-    build-essential \
-    cmake \
-    doxygen \
-    parallel \
-    mingw-w64 \
-    wine64 \
-    wine32 \
-    lcov \
-    python3-dev \
-    python3-pip \
-    gcc-multilib
-
-RUN pip3 install cffi autopep8
-
-CMD ["/bin/bash"]
+# Dockerfile
+#
+# Ubuntu 22.04 
+#
+# @author  Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
+# NOTES:
+#
+# Create the image:
+#     docker build -t libamcl .
+#
+# Run tests:
+#     docker run --rm libamcl ./scripts/test.sh
+#
+# Generate coverage figures:
+#     CONTAINER_ID=$(docker run -d libamcl ./scripts/coverage.sh)
+#     docker logs $CONTAINER_ID
+#     docker cp ${CONTAINER_ID}:"/root/target/Coverage/coverage" ./
+#     docker rm -f ${CONTAINER_ID} || true
+#
+# To login to container:
+#     docker run -it --rm libamcl bash
+# ------------------------------------------------------------------------------
+
+FROM ubuntu:22.04
+
+LABEL maintainer="kealanmccusker@gmail.com"
+
+WORKDIR /root
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+ENV LD_LIBRARY_PATH=/usr/local/lib:./
+
+ENV ASAN_OPTIONS=verify_asan_link_order=0
+
+RUN echo "## Start building" \
+    && echo "## Update and install packages" \
+    && apt-get -y update \
+    && apt-get install -y --no-install-recommends \
+        build-essential \
+	cmake \
+	doxygen \
+	lcov \
+	python3-dev \
+	python3-pip \
+	wget \
+	git \
+	libffi-dev \
+    && echo "## Done"
+
+RUN pip3 install cffi
+
+ADD . /root
+
+RUN ./scripts/build.sh
+
+RUN ./scripts/test.sh
+
+
diff --git a/README.md b/README.md
index 615570f..31be4c9 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,8 @@
 
 # AMCL - *Apache Milagro Crypto Library*
 
+[![Master Branch](https://img.shields.io/badge/-master:-gray.svg)](https://github.com/apache/incubator-milagro-crypto-c/tree/master)
+
 * **category**:    Library
 * **copyright**:   2019 The Apache Software Foundation
 * **license**:     ASL 2.0 ([Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0))
@@ -119,21 +121,23 @@ brew install parallel
 
 ##### Quick start
 
-Either clone the repository using Git:
+Clone the repository
 
 ```
 git clone https://github.com/apache/incubator-milagro-crypto-c.git
 cd incubator-milagro-crypto-c
 ```
 
-Or, if using an official Apache release, download the compressed archive, extract it and navigate into its root directory.
+Edit and run this script
+
+```
+./scripts/build.sh
+```
 
-A Makefile is present at the project root that reads the options defined in
-config.mk. Change these options and then type the following to build and test
-the library.
+or use the docker build
 
 ```
-make
+./scripts/docker.sh -h
 ```
 
 ##### Multiple curves and RSA security levels
@@ -167,6 +171,12 @@ make doc
 sudo make install
 ```
 
+NOTE: When running the ASan tests, make sure to export the following variable:
+
+```
+export ASAN_OPTIONS=verify_asan_link_order=0
+```
+
 On Debian/Ubuntu machine instead of executing the *"sudo make install"* command it is possible to execute *"sudo checkinstall"* to build and install a DEB package.
 
 Now you can set the path to where libs and python package are installed:
@@ -300,7 +310,7 @@ To format the code (please use this command before submitting any pull request):
 ```
 make format
 ```
-### Contributors
+### Contributors 
 
 The following people have contributed to milagro-crypto-c
 
diff --git a/amcl.pc.in b/amcl.pc.in
index 7b17086..c7e0f69 100644
--- a/amcl.pc.in
+++ b/amcl.pc.in
@@ -1,7 +1,7 @@
 prefix="@CMAKE_INSTALL_PREFIX@"
 exec_prefix=${prefix}
 libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
-includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/amcl
 
 Name: amcl
 Description: AMCL is a standards compliant C cryptographic library designed to support the Internet of Things (IoT).
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 782cbd4..1ef97ba 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -44,6 +44,11 @@ foreach(curve ${AMCL_CURVE})
   add_executable(benchtest_ec_${TC} ${benchtest_ec_${TC}_GEN_SRCS} $<TARGET_OBJECTS:amcl_bench_utils>)
   target_link_libraries(benchtest_ec_${TC} PRIVATE amcl_curve_${TC})
 
+  # ECDSA Benchmark
+  amcl_configure_file_curve(benchtest_ecdsa_ZZZ.c.in benchtest_ecdsa_${TC}.c "${curve}" benchtest_ecdsa_${TC}_GEN_SRCS)
+  add_executable(benchtest_ecdsa_${TC} ${benchtest_ecdsa_${TC}_GEN_SRCS} $<TARGET_OBJECTS:amcl_bench_utils>)
+  target_link_libraries(benchtest_ecdsa_${TC} PRIVATE amcl_curve_${TC})
+
   # Pairing Benchmark
   if(TARGET amcl_pairing_${TC})
     amcl_configure_file_curve(benchtest_pair_ZZZ.c.in benchtest_pair_${TC}.c "${curve}" benchtest_pair_${TC}_GEN_SRCS)
@@ -57,7 +62,14 @@ foreach(curve ${AMCL_CURVE})
     add_executable(benchtest_mpin_${TC} ${benchtest_mpin_${TC}_GEN_SRCS} $<TARGET_OBJECTS:amcl_bench_utils>)
     target_link_libraries(benchtest_mpin_${TC} PRIVATE amcl_mpin_${TC})
   endif()
-  
+
+  # BLS Benchmark
+  if(TARGET amcl_bls_${TC})
+    amcl_configure_file_curve(benchtest_bls_ZZZ.c.in benchtest_bls_${TC}.c "${curve}" benchtest_bls_${TC}_GEN_SRCS)
+    add_executable(benchtest_bls_${TC} ${benchtest_bls_${TC}_GEN_SRCS} $<TARGET_OBJECTS:amcl_bench_utils>)
+    target_link_libraries(benchtest_bls_${TC} PRIVATE amcl_bls_${TC})
+  endif()
+
 endforeach()
 
 foreach(level ${AMCL_RSA})
diff --git a/benchmark/bench.c.in b/benchmark/bench.c.in
index c49263b..a8924c3 100644
--- a/benchmark/bench.c.in
+++ b/benchmark/bench.c.in
@@ -78,7 +78,6 @@ static void print_platform_info()
 
 static void print_amcl_configuration()
 {
-    printf("Project Version:\t@BUILD_VERSION@\n");
     printf("CFLAGS:\t\t\t@CMAKE_C_FLAGS@\n");
     printf("Build type:\t\t@CMAKE_BUILD_TYPE@\n");
     printf("AMCL Version:\t\t%d.%d.%d\n", AMCL_VERSION_MAJOR, AMCL_VERSION_MINOR, AMCL_VERSION_PATCH);
diff --git a/benchmark/benchtest_bls_ZZZ.c.in b/benchmark/benchtest_bls_ZZZ.c.in
new file mode 100644
index 0000000..b9b941a
--- /dev/null
+++ b/benchmark/benchtest_bls_ZZZ.c.in
@@ -0,0 +1,133 @@
+/*
+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.
+*/
+
+/* Time BLS Protocol */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "config_curve_ZZZ.h"
+#include "randapi.h"
+#include "bench.h"
+
+#if CURVE_SECURITY_ZZZ == 128
+#include "bls_ZZZ.h"
+#elif CURVE_SECURITY_ZZZ == 192
+#include "bls192_ZZZ.h"
+#elif CURVE_SECURITY_ZZZ == 256
+#include "bls256_ZZZ.h"
+#endif
+
+// Support multiple security levels
+#if CURVE_SECURITY_ZZZ == 128
+#define G2LEN 4*BFS_ZZZ
+#elif CURVE_SECURITY_ZZZ == 192
+#define G2LEN 8*BFS_ZZZ
+#elif CURVE_SECURITY_ZZZ == 256
+#define G2LEN 16*BFS_ZZZ
+#endif
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10
+
+int bls(csprng *RNG)
+{
+    int rc;
+
+    char m[2000];
+    octet M = {0,sizeof(m),m};
+
+    char sk1[BGS_ZZZ];
+    octet SK1 = {0,sizeof(sk1),sk1};
+    char pk1[G2LEN];
+    octet PK1 = {0,sizeof(pk1),pk1};
+    char sig1[BFS_ZZZ+1];
+    octet SIG1 = {0,sizeof(sig1),sig1};
+
+    int iterations;
+    clock_t start;
+    double elapsed;
+
+    printf("\nBenchmark test BLS - ");
+
+    printf("ZZZ Curve\n");
+
+    print_system_info();
+
+    // Generate key pairs
+    BLS_ZZZ_KEY_PAIR_GENERATE(RNG,&SK1,&PK1);
+
+    OCT_jstring(&M,"test message");
+
+    // Sign the message
+    iterations=0;
+    start=clock();
+    do
+    {
+      BLS_ZZZ_SIGN(&SIG1,&M,&SK1);
+      iterations++;
+      elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
+    }
+    while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("BLS_ZZZ_SIGN \t %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    // Verify signature
+    iterations=0;
+    start=clock();
+    do
+    {
+      rc=BLS_ZZZ_VERIFY(&SIG1,&M,&PK1);
+      if (rc!=BLS_OK)
+	{
+	  printf("Error: Invalid Signature\n");
+          return 1;
+	}
+      iterations++;
+      elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
+    }
+    while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("BLS_ZZZ_VERIFY \t %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    return 0;
+}
+
+int main()
+{
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    char seed[16] = {0};
+    octet SEED = {sizeof(seed),sizeof(seed),seed};
+
+    // CSPRNG
+    csprng RNG;
+
+    // fake random source
+    OCT_fromHex(&SEED,seedHex);
+
+    /* initialise strong RNG */
+    CREATE_CSPRNG(&RNG,&SEED);
+
+    bls(&RNG);
+
+    KILL_CSPRNG(&RNG);
+}
+
diff --git a/benchmark/benchtest_ec_ZZZ.c.in b/benchmark/benchtest_ec_ZZZ.c.in
index 4994062..e00a367 100644
--- a/benchmark/benchtest_ec_ZZZ.c.in
+++ b/benchmark/benchtest_ec_ZZZ.c.in
@@ -38,15 +38,18 @@ int main()
 #if CURVETYPE_ZZZ!=MONTGOMERY
     BIG_XXX y;
 #endif
-    BIG_XXX s,r,x;
-    ECP_ZZZ P,G;
-    int i,iterations;
+    BIG_XXX s;
+    BIG_XXX r;
+    BIG_XXX x;
+    ECP_ZZZ P;
+    ECP_ZZZ G;
+    int iterations;
     clock_t start;
     double elapsed;
     char pr[10];
-    unsigned long ran;
+    time_t ran;
 
-    printf("\nBechmark test EC - ");
+    printf("\nBenchmark test EC - ");
 
     printf("ZZZ Curve\n");
 
@@ -62,12 +65,12 @@ int main()
 
     print_system_info();
 
-    time((time_t *)&ran);
-    pr[0]=ran;
-    pr[1]=ran>>8;
-    pr[2]=ran>>16;
-    pr[3]=ran>>24;
-    for (i=4; i<10; i++) pr[i]=i;
+    time(&ran);
+    pr[0]=(char)ran;
+    pr[1]=(char)(ran>>4);
+    pr[2]=(char)(ran>>12);
+    pr[3]=(char)(ran>>16);
+    for (int i=4; i<10; i++) pr[i]=(char)i;
     RAND_seed(&RNG,10,pr);
 
     BIG_XXX_rcopy(x,CURVE_Gx_ZZZ);
@@ -97,7 +100,7 @@ int main()
         ECP_ZZZ_mul(&P,s);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
diff --git a/benchmark/benchtest_ecdsa_ZZZ.c.in b/benchmark/benchtest_ecdsa_ZZZ.c.in
new file mode 100644
index 0000000..29e140d
--- /dev/null
+++ b/benchmark/benchtest_ecdsa_ZZZ.c.in
@@ -0,0 +1,138 @@
+/*
+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.
+*/
+
+/* Time ECDSA Protocol */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ecdh_ZZZ.h"
+#include "ecdh_support.h"
+#include "randapi.h"
+#include "bench.h"
+
+#define MIN_TIME 10.0
+#define MIN_ITERS 10
+
+int ecdsa(csprng *RNG)
+{
+    int rc;
+
+    char m[2000];
+    octet M = {0,sizeof(m),m};
+
+    char s0[2*EGS_ZZZ];
+    octet S0= {0,sizeof(s0),s0};
+
+    char w0[2*EFS_ZZZ+1];
+    octet W0= {0,sizeof(w0),w0};
+
+    char ds[EGS_ZZZ];
+    octet DS= {0,sizeof(ds),ds};
+
+    char cs[EGS_ZZZ];
+    octet CS= {0,sizeof(cs),cs};
+
+    int iterations;
+    clock_t start;
+    double elapsed;
+
+    printf("\nBenchmark test ECDSA - ");
+
+    printf("ZZZ Curve\n");
+
+    print_system_info();
+
+    // Generate key pair
+    ECP_ZZZ_KEY_PAIR_GENERATE(RNG,&S0,&W0);
+    rc=ECP_ZZZ_PUBLIC_KEY_VALIDATE(&W0);
+    if (rc!=0)
+    {
+        printf("ECP Public Key is invalid!\n");
+        return 0;
+    }
+
+
+#if CURVETYPE_ZZZ != MONTGOMERY
+
+    OCT_jstring(&M,"test message");
+
+    // Sign the message
+    iterations=0;
+    start=clock();
+    do
+    {
+      rc=ECP_ZZZ_SP_DSA(HASH_TYPE_ZZZ,RNG,NULL,&S0,&M,&CS,&DS);
+      if (rc!=0)
+	{
+	  printf("Error: ECP_ZZZ_SP_DSA\n");
+          return 1;
+	}
+      iterations++;
+      elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
+    }
+    while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("ECDSA Signing \t %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+    // Verify signature
+    iterations=0;
+    start=clock();
+    do
+    {
+      rc=ECP_ZZZ_VP_DSA(HASH_TYPE_ZZZ,&W0,&M,&CS,&DS);
+      if (rc!=0)
+	{
+	  printf("Error: ECP_ZZZ_VP_DSA\n");
+          return 1;
+	}
+      iterations++;
+      elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
+    }
+    while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+    elapsed=1000.0*elapsed/iterations;
+    printf("ECDSA Verification \t %8d iterations  ",iterations);
+    printf(" %8.2lf ms per iteration\n",elapsed);
+
+#endif
+
+    return 0;
+}
+
+int main()
+{
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    char seed[16] = {0};
+    octet SEED = {sizeof(seed),sizeof(seed),seed};
+
+    // CSPRNG
+    csprng RNG;
+
+    // fake random source
+    OCT_fromHex(&SEED,seedHex);
+
+    /* initialise strong RNG */
+    CREATE_CSPRNG(&RNG,&SEED);
+
+    ecdsa(&RNG);
+
+    KILL_CSPRNG(&RNG);
+}
+
diff --git a/benchmark/benchtest_ff_WWW.c.in b/benchmark/benchtest_ff_WWW.c.in
index 537d551..0656310 100644
--- a/benchmark/benchtest_ff_WWW.c.in
+++ b/benchmark/benchtest_ff_WWW.c.in
@@ -48,8 +48,14 @@ int main()
     double elapsed;
 
     // Material for exponents
-    BIG_XXX A[FFLEN_WWW], B[FFLEN_WWW], C[FFLEN_WWW], D[FFLEN_WWW];
-    BIG_XXX E[FFLEN_WWW], F[FFLEN_WWW], G[FFLEN_WWW], H[FFLEN_WWW];
+    BIG_XXX A[FFLEN_WWW];
+    BIG_XXX B[FFLEN_WWW];
+    BIG_XXX C[FFLEN_WWW];
+    BIG_XXX D[FFLEN_WWW];
+    BIG_XXX E[FFLEN_WWW];
+    BIG_XXX F[FFLEN_WWW];
+    BIG_XXX G[FFLEN_WWW];
+    BIG_XXX H[FFLEN_WWW];
     BIG_XXX N[FFLEN_WWW];
     BIG_XXX R[FFLEN_WWW];
 
@@ -72,12 +78,11 @@ int main()
     octet OCT = {0,sizeof(oct),oct};
 
     /* Fake random source */
-    int i;
     char seed[256];
     csprng RNG;
 
     RAND_clean(&RNG);
-    for (i=0; i<256; i++) seed[i]=(char)i;
+    for (int i=0; i<256; i++) seed[i]=(char)i;
     RAND_seed(&RNG,256,seed);
 
     /* Read N from hex */
@@ -87,7 +92,7 @@ int main()
     /* Compute additional values */
     FF_WWW_invmod2m(ND, N, FFLEN_WWW);
 
-    printf("\nBechmark FF exponentiation - FF_WWW\n");
+    printf("\nBenchmark FF exponentiation - FF_WWW\n");
 
     print_system_info();
 
@@ -109,7 +114,7 @@ int main()
     {
         FF_WWW_nt_pow(R, A, E, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -122,7 +127,7 @@ int main()
     {
         FF_WWW_nt_pow_2(R, A, E, B, F, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -135,7 +140,7 @@ int main()
     {
         FF_WWW_nt_pow_3(R, A, E, B, F, C, G, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -148,14 +153,14 @@ int main()
     {
         FF_WWW_nt_pow_4(R, A, E, B, F, C, G, D, H, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
     printf("FF_WWW_nt_pow_4\t%8d iterations\t",iterations);
     printf("%8.2lf ms per iteration\n",elapsed);
 
-    /* Benchmark constant-time exponenets */
+    /* Benchmark constant-time exponents */
 
     iterations=0;
     start=clock();
@@ -163,7 +168,7 @@ int main()
     {
         FF_WWW_ct_pow(R, A, E, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -176,7 +181,7 @@ int main()
     {
         FF_WWW_ct_pow_2(R, A, E, B, F, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -189,7 +194,7 @@ int main()
     {
         FF_WWW_ct_pow_3(R, A, E, B, F, C, G, N, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -204,7 +209,7 @@ int main()
     {
         FF_WWW_2w_precompute(X, T, 4, 1, N, ND, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -217,7 +222,7 @@ int main()
     {
         FF_WWW_ct_2w_pow(R, T, EXP, 4, 1, N, ND, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -230,7 +235,7 @@ int main()
     {
         FF_WWW_nt_2w_pow(R, T, EXP, 4, 1, N, ND, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -243,7 +248,7 @@ int main()
     {
         FF_WWW_bi_precompute(X, T, 4, 3, N, ND, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -256,7 +261,7 @@ int main()
     {
         FF_WWW_bi_pow(R, T, EXP, 4, 3, N, ND, FFLEN_WWW, FFLEN_WWW);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
diff --git a/benchmark/benchtest_mpin_ZZZ.c.in b/benchmark/benchtest_mpin_ZZZ.c.in
index 1a8af0f..fdf5b4a 100644
--- a/benchmark/benchtest_mpin_ZZZ.c.in
+++ b/benchmark/benchtest_mpin_ZZZ.c.in
@@ -48,13 +48,34 @@ under the License.
 
 int mpin(csprng *RNG)
 {
-    int pin,rtn;
+    int pin;
+    int rtn;
     int date=0;
-    char x[PGS_ZZZ],s[PGS_ZZZ],y[PGS_ZZZ],client_id[100],sst[G2LEN],token[2*PFS_ZZZ+1],sec[2*PFS_ZZZ+1],permit[2*PFS_ZZZ+1],xcid[2*PFS_ZZZ+1],xid[2*PFS_ZZZ+1],e[GTLEN],f[GTLEN];
-    char hcid[PFS_ZZZ],hsid[PFS_ZZZ],hid[2*PFS_ZZZ+1],htid[2*PFS_ZZZ+1],h[PGS_ZZZ];
-    char r[PGS_ZZZ],z[2*PFS_ZZZ+1],w[PGS_ZZZ],t[2*PFS_ZZZ+1];
-    char g1[GTLEN],g2[GTLEN];
-    char ck[AESKEY_ZZZ],sk[AESKEY_ZZZ];
+    char x[PGS_ZZZ];
+    char s[PGS_ZZZ];
+    char y[PGS_ZZZ];
+    char client_id[100];
+    char sst[G2LEN];
+    char token[2*PFS_ZZZ+1];
+    char sec[2*PFS_ZZZ+1];
+    char permit[2*PFS_ZZZ+1];
+    char xcid[2*PFS_ZZZ+1];
+    char xid[2*PFS_ZZZ+1];
+    char e[GTLEN];
+    char f[GTLEN];
+    char hcid[PFS_ZZZ];
+    char hsid[PFS_ZZZ];
+    char hid[2*PFS_ZZZ+1];
+    char htid[2*PFS_ZZZ+1];
+    char h[PGS_ZZZ];
+    char r[PGS_ZZZ];
+    char z[2*PFS_ZZZ+1];
+    char w[PGS_ZZZ];
+    char t[2*PFS_ZZZ+1];
+    char g1[GTLEN];
+    char g2[GTLEN];
+    char ck[AESKEY_ZZZ];
+    char sk[AESKEY_ZZZ];
     octet S= {0,sizeof(s),s};
     octet X= {0,sizeof(x),x};
     octet Y= {0,sizeof(y),y};
@@ -80,14 +101,20 @@ int mpin(csprng *RNG)
     octet G2= {0,sizeof(g2),g2};
     octet SK= {0,sizeof(sk),sk};
     octet CK= {0,sizeof(ck),ck};
-    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    octet *pxID;
+    octet *pxCID;
+    octet *pHID;
+    octet *pHTID;
+    octet *pE;
+    octet *pF;
+    const octet *prHID;
     char idhex[100];
 
     int iterations;
     clock_t start;
     double elapsed;
 
-    printf("\nBechmark test MPIN - ");
+    printf("\nBenchmark test MPIN - ");
 
     printf("ZZZ Curve\n");
 
@@ -107,7 +134,7 @@ int mpin(csprng *RNG)
     printf("\n");
 
     OCT_toHex(&CLIENT_ID,idhex);
-    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+    printf("Client ID= %s\n",idhex);
 
     /* Client and Server are issued secrets by DTA */
     MPIN_ZZZ_GET_SERVER_SECRET(&S,&SST);
@@ -129,15 +156,9 @@ int mpin(csprng *RNG)
 
     /* MPin Protocol */
     pxID=&xID;
-    pxCID=&xCID;
     pHID=&HID;
-    pHTID=&HTID;
-    pE=&E;
-    pF=&F;
-    pPERMIT=&PERMIT;
 
     prHID=pHID;
-    pPERMIT=NULL;
     pxCID=NULL;
     pHTID=NULL;
     pE=NULL;
@@ -151,10 +172,10 @@ int mpin(csprng *RNG)
     start=clock();
     do
     {
-        MPIN_ZZZ_CLIENT(HASH_TYPE_ZZZ,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,pPERMIT,NULL,timeValue,&Y);
+        MPIN_ZZZ_CLIENT(HASH_TYPE_ZZZ,date,&CLIENT_ID,RNG,&X,pin,&TOKEN,&SEC,pxID,pxCID,NULL,NULL,timeValue,&Y);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -171,7 +192,7 @@ int mpin(csprng *RNG)
         rtn = MPIN_ZZZ_SERVER(HASH_TYPE_ZZZ,date,pHID,pHTID,&Y,&SST,pxID,pxCID,&SEC,pE,pF,&CLIENT_ID,NULL,timeValue,NULL);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -235,23 +256,22 @@ int mpin(csprng *RNG)
 
 int main()
 {
-    int i;
-    unsigned long ran;
+    time_t ran;
 
     char raw[100];
     octet RAW= {0,sizeof(raw),raw};
     /* Crypto Strong RNG */
     csprng RNG;
 
-    time((time_t *)&ran);
+    time(&ran);
 
     /* fake random seed source */
     RAW.len=100;
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=0; i<100; i++) RAW.val[i]=i+1;
+    RAW.val[0]=(char)ran;
+    RAW.val[1]=(char)(ran>>4);
+    RAW.val[2]=(char)(ran>>12);
+    RAW.val[3]=(char)(ran>>16);
+    for (int i=0; i<100; i++) RAW.val[i]=(char)(i+1);
 
     /* initialise strong RNG */
     CREATE_CSPRNG(&RNG,&RAW);
diff --git a/benchmark/benchtest_paillier.c.in b/benchmark/benchtest_paillier.c.in
index f10511b..31c4700 100644
--- a/benchmark/benchtest_paillier.c.in
+++ b/benchmark/benchtest_paillier.c.in
@@ -109,7 +109,7 @@ int paillier(csprng *RNG)
     {
         PAILLIER_KEY_PAIR(RNG, NULL, NULL,&PUB, &PRIV);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -135,7 +135,7 @@ int paillier(csprng *RNG)
     {
         PAILLIER_ENCRYPT(RNG, &PUB, &PTIN[0], &CT[0], NULL);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -144,14 +144,14 @@ int paillier(csprng *RNG)
 
     PAILLIER_ENCRYPT(RNG, &PUB, &PTIN[1], &CT[1], NULL);
 
-    // Multiple by constant
+    // Multiply by constant
     iterations=0;
     start=clock();
     do
     {
         PAILLIER_MULT(&PUB, &CT[0], &PTK[0], &CTA[0]);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -167,7 +167,7 @@ int paillier(csprng *RNG)
     {
         PAILLIER_ADD(&PUB, &CTA[0], &CTA[1], &CT3);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -181,7 +181,7 @@ int paillier(csprng *RNG)
     {
         PAILLIER_DECRYPT(&PRIV, &CT3, &PT3);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -219,7 +219,7 @@ int paillier(csprng *RNG)
 
 int main()
 {
-    char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
     char seed[16] = {0};
     octet SEED = {sizeof(seed),sizeof(seed),seed};
 
diff --git a/benchmark/benchtest_pair_ZZZ.c.in b/benchmark/benchtest_pair_ZZZ.c.in
index 0be66ff..a7411e9 100644
--- a/benchmark/benchtest_pair_ZZZ.c.in
+++ b/benchmark/benchtest_pair_ZZZ.c.in
@@ -78,19 +78,19 @@
 int main()
 {
     csprng RNG;
-    unsigned long ran;
+    time_t ran;
     char pr[10];
 
     printf("Bechmark test PAIR - ZZZ Curve\n");
 
     print_system_info();
 
-    time((time_t *)&ran);
-    pr[0]=ran;
-    pr[1]=ran>>8;
-    pr[2]=ran>>16;
-    pr[3]=ran>>24;
-    for (int i=4; i<10; i++) pr[i]=i;
+    time(&ran);
+    pr[0]=(char)ran;
+    pr[1]=(char)(ran>>4);
+    pr[2]=(char)(ran>>12);
+    pr[3]=(char)(ran>>16);
+    for (int i=4; i<10; i++) pr[i]=(char)i;
 
     RAND_seed(&RNG,10,pr);
 
@@ -98,22 +98,30 @@ int main()
     clock_t start;
     double elapsed;
 
-    ECP_ZZZ P,G;
+    ECP_ZZZ P;
+    ECP_ZZZ G;
 #if CURVE_SECURITY_ZZZ == 128
-    ECP2_ZZZ Q,W;
-    FP12_YYY g,w;
+    ECP2_ZZZ Q;
+    ECP2_ZZZ W;
+    FP12_YYY g;
+    FP12_YYY w;
     FP4_YYY cm;
 #elif CURVE_SECURITY_ZZZ == 192
-    ECP4_ZZZ Q,W;
-    FP24_YYY g,w;
+    ECP4_ZZZ Q;
+    ECP4_ZZZ W;
+    FP24_YYY g;
+    FP24_YYY w;
     FP8_YYY cm;
 #elif CURVE_SECURITY_ZZZ == 256
-    ECP8_ZZZ Q,W;
-    FP48_YYY g,w;
+    ECP8_ZZZ Q;
+    ECP8_ZZZ W;
+    FP48_YYY g;
+    FP48_YYY w;
     FP16_YYY cm;
 #endif
 
-    BIG_XXX s,r;
+    BIG_XXX s;
+    BIG_XXX r;
     printf("\nTesting/Timing ZZZ Pairings\n");
 
     ECP_ZZZ_generator(&G);
@@ -137,7 +145,7 @@ int main()
         PAIR_ZZZ_G1mul(&P,s);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -163,7 +171,7 @@ int main()
         PAIR_ZZZ_G2mul(&Q,s);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -191,7 +199,7 @@ int main()
         PAIR_ZZZ_GTpow(&g,s);
 
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -206,7 +214,7 @@ int main()
     {
         GT_ZZZ_compow(&cm,&g,s,r);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -219,7 +227,7 @@ int main()
     {
         PAIR_ZZZ_ate(&w,&Q,&P);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -233,7 +241,7 @@ int main()
         GT_ZZZ_copy(&g,&w);
         PAIR_ZZZ_fexp(&g);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
diff --git a/benchmark/benchtest_rsa_WWW.c.in b/benchmark/benchtest_rsa_WWW.c.in
index 4e803ed..4aa0014 100644
--- a/benchmark/benchtest_rsa_WWW.c.in
+++ b/benchmark/benchtest_rsa_WWW.c.in
@@ -37,27 +37,30 @@ int main()
 {
     csprng RNG;
 
-    int i,iterations;
+    int i;
+    int iterations;
     clock_t start;
     double elapsed;
     char pr[10];
 
-    unsigned long ran;
+    time_t ran;
     rsa_public_key_WWW pub;
     rsa_private_key_WWW priv;
-    char m[RFS_WWW],d[RFS_WWW],c[RFS_WWW];
+    char m[RFS_WWW];
+    char d[RFS_WWW];
+    char c[RFS_WWW];
     octet M= {0,sizeof(m),m};
     octet D= {0,sizeof(d),d};
     octet C= {0,sizeof(c),c};
 
     print_system_info();
 
-    time((time_t *)&ran);
-    pr[0]=ran;
-    pr[1]=ran>>8;
-    pr[2]=ran>>16;
-    pr[3]=ran>>24;
-    for (i=4; i<10; i++) pr[i]=i;
+    time(&ran);
+    pr[0]=(char)ran;
+    pr[1]=(char)(ran>>4);
+    pr[2]=(char)(ran>>12);
+    pr[3]=(char)(ran>>16);
+    for (i=4; i<10; i++) pr[i]=(char)i;
     RAND_seed(&RNG,10,pr);
 
     printf("Generating %d-bit RSA public/private key pair\n",FFLEN_WWW*BIGBITS_XXX);
@@ -68,17 +71,15 @@ int main()
     {
         RSA_WWW_KEY_PAIR(&RNG,65537,&priv,&pub,NULL,NULL);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
     printf("RSA gen - %8d iterations  ",iterations);
     printf(" %8.2lf ms per iteration\n",elapsed);
 
-    //FF_randomnum(plain,pub.n,&RNG,FFLEN);
-
     M.len=RFS_WWW;
-    for (i=0; i<RFS_WWW; i++) M.val[i]=i%128;
+    for (i=0; i<RFS_WWW; i++) M.val[i]=(char)(i%128);
 
     iterations=0;
     start=clock();
@@ -86,7 +87,7 @@ int main()
     {
         RSA_WWW_ENCRYPT(&pub,&M,&C);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
@@ -99,7 +100,7 @@ int main()
     {
         RSA_WWW_DECRYPT(&priv,&C,&D);
         iterations++;
-        elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+        elapsed=(double)(clock()-start)/(double)CLOCKS_PER_SEC;
     }
     while (elapsed<MIN_TIME || iterations<MIN_ITERS);
     elapsed=1000.0*elapsed/iterations;
diff --git a/cmake/AMCLParameters.cmake b/cmake/AMCLParameters.cmake
index b9f8a93..09f0940 100644
--- a/cmake/AMCLParameters.cmake
+++ b/cmake/AMCLParameters.cmake
@@ -34,65 +34,65 @@ cmake_minimum_required(VERSION 3.1)
 #######################################
 # AMCL Curve parameters
 #######################################
-set(AMCL_CURVE_FIELDS        TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS )
-set(AMCL_CURVE_64_ED25519    256 25519      ED25519    32  56   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_C25519     256 25519      C25519     32  56   255 5  PSEUDO_MERSENNE      MONTGOMERY  NOT .      .         128)
-set(AMCL_CURVE_64_NIST256    256 NIST256    NIST256    32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_BRAINPOOL  256 BRAINPOOL  BRAINPOOL  32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_ANSSI      256 ANSSI      ANSSI      32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_HIFIVE     336 HIFIVE     HIFIVE     42  60   336 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_GOLDILOCKS 448 GOLDILOCKS GOLDILOCKS 56  58   448 7  GENERALISED_MERSENNE EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_NIST384    384 NIST384    NIST384    48  56   384 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_C41417     416 C41417     C41417     52  60   414 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_NIST521    528 NIST521    NIST521    66  60   521 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_NUMS256W   256 256PMW     NUMS256W   32  56   256 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_NUMS256E   256 256PME     NUMS256E   32  56   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_NUMS384W   384 384PM      NUMS384W   48  56   384 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_NUMS384E   384 384PM      NUMS384E   48  56   384 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_NUMS512W   512 512PM      NUMS512W   64  56   512 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_NUMS512E   512 512PM      NUMS512E   64  56   512 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_64_SECP256K1  256 SECP256K1  SECP256K1  32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_64_BN254      256 BN254      BN254      32  56   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_64_BN254CX    256 BN254CX    BN254CX    32  56   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_64_BLS381     384 BLS381     BLS381     48  58   381 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_64_BLS383     384 BLS383     BLS383     48  58   383 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 128)
-set(AMCL_CURVE_64_BLS24      480 BLS24      BLS24      60  56   479 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 192)
-set(AMCL_CURVE_64_BLS48      560 BLS48      BLS48      70  58   556 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 256)
-set(AMCL_CURVE_64_FP256BN    256 FP256BN    FP256BN    32  56   256 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_64_FP512BN    512 FP512BN    FP512BN    64  60   512 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE POSITIVEX 128)
-set(AMCL_CURVE_64_BLS461     464 BLS461     BLS461     58  60   461 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128)
-#  (                         TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS )
-set(AMCL_CURVE_32_ED25519    256 25519      ED25519    32  29   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_C25519     256 25519      C25519     32  29   255 5  PSEUDO_MERSENNE      MONTGOMERY  NOT .      .         128)
-set(AMCL_CURVE_32_NIST256    256 NIST256    NIST256    32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_BRAINPOOL  256 BRAINPOOL  BRAINPOOL  32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_ANSSI      256 ANSSI      ANSSI      32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_HIFIVE     336 HIFIVE     HIFIVE     42  29   336 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_GOLDILOCKS 448 GOLDILOCKS GOLDILOCKS 56  29   448 7  GENERALISED_MERSENNE EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_NIST384    384 NIST384    NIST384    48  29   384 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_C41417     416 C41417     C41417     52  29   414 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_NIST521    528 NIST521    NIST521    66  28   521 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_NUMS256W   256 256PMW     NUMS256W   32  28   256 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_NUMS256E   256 256PME     NUMS256E   32  29   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_NUMS384W   384 384PM      NUMS384W   48  29   384 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_NUMS384E   384 384PM      NUMS384E   48  29   384 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_NUMS512W   512 512PM      NUMS512W   64  29   512 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_NUMS512E   512 512PM      NUMS512E   64  29   512 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_32_SECP256K1  256 SECP256K1  SECP256K1  32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128)
-set(AMCL_CURVE_32_BN254      256 BN254      BN254      32  28   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_32_BN254CX    256 BN254CX    BN254CX    32  28   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_32_BLS381     384 BLS381     BLS381     48  29   381 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_32_BLS383     384 BLS383     BLS383     48  29   383 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 128)
-set(AMCL_CURVE_32_BLS24      480 BLS24      BLS24      60  29   479 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 192)
-set(AMCL_CURVE_32_BLS48      560 BLS48      BLS48      70  29   556 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 256)
-set(AMCL_CURVE_32_FP256BN    256 FP256BN    FP256BN    32  28   256 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_32_FP512BN    512 FP512BN    FP512BN    64  29   512 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE POSITIVEX 128)
-set(AMCL_CURVE_32_BLS461     464 BLS461     BLS461     58  28   461 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128)
-#  (                         TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS )
-set(AMCL_CURVE_16_ED25519    256 25519      ED25519    32  13   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_16_NUMS256E   256 256PME     NUMS256E   32  13   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128)
-set(AMCL_CURVE_16_BN254      256 BN254      BN254      32  13   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
-set(AMCL_CURVE_16_BN254CX    256 BN254CX    BN254CX    32  13   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128)
+set(AMCL_CURVE_FIELDS        TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS  AB)
+set(AMCL_CURVE_64_ED25519    256 25519      ED25519    32  56   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_C25519     256 25519      C25519     32  56   255 5  PSEUDO_MERSENNE      MONTGOMERY  NOT .      .         128 . )
+set(AMCL_CURVE_64_NIST256    256 NIST256    NIST256    32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_BRAINPOOL  256 BRAINPOOL  BRAINPOOL  32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_ANSSI      256 ANSSI      ANSSI      32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_HIFIVE     336 HIFIVE     HIFIVE     42  60   336 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_GOLDILOCKS 448 GOLDILOCKS GOLDILOCKS 56  58   448 7  GENERALISED_MERSENNE EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_NIST384    384 NIST384    NIST384    48  56   384 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_C41417     416 C41417     C41417     52  60   414 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_NIST521    528 NIST521    NIST521    66  60   521 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS256W   256 256PMW     NUMS256W   32  56   256 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS256E   256 256PME     NUMS256E   32  56   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS384W   384 384PM      NUMS384W   48  56   384 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS384E   384 384PM      NUMS384E   48  56   384 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS512W   512 512PM      NUMS512W   64  56   512 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_NUMS512E   512 512PM      NUMS512E   64  56   512 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_64_SECP256K1  256 SECP256K1  SECP256K1  32  56   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_64_BN254      256 BN254      BN254      32  56   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_64_BN254CX    256 BN254CX    BN254CX    32  56   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_64_BLS381     384 BLS381     BLS381     48  58   381 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128 65)
+set(AMCL_CURVE_64_BLS383     384 BLS383     BLS383     48  58   383 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 128 . )
+set(AMCL_CURVE_64_BLS24      480 BLS24      BLS24      60  56   479 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 192 . )
+set(AMCL_CURVE_64_BLS48      560 BLS48      BLS48      70  58   556 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 256 . )
+set(AMCL_CURVE_64_FP256BN    256 FP256BN    FP256BN    32  56   256 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_64_FP512BN    512 FP512BN    FP512BN    64  60   512 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE POSITIVEX 128 . )
+set(AMCL_CURVE_64_BLS461     464 BLS461     BLS461     58  60   461 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128 . )
+#  (                         TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS  AB)
+set(AMCL_CURVE_32_ED25519    256 25519      ED25519    32  29   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_C25519     256 25519      C25519     32  29   255 5  PSEUDO_MERSENNE      MONTGOMERY  NOT .      .         128 . )
+set(AMCL_CURVE_32_NIST256    256 NIST256    NIST256    32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_BRAINPOOL  256 BRAINPOOL  BRAINPOOL  32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_ANSSI      256 ANSSI      ANSSI      32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_HIFIVE     336 HIFIVE     HIFIVE     42  29   336 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_GOLDILOCKS 448 GOLDILOCKS GOLDILOCKS 56  29   448 7  GENERALISED_MERSENNE EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_NIST384    384 NIST384    NIST384    48  29   384 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_C41417     416 C41417     C41417     52  29   414 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_NIST521    528 NIST521    NIST521    66  28   521 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS256W   256 256PMW     NUMS256W   32  28   256 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS256E   256 256PME     NUMS256E   32  29   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS384W   384 384PM      NUMS384W   48  29   384 3  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS384E   384 384PM      NUMS384E   48  29   384 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS512W   512 512PM      NUMS512W   64  29   512 7  PSEUDO_MERSENNE      WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_NUMS512E   512 512PM      NUMS512E   64  29   512 7  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_32_SECP256K1  256 SECP256K1  SECP256K1  32  28   256 7  NOT_SPECIAL          WEIERSTRASS NOT .      .         128 . )
+set(AMCL_CURVE_32_BN254      256 BN254      BN254      32  28   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_32_BN254CX    256 BN254CX    BN254CX    32  28   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_32_BLS381     384 BLS381     BLS381     48  29   381 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128 65)
+set(AMCL_CURVE_32_BLS383     384 BLS383     BLS383     48  29   383 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 128 . )
+set(AMCL_CURVE_32_BLS24      480 BLS24      BLS24      60  29   479 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 192 . )
+set(AMCL_CURVE_32_BLS48      560 BLS48      BLS48      70  29   556 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE POSITIVEX 256 . )
+set(AMCL_CURVE_32_FP256BN    256 FP256BN    FP256BN    32  28   256 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_32_FP512BN    512 FP512BN    FP512BN    64  29   512 3  NOT_SPECIAL          WEIERSTRASS BN  M_TYPE POSITIVEX 128 . )
+set(AMCL_CURVE_32_BLS461     464 BLS461     BLS461     58  28   461 3  NOT_SPECIAL          WEIERSTRASS BLS M_TYPE NEGATIVEX 128 . )
+#  (                         TB  TF         TC         NB  BASE NBT M8 MT                   CT          PF  ST     SX        CS  AB)
+set(AMCL_CURVE_16_ED25519    256 25519      ED25519    32  13   255 5  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_16_NUMS256E   256 256PME     NUMS256E   32  13   256 3  PSEUDO_MERSENNE      EDWARDS     NOT .      .         128 . )
+set(AMCL_CURVE_16_BN254      256 BN254      BN254      32  13   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
+set(AMCL_CURVE_16_BN254CX    256 BN254CX    BN254CX    32  13   254 3  NOT_SPECIAL          WEIERSTRASS BN  D_TYPE NEGATIVEX 128 . )
 
 #######################################
 # AMCL RSA parameters
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 7c5445a..df41320 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -2509,15 +2509,6 @@ MAX_DOT_GRAPH_DEPTH    = 0
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10) support
-# this, this feature is disabled by default.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
 DOT_MULTI_TARGETS      = NO
 
 # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index d22cffe..8ffcc97 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -50,12 +50,12 @@ foreach(curve ${AMCL_CURVE})
     amcl_configure_file_curve(example_bls_ZZZ.c.in example_bls_${TC}.c "${curve}" example_bls_${TC}_GEN_SRCS)
     add_executable(example_bls_${TC} ${example_bls_${TC}_GEN_SRCS})
     target_link_libraries(example_bls_${TC} PRIVATE amcl_bls_${TC})
-    
+
     amcl_configure_file_curve(example_bls_sss_ZZZ.c.in example_bls_sss_${TC}.c "${curve}" example_bls_sss_${TC}_GEN_SRCS)
     add_executable(example_bls_sss_${TC} ${example_bls_sss_${TC}_GEN_SRCS})
     target_link_libraries(example_bls_sss_${TC} PRIVATE amcl_bls_${TC})
   endif()
-  
+
 endforeach()
 
 foreach(level ${AMCL_RSA})
diff --git a/examples/example_bls_ZZZ.c.in b/examples/example_bls_ZZZ.c.in
index 27111d6..3b60f56 100644
--- a/examples/example_bls_ZZZ.c.in
+++ b/examples/example_bls_ZZZ.c.in
@@ -21,7 +21,7 @@ under the License.
 
   Build executable after installation:
 
-  1. Change headers;
+  1. Change headers
 
     #include "bls_ZZZ.h" -> #include <amcl/bls_ZZZ.h>
 
@@ -274,7 +274,7 @@ int main()
     printf("%d bit build\n",CHUNK);
 #endif
 
-    char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
     char seed[16] = {0};
     octet SEED = {sizeof(seed),sizeof(seed),seed};
 
diff --git a/examples/example_bls_sss_ZZZ.c.in b/examples/example_bls_sss_ZZZ.c.in
index b9c0aeb..3c15705 100644
--- a/examples/example_bls_sss_ZZZ.c.in
+++ b/examples/example_bls_sss_ZZZ.c.in
@@ -21,7 +21,7 @@ under the License.
 
   Build executable after installation:
 
-  1. Change headers;
+  1. Change headers
 
     #include "bls_ZZZ.h" -> #include <amcl/bls_ZZZ.h>
 
@@ -221,7 +221,7 @@ int main()
     printf("%d bit build\n",CHUNK);
 #endif
 
-    char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
     char seed[16] = {0};
     octet SEED = {sizeof(seed),sizeof(seed),seed};
 
diff --git a/examples/example_dvs_ZZZ.c.in b/examples/example_dvs_ZZZ.c.in
index d706595..3888885 100644
--- a/examples/example_dvs_ZZZ.c.in
+++ b/examples/example_dvs_ZZZ.c.in
@@ -50,7 +50,9 @@ under the License.
 
 int main()
 {
-    int i,PIN1,PIN2,rtn;
+    int PIN1;
+    int PIN2;
+    int rtn;
 
     char id[256+G2LEN];
     octet ID = {0,sizeof(id),id};
@@ -63,13 +65,16 @@ int main()
     char hm[PFS_ZZZ];
     octet HM= {0,sizeof(hm), hm};
 
-    char x[PGS_ZZZ],y1[PGS_ZZZ],y2[PGS_ZZZ];
+    char x[PGS_ZZZ];
+    char y1[PGS_ZZZ];
+    char y2[PGS_ZZZ];
     octet X= {0, sizeof(x),x};
     octet Y1= {0,sizeof(y1),y1};
     octet Y2= {0,sizeof(y2),y2};
 
     /* Master secret shares */
-    char ms1[PGS_ZZZ], ms2[PGS_ZZZ];
+    char ms1[PGS_ZZZ];
+    char ms2[PGS_ZZZ];
     octet MS1= {0,sizeof(ms1),ms1};
     octet MS2= {0,sizeof(ms2),ms2};
 
@@ -78,18 +83,23 @@ int main()
     octet HCID= {0,sizeof(hcid), hcid};
 
     /* Client secret and shares */
-    char cs1[2*PFS_ZZZ+1], cs2[2*PFS_ZZZ+1], sec[2*PFS_ZZZ+1];
+    char cs1[2*PFS_ZZZ+1];
+    char cs2[2*PFS_ZZZ+1];
+    char sec[2*PFS_ZZZ+1];
     octet SEC= {0,sizeof(sec),sec};
     octet CS1= {0,sizeof(cs1), cs1};
     octet CS2= {0,sizeof(cs2), cs2};
 
     /* Client Public Key and z */
-    char z[PGS_ZZZ], pa[G2LEN];
+    char z[PGS_ZZZ];
+    char pa[G2LEN];
     octet Z= {0,sizeof(z),z};
     octet Pa= {0,sizeof(pa),pa};
 
     /* Server secret and shares */
-    char ss1[G2LEN], ss2[G2LEN], serverSecret[G2LEN];
+    char ss1[G2LEN];
+    char ss2[G2LEN];
+    char serverSecret[G2LEN];
     octet ServerSecret= {0,sizeof(serverSecret),serverSecret};
     octet SS1= {0,sizeof(ss1),ss1};
     octet SS2= {0,sizeof(ss2),ss2};
@@ -120,7 +130,7 @@ int main()
 
     /* unrandom seed value! */
     SEED.len=32;
-    for (i=0; i<32; i++) SEED.val[i]=i+1;
+    for (int i=0; i<32; i++) SEED.val[i]=(char)(i+1);
 
     /* initialise random number generator */
     CREATE_CSPRNG(&RNG,&SEED);
@@ -244,7 +254,7 @@ int main()
     /* Client: Sign message */
     TimeValue = GET_TIME();
     printf("TimeValue %d \n", TimeValue);
-    char* message = "sign this message";
+    const char* message = "sign this message";
     OCT_jstring(&M,message);
     HASH_ID(HASH_TYPE_ZZZ,&M,&HM);
     printf("HM: 0x");
diff --git a/examples/example_ecdh_ZZZ.c.in b/examples/example_ecdh_ZZZ.c.in
index 1bbfc29..2691db3 100644
--- a/examples/example_ecdh_ZZZ.c.in
+++ b/examples/example_ecdh_ZZZ.c.in
@@ -29,13 +29,22 @@ under the License.
 
 int ecdh(csprng *RNG)
 {
-    int i,res;
+    int i;
+    int res;
     char *pp="M0ng00se";
     /* These octets are automatically protected against buffer overflow attacks */
     /* Note salt must be big enough to include an appended word */
     /* Note ECIES ciphertext C must be big enough to include at least 1 appended block */
     /* Recall EFS_ZZZ is field size in bytes. So EFS_ZZZ=32 for 256-bit curve */
-    char s0[2*EGS_ZZZ],s1[EGS_ZZZ],w0[2*EFS_ZZZ+1],w1[2*EFS_ZZZ+1],z0[EFS_ZZZ],z1[EFS_ZZZ],key[AESKEY_ZZZ],salt[40],pw[40];
+    char s0[2*EGS_ZZZ];
+    char s1[EGS_ZZZ];
+    char w0[2*EFS_ZZZ+1];
+    char w1[2*EFS_ZZZ+1];
+    char z0[EFS_ZZZ];
+    char z1[EFS_ZZZ];
+    char key[AESKEY_ZZZ];
+    char salt[40];
+    char pw[40];
     octet S0= {0,sizeof(s0),s0};
     octet S1= {0,sizeof(s1),s1};
     octet W0= {0,sizeof(w0),w0};
@@ -47,7 +56,7 @@ int ecdh(csprng *RNG)
     octet PW= {0,sizeof(pw),pw};
 
     SALT.len=8;
-    for (i=0; i<8; i++) SALT.val[i]=i+1; // set Salt
+    for (i=0; i<8; i++) SALT.val[i]=(char)(i+1); // set Salt
 
     printf("Alice's Passphrase= %s\n",pp);
 
@@ -107,7 +116,14 @@ int ecdh(csprng *RNG)
 
 #if CURVETYPE_ZZZ != MONTGOMERY
 
-    char ds[EGS_ZZZ],p1[30],p2[30],v[2*EFS_ZZZ+1],m[32],c[64],t[32],cs[EGS_ZZZ];
+    char ds[EGS_ZZZ];
+    char p1[30];
+    char p2[30];
+    char v[2*EFS_ZZZ+1];
+    char m[32];
+    char c[64];
+    char t[32];
+    char cs[EGS_ZZZ];
     octet DS= {0,sizeof(ds),ds};
     octet CS= {0,sizeof(cs),cs};
     octet P1= {0,sizeof(p1),p1};
@@ -130,7 +146,7 @@ int ecdh(csprng *RNG)
     P2.val[3]=0x3;
 
     M.len=17;
-    for (i=0; i<=16; i++) M.val[i]=i;
+    for (i=0; i<=16; i++) M.val[i]=(char)i;
 
     ECP_ZZZ_ECIES_ENCRYPT(HASH_TYPE_ZZZ,&P1,&P2,RNG,&W1,&M,12,&V,&C,&T);
 
@@ -203,7 +219,6 @@ int ecdh(csprng *RNG)
 
 int main()
 {
-    int i;
     unsigned long ran;
 
     char raw[100];
@@ -215,11 +230,11 @@ int main()
 
     /* fake random seed source */
     RAW.len=100;
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=0; i<100; i++) RAW.val[i]=i+1;
+    RAW.val[0]=(char)ran;
+    RAW.val[1]=(char)(ran>>8);
+    RAW.val[2]=(char)(ran>>16);
+    RAW.val[3]=(char)(ran>>24);
+    for (int i=0; i<100; i++) RAW.val[i]=(char)(i+1);
 
     /* initialise strong RNG */
     CREATE_CSPRNG(&RNG,&RAW);
diff --git a/examples/example_mpin_ZZZ.c.in b/examples/example_mpin_ZZZ.c.in
index 91e78de..f27d276 100644
--- a/examples/example_mpin_ZZZ.c.in
+++ b/examples/example_mpin_ZZZ.c.in
@@ -50,25 +50,48 @@ under the License.
 #endif
 #define GTLEN 3*G2LEN
 
-//#define PERMITS  /* for time permits ON or OFF */
+//#define PERMITS   //for time permits ON or OFF
 #define PINERROR /* For PIN ERROR detection ON or OFF */
 #define FULL     /* for M-Pin Full or M-Pin regular */
-//#define SINGLE_MPIN_PASS /* SINGLE MPIN_PASS M-Pin */
+//#define SINGLE_MPIN_PASS //SINGLE MPIN_PASS M-Pin
 
 int mpin(csprng *RNG)
 {
-    int pin,pin2,rtn,err;
+    int pin;
+    int pin2;
+    int rtn;
+    int err;
 #ifdef PERMITS
     int date=today();
 #else
     int date=0;
 #endif
-    char x[PGS_ZZZ],s[PGS_ZZZ],y[PGS_ZZZ],client_id[100],sst[G2LEN],token[2*PFS_ZZZ+1],sec[2*PFS_ZZZ+1],permit[2*PFS_ZZZ+1],xcid[2*PFS_ZZZ+1],xid[2*PFS_ZZZ+1],e[GTLEN],f[GTLEN];
-    char hcid[PFS_ZZZ],hsid[PFS_ZZZ],hid[2*PFS_ZZZ+1],htid[2*PFS_ZZZ+1],h[PGS_ZZZ];
+    char x[PGS_ZZZ];
+    char s[PGS_ZZZ];
+    char y[PGS_ZZZ];
+    char client_id[100];
+    char sst[G2LEN];
+    char token[2*PFS_ZZZ+1];
+    char sec[2*PFS_ZZZ+1];
+    char permit[2*PFS_ZZZ+1];
+    char xcid[2*PFS_ZZZ+1];
+    char xid[2*PFS_ZZZ+1];
+    char e[GTLEN];
+    char f[GTLEN];
+    char hcid[PFS_ZZZ];
+    char hsid[PFS_ZZZ];
+    char hid[2*PFS_ZZZ+1];
+    char htid[2*PFS_ZZZ+1];
+    char h[PGS_ZZZ];
 #ifdef FULL
-    char r[PGS_ZZZ],z[2*PFS_ZZZ+1],w[PGS_ZZZ],t[2*PFS_ZZZ+1];
-    char g1[GTLEN],g2[GTLEN];
-    char ck[AESKEY_ZZZ],sk[AESKEY_ZZZ];
+    char r[PGS_ZZZ];
+    char z[2*PFS_ZZZ+1];
+    char w[PGS_ZZZ];
+    char t[2*PFS_ZZZ+1];
+    char g1[GTLEN];
+    char g2[GTLEN];
+    char ck[AESKEY_ZZZ];
+    char sk[AESKEY_ZZZ];
 #endif
     octet S= {0,sizeof(s),s};
     octet X= {0,sizeof(x),x};
@@ -97,7 +120,14 @@ int mpin(csprng *RNG)
     octet SK= {0,sizeof(sk),sk};
     octet CK= {0,sizeof(ck),ck};
 #endif
-    octet *pxID,*pxCID,*pHID,*pHTID,*pE,*pF,*pPERMIT,*prHID;
+    octet *pxID;
+    octet *pxCID;
+    octet *pHID;
+    octet *pHTID;
+    octet *pE;
+    octet *pF;
+    const octet *pPERMIT;
+    const octet *prHID;
     char idhex[100];
 
     /* Trusted Authority set-up */
@@ -114,7 +144,7 @@ int mpin(csprng *RNG)
     printf("\n");
 
     OCT_toHex(&CLIENT_ID,idhex);
-    printf("Client ID= %s\n",idhex);// OCT_toHex(&CLIENT_ID); printf("\n");
+    printf("Client ID= %s\n",idhex);
 
     /* Client and Server are issued secrets by DTA */
     MPIN_ZZZ_GET_SERVER_SECRET(&S,&SST);
@@ -168,7 +198,8 @@ int mpin(csprng *RNG)
 
     /* Client enters PIN */
     printf("\nPIN= ");
-    if(scanf("%d",&pin)) {};
+    while(! scanf("%d",&pin))
+        printf("scan error");
     /* to avoid silly compile error */
     getchar();
 
@@ -189,18 +220,16 @@ int mpin(csprng *RNG)
     */
 
     pxID=&xID;
-    pxCID=&xCID;
     pHID=&HID;
-    pHTID=&HTID;
-    pE=&E;
-    pF=&F;
-    pPERMIT=&PERMIT;
 
 #ifdef PERMITS
     prHID=pHTID;
+    pHTID=&HTID;
+    pxCID=&xCID;
+    pPERMIT=&PERMIT;
+
 #ifndef PINERROR
     pxID=NULL;
-//   pHID=NULL;  //new
 #endif
 #else
     prHID=pHID;
@@ -211,6 +240,9 @@ int mpin(csprng *RNG)
 #ifndef PINERROR
     pE=NULL;
     pF=NULL;
+#else
+    pE=&E;
+    pF=&F;
 #endif
 
 #ifdef SINGLE_MPIN_PASS
@@ -344,7 +376,7 @@ int mpin(csprng *RNG)
 
 int main()
 {
-    char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
     char seed[16] = {0};
     octet SEED = {sizeof(seed),sizeof(seed),seed};
 
diff --git a/examples/example_paillier.c b/examples/example_paillier.c
index 98eebc6..e024af6 100644
--- a/examples/example_paillier.c
+++ b/examples/example_paillier.c
@@ -205,7 +205,7 @@ int paillier(csprng *RNG)
 
 int main()
 {
-    char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
+    const char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30";
     char seed[16] = {0};
     octet SEED = {sizeof(seed),sizeof(seed),seed};
 
diff --git a/examples/example_rsa_WWW.c.in b/examples/example_rsa_WWW.c.in
index 8d03d05..21c1f22 100644
--- a/examples/example_rsa_WWW.c.in
+++ b/examples/example_rsa_WWW.c.in
@@ -26,7 +26,11 @@ under the License.
 
 int rsa(csprng *RNG)
 {
-    char m[RFS_WWW],ml[RFS_WWW],c[RFS_WWW],e[RFS_WWW],s[RFS_WWW];
+    char m[RFS_WWW];
+    char ml[RFS_WWW];
+    char c[RFS_WWW];
+    char e[RFS_WWW];
+    char s[RFS_WWW];
     rsa_public_key_WWW pub;
     rsa_private_key_WWW priv;
 
@@ -81,7 +85,6 @@ int rsa(csprng *RNG)
 
 int main()
 {
-    int i;
     unsigned long ran;
 
     char raw[100];
@@ -91,11 +94,11 @@ int main()
     time((time_t *)&ran);
 
     RAW.len=100;				/* fake random seed source */
-    RAW.val[0]=ran;
-    RAW.val[1]=ran>>8;
-    RAW.val[2]=ran>>16;
-    RAW.val[3]=ran>>24;
-    for (i=0; i<100; i++) RAW.val[i]=i+1;
+    RAW.val[0]=(char)ran;
+    RAW.val[1]=(char)(ran>>8);
+    RAW.val[2]=(char)(ran>>16);
+    RAW.val[3]=(char)(ran>>24);
+    for (int i=0; i<100; i++) RAW.val[i]=(char)(i+1);
 
     CREATE_CSPRNG(&RNG,&RAW);   /* initialise strong RNG */
 
diff --git a/include/amcl.h.in b/include/amcl.h.in
index ea9175c..8eda4c4 100644
--- a/include/amcl.h.in
+++ b/include/amcl.h.in
@@ -98,6 +98,7 @@ typedef struct
     int len;           /**< Hash length in bytes */
 } sha3;
 
+
 #define SHA256 32 /**< SHA-256 hashing */
 #define SHA384 48 /**< SHA-384 hashing */
 #define SHA512 64 /**< SHA-512 hashing */
@@ -110,6 +111,21 @@ typedef struct
 #define SHAKE128 16 /**< SHAKE128   hash */
 #define SHAKE256 32 /**< SHAKE256 hash */
 
+#define SHA256_HASH_SIZE  32
+#define SHA256_BLOCK_SIZE 64
+// Return codes for HMAC
+#define SUCCESS                 0x00000000
+#define ERR_NULLPOINTER_HMAC    0x00000001
+#define ERR_KEYSIZE_HMAC        0x00000002
+#define ERR_BADARGLEN_HMAC      0x00000003
+/**
+ * @brief HMAC-SHA256 function instance.
+ */
+typedef struct {
+    hash256 sha256_ctx; 			/**< SHA-256 function instance */
+    char 	k0[SHA256_BLOCK_SIZE]; 	/**< The key after any required pre-processing */
+} hmac_sha256;
+
 
 /* NewHope parameters */
 
@@ -139,7 +155,7 @@ typedef struct
 #define CTR8  37 /**< Counter Mode - 8 bytes */
 #define CTR16 45 /**< Counter Mode - 16 bytes */
 
-#define uchar unsigned char  /**<  Unsigned char */
+typedef unsigned char uchar;  /**<  Unsigned char */
 
 /**
 	@brief AES instance
@@ -219,12 +235,12 @@ typedef struct
  *
 	@param O Octet to be output
  */
-extern void OCT_output(octet *O);
+extern void OCT_output(const 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);
+extern void OCT_output_string(const octet *O);
 /**	@brief Wipe clean an octet
  *
 	@param O Octet to be cleaned
@@ -237,7 +253,7 @@ extern void OCT_clear(octet *O);
 	@param P second Octet to be compared
 	@return 1 if equal, else 0
  */
-extern int  OCT_comp(octet *O,octet *P);
+extern int  OCT_comp(const octet *O,const octet *P);
 /**	@brief Compare first n bytes of two octets
  *
     Terminates early if O.len > n or P.len > n
@@ -246,14 +262,14 @@ extern int  OCT_comp(octet *O,octet *P);
 	@param n number of bytes to compare
 	@return 1 if equal, else 0
  */
-extern int  OCT_ncomp(octet *O,octet *P,int n);
+extern int  OCT_ncomp(const octet *O,const 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);
+extern void OCT_jstring(octet *O,const char *s);
 /**	@brief Join bytes to end of an octet
  *
 	Truncates if there is no room
@@ -261,7 +277,7 @@ extern void OCT_jstring(octet *O,char *s);
 	@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);
+extern void OCT_jbytes(octet *O,const char *s,int n);
 /**	@brief Join single byte to end of an octet, repeated n times
  *
 	Truncates if there is no room
@@ -276,13 +292,13 @@ extern void OCT_jbyte(octet *O,int b,int n);
 	@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);
+extern void OCT_joctet(octet *O,const 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);
+extern void OCT_xor(octet *O,const octet *P);
 /**	@brief reset Octet to zero length
  *
 	@param O Octet to be emptied
@@ -300,21 +316,21 @@ extern int OCT_pad(octet *O,int n);
 	@param b zero terminated byte array to take base64 conversion
 	@param O Octet to be converted
  */
-extern void OCT_tobase64(char *b,octet *O);
+extern void OCT_tobase64(char *b,const 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);
+extern void OCT_frombase64(octet *O,const 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);
+extern void OCT_copy(octet *O,const octet *P);
 /**	@brief XOR every byte of an octet with input m
  *
  	@param O Octet
@@ -361,21 +377,20 @@ extern void OCT_shl(octet *O,int n);
 	@param dst Octet
 	@param src Hex string to be converted
  */
-extern void OCT_fromHex(octet *dst,char *src);
+extern void OCT_fromHex(octet *dst,const char *src);
 /**	@brief Convert an Octet to printable hex number
  *
     Truncates if there is no room
 	@param dst hex value
 	@param src Octet to be converted
  */
-extern void OCT_toHex(octet *src,char *dst);
+extern void OCT_toHex(const 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);
-
+extern void OCT_toStr(const octet *src,char *dst);
 
 
 /* Hash function */
@@ -396,6 +411,91 @@ extern void HASH256_process(hash256 *H,int b);
 	@param h is the output 32-byte hash
  */
 extern void HASH256_hash(hash256 *H,char *h);
+/**
+ * @brief One-shot API for SHA-256
+ * 
+ * @param digest The output 32-byte hash
+ * @param in     The input to hash
+ * @param inlen  The input length (in bytes)
+ */
+extern void HASH256_oneshot(char *digest,
+                    const char *in, int inlen);
+
+/* HMAC functions */
+/**	@brief Initialise an instance of HMAC-SHA256
+ *
+ * @param  hmac_sha256_ctx An instance of HMAC-SHA256
+ * @param  key             Secret key
+ * @param  keylen          Key length in bytes
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HMAC_SHA256_init(hmac_sha256 *hmac_sha256_ctx,
+                    		const char* key,    int keylen);
+/**	@brief Update an instance of HMAC-SHA256 by adding data to authenticate
+ *
+ * @param  sha256_ctx An instance of SHA256
+ * @param  in         Input data to authenticate
+ * @param  inlen      Input length in bytes
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HMAC_SHA256_update(hash256 *sha256_ctx,
+                        	const char* in,     int inlen);
+/**	@brief Finalize an instance of HMAC-SHA256 by producing the output tag
+ *
+ * @param  hmac_sha256_ctx  An instance of HMAC-SHA256
+ * @param  out              MAC
+ * @param  outlen           MAC length in bytes (fixed at 32) 
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HMAC_SHA256_final(hmac_sha256 *hmac_sha256_ctx,
+							char* out, int outlen);
+/**	@brief Generate message authentication code using HMAC-SHA256 (one-shot)
+ *
+ * @param  out      MAC
+ * @param  outlen   MAC length in bytes (fixed at 32) 
+ * @param  key      Secret key
+ * @param  keylen   Key length in bytes
+ * @param  in       Input data to authenticate
+ * @param  inlen    Input length in bytes
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HMAC_SHA256_oneshot(char* out, 			int outlen,
+                				const char* key, 	int keylen,
+                				const char* in, 	int inlen);
+
+/* HKDf functions */
+/**	@brief Takes the input keying material and extracts from it a fixed-length
+ * pseudorandom key K as defined in RFC5869.
+ *
+ * @param  prk      Output pseudorandom key
+ * @param  salt     Optional salt value (set to HashLen zeros if omitted)
+ * @param  saltlen  Salt length in bytes
+ * @param  ikm      Input Keying Material
+ * @param  ikmlen   IKM length in bytes
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HKDF_SHA256_extract(char prk[SHA256_HASH_SIZE],
+                        const char *salt, unsigned int saltlen,
+                        const char *ikm,  unsigned int ikmlen);
+/**	@brief Expands the pseudorandom key to the desired length as defined in
+ * RFC 5869.
+ *
+ * @param  okm      Output Keying Material
+ * @param  okmlen   OKM length in bytes (should be <= 255 according to the RFC)
+ * @param  prk      Pseudorandom key
+ * @param  info     Optional context and application specific information
+ * @param  infolen  Info length in bytes
+ * 
+ * @return	0 if success, error code otherwise
+ */
+extern int HKDF_SHA256_expand(char *okm, unsigned int okmlen,
+                        const char *prk, unsigned int prklen,
+                        const char *info, unsigned int infolen);
 
 
 /**	@brief Initialise an instance of SHA384
@@ -478,13 +578,13 @@ extern void  SHA3_squeeze(sha3 *H,char *h,int len);
 	@param m is the new active mode of operation (ECB, CBC, OFB, CFB etc)
 	@param iv the new Initialisation Vector
  */
-extern void AES_reset(amcl_aes *A,int m,char *iv);
+extern void AES_reset(amcl_aes *A,int m,const char *iv);
 /**	@brief Extract chaining vector from AMCL_AES instance
  *
 	@param A an instance of the AMCL_AES
 	@param f the extracted chaining vector
  */
-extern void AES_getreg(amcl_aes *A,char * f);
+extern void AES_getreg(const amcl_aes *A,char * f);
 /**	@brief Initialise an instance of AMCL_AES and its mode of operation
  *
 	@param A an instance AMCL_AES
@@ -494,19 +594,19 @@ extern void AES_getreg(amcl_aes *A,char * f);
 	@param iv the Initialisation Vector
 	@return 0 for invalid n
  */
-extern int AES_init(amcl_aes *A,int m,int n,char *k,char *iv);
+extern int AES_init(amcl_aes *A,int m,int n,char *k,const char *iv);
 /**	@brief Encrypt a single 16 byte block in ECB mode
  *
 	@param A an instance of the AMCL_AES
 	@param b is an array of 16 plaintext bytes, on exit becomes ciphertext
  */
-extern void AES_ecb_encrypt(amcl_aes *A,uchar * b);
+extern void AES_ecb_encrypt(const amcl_aes *A,uchar * b);
 /**	@brief Decrypt a single 16 byte block in ECB mode
  *
 	@param A an instance of the AMCL_AES
 	@param b is an array of 16 cipherext bytes, on exit becomes plaintext
  */
-extern void AES_ecb_decrypt(amcl_aes *A,uchar * b);
+extern void AES_ecb_decrypt(const amcl_aes *A,uchar * b);
 /**	@brief Encrypt a single 16 byte block in active mode
  *
 	@param A an instance of the AMCL_AES
@@ -537,7 +637,7 @@ extern void AES_end(amcl_aes *A);
 	@param n the number of bytes in the Initialisation Vector (IV)
 	@param iv the IV
  */
-extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
+extern void GCM_init(gcm *G,int nk,char *k,int n,const 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
@@ -545,7 +645,7 @@ extern void GCM_init(gcm *G,int nk,char *k,int n,char *iv);
 	@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);
+extern int GCM_add_header(gcm *G,const 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
@@ -554,7 +654,7 @@ extern int GCM_add_header(gcm *G,char *b,int n);
 	@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);
+extern int GCM_add_plain(gcm *G,char *c,const 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
@@ -563,7 +663,7 @@ extern int GCM_add_plain(gcm *G,char *c,char *p,int n);
 	@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);
+extern int GCM_add_cipher(gcm *G,char *p,const char *c,int n);
 /**	@brief Finish off and extract authentication tag (HMAC)
  *
 	@param G is an active instance AES-GCM
@@ -582,7 +682,7 @@ extern void GCM_finish(gcm *G,char *t);
 	@param b an array of seed bytes
 
  */
-extern void RAND_seed(csprng *R,int n,char *b);
+extern void RAND_seed(csprng *R,int n,const char *b);
 /**	@brief Delete all internal state of a random number generator
  *
 	@param R an instance of a Cryptographically Secure Random Number Generator
diff --git a/include/arch.h.in b/include/arch.h.in
index aa726db..e417554 100644
--- a/include/arch.h.in
+++ b/include/arch.h.in
@@ -67,16 +67,16 @@
 #define unsign64 unsigned long long  /**< 64-bit unsigned integer */
 #else
 #include <stdint.h>
-#define byte uint8_t			/**< 8-bit unsigned integer */
+typedef uint8_t byte;   		/**< 8-bit unsigned integer */
 #define sign8 int8_t			/**< 8-bit signed integer */
 #define sign16 int16_t			/**< 16-bit signed integer */
-#define sign32 int32_t			/**< 32-bit signed integer */
+typedef int32_t sign32;   		/**< 32-bit signed integer */
 #define sign64 int64_t			/**< 64-bit signed integer */
-#define unsign32 uint32_t		/**< 32-bit unsigned integer */
-#define unsign64 uint64_t		/**< 64-bit unsigned integer */
+typedef uint32_t unsign32; 		/**< 32-bit unsigned integer */
+typedef uint64_t unsign64;  	/**< 64-bit unsigned integer */
 #endif
 
-#define uchar unsigned char  /**<  Unsigned char */
+typedef unsigned char uchar;  /**<  Unsigned char */
 
 /* Don't mess with anything below this line unless you know what you are doing */
 /* This next is probably OK, but may need changing for non-C99-standard environments */
@@ -106,13 +106,13 @@
 #if CHUNK == 64
 
 #ifndef C99
-#define chunk __int64		/**< C type corresponding to word length */
+#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 */
 
 #if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
-#define dchunk __int128                /**< Always define double length chunk type if available (supported by GCC & Clang on 64-bit architectures) */
+#define dchunk __int128      /**< Always define double length chunk type if available (supported by GCC & Clang on 64-bit architectures) */
 #endif
 
 #endif
diff --git a/include/big.h.in b/include/big.h.in
index 1da1f71..0b8f4f1 100644
--- a/include/big.h.in
+++ b/include/big.h.in
@@ -66,29 +66,29 @@ typedef chunk DBIG_XXX[DNLEN_XXX];   /**< Define type DBIG as array of chunks */
 	@param x a BIG number
 	@return 1 if zero, else returns 0
  */
-extern int BIG_XXX_iszilch(BIG_XXX x);
+extern int BIG_XXX_iszilch(const BIG_XXX x);
 /**	@brief Tests for BIG equal to one - input must be normalised
  *
 	@param x a BIG number
 	@return 1 if one, else returns 0
  */
-extern int BIG_XXX_isunity(BIG_XXX x);
+extern int BIG_XXX_isunity(const BIG_XXX x);
 /**	@brief Tests for DBIG equal to zero - input must be normalised
  *
 	@param x a DBIG number
 	@return 1 if zero, else returns 0
  */
-extern int BIG_XXX_diszilch(DBIG_XXX x);
+extern int BIG_XXX_diszilch(const DBIG_XXX x);
 /**	@brief Outputs a BIG number to the console
  *
 	@param x a BIG number
  */
-extern void BIG_XXX_output(BIG_XXX x);
+extern void BIG_XXX_output(const BIG_XXX x);
 /**	@brief Outputs a BIG number to the console in raw form (for debugging)
  *
 	@param x a BIG number
  */
-extern void BIG_XXX_rawoutput(BIG_XXX x);
+extern void BIG_XXX_rawoutput(const BIG_XXX x);
 /**	@brief Conditional constant time swap of two BIG numbers
  *
 	Conditionally swaps parameters in constant time (without branching)
@@ -104,7 +104,7 @@ extern void BIG_XXX_cswap(BIG_XXX x,BIG_XXX y,int s);
 	@param y another BIG number
 	@param s copy takes place if not equal to 0
  */
-extern void BIG_XXX_cmove(BIG_XXX x,BIG_XXX y,int s);
+extern void BIG_XXX_cmove(BIG_XXX x,const BIG_XXX y,int s);
 /**	@brief Conditional copy of DBIG number
  *
 	Conditionally copies second parameter to the first (without branching)
@@ -112,33 +112,33 @@ extern void BIG_XXX_cmove(BIG_XXX x,BIG_XXX y,int s);
 	@param y another DBIG number
 	@param s copy takes place if not equal to 0
  */
-extern void BIG_XXX_dcmove(BIG_XXX x,BIG_XXX y,int s);
+extern void BIG_XXX_dcmove(DBIG_XXX x,const DBIG_XXX y,int s);
 /**	@brief Convert from BIG number to byte array
  *
 	@param a byte array
 	@param x BIG number
  */
-extern void BIG_XXX_toBytes(char *a,BIG_XXX x);
+extern void BIG_XXX_toBytes(char *a,const BIG_XXX x);
 /**	@brief Convert to BIG number from byte array
  *
 	@param x BIG number
 	@param a byte array
  */
-extern void BIG_XXX_fromBytes(BIG_XXX x,char *a);
+extern void BIG_XXX_fromBytes(BIG_XXX x,const char *a);
 /**	@brief Convert to BIG number from byte array of given length
  *
 	@param x BIG number
 	@param a byte array
 	@param s byte array length
  */
-extern void BIG_XXX_fromBytesLen(BIG_XXX x,char *a,int s);
+extern void BIG_XXX_fromBytesLen(BIG_XXX x,const char *a,int s);
 /**@brief Convert to DBIG number from byte array of given length
  *
    @param x DBIG number
    @param a byte array
    @param s byte array length
  */
-extern void BIG_XXX_dfromBytesLen(DBIG_XXX x,char *a,int s);
+extern void BIG_XXX_dfromBytesLen(DBIG_XXX x,const char *a,int s);
 /**	@brief Outputs a DBIG number to the console
  *
 	@param x a DBIG number
@@ -149,7 +149,7 @@ extern void BIG_XXX_doutput(DBIG_XXX x);
  *
 	@param x a DBIG number
  */
-extern void BIG_XXX_drawoutput(DBIG_XXX x);
+extern void BIG_XXX_drawoutput(const DBIG_XXX x);
 
 /**	@brief Copy BIG from Read-Only Memory to a BIG
  *
@@ -162,37 +162,37 @@ extern void BIG_XXX_rcopy(BIG_XXX x,const BIG_XXX y);
 	@param x BIG number
 	@param y BIG number to be copied
  */
-extern void BIG_XXX_copy(BIG_XXX x,BIG_XXX y);
+extern void BIG_XXX_copy(BIG_XXX x,const BIG_XXX y);
 /**	@brief Copy DBIG to another DBIG
  *
 	@param x DBIG number
 	@param y DBIG number to be copied
  */
-extern void BIG_XXX_dcopy(DBIG_XXX x,DBIG_XXX y);
+extern void BIG_XXX_dcopy(DBIG_XXX x,const DBIG_XXX y);
 /**	@brief Copy BIG to upper half of DBIG
  *
 	@param x DBIG number
 	@param y BIG number to be copied
  */
-extern void BIG_XXX_dsucopy(DBIG_XXX x,BIG_XXX y);
+extern void BIG_XXX_dsucopy(DBIG_XXX x,const BIG_XXX y);
 /**	@brief Copy BIG to lower half of DBIG
  *
 	@param x DBIG number
 	@param y BIG number to be copied
  */
-extern void BIG_XXX_dscopy(DBIG_XXX x,BIG_XXX y);
+extern void BIG_XXX_dscopy(DBIG_XXX x,const BIG_XXX y);
 /**	@brief Copy lower half of DBIG to a BIG
  *
 	@param x BIG number
 	@param y DBIG number to be copied
  */
-extern void BIG_XXX_sdcopy(BIG_XXX x,DBIG_XXX y);
+extern void BIG_XXX_sdcopy(BIG_XXX x,const DBIG_XXX y);
 /**	@brief Copy upper half of DBIG to a BIG
  *
 	@param x BIG number
 	@param y DBIG number to be copied
  */
-extern void BIG_XXX_sducopy(BIG_XXX x,DBIG_XXX y);
+extern void BIG_XXX_sducopy(BIG_XXX x,const DBIG_XXX y);
 /**	@brief Set BIG to zero
  *
 	@param x BIG number to be set to zero
@@ -219,7 +219,7 @@ extern void BIG_XXX_invmod2m(BIG_XXX x);
 	@param y BIG number
 	@param z BIG number
  */
-extern void BIG_XXX_add(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+extern void BIG_XXX_add(BIG_XXX x,const BIG_XXX y,const BIG_XXX z);
 
 /**	@brief Set BIG to logical or of two BIGs - output normalised
  *
@@ -241,7 +241,7 @@ extern void BIG_XXX_inc(BIG_XXX x,int i);
 	@param y BIG number
 	@param z BIG number
  */
-extern void BIG_XXX_sub(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+extern void BIG_XXX_sub(BIG_XXX x,const BIG_XXX y,const BIG_XXX z);
 /**	@brief Decrement BIG by a small integer - output not normalised
  *
 	@param x BIG number to be decremented
@@ -254,21 +254,21 @@ extern void BIG_XXX_dec(BIG_XXX x,int i);
 	@param y DBIG number
 	@param z DBIG number
  */
-extern void BIG_XXX_dadd(DBIG_XXX x,DBIG_XXX y,DBIG_XXX z);
+extern void BIG_XXX_dadd(DBIG_XXX x,const DBIG_XXX y,const DBIG_XXX z);
 /**	@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_XXX_dsub(DBIG_XXX x,DBIG_XXX y,DBIG_XXX z);
+extern void BIG_XXX_dsub(DBIG_XXX x,const DBIG_XXX y,const DBIG_XXX 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_XXX_imul(BIG_XXX x,BIG_XXX y,int i);
+extern void BIG_XXX_imul(BIG_XXX x,const BIG_XXX y,int i);
 /**	@brief Multiply BIG by not-so-small small integer - output normalised
  *
 	@param x BIG number, product of other two
@@ -276,7 +276,7 @@ extern void BIG_XXX_imul(BIG_XXX x,BIG_XXX y,int i);
 	@param i small integer
 	@return Overflowing bits
  */
-extern chunk BIG_XXX_pmul(BIG_XXX x,BIG_XXX y,int i);
+extern chunk BIG_XXX_pmul(BIG_XXX x,const BIG_XXX y,int i);
 /**	@brief Divide BIG by 3 - output normalised
  *
 	@param x BIG number
@@ -289,14 +289,14 @@ extern int BIG_XXX_div3(BIG_XXX x);
 	@param y BIG number
 	@param i small integer
  */
-extern void BIG_XXX_pxmul(DBIG_XXX x,BIG_XXX y,int i);
+extern void BIG_XXX_pxmul(DBIG_XXX x,const BIG_XXX 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_XXX_mul(DBIG_XXX x,BIG_XXX y,BIG_XXX z);
+extern void BIG_XXX_mul(DBIG_XXX x,const BIG_XXX y,const BIG_XXX 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
@@ -304,13 +304,13 @@ extern void BIG_XXX_mul(DBIG_XXX x,BIG_XXX y,BIG_XXX z);
 	@param y BIG number
 	@param z BIG number
  */
-extern void BIG_XXX_smul(BIG_XXX x,BIG_XXX y,BIG_XXX z);
+extern void BIG_XXX_smul(BIG_XXX x,const BIG_XXX y,const BIG_XXX 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_XXX_sqr(DBIG_XXX x,BIG_XXX y);
+extern void BIG_XXX_sqr(DBIG_XXX x,const BIG_XXX y);
 
 /**	@brief Montgomery reduction of a DBIG to a BIG  - input normalised and output normalised
  *
@@ -319,7 +319,7 @@ extern void BIG_XXX_sqr(DBIG_XXX x,BIG_XXX y);
 	@param MC the Montgomery Constant
 	@param d DBIG number to be reduced
  */
-extern void BIG_XXX_monty(BIG_XXX a,BIG_XXX md,chunk MC,DBIG_XXX d);
+extern void BIG_XXX_monty(BIG_XXX a,const BIG_XXX md,chunk MC,const DBIG_XXX d);
 
 /**	@brief Shifts a BIG left by any number of bits - input must be normalised, output normalised
  *
@@ -355,7 +355,7 @@ extern void BIG_XXX_shr(BIG_XXX x,int s);
 	@param m BIG number to be shifted and subtracted
 	@return sign of r
  */
-extern int BIG_XXX_ssn(BIG_XXX r,BIG_XXX a, BIG_XXX m);
+extern int BIG_XXX_ssn(BIG_XXX r,const BIG_XXX a, BIG_XXX m);
 
 /**	@brief Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
  *
@@ -381,7 +381,7 @@ extern void BIG_XXX_dshr(DBIG_XXX x,int s);
 	@param s Bit position at which to split
 	@return carry-out from top half
  */
-extern chunk BIG_XXX_split(BIG_XXX x,BIG_XXX y,DBIG_XXX z,int s);
+extern chunk BIG_XXX_split(BIG_XXX x,BIG_XXX y,const DBIG_XXX z,int s);
 /**	@brief Normalizes a BIG number - output normalised
  *
 	All digits of the input BIG are reduced mod 2^BASEBITS
@@ -400,40 +400,40 @@ extern void BIG_XXX_dnorm(DBIG_XXX x);
 	@param y second BIG number to be compared
 	@return -1 is x<y, 0 if x=y, 1 if x>y
  */
-extern int BIG_XXX_comp(BIG_XXX x,BIG_XXX y);
+extern int BIG_XXX_comp(const BIG_XXX x,const BIG_XXX 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_XXX_dcomp(DBIG_XXX x,DBIG_XXX y);
+extern int BIG_XXX_dcomp(const DBIG_XXX x,const DBIG_XXX y);
 /**	@brief Calculate number of bits in a BIG - output normalised - leaks log2(x)
  *
 	@param x BIG number
 	@return Number of bits in x
  */
-extern int BIG_XXX_nbits(BIG_XXX x);
+extern int BIG_XXX_nbits(const BIG_XXX x);
 /**	@brief Calculate number of bits in a DBIG - output normalised - leaks log2(x)
  *
 	@param x DBIG number
 	@return Number of bits in x
  */
-extern int BIG_XXX_dnbits(DBIG_XXX x);
+extern int BIG_XXX_dnbits(const DBIG_XXX x);
 /**	@brief Reduce x mod n - input and output normalised - leaks log2(x)-log2(n)
  *
 	Slow but rarely used
 	@param x BIG number to be reduced mod n
 	@param n The modulus
  */
-extern void BIG_XXX_mod(BIG_XXX x,BIG_XXX n);
+extern void BIG_XXX_mod(BIG_XXX x,const BIG_XXX n);
 /**	@brief Divide x by n - output normalised - leaks log2(x)-log2(n)
  *
 	Slow but rarely used
 	@param x BIG number to be divided by n
 	@param n The Divisor
  */
-extern void BIG_XXX_sdiv(BIG_XXX x,BIG_XXX n);
+extern void BIG_XXX_sdiv(BIG_XXX x,const BIG_XXX n);
 /**	@brief  x=y mod n - output normalised - leaks log2(y)-log2(n)
  *
 	Slow but rarely used. y is destroyed.
@@ -441,7 +441,7 @@ extern void BIG_XXX_sdiv(BIG_XXX x,BIG_XXX n);
 	@param y DBIG number
 	@param n Modulus
  */
-extern void BIG_XXX_dmod(BIG_XXX x,DBIG_XXX y,BIG_XXX n);
+extern void BIG_XXX_dmod(BIG_XXX x,DBIG_XXX y,const BIG_XXX n);
 /**	@brief  x=y/n - output normalised - leaks log2(y)-log2(n)
  *
 	Slow but rarely used. y is destroyed.
@@ -449,20 +449,20 @@ extern void BIG_XXX_dmod(BIG_XXX x,DBIG_XXX y,BIG_XXX n);
 	@param y DBIG number
 	@param n Modulus
  */
-extern void BIG_XXX_ddiv(BIG_XXX x,DBIG_XXX y,BIG_XXX n);
+extern void BIG_XXX_ddiv(BIG_XXX x,DBIG_XXX y,const BIG_XXX n);
 /**	@brief  return parity of BIG, that is the least significant bit
  *
 	@param x BIG number
 	@return 0 or 1
  */
-extern int BIG_XXX_parity(BIG_XXX x);
+extern int BIG_XXX_parity(const BIG_XXX 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_XXX_bit(BIG_XXX x,int i);
+extern int BIG_XXX_bit(const BIG_XXX x,int i);
 /**	@brief  return i-th of BIG
  *
 	@param x BIG number
@@ -470,7 +470,7 @@ extern int BIG_XXX_bit(BIG_XXX x,int i);
 	@param w the width of the window to return
 	@return bits in the window as an integer
  */
-int BIG_XXX_bits(BIG_XXX x, int i, int w);
+int BIG_XXX_bits(const BIG_XXX x, int i, int w);
 /**	@brief  return least significant bits of a BIG
  *
 	@param x BIG number
@@ -492,7 +492,7 @@ extern void BIG_XXX_random(BIG_XXX x,csprng *r);
 	@param n The modulus
 	@param r A pointer to a Cryptographically Secure Random Number Generator
  */
-extern void BIG_XXX_randomnum(BIG_XXX x,BIG_XXX n,csprng *r);
+extern void BIG_XXX_randomnum(BIG_XXX x,const BIG_XXX 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
@@ -512,7 +512,7 @@ extern void BIG_XXX_randomnum(BIG_XXX x,BIG_XXX n,csprng *r);
 	@param z BIG number
 	@param n The BIG Modulus
  */
-extern void BIG_XXX_modmul(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
+extern void BIG_XXX_modmul(BIG_XXX x,const BIG_XXX y,const BIG_XXX z,const BIG_XXX n);
 /**	@brief  Calculate x=y/z mod n - leaks log2(x)-log2(n)
  *
 	Slow method for modular division
@@ -521,7 +521,7 @@ extern void BIG_XXX_modmul(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
 	@param z BIG number
 	@param n The BIG Modulus
  */
-extern void BIG_XXX_moddiv(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
+extern void BIG_XXX_moddiv(BIG_XXX x,const BIG_XXX y,const BIG_XXX z,const BIG_XXX n);
 /**	@brief  Calculate x=y^2 mod n - leaks log2(x)-log2(n)
  *
 	Slow method for modular squaring
@@ -529,7 +529,7 @@ extern void BIG_XXX_moddiv(BIG_XXX x,BIG_XXX y,BIG_XXX z,BIG_XXX n);
 	@param y BIG number
 	@param n The BIG Modulus
  */
-extern void BIG_XXX_modsqr(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+extern void BIG_XXX_modsqr(BIG_XXX x,const BIG_XXX y,const BIG_XXX n);
 /**	@brief  Calculate x=-y mod n - leaks log2(x)-log2(n)
  *
 	Modular negation
@@ -537,14 +537,14 @@ extern void BIG_XXX_modsqr(BIG_XXX x,BIG_XXX y,BIG_XXX n);
 	@param y BIG number
 	@param n The BIG Modulus
  */
-extern void BIG_XXX_modneg(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+extern void BIG_XXX_modneg(BIG_XXX x,const BIG_XXX y,const BIG_XXX n);
 /**	@brief  Calculate jacobi Symbol (x/y) - not constant time
  *
 	@param x BIG number
 	@param y BIG number
 	@return Jacobi symbol, -1,0 or 1
  */
-extern int BIG_XXX_jacobi(BIG_XXX x,BIG_XXX y);
+extern int BIG_XXX_jacobi(BIG_XXX x,const BIG_XXX y);
 /**	@brief  Calculate x=1/y mod n
  *
 	Modular Inversion - This is slow. Uses binary method.
@@ -552,7 +552,7 @@ extern int BIG_XXX_jacobi(BIG_XXX x,BIG_XXX y);
 	@param y BIG number
 	@param n The BIG Modulus
  */
-extern void BIG_XXX_invmodp(BIG_XXX x,BIG_XXX y,BIG_XXX n);
+extern void BIG_XXX_invmodp(BIG_XXX x,const BIG_XXX y,const BIG_XXX n);
 /** @brief Calculate x=x mod 2^m
  *
 	Truncation
@@ -596,8 +596,14 @@ static inline chunk muladd_XXX(chunk x,chunk y,chunk c,chunk *r)
 
 static inline chunk muladd_XXX(chunk x,chunk y,chunk c,chunk *r)
 {
-    chunk x0,x1,y0,y1;
-    chunk bot,top,mid,carry;
+    chunk x0;
+    chunk x1;
+    chunk y0;
+    chunk y1;
+    chunk bot;
+    chunk top;
+    chunk mid;
+    chunk carry;
     x0=x&HMASK_XXX;
     x1=(x>>HBITS_XXX);
     y0=y&HMASK_XXX;
diff --git a/include/bls.h.in b/include/bls.h.in
index 2e0bd91..07d7968 100644
--- a/include/bls.h.in
+++ b/include/bls.h.in
@@ -62,7 +62,7 @@ int BLS_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W);
 	@param S    Private key
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_SIGN(octet *SIG,octet *M,octet *S);
+int BLS_ZZZ_SIGN(octet *SIG,const octet *M,const octet *S);
 
 /**	@brief Verify a signature
  *
@@ -71,7 +71,7 @@ int BLS_ZZZ_SIGN(octet *SIG,octet *M,octet *S);
 	@param W    Public key
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_VERIFY(octet *SIG,octet *M,octet *W);
+int BLS_ZZZ_VERIFY(const octet *SIG,const octet *M,const octet *W);
 
 /**	@brief Add two members from the group G1
  *
@@ -80,7 +80,7 @@ int BLS_ZZZ_VERIFY(octet *SIG,octet *M,octet *W);
 	@param  R   member of G1. R = R1+R2
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R);
+int BLS_ZZZ_ADD_G1(const octet *R1,const octet *R2,octet *R);
 
 /**	@brief Add two members from the group G2
  *
@@ -89,7 +89,7 @@ int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R);
 	@param  W   member of G2. W = W1+W2
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W);
+int BLS_ZZZ_ADD_G2(const octet *W1,const octet *W2,octet *W);
 
 /**	@brief Use Shamir's secret sharing to distribute BLS secret keys
  *
@@ -102,7 +102,7 @@ int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W);
 	@param  SKO Secret key that is shared
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO);
+int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, const octet* SKI, octet* SKO);
 
 /**	@brief Use Shamir's secret sharing to recover a BLS secret key
  *
@@ -112,7 +112,7 @@ int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SK
 	@param  SK  Secret key that is recovered
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK);
+int BLS_ZZZ_RECOVER_SECRET(int k, const octet* X, const octet* Y, octet* SK);
 
 /**	@brief Use Shamir's secret sharing to recover a BLS signature
  *
@@ -122,7 +122,7 @@ int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK);
 	@param  SIG Signature that is recovered
 	@return     Zero for success or else an error code
  */
-int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG);
+int BLS_ZZZ_RECOVER_SIGNATURE(int k, const octet* X, const octet* Y, octet* SIG);
 
 #endif
 
diff --git a/include/bls_ietf.h.in b/include/bls_ietf.h.in
new file mode 100644
index 0000000..5abf133
--- /dev/null
+++ b/include/bls_ietf.h.in
@@ -0,0 +1,439 @@
+/*
+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 bls_ietf_ZZZ.h
+ *
+ * @author Alexandre Adomnicai
+ *
+ * @date December 2022
+ *
+ * @brief BLS Header file IETF-compliant according to https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05
+ *
+ */
+
+#ifndef BLS_IETF_ZZZ_H
+#define BLS_IETF_ZZZ_H
+
+#include "pair_ZZZ.h"
+
+#if CURVE_SECURITY_ZZZ == 128
+#define SK_LEN      32
+#else
+#error "IETF-compliant BLS currently only supports 128-bit security level (i.e. BLS12-381)"
+#endif
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define BGS_ZZZ MODBYTES_XXX  /**< BLS Group Size */
+#define BFS_ZZZ MODBYTES_XXX  /**< BLS Field Size */
+
+#define SUCCESS               0x00000000
+#define ERR_NULLPOINTER_BLS   0x00000201
+#define ERR_BADARGLEN_BLS     0x00000202
+#define ERR_BADENCODING_BLS   0x00000203
+#define ERR_NOTONCURVE_BLS    0x00000204
+#define ERR_BADSIGNATURE_BLS  0x00000205
+#define ERR_INVALIDPUBKEY_BLS 0x00000206
+#define ERR_BADPOP_BLS        0x00000207
+
+extern const BIG_XXX ISO11_XNUM_BLS381[12]; /**< constants used to compute x_num for the 11-isogeny map for BLS12-381 G1 */
+extern const BIG_XXX ISO11_XDEN_BLS381[11]; /**< constants used to compute x_den for the 11-isogeny map for BLS12-381 G1 */
+extern const BIG_XXX ISO11_YNUM_BLS381[16]; /**< constants used to compute y_num for the 11-isogeny map for BLS12-381 G1 */
+extern const BIG_XXX ISO11_YDEN_BLS381[16]; /**< constants used to compute y_den for the 11-isogeny map for BLS12-381 G1 */
+
+extern const BIG_XXX ISO3_XNUMre_BLS381[4]; /**< constants used to compute x_num for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_XNUMim_BLS381[4]; /**< constants used to compute x_num for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_XDENre_BLS381[2]; /**< constants used to compute x_den for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_XDENim_BLS381[2]; /**< constants used to compute x_den for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_YNUMre_BLS381[4]; /**< constants used to compute y_num for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_YNUMim_BLS381[4]; /**< constants used to compute y_num for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_YDENre_BLS381[3]; /**< constants used to compute y_den for the 3-isogeny map for BLS12-381 G2 */
+extern const BIG_XXX ISO3_YDENim_BLS381[3]; /**< constants used to compute y_den for the 3-isogeny map for BLS12-381 G2 */
+
+/* BLS API functions */
+
+/**
+ * @brief Generation of a BLS secret key according to the RFC draft (Section 2.3).
+ *
+ * @param sk      Output secret key
+ * @param ikm     Secret input keying material
+ * @param ikmlen  Input keying material length in bytes (>= 32)
+ * @param salt    Salt value
+ * @param saltlen Salt length in bytes (>= 0)
+ * @param info    Optional octet string (empty string if omitted)
+ * @param infolen Info length in bytes (>= 0)
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_keygen(char sk[SK_LEN],
+  const char *ikm,  unsigned int ikmlen,
+  const char *salt, unsigned int saltlen,
+  const char *info, unsigned int infolen);
+
+/**
+ * @brief Derivation of a BLS public key in G1 (i.e. minimal-pubkey-size setting)
+ * from a secret key according to the RFC draft (Section 2.4).
+ *
+ * @param pk Output public key
+ * @param sk Secret key
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_sk_to_pk_G1(ECP_ZZZ *pk, const char *sk);
+
+/**
+ * @brief Derivation of a BLS public key in G2 (i.e. minimal-sig-size setting)
+ * from a secret key according to the RFC draft (Section 2.4).
+ *
+ * @param pk Output public key
+ * @param sk Secret key
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_sk_to_pk_G2(ECP2_ZZZ *pk, const char *sk);
+
+/**
+ * @brief Serialization of a point in G1 into an octet string.
+ * Same as ECP_ZZZ_toOctet but the order differs to match the Zcash
+ * serialization format: FP elements are encoded in big-endian format
+ * (i.e. imaginary|real) while ECP2_ZZZ_toOctet uses little-endian
+ * (i.e. real|imaginary).
+ *
+ * @param bytes Output octet string
+ * @param point Point in G1
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_serialize_G1(octet *bytes, const ECP_ZZZ *point);
+
+/**
+ * @brief Serialization of a point in G2 into an octet string.
+ * Same as ECP_ZZZ_fromOctet but the order differs to match the Zcash
+ * serialization format: FP elements are encoded in big-endian format
+ * (i.e. imaginary|real) while ECP_ZZZ_fromOctet uses little-endian
+ * (i.e. real|imaginary).
+ *
+ * @param point Output Point in G1
+ * @param bytes octet string
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_deserialize_G1(ECP_ZZZ *point, const octet *bytes);
+
+/**
+ * @brief Serialization of a point in G2 into an octet string.
+ * Same as ECP2_ZZZ_toOctet but the order differs to match the Zcash
+ * serialization format: FP elements are encoded in big-endian format
+ * (i.e. imaginary|real) while ECP2_ZZZ_toOctet uses little-endian
+ * (i.e. real|imaginary).
+ *
+ * @param bytes Output octet string
+ * @param point Point in G2
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_serialize_G2(octet *bytes, const ECP2_ZZZ *point);
+
+/**
+ * @brief Deserialization of an octet string into a point in G2.
+ * Same as ECP2_ZZZ_fromOctet but the order differs to match the Zcash
+ * serialization format: FP elements are encoded in big-endian format
+ * (i.e. imaginary|real) while ECP2_ZZZ_fromOctet uses little-endian
+ * (i.e. real|imaginary).
+ *
+ * @param point Output Point in G2
+ * @param bytes octet string
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_deserialize_G2(ECP2_ZZZ *point, const octet *bytes);
+
+/**
+ * @brief Compression of a point in G1 into an octet string.
+ * The most-significant 3 bits are encoded according to ZCash serialization format:
+ * https://github.com/zkcrypto/pairing/blob/34aa52b0f7bef705917252ea63e5a13fa01af551/src/bls12_381/README.md#serialization
+ *
+ * @param bytes Output octet string
+ * @param point Point in G1
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_compress_G1(octet *bytes, const ECP_ZZZ *point);
+
+/**
+ * @brief Uncompression of a compressed point in G1.
+ *
+ * @param point Output uncompressed point in G1
+ * @param bytes Compressed point in G1
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_uncompress_G1(ECP_ZZZ *point, const octet *bytes);
+
+/**
+ * @brief Compression of a point in G2 into an octet string.
+ * The most-significant 3 bits are encoded according to ZCash serialization format:
+ * https://github.com/zkcrypto/pairing/blob/34aa52b0f7bef705917252ea63e5a13fa01af551/src/bls12_381/README.md#serialization
+ *
+ * @param bytes Output octet string
+ * @param point Point in G2
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_compress_G2(octet *bytes, const ECP2_ZZZ *point);
+
+/**
+ * @brief Uncompression of a compressed point in G2.
+ *
+ * @param point Output uncompressed point in G2
+ * @param bytes Compressed point in G2
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_uncompress_G2(ECP2_ZZZ *point, const octet *bytes);
+
+/**
+ * @brief Hash a byte string into an elliptic curve point on G1 using an uniform encoding type.
+ *
+ * @param P Output point
+ * @param msg Input byte string
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_hash2curve_G1(ECP_ZZZ *P, const octet* msg, const octet* dst);
+
+/**
+ * @brief Hash a byte string into an elliptic curve point on G1 using a non-uniform encoding type.
+ *
+ * @param P Output point
+ * @param msg Input byte string
+ * @param dst Domain seperation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_encode2curve_G1(ECP_ZZZ *P, const octet* msg, const octet* dst);
+
+/**
+ * @brief Hash a byte string into an elliptic curve point on G2 using an uniform encoding type.
+ *
+ * @param P Output point
+ * @param msg Input byte string
+ * @param dst Domain seperation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_hash2curve_G2(ECP2_ZZZ *P, const octet* msg, const octet* dst);
+
+/**
+ * @brief Hash a byte string into an elliptic curve point on G2 using a non-uniform encoding type.
+ *
+ * @param P Output point
+ * @param msg Input byte string
+ * @param dst Domain seperation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_encode2curve_G2(ECP2_ZZZ *P, const octet* msg, const octet* dst);
+
+/**
+ * @brief Generate a signature in the minimal-signature-size setting. Note that
+ * the output signature is in the compressed serialization formats as stated in
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html#appendix-A.
+ *
+ * @param sig Output signature
+ * @param sk Private key
+ * @param msg Message to sign
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_sign_G1(octet *sig, const char *sk, const octet *msg, const octet *dst);
+
+/**
+ * @brief Generate a signature in the minimal-pubkey-size setting. Note that
+ * the output signature is in the compressed serialization formats as stated in
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html#appendix-A.
+ *
+ * @param sig Output signature
+ * @param sk Private key
+ * @param msg Message to sign
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_sign_G2(octet *sig, const char *sk, const octet *msg, const octet *dst);
+
+/**
+ * @brief Verify a signature in the minimal-signature-size setting.
+ *
+ * @param sig Signature
+ * @param pk Public key in G2
+ * @param msg Signed message
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_verify_G1(const octet *sig, const ECP2_ZZZ *PK, const octet *msg, const octet *dst);
+
+/**
+ * @brief Verify a signature in the minimal-pubkey-size setting.
+ *
+ * @param sig Signature
+ * @param pk Public key in G1
+ * @param msg Signed message
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_verify_G2(const octet *sig, const ECP_ZZZ *PK, const octet *msg, const octet *dst);
+
+/**
+ * @brief Aggregate multiple signatures into a single one in the minimal-signature-size setting.
+ * Note that the output signature is in the compressed serialization formats as stated in
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html#appendix-A.
+ *
+ * @param out Output signature
+ * @param in Input signatures to aggregate
+ * @param n Number of input signatures
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_aggregate_G1(octet *out, const octet *in, unsigned int n);
+
+/**
+ * @brief Aggregate multiple signatures into a single one in the minimal-pubkey-size setting.
+ * Note that the output signature is in the compressed serialization formats as stated in
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html#appendix-A.
+ *
+ * @param out Output signature
+ * @param in Input signatures to aggregate
+ * @param n Number of input signatures
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_aggregate_G2(octet *out, const octet *in, unsigned int n);
+
+/**
+ * @brief Verify an aggregated signature in the minimal-signature-size setting.
+ *
+ * @param sig Aggregated signature
+ * @param pk Public keys in G2
+ * @param msg Signed messages
+ * @param n Number of public keys/messages
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_aggregate_verify_G1(const octet *sig, const ECP2_ZZZ PK[], const octet msg[], unsigned int n, const octet *dst);
+
+/**
+ * @brief Verify an aggregated signature in the minimal-pubkey-size setting.
+ *
+ * @param sig Aggregated signature
+ * @param pk Public keys in G1
+ * @param msg Signed messages
+ * @param n Number of public keys/messages
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_core_aggregate_verify_G2(const octet *sig, const ECP_ZZZ PK[], const octet msg[], unsigned int n, const octet *dst);
+
+/**
+ * @brief Generate a proof of possession (POP) for a given secret key in the
+ * minimal-sig-size setting.
+ *
+ * @param proof Output proof of possession
+ * @param sk Secret key
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_pop_prove_G1(octet *proof, const char *sk);
+
+/**
+ * @brief Generate a proof of possession (POP) for a given secret key in the
+ * minimal-pubkey-size setting.
+ *
+ * @param proof Output proof of possession
+ * @param sk Secret key
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_pop_prove_G2(octet *proof, const char *sk);
+
+/**
+ * @brief Verify a proof of possession and its corresponding public key in the
+ * minimal-sig-size setting.
+ *
+ * @param proof Proof of possession
+ * @param PK Public key associated to the proof of possession
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_pop_verify_G1(const octet *proof, const ECP2_ZZZ *PK);
+
+/**
+ * @brief Verify a proof of possession and its corresponding public key in the
+ * minimal-pubkey-size setting.
+ *
+ * @param proof Proof of possession
+ * @param PK Public key associated to the proof of possession
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_pop_verify_G2(const octet *proof, const ECP_ZZZ *PK);
+
+/**
+ * @brief Verify an aggregated signature of the same message under different
+ * public keys in the minimal-sig-size setting.
+ * Note it is the responsibility of the caller that all public keys passed as
+ * arguments to this algorithm MUST have a corresponding proof of possession,
+ * and the result of evaluating PopVerify on each public key and its proof MUST
+ * be VALID.
+ *
+ * @param sig Aggregated signature
+ * @param pk Public keys in G2
+ * @param msg Signed message
+ * @param n Number of public keys
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_fast_aggregate_verify_G1(const octet *sig, const ECP2_ZZZ PK[], const octet *msg, unsigned int n, const octet *dst);
+
+/**
+ * @brief Verify an aggregated signature of the same message under different
+ * public keys in the minimal-pubkey-size setting.
+ * Note it is the responsibility of the caller that all public keys passed as
+ * arguments to this algorithm MUST have a corresponding proof of possession,
+ * and the result of evaluating PopVerify on each public key and its proof MUST
+ * be VALID.
+ *
+ * @param sig Aggregated signature
+ * @param pk Public keys in G1
+ * @param msg Signed message
+ * @param n Number of public keys
+ * @param dst Domain separation tag
+ *
+ * @return 0 if successful, error code otherwise
+ */
+int BLS_IETF_ZZZ_fast_aggregate_verify_G2(const octet *sig, const ECP_ZZZ PK[], const octet *msg, unsigned int n, const octet *dst);
+
+#endif
diff --git a/include/config_curve.h.in b/include/config_curve.h.in
index 9b28c1a..08953b5 100644
--- a/include/config_curve.h.in
+++ b/include/config_curve.h.in
@@ -31,8 +31,8 @@ under the License.
 
 
 #if PAIRING_FRIENDLY_ZZZ != NOT
-//#define USE_GLV_ZZZ	  /**< Note this method is patented (GLV), so maybe you want to comment this out */
-//#define USE_GS_G2_ZZZ /**< Well we didn't patent it :) But may be covered by GLV patent :( */
+//#define USE_GLV_ZZZ	//Note this method is patented (GLV), so maybe you want to comment this out
+//#define USE_GS_G2_ZZZ //Well we didn't patent it :) But may be covered by GLV patent :(
 #define USE_GS_GT_ZZZ /**< Not patented, so probably safe to always use this */
 
 #define POSITIVEX 0
diff --git a/include/ecdh.h.in b/include/ecdh.h.in
index cbeae6a..d37c6d9 100644
--- a/include/ecdh.h.in
+++ b/include/ecdh.h.in
@@ -34,8 +34,8 @@ under the License.
 
 /*** START OF USER CONFIGURABLE SECTION -  ***/
 
-//#define EAS_ZZZ 16 /**< Symmetric Key size - 128 bits */
-//#define HASH_TYPE_ECC_ZZZ SHA512  /**< Hash type */
+//#define //EAS_ZZZ 16 Symmetric Key size - 128 bits
+//#define //HASH_TYPE_ECC_ZZZ SHA512 Hash type
 
 /*** END OF USER CONFIGURABLE SECTION ***/
 
@@ -66,7 +66,7 @@ extern int  ECP_ZZZ_KEY_PAIR_GENERATE(csprng *R,octet *s,octet *W);
 	@param W the input public key to be validated
 	@return 0 if public key is OK, or an error code
  */
-extern int  ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W);
+extern int  ECP_ZZZ_PUBLIC_KEY_VALIDATE(const octet *W);
 
 /* ECDH primitives */
 
@@ -78,8 +78,7 @@ extern int  ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W);
 	@param K the output shared key, in fact the x-coordinate of s.W
 	@return 0 or an error code
  */
-extern int ECP_ZZZ_SVDP_DH(octet *s,octet *W,octet *K);
-/*extern int ECPSVDP_DHC(octet *,octet *,int,octet *);*/
+extern int ECP_ZZZ_SVDP_DH(const octet *s,const octet *W,octet *K);
 
 /*#if CURVETYPE!=MONTGOMERY */
 /* ECIES functions */
@@ -99,7 +98,7 @@ extern int ECP_ZZZ_SVDP_DH(octet *s,octet *W,octet *K);
 	@param C the output ciphertext
 	@param T the output HMAC tag, part of the ciphertext
  */
-extern void ECP_ZZZ_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,octet *M,int len,octet *V,octet *C,octet *T);
+extern void ECP_ZZZ_ECIES_ENCRYPT(int h,const octet *P1,const octet *P2,csprng *R,const octet *W,const octet *M,int len,octet *V,octet *C,octet *T);
 /**	@brief ECIES Decryption
  *
 	IEEE-1363 ECIES Decryption
@@ -113,7 +112,7 @@ extern void ECP_ZZZ_ECIES_ENCRYPT(int h,octet *P1,octet *P2,csprng *R,octet *W,o
 	@param M the output plaintext message
 	@return 1 if successful, else 0
  */
-extern int ECP_ZZZ_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M);
+extern int ECP_ZZZ_ECIES_DECRYPT(int h,const octet *P1,const octet *P2,const octet *V,octet *C,const octet *T,const octet *U,octet *M);
 
 /* ECDSA functions */
 /**	@brief ECDSA Signature
@@ -128,7 +127,7 @@ extern int ECP_ZZZ_ECIES_DECRYPT(int h,octet *P1,octet *P2,octet *V,octet *C,oct
 	@param d component of the output signature
 
  */
-extern int ECP_ZZZ_SP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,octet *d);
+extern int ECP_ZZZ_SP_DSA(int h,csprng *R,const octet *k,const octet *s,const octet *M,octet *c,octet *d);
 /**	@brief ECDSA Signature Verification
  *
 	IEEE-1363 ECDSA Signature Verification
@@ -139,7 +138,7 @@ extern int ECP_ZZZ_SP_DSA(int h,csprng *R,octet *k,octet *s,octet *M,octet *c,oc
 	@param d component of the input signature
 	@return 0 or an error code
  */
-extern int ECP_ZZZ_VP_DSA(int h,octet *W,octet *M,octet *c,octet *d);
+extern int ECP_ZZZ_VP_DSA(int h,const octet *W,const octet *M,octet *c,octet *d);
 /*#endif*/
 
 #endif
diff --git a/include/ecdh_support.h b/include/ecdh_support.h
index 85b200d..78fb167 100644
--- a/include/ecdh_support.h
+++ b/include/ecdh_support.h
@@ -40,7 +40,7 @@
 	@param w output
 	@param pad padding
  */
-extern void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad);
+extern void ehashit(int sha,const octet *p,int n,const octet *x,octet *w,int pad);
 
 /**	@brief hash an octet into another octet
  *
@@ -48,7 +48,7 @@ extern void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad);
 	@param I input octet
 	@param O output octet - H(I)
  */
-extern void HASH(int h,octet *I,octet *O);
+extern void HASH(int h,const 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.
@@ -59,9 +59,7 @@ extern void HASH(int h,octet *I,octet *O);
 	@param tag is the output HMAC
 	@return 0 for bad parameters, else 1
  */
-extern int HMAC(int h,octet *M,octet *K,int len,octet *tag);
-
-/*extern void KDF1(octet *,int,octet *);*/
+extern int HMAC(int h,const octet *M,const octet *K,int len,octet *tag);
 
 /**	@brief Key Derivation Function - generates key K from inputs Z and P
  *
@@ -72,7 +70,7 @@ extern int HMAC(int h,octet *M,octet *K,int len,octet *tag);
 	@param len is output desired length of key
 	@param K is the derived key
  */
-extern void KDF2(int h,octet *Z,octet *P,int len,octet *K);
+extern void KDF2(int h,const octet *Z,const 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.
@@ -83,7 +81,7 @@ extern void KDF2(int h,octet *Z,octet *P,int len,octet *K);
 	@param len is output desired length
 	@param K is the derived key
  */
-extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K);
+extern void PBKDF2(int h,const 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.
@@ -91,7 +89,7 @@ extern void PBKDF2(int h,octet *P,octet *S,int rep,int len,octet *K);
 	@param P input plaintext octet
 	@param C output ciphertext octet
  */
-extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
+extern void AES_CBC_IV0_ENCRYPT(octet *K,const 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.
@@ -100,7 +98,7 @@ extern void AES_CBC_IV0_ENCRYPT(octet *K,octet *P,octet *C);
 	@param P output plaintext octet
 	@return 0 if bad input, else 1
  */
-extern int AES_CBC_IV0_DECRYPT(octet *K,octet *C,octet *P);
+extern int AES_CBC_IV0_DECRYPT(octet *K,const octet *C,octet *P);
 
 /* ECDH primitives - support functions */
 /**	@brief Generate an ECC public/private key pair
diff --git a/include/ecp.h.in b/include/ecp.h.in
index f07230b..a0ca988 100644
--- a/include/ecp.h.in
+++ b/include/ecp.h.in
@@ -97,6 +97,10 @@ extern const BIG_XXX CURVE_SB_ZZZ[2][2]; /**< BN curve constant for GLV decompos
 extern const BIG_XXX CURVE_WB_ZZZ[4];	 /**< BN curve constant for GS decomposition */
 extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
 
+extern const BIG_XXX SSWU_A1_ZZZ; /**< Parameter A' of the Weierstrass curve for 11-isogeny for BLS12-381 G1 */
+extern const BIG_XXX SSWU_B1_ZZZ; /**< Parameter B' of the Weierstrass curve for 11-isogeny for BLS12-381 G1 */
+extern const BIG_XXX SSWU_Z1_ZZZ; /**< A non-zero element of finite field for EC mapping */
+extern const BIG_XXX H_EFF_G1;    /**< Scalar parameter for clear_cofactor for BLS12-381 G1 */
 
 /**
 	@brief ECP structure - Elliptic Curve Point over base field
@@ -104,7 +108,7 @@ extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposi
 
 typedef struct
 {
-//    int inf; /**< Infinity Flag - not needed for Edwards representation */
+//    int inf; //Infinity Flag - not needed for Edwards representation
 
     FP_YYY x; /**< x-coordinate of point */
 #if CURVETYPE_ZZZ!=MONTGOMERY
@@ -120,20 +124,20 @@ typedef struct
 	@param P ECP point to be tested
 	@return 1 if infinity, else returns 0
  */
-extern int ECP_ZZZ_isinf(ECP_ZZZ *P);
+extern int ECP_ZZZ_isinf(const ECP_ZZZ *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_ZZZ_equals(ECP_ZZZ *P,ECP_ZZZ *Q);
+extern int ECP_ZZZ_equals(const ECP_ZZZ *P,const ECP_ZZZ *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_ZZZ_copy(ECP_ZZZ *P,ECP_ZZZ *Q);
+extern void ECP_ZZZ_copy(ECP_ZZZ *P,const ECP_ZZZ *Q);
 /**	@brief Negation of an ECP point
  *
 	@param P ECP instance, on exit = -P
@@ -168,7 +172,7 @@ extern int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x);
 	@param P ECP instance (x,[y])
 	@return -1 if P is point-at-infinity, else 0
  */
-extern int ECP_ZZZ_get(BIG_XXX x,ECP_ZZZ *P);
+extern int ECP_ZZZ_get(BIG_XXX x,const ECP_ZZZ *P);
 /**	@brief Adds ECP instance Q to ECP instance P, given difference D=P-Q
  *
 	Differential addition of points on a Montgomery curve
@@ -186,7 +190,7 @@ extern void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q,ECP_ZZZ *D);
 	@param y BIG y coordinate of point
 	@return 1 if point exists, else 0
  */
-extern int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y);
+extern int ECP_ZZZ_set(ECP_ZZZ *P,const BIG_XXX x,const BIG_XXX y);
 /**	@brief Extract x and y coordinates of an ECP point P
  *
 	If x=y, returns only x
@@ -195,19 +199,19 @@ extern int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y);
 	@param P ECP instance (x,y)
 	@return sign of y, or -1 if P is point-at-infinity
  */
-extern int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,ECP_ZZZ *P);
+extern int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,const ECP_ZZZ *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_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q);
+extern void ECP_ZZZ_add(ECP_ZZZ *P,const ECP_ZZZ *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_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q);
+extern void ECP_ZZZ_sub(ECP_ZZZ *P,const ECP_ZZZ *Q);
 /**	@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.
@@ -216,7 +220,7 @@ extern void ECP_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q);
 	@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_ZZZ_setx(ECP_ZZZ *P,BIG_XXX x,int s);
+extern int ECP_ZZZ_setx(ECP_ZZZ *P,const BIG_XXX x,int s);
 
 #endif
 
@@ -231,7 +235,7 @@ extern void ECP_ZZZ_cfp(ECP_ZZZ *Q);
 	@param Q ECP instance of correct order
 	@param w OCTET byte array to be mapped
  */
-extern void ECP_ZZZ_mapit(ECP_ZZZ *Q,octet *w);
+extern void ECP_ZZZ_mapit(ECP_ZZZ *Q,const octet *w);
 
 /**	@brief Converts an ECP point from Projective (x,y,z) coordinates to affine (x,y) coordinates
  *
@@ -253,7 +257,7 @@ extern void ECP_ZZZ_output(ECP_ZZZ * P);
  *
 	@param P ECP instance to be printed
  */
-extern void ECP_ZZZ_rawoutput(ECP_ZZZ * P);
+extern void ECP_ZZZ_rawoutput(const ECP_ZZZ * P);
 
 /**	@brief Formats and outputs an ECP point to an octet string
 	The octet string is normally in the standard form 0x04|x|y
@@ -264,7 +268,7 @@ extern void ECP_ZZZ_rawoutput(ECP_ZZZ * P);
 	@param S output octet string
 	@param P ECP instance to be converted to an octet string
  */
-extern void ECP_ZZZ_toOctet(octet *S,ECP_ZZZ *P,bool c);
+extern void ECP_ZZZ_toOctet(octet *S,const ECP_ZZZ *P,bool c);
 /**	@brief Creates an ECP point from an octet string
  *
 	The octet string is normally in the standard form 0x04|x|y
@@ -275,7 +279,7 @@ extern void ECP_ZZZ_toOctet(octet *S,ECP_ZZZ *P,bool c);
 	@param S input octet string
 	return 1 if octet string corresponds to a point on the curve, else 0
  */
-extern int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *S);
+extern int ECP_ZZZ_fromOctet(ECP_ZZZ *P,const octet *S);
 /**	@brief Doubles an ECP instance P
  *
 	@param P ECP instance, on exit =2*P
@@ -295,7 +299,7 @@ extern void ECP_ZZZ_pinmul(ECP_ZZZ *P,int i,int b);
 	@param b BIG number multiplier
 
  */
-extern void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX b);
+extern void ECP_ZZZ_mul(ECP_ZZZ *P,const BIG_XXX b);
 /**	@brief Calculates double multiplication P=e*P+f*Q, side-channel resistant
  *
 	@param P ECP instance, on exit =e*P+f*Q
@@ -303,12 +307,23 @@ extern void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX b);
 	@param e BIG number multiplier
 	@param f BIG number multiplier
  */
-extern void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f);
+extern void ECP_ZZZ_mul2(ECP_ZZZ *P,const ECP_ZZZ *Q,const BIG_XXX e,const BIG_XXX f);
 /**	@brief Get Group Generator from ROM
  *
 	@param G ECP instance
  */
 extern void ECP_ZZZ_generator(ECP_ZZZ *G);
 
+/**
+ * @brief Maps a field element to an EC point using Simplified Shallue-van de Woestijne-Ulas (SSWU) method as defined at
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-for-ab-0.
+ * 
+ * @param x x-coordinate of output EC point
+ * @param y y-coordinate of output EC point
+ * @param u Input field element
+ * 
+ * @return 0 if successful, error code otherwise
+ */
+extern int ECP_ZZZ_sswu(FP_YYY *x, FP_YYY *y, FP_YYY u);
 
 #endif
diff --git a/include/ecp2.h.in b/include/ecp2.h.in
index 046953a..12c7557 100644
--- a/include/ecp2.h.in
+++ b/include/ecp2.h.in
@@ -30,13 +30,15 @@
 #include "fp2_YYY.h"
 #include "config_curve_ZZZ.h"
 
+#define ERR_NULLPOINTER_ECP2 0x00000081
+
 /**
 	@brief ECP2 Structure - Elliptic Curve Point over quadratic extension field
 */
 
 typedef struct
 {
-//    int inf; /**< Infinity Flag */
+//    int inf;  //Infinity Flag
     FP2_YYY x;   /**< x-coordinate of point */
     FP2_YYY y;   /**< y-coordinate of point */
     FP2_YYY z;   /**< z-coordinate of point */
@@ -67,19 +69,27 @@ extern const BIG_XXX CURVE_Pxb_ZZZ; /**< imaginary part of x-coordinate of gener
 extern const BIG_XXX CURVE_Pya_ZZZ; /**< real part of y-coordinate of generator point in group G2 */
 extern const BIG_XXX CURVE_Pyb_ZZZ; /**< imaginary part of y-coordinate of generator point in group G2 */
 
+/* For SSWU with AB == 0 */
+extern const BIG_XXX SSWU_A2re_ZZZ; /**< Parameter A' (real part) of the Weierstrass curve for 3-isogeny for BLS12-381 G2 */
+extern const BIG_XXX SSWU_A2im_ZZZ; /**< Parameter A' (imaginary part) of the Weierstrass curve for 3-isogeny for BLS12-381 G2 */
+extern const BIG_XXX SSWU_B2re_ZZZ; /**< Parameter B' (real part) of the Weierstrass curve for 3-isogeny for BLS12-381 G2 */
+extern const BIG_XXX SSWU_B2im_ZZZ; /**< Parameter B' (imaginary part) of the Weierstrass curve for 3-isogeny for BLS12-381 G2 */
+extern const BIG_XXX SSWU_Z2re_ZZZ; /**< A non-zero element (real part) of finite field for EC mapping */
+extern const BIG_XXX SSWU_Z2im_ZZZ; /**< A non-zero element (imaginary part) of finite field for EC mapping */
+
 /* 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_ZZZ_isinf(ECP2_ZZZ *P);
+extern int ECP2_ZZZ_isinf(const ECP2_ZZZ *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_ZZZ_copy(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+extern void ECP2_ZZZ_copy(ECP2_ZZZ *P,const ECP2_ZZZ *Q);
 /**	@brief Set ECP2 to point-at-infinity
  *
 	@param P ECP2 instance to be set to infinity
@@ -105,17 +115,17 @@ extern void ECP2_ZZZ_affine(ECP2_ZZZ *P);
 	@param P ECP2 instance (x,y)
 	@return -1 if P is point-at-infinity, else 0
  */
-extern int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,ECP2_ZZZ *P);
+extern int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,const ECP2_ZZZ *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_ZZZ_output(ECP2_ZZZ *P);
+extern void ECP2_ZZZ_output(const ECP2_ZZZ *P);
 /**	@brief Formats and outputs an ECP2 point to the console, in projective coordinates
  *
 	@param P ECP2 instance to be printed
  */
-extern void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P);
+extern void ECP2_ZZZ_outputxyz(const ECP2_ZZZ *P);
 /**	@brief Formats and outputs an ECP2 point to an octet string
  *
 	The octet string is created in the form x|y.
@@ -123,7 +133,7 @@ extern void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P);
 	@param S output octet string
 	@param P ECP2 instance to be converted to an octet string
  */
-extern void ECP2_ZZZ_toOctet(octet *S,ECP2_ZZZ *P);
+extern void ECP2_ZZZ_toOctet(octet *S,const ECP2_ZZZ *P);
 /**	@brief Creates an ECP2 point from an octet string
  *
 	The octet string is in the form x|y
@@ -132,7 +142,7 @@ extern void ECP2_ZZZ_toOctet(octet *S,ECP2_ZZZ *P);
 	@param S input octet string
 	return 1 if octet string corresponds to a point on the curve, else 0
  */
-extern int ECP2_ZZZ_fromOctet(ECP2_ZZZ *P,octet *S);
+extern int ECP2_ZZZ_fromOctet(ECP2_ZZZ *P,const octet *S);
 /**	@brief Calculate Right Hand Side of curve equation y^2=f(x)
  *
 	Function f(x)=x^3+Ax+B
@@ -140,7 +150,7 @@ extern int ECP2_ZZZ_fromOctet(ECP2_ZZZ *P,octet *S);
 	@param r FP2 value of f(x)
 	@param x FP2 instance
  */
-extern void ECP2_ZZZ_rhs(FP2_YYY *r,FP2_YYY *x);
+extern void ECP2_ZZZ_rhs(FP2_YYY *r,const FP2_YYY *x);
 /**	@brief Set ECP2 to point(x,y) given x and y
  *
 	Point P set to infinity if no such point on the curve.
@@ -149,7 +159,7 @@ extern void ECP2_ZZZ_rhs(FP2_YYY *r,FP2_YYY *x);
 	@param y FP2 y coordinate of point
 	@return 1 if point exists, else 0
  */
-extern int ECP2_ZZZ_set(ECP2_ZZZ *P,FP2_YYY *x,FP2_YYY *y);
+extern int ECP2_ZZZ_set(ECP2_ZZZ *P,const FP2_YYY *x,const FP2_YYY *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.
@@ -157,7 +167,7 @@ extern int ECP2_ZZZ_set(ECP2_ZZZ *P,FP2_YYY *x,FP2_YYY *y);
 	@param x BIG x coordinate of point
 	@return 1 if point exists, else 0
  */
-extern int ECP2_ZZZ_setx(ECP2_ZZZ *P,FP2_YYY *x);
+extern int ECP2_ZZZ_setx(ECP2_ZZZ *P,const FP2_YYY *x);
 /**	@brief Negation of an ECP2 point
  *
 	@param P ECP2 instance, on exit = -P
@@ -173,13 +183,13 @@ extern int ECP2_ZZZ_dbl(ECP2_ZZZ *P);
 	@param P ECP2 instance, on exit =P+Q
 	@param Q ECP2 instance to be added to P
  */
-extern int ECP2_ZZZ_add(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+extern int ECP2_ZZZ_add(ECP2_ZZZ *P,const ECP2_ZZZ *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_ZZZ_sub(ECP2_ZZZ *P,ECP2_ZZZ *Q);
+extern void ECP2_ZZZ_sub(ECP2_ZZZ *P,const ECP2_ZZZ *Q);
 /**	@brief Multiplies an ECP2 instance P by a BIG, side-channel resistant
  *
 	Uses fixed sized windows.
@@ -187,7 +197,7 @@ extern void ECP2_ZZZ_sub(ECP2_ZZZ *P,ECP2_ZZZ *Q);
 	@param b BIG number multiplier
 
  */
-extern void ECP2_ZZZ_mul(ECP2_ZZZ *P,BIG_XXX b);
+extern void ECP2_ZZZ_mul(ECP2_ZZZ *P,const BIG_XXX b);
 /**	@brief Multiplies an ECP2 instance P by the internal modulus p, using precalculated Frobenius constant f
  *
 	Fast point multiplication using Frobenius
@@ -202,14 +212,14 @@ extern void ECP2_ZZZ_frob(ECP2_ZZZ *P,FP2_YYY *f);
 	@param Q ECP2 array of 4 points
 	@param b BIG array of 4 multipliers
  */
-extern void ECP2_ZZZ_mul4(ECP2_ZZZ *P,ECP2_ZZZ *Q,BIG_XXX *b);
+extern void ECP2_ZZZ_mul4(ECP2_ZZZ *P,const ECP2_ZZZ Q[4],const BIG_XXX b[4]);
 
 /**	@brief Maps random BIG to curve point of correct order
  *
 	@param P ECP2 instance of correct order
 	@param w OCTET byte array to be mapped
  */
-extern void ECP2_ZZZ_mapit(ECP2_ZZZ *P,octet *w);
+extern void ECP2_ZZZ_mapit(ECP2_ZZZ *P,const octet *w);
 
 /**	@brief Get Group Generator from ROM
  *
@@ -217,4 +227,21 @@ extern void ECP2_ZZZ_mapit(ECP2_ZZZ *P,octet *w);
  */
 extern void ECP2_ZZZ_generator(ECP2_ZZZ *G);
 
+/**
+ * @brief Maps a quadratic extension field element to an ECP2 using Simplified Shallue-van de Woestijne-Ulas (SSWU) method as defined at
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-for-ab-0.
+ * 
+ * @param x x-coordinate of output ECP2
+ * @param y y-coordinate of output ECP2
+ * @param u Input quadratic extension field element
+ */
+extern int ECP2_ZZZ_sswu(FP2_YYY *x, FP2_YYY *y, FP2_YYY u);
+
+/**
+ * @brief Cofactor clearing 
+ * 
+ * @param P Input/output point
+ */
+extern int ECP2_ZZZ_clearcofactor(ECP2_ZZZ *P);
+
 #endif
diff --git a/include/ff.h.in b/include/ff.h.in
index 931dd54..16cc6c2 100644
--- a/include/ff.h.in
+++ b/include/ff.h.in
@@ -33,9 +33,8 @@
 #define HFLEN_WWW (FFLEN_WWW/2) /**< Useful for half-size RSA private key operations */
 #define P_MBITS_WWW (MODBYTES_XXX*8) /**< Number of bits in modulus */
 #define P_TBITS_WWW (P_MBITS_WWW%BASEBITS_XXX) /**< TODO  */
-#define P_EXCESS_WWW(a) (((a[NLEN_XXX-1])>>(P_TBITS_WWW))+1) /**< TODO */
-#define P_FEXCESS_WWW ((chunk)1<<(BASEBITS_XXX*NLEN_XXX-P_MBITS_WWW-1)) /**< TODO */
-
+#define P_EXCESS_WWW(a) (((a[NLEN_XXX-1])>>(P_TBITS_WWW))+1) /**< TODO  */
+#define P_FEXCESS_WWW ((chunk)1<<(BASEBITS_XXX*NLEN_XXX-P_MBITS_WWW-1)) /**< TODO  */
 
 /* Finite Field Prototypes */
 /**	@brief Copy one FF element of given length to another
@@ -175,7 +174,7 @@ extern void FF_WWW_toOctet(octet *S,BIG_XXX *x,int n);
 	@param S input octet string
 	@param n size of FF in BIGs
  */
-extern void FF_WWW_fromOctet(BIG_XXX *x,octet *S,int n);
+extern void FF_WWW_fromOctet(BIG_XXX *x,const octet *S,int n);
 /**	@brief Multiplication of two FFs
  *
 	Uses Karatsuba method internally
@@ -341,7 +340,7 @@ extern void FF_WWW_ct_pow(BIG_XXX *r,BIG_XXX *x,BIG_XXX * e,BIG_XXX *p,int n, in
 	@param p FF modulus
 	@param n size of FF in BIGs
  */
-extern void FF_WWW_ct_pow_big(BIG_XXX *r,BIG_XXX *x,BIG_XXX e,BIG_XXX *p,int n);
+extern void FF_WWW_ct_pow_big(BIG_XXX *r,BIG_XXX *x,const BIG_XXX e,BIG_XXX *p,int n);
 /**	@brief Calculate r=x^e.y^f mod p for FF e and f, side channel resistant
  *
 	@param r  FF instance, on exit = x^e.y^f mod p
diff --git a/include/fp.h.in b/include/fp.h.in
index 245e6e5..23a5615 100644
--- a/include/fp.h.in
+++ b/include/fp.h.in
@@ -64,7 +64,7 @@ extern const chunk MConst_YYY;		/**< Constant associated with Modulus - for Mont
 	@param x BIG number to be tested
 	@return 1 if zero, else returns 0
  */
-extern int FP_YYY_iszilch(FP_YYY *x);
+extern int FP_YYY_iszilch(const FP_YYY *x);
 
 
 /**	@brief Set FP to zero
@@ -78,7 +78,7 @@ extern void FP_YYY_zero(FP_YYY *x);
 	@param y FP number to be copied to
 	@param x FP to be copied from
  */
-extern void FP_YYY_copy(FP_YYY *y,FP_YYY *x);
+extern void FP_YYY_copy(FP_YYY *y,const FP_YYY *x);
 
 /**	@brief Copy from ROM to an FP
  *
@@ -94,7 +94,7 @@ extern void FP_YYY_rcopy(FP_YYY *y,const BIG_XXX x);
 	@param y FP number
 	@return 1 if equal, else returns 0
  */
-extern int FP_YYY_equals(FP_YYY *x,FP_YYY *y);
+extern int FP_YYY_equals(const FP_YYY *x,const FP_YYY *y);
 
 
 /**	@brief Conditional constant time swap of two FP numbers
@@ -112,19 +112,19 @@ extern void FP_YYY_cswap(FP_YYY *x,FP_YYY *y,int s);
 	@param y another FP number
 	@param s copy takes place if not equal to 0
  */
-extern void FP_YYY_cmove(FP_YYY *x,FP_YYY *y,int s);
+extern void FP_YYY_cmove(FP_YYY *x,const FP_YYY *y,int s);
 /**	@brief Converts from BIG integer to residue form mod Modulus
  *
 	@param x BIG number to be converted
 	@param y FP result
  */
-extern void FP_YYY_nres(FP_YYY *y,BIG_XXX x);
+extern void FP_YYY_nres(FP_YYY *y,const BIG_XXX x);
 /**	@brief Converts from residue form back to BIG integer form
  *
 	@param y FP number to be converted to BIG
 	@param x BIG result
  */
-extern void FP_YYY_redc(BIG_XXX x,FP_YYY *y);
+extern void FP_YYY_redc(BIG_XXX x,const FP_YYY *y);
 /**	@brief Sets FP to representation of unity in residue form
  *
 	@param x FP number to be set equal to unity.
@@ -136,7 +136,7 @@ extern void FP_YYY_one(FP_YYY *x);
 	@param r BIG number, on exit = d mod Modulus
 	@param d DBIG number to be reduced
  */
-extern void FP_YYY_mod(BIG_XXX r,DBIG_XXX d);
+extern void FP_YYY_mod(BIG_XXX r,const DBIG_XXX d);
 
 #ifdef FUSED_MODMUL
 extern void FP_YYY_modmul(BIG_XXX,BIG_XXX,BIG_XXX);
@@ -149,14 +149,14 @@ extern void FP_YYY_modmul(BIG_XXX,BIG_XXX,BIG_XXX);
 	@param y FP number, the multiplicand
 	@param z FP number, the multiplier
  */
-extern void FP_YYY_mul(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+extern void FP_YYY_mul(FP_YYY *x,const FP_YYY *y,const FP_YYY *z);
 /**	@brief Fast Modular multiplication of an FP, by a small integer, mod Modulus
  *
 	@param x FP number, on exit the modular product = y*i mod Modulus
 	@param y FP number, the multiplicand
 	@param i a small number, the multiplier
  */
-extern void FP_YYY_imul(FP_YYY *x,FP_YYY *y,int i);
+extern void FP_YYY_imul(FP_YYY *x,const FP_YYY *y,int i);
 /**	@brief Fast Modular squaring of an FP, mod Modulus
  *
 	Uses appropriate fast modular reduction method
@@ -171,20 +171,20 @@ extern void FP_YYY_sqr(FP_YYY *x,FP_YYY *y);
 	@param y FP number
 	@param z FP number
  */
-extern void FP_YYY_add(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+extern void FP_YYY_add(FP_YYY *x,const FP_YYY *y,const FP_YYY *z);
 /**	@brief Modular subtraction of two FPs, mod Modulus
  *
 	@param x FP number, on exit the modular difference = y-z mod Modulus
 	@param y FP number
 	@param z FP number
  */
-extern void FP_YYY_sub(FP_YYY *x,FP_YYY *y,FP_YYY *z);
+extern void FP_YYY_sub(FP_YYY *x,const FP_YYY *y,const FP_YYY *z);
 /**	@brief Modular division by 2 of an FP, mod Modulus
  *
 	@param x FP number, on exit =y/2 mod Modulus
 	@param y FP number
  */
-extern void FP_YYY_div2(FP_YYY *x,FP_YYY *y);
+extern void FP_YYY_div2(FP_YYY *x,const FP_YYY *y);
 /**	@brief Fast Modular exponentiation of an FP, to the power of a BIG, mod Modulus
  *
 	@param x FP number, on exit  = y^z mod Modulus
@@ -204,18 +204,18 @@ extern void FP_YYY_sqrt(FP_YYY *x,FP_YYY *y);
 	@param x FP number, on exit = -y mod Modulus
 	@param y FP number
  */
-extern void FP_YYY_neg(FP_YYY *x,FP_YYY *y);
+extern void FP_YYY_neg(FP_YYY *x,const FP_YYY *y);
 /**	@brief Outputs an FP number to the console
  *
 	Converts from residue form before output
 	@param x an FP number
  */
-extern void FP_YYY_output(FP_YYY *x);
+extern void FP_YYY_output(const FP_YYY *x);
 /**	@brief Outputs an FP number to the console, in raw form
  *
 	@param x a BIG number
  */
-extern void FP_YYY_rawoutput(FP_YYY *x);
+extern void FP_YYY_rawoutput(const FP_YYY *x);
 /**	@brief Reduces possibly unreduced FP mod Modulus
  *
 	@param x FP number, on exit reduced mod Modulus
diff --git a/include/fp12.h.in b/include/fp12.h.in
index 5cb5d83..38ff93c 100644
--- a/include/fp12.h.in
+++ b/include/fp12.h.in
@@ -50,19 +50,19 @@ extern const BIG_XXX Frb_YYY; /**< imaginary part of BN curve Frobenius Constant
 	@param x FP12 number to be tested
 	@return 1 if zero, else returns 0
  */
-extern int FP12_YYY_iszilch(FP12_YYY *x);
+extern int FP12_YYY_iszilch(const FP12_YYY *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_YYY_isunity(FP12_YYY *x);
+extern int FP12_YYY_isunity(const FP12_YYY *x);
 /**	@brief Copy FP12 to another FP12
  *
 	@param x FP12 instance, on exit = y
 	@param y FP12 instance to be copied
  */
-extern void FP12_YYY_copy(FP12_YYY *x,FP12_YYY *y);
+extern void FP12_YYY_copy(FP12_YYY *x,const FP12_YYY *y);
 /**	@brief Set FP12 to unity
  *
 	@param x FP12 instance to be set to one
@@ -81,21 +81,21 @@ extern void FP12_YYY_zero(FP12_YYY *x);
 	@param y FP12 instance to be compared
 	@return 1 if x=y, else returns 0
  */
-extern int FP12_YYY_equals(FP12_YYY *x,FP12_YYY *y);
+extern int FP12_YYY_equals(const FP12_YYY *x,const FP12_YYY *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_YYY_conj(FP12_YYY *x,FP12_YYY *y);
+extern void FP12_YYY_conj(FP12_YYY *x,const FP12_YYY *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_YYY_from_FP4(FP12_YYY *x,FP4_YYY *a);
+extern void FP12_YYY_from_FP4(FP12_YYY *x,const FP4_YYY *a);
 /**	@brief Initialise FP12 from three FP4s
  *
 	@param x FP12 instance to be initialised
@@ -103,7 +103,7 @@ extern void FP12_YYY_from_FP4(FP12_YYY *x,FP4_YYY *a);
 	@param b FP4 to form second part of FP12
 	@param c FP4 to form third part of FP12
  */
-extern void FP12_YYY_from_FP4s(FP12_YYY *x,FP4_YYY *a,FP4_YYY* b,FP4_YYY *c);
+extern void FP12_YYY_from_FP4s(FP12_YYY *x,const FP4_YYY *a,const FP4_YYY* b,const FP4_YYY *c);
 /**	@brief Fast Squaring of an FP12 in "unitary" form
  *
 	@param x FP12 instance, on exit = y^2
@@ -122,14 +122,14 @@ extern void FP12_YYY_sqr(FP12_YYY *x,FP12_YYY *y);
 	@param x FP12 instance, on exit = x*y
 	@param y FP12 instance, of special form
  */
-extern void FP12_YYY_smul(FP12_YYY *x,FP12_YYY *y);
+extern void FP12_YYY_smul(FP12_YYY *x,const FP12_YYY *y);
 
 /**	@brief Fast multiplication of what may be sparse multiplicands
  *
 	@param x FP12 instance, on exit = x*y
 	@param y FP12 instance, of special form
  */
-extern void FP12_YYY_ssmul(FP12_YYY *x,FP12_YYY *y);
+extern void FP12_YYY_ssmul(FP12_YYY *x,const FP12_YYY *y);
 
 
 /**	@brief Full unconditional Multiplication of two FP12s
@@ -137,7 +137,7 @@ extern void FP12_YYY_ssmul(FP12_YYY *x,FP12_YYY *y);
 	@param x FP12 instance, on exit = x*y
 	@param y FP12 instance, the multiplier
  */
-extern void FP12_YYY_mul(FP12_YYY *x,FP12_YYY *y);
+extern void FP12_YYY_mul(FP12_YYY *x,const FP12_YYY *y);
 /**	@brief Inverting an FP12
  *
 	@param x FP12 instance, on exit = 1/y
@@ -150,7 +150,7 @@ extern void FP12_YYY_inv(FP12_YYY *x,FP12_YYY *y);
 	@param x FP12 instance
 	@param b BIG number
  */
-extern void FP12_YYY_pow(FP12_YYY *r,FP12_YYY *x,BIG_XXX b);
+extern void FP12_YYY_pow(FP12_YYY *r,const FP12_YYY *x,const BIG_XXX b);
 /**	@brief Raises an FP12 instance x to a small integer power, side-channel resistant
  *
 	@param x FP12 instance, on exit = x^i
@@ -166,7 +166,7 @@ extern void FP12_YYY_pinpow(FP12_YYY *x,int i,int b);
 	@param e BIG exponent
 	@param r BIG group order
  */
-extern void FP12_YYY_compow(FP4_YYY *c,FP12_YYY *x,BIG_XXX e,BIG_XXX r);
+extern void FP12_YYY_compow(FP4_YYY *c,const FP12_YYY *x,const BIG_XXX e,const BIG_XXX r);
 
 /**	@brief Calculate x[0]^b[0].x[1]^b[1].x[2]^b[2].x[3]^b[3], side-channel resistant
  *
@@ -174,13 +174,13 @@ extern void FP12_YYY_compow(FP4_YYY *c,FP12_YYY *x,BIG_XXX e,BIG_XXX r);
 	@param x FP12 array with 4 FP12s
 	@param b BIG array of 4 exponents
  */
-extern void FP12_YYY_pow4(FP12_YYY *r,FP12_YYY *x,BIG_XXX *b);
+extern void FP12_YYY_pow4(FP12_YYY *r,const FP12_YYY *x,const BIG_XXX b[4]);
 /**	@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_YYY_frob(FP12_YYY *x,FP2_YYY *f);
+extern void FP12_YYY_frob(FP12_YYY *x,const FP2_YYY *f);
 /**	@brief Reduces all components of possibly unreduced FP12 mod Modulus
  *
 	@param x FP12 instance, on exit reduced mod Modulus
@@ -202,7 +202,7 @@ extern void FP12_YYY_output(FP12_YYY *x);
 	@param S output octet string
 	@param x FP12 instance to be converted to an octet string
  */
-extern void FP12_YYY_toOctet(octet *S,FP12_YYY *x);
+extern void FP12_YYY_toOctet(octet *S,const FP12_YYY *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.
@@ -210,14 +210,14 @@ extern void FP12_YYY_toOctet(octet *S,FP12_YYY *x);
 	@param S input octet string
 
  */
-extern void FP12_YYY_fromOctet(FP12_YYY *x,octet *S);
+extern void FP12_YYY_fromOctet(FP12_YYY *x,const 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_YYY_trace(FP4_YYY *t,FP12_YYY *x);
+extern void FP12_YYY_trace(FP4_YYY *t,const FP12_YYY *x);
 
 /**	@brief Conditional copy of FP12 number
  *
@@ -226,7 +226,7 @@ extern void FP12_YYY_trace(FP4_YYY *t,FP12_YYY *x);
 	@param y another FP12 instance
 	@param s copy only takes place if not equal to 0
  */
-extern void FP12_YYY_cmove(FP12_YYY *x,FP12_YYY *y,int s);
+extern void FP12_YYY_cmove(FP12_YYY *x,const FP12_YYY *y,int s);
 
 
 #endif
diff --git a/include/fp16.h.in b/include/fp16.h.in
index bb13ed3..c1ecdb0 100644
--- a/include/fp16.h.in
+++ b/include/fp16.h.in
@@ -157,7 +157,7 @@ extern void FP16_YYY_qmul(FP16_YYY *x,FP16_YYY *y,FP2_YYY *a);
 	@param y FP16 instance
 	@param i an integer
  */
-extern void FP16_YYY_imul(FP16_YYY *x,FP16_YYY *y,int i);
+extern void FP16_YYY_imul(FP16_YYY *x,const FP16_YYY *y,int i);
 /**	@brief Squaring an FP16
  *
 	@param x FP16 instance, on exit = y^2
diff --git a/include/fp2.h.in b/include/fp2.h.in
index 8442141..76b8434 100644
--- a/include/fp2.h.in
+++ b/include/fp2.h.in
@@ -46,7 +46,7 @@ typedef struct
 	@param x FP2 number to be tested
 	@return 1 if zero, else returns 0
  */
-extern int FP2_YYY_iszilch(FP2_YYY *x);
+extern int FP2_YYY_iszilch(const FP2_YYY *x);
 /**	@brief Conditional copy of FP2 number
  *
 	Conditionally copies second parameter to the first (without branching)
@@ -54,54 +54,54 @@ extern int FP2_YYY_iszilch(FP2_YYY *x);
 	@param y another FP2 instance
 	@param s copy only takes place if not equal to 0
  */
-extern void FP2_YYY_cmove(FP2_YYY *x,FP2_YYY *y,int s);
+extern void FP2_YYY_cmove(FP2_YYY *x,const FP2_YYY *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_YYY_isunity(FP2_YYY *x);
+extern int FP2_YYY_isunity(const FP2_YYY *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_YYY_equals(FP2_YYY *x,FP2_YYY *y);
+extern int FP2_YYY_equals(const FP2_YYY *x,const FP2_YYY *y);
 /**	@brief Initialise FP2 from two FP numbers
  *
 	@param x FP2 instance to be initialised
 	@param a FP to form real part of FP2
 	@param b FP to form imaginary part of FP2
  */
-extern void FP2_YYY_from_FPs(FP2_YYY *x,FP_YYY *a,FP_YYY *b);
+extern void FP2_YYY_from_FPs(FP2_YYY *x,const FP_YYY *a,const FP_YYY *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_YYY_from_BIGs(FP2_YYY *x,BIG_XXX a,BIG_XXX b);
+extern void FP2_YYY_from_BIGs(FP2_YYY *x,const BIG_XXX a,const BIG_XXX b);
 /**	@brief Initialise FP2 from single FP
  *
 	Imaginary part is set to zero
 	@param x FP2 instance to be initialised
 	@param a FP to form real part of FP2
  */
-extern void FP2_YYY_from_FP(FP2_YYY *x,FP_YYY *a);
+extern void FP2_YYY_from_FP(FP2_YYY *x,const FP_YYY *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_YYY_from_BIG(FP2_YYY *x,BIG_XXX a);
+extern void FP2_YYY_from_BIG(FP2_YYY *x,const BIG_XXX a);
 /**	@brief Copy FP2 to another FP2
  *
 	@param x FP2 instance, on exit = y
 	@param y FP2 instance to be copied
  */
-extern void FP2_YYY_copy(FP2_YYY *x,FP2_YYY *y);
+extern void FP2_YYY_copy(FP2_YYY *x,const FP2_YYY *y);
 /**	@brief Set FP2 to zero
  *
 	@param x FP2 instance to be set to zero
@@ -117,55 +117,55 @@ extern void FP2_YYY_one(FP2_YYY *x);
 	@param x FP2 instance, on exit = -y
 	@param y FP2 instance
  */
-extern void FP2_YYY_neg(FP2_YYY *x,FP2_YYY *y);
+extern void FP2_YYY_neg(FP2_YYY *x,const FP2_YYY *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_YYY_conj(FP2_YYY *x,FP2_YYY *y);
+extern void FP2_YYY_conj(FP2_YYY *x,const FP2_YYY *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_YYY_add(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+extern void FP2_YYY_add(FP2_YYY *x,const FP2_YYY *y,const FP2_YYY *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_YYY_sub(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+extern void FP2_YYY_sub(FP2_YYY *x,const FP2_YYY *y,const FP2_YYY *z);
 /**	@brief Multiplication of an FP2 by an FP
  *
 	@param x FP2 instance, on exit = y*b
 	@param y FP2 instance
 	@param b FP residue
  */
-extern void FP2_YYY_pmul(FP2_YYY *x,FP2_YYY *y,FP_YYY *b);
+extern void FP2_YYY_pmul(FP2_YYY *x,const FP2_YYY *y,const FP_YYY *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_YYY_imul(FP2_YYY *x,FP2_YYY *y,int i);
+extern void FP2_YYY_imul(FP2_YYY *x,const FP2_YYY *y,int i);
 /**	@brief Squaring an FP2
  *
 	@param x FP2 instance, on exit = y^2
 	@param y FP2 instance
  */
-extern void FP2_YYY_sqr(FP2_YYY *x,FP2_YYY *y);
+extern void FP2_YYY_sqr(FP2_YYY *x,const FP2_YYY *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_YYY_mul(FP2_YYY *x,FP2_YYY *y,FP2_YYY *z);
+extern void FP2_YYY_mul(FP2_YYY *x,FP2_YYY *y,const FP2_YYY *z);
 /**	@brief Formats and outputs an FP2 to the console
  *
 	@param x FP2 instance
@@ -175,7 +175,7 @@ extern void FP2_YYY_output(FP2_YYY *x);
  *
 	@param x FP2 instance
  */
-extern void FP2_YYY_rawoutput(FP2_YYY *x);
+extern void FP2_YYY_rawoutput(const FP2_YYY *x);
 /**	@brief Inverting an FP2
  *
 	@param x FP2 instance, on exit = 1/y
@@ -187,7 +187,7 @@ extern void FP2_YYY_inv(FP2_YYY *x,FP2_YYY *y);
 	@param x FP2 instance, on exit = y/2
 	@param y FP2 instance
  */
-extern void FP2_YYY_div2(FP2_YYY *x,FP2_YYY *y);
+extern void FP2_YYY_div2(FP2_YYY *x,const FP2_YYY *y);
 /**	@brief Multiply an FP2 by (1+sqrt(-1))
  *
 	Note that (1+sqrt(-1)) is irreducible for FP4
@@ -222,13 +222,13 @@ extern void FP2_YYY_reduce(FP2_YYY *x);
 	@param y FP2 instance
 	@param b BIG number
  */
-extern void FP2_YYY_pow(FP2_YYY *x,FP2_YYY *y,BIG_XXX b);
+extern void FP2_YYY_pow(FP2_YYY *x,const FP2_YYY *y,BIG_XXX b);
 /**	@brief Square root of an FP2
  *
 	@param x FP2 instance, on exit = sqrt(y)
 	@param y FP2 instance
  */
-extern int FP2_YYY_sqrt(FP2_YYY *x,FP2_YYY *y);
+extern int FP2_YYY_sqrt(FP2_YYY *x,const FP2_YYY *y);
 
 /**	@brief Multiply an FP2 by sqrt(-1)
  *
diff --git a/include/fp4.h.in b/include/fp4.h.in
index 4c6dda9..29697aa 100644
--- a/include/fp4.h.in
+++ b/include/fp4.h.in
@@ -47,40 +47,40 @@ typedef struct
 	@param x FP4 number to be tested
 	@return 1 if zero, else returns 0
  */
-extern int FP4_YYY_iszilch(FP4_YYY *x);
+extern int FP4_YYY_iszilch(const FP4_YYY *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_YYY_isunity(FP4_YYY *x);
+extern int FP4_YYY_isunity(const FP4_YYY *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_YYY_equals(FP4_YYY *x,FP4_YYY *y);
+extern int FP4_YYY_equals(const FP4_YYY *x,const FP4_YYY *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_YYY_isreal(FP4_YYY *x);
+extern int FP4_YYY_isreal(const FP4_YYY *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_YYY_from_FP2s(FP4_YYY *x,FP2_YYY *a,FP2_YYY *b);
+extern void FP4_YYY_from_FP2s(FP4_YYY *x,const FP2_YYY *a,const FP2_YYY *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_YYY_from_FP2(FP4_YYY *x,FP2_YYY *a);
+extern void FP4_YYY_from_FP2(FP4_YYY *x,const FP2_YYY *a);
 
 /**	@brief Initialise FP4 from single FP2
  *
@@ -88,7 +88,7 @@ extern void FP4_YYY_from_FP2(FP4_YYY *x,FP2_YYY *a);
 	@param x FP4 instance to be initialised
 	@param a FP2 to form imaginary part of FP4
  */
-extern void FP4_YYY_from_FP2H(FP4_YYY *x,FP2_YYY *a);
+extern void FP4_YYY_from_FP2H(FP4_YYY *x,const FP2_YYY *a);
 
 
 /**	@brief Copy FP4 to another FP4
@@ -96,7 +96,7 @@ extern void FP4_YYY_from_FP2H(FP4_YYY *x,FP2_YYY *a);
 	@param x FP4 instance, on exit = y
 	@param y FP4 instance to be copied
  */
-extern void FP4_YYY_copy(FP4_YYY *x,FP4_YYY *y);
+extern void FP4_YYY_copy(FP4_YYY *x,const FP4_YYY *y);
 /**	@brief Set FP4 to zero
  *
 	@param x FP4 instance to be set to zero
@@ -119,35 +119,35 @@ extern void FP4_YYY_neg(FP4_YYY *x,FP4_YYY *y);
 	@param x FP4 instance, on exit = conj(y)
 	@param y FP4 instance
  */
-extern void FP4_YYY_conj(FP4_YYY *x,FP4_YYY *y);
+extern void FP4_YYY_conj(FP4_YYY *x,const FP4_YYY *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_YYY_nconj(FP4_YYY *x,FP4_YYY *y);
+extern void FP4_YYY_nconj(FP4_YYY *x,const FP4_YYY *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_YYY_add(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+extern void FP4_YYY_add(FP4_YYY *x,const FP4_YYY *y,const FP4_YYY *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_YYY_sub(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+extern void FP4_YYY_sub(FP4_YYY *x,const FP4_YYY *y,FP4_YYY *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_YYY_pmul(FP4_YYY *x,FP4_YYY *y,FP2_YYY *a);
+extern void FP4_YYY_pmul(FP4_YYY *x,FP4_YYY *y,const FP2_YYY *a);
 
 /**	@brief Multiplication of an FP4 by an FP
  *
@@ -155,7 +155,7 @@ extern void FP4_YYY_pmul(FP4_YYY *x,FP4_YYY *y,FP2_YYY *a);
 	@param y FP4 instance
 	@param a FP multiplier
  */
-extern void FP4_YYY_qmul(FP4_YYY *x,FP4_YYY *y,FP_YYY *a);
+extern void FP4_YYY_qmul(FP4_YYY *x,const FP4_YYY *y,const FP_YYY *a);
 
 /**	@brief Multiplication of an FP4 by a small integer
  *
@@ -163,7 +163,7 @@ extern void FP4_YYY_qmul(FP4_YYY *x,FP4_YYY *y,FP_YYY *a);
 	@param y FP4 instance
 	@param i an integer
  */
-extern void FP4_YYY_imul(FP4_YYY *x,FP4_YYY *y,int i);
+extern void FP4_YYY_imul(FP4_YYY *x,const FP4_YYY *y,int i);
 /**	@brief Squaring an FP4
  *
 	@param x FP4 instance, on exit = y^2
@@ -176,13 +176,13 @@ extern void FP4_YYY_sqr(FP4_YYY *x,FP4_YYY *y);
 	@param y FP4 instance
 	@param z FP4 instance
  */
-extern void FP4_YYY_mul(FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+extern void FP4_YYY_mul(FP4_YYY *x,FP4_YYY *y,const FP4_YYY *z);
 /**	@brief Inverting an FP4
  *
 	@param x FP4 instance, on exit = 1/y
 	@param y FP4 instance
  */
-extern void FP4_YYY_inv(FP4_YYY *x,FP4_YYY *y);
+extern void FP4_YYY_inv(FP4_YYY *x,const FP4_YYY *y);
 /**	@brief Formats and outputs an FP4 to the console
  *
 	@param x FP4 instance to be printed
@@ -192,7 +192,7 @@ extern void FP4_YYY_output(FP4_YYY *x);
  *
 	@param x FP4 instance to be printed
  */
-extern void FP4_YYY_rawoutput(FP4_YYY *x);
+extern void FP4_YYY_rawoutput(const FP4_YYY *x);
 /**	@brief multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
  *
 	@param x FP4 instance, on exit = sqrt(1+sqrt(-1)*x
@@ -214,7 +214,7 @@ extern void FP4_YYY_reduce(FP4_YYY *x);
 	@param y FP4 instance
 	@param b BIG number
  */
-extern void FP4_YYY_pow(FP4_YYY *x,FP4_YYY *y,BIG_XXX b);
+extern void FP4_YYY_pow(FP4_YYY *x,const FP4_YYY *y,const BIG_XXX b);
 /**	@brief Raises an FP4 to the power of the internal modulus p, using the Frobenius
  *
 	@param x FP4 instance, on exit = x^p
@@ -229,13 +229,13 @@ extern void FP4_YYY_frob(FP4_YYY *x,FP2_YYY *f);
 	@param y FP4 instance
 	@param z FP4 instance
  */
-extern void FP4_YYY_xtr_A(FP4_YYY *r,FP4_YYY *w,FP4_YYY *x,FP4_YYY *y,FP4_YYY *z);
+extern void FP4_YYY_xtr_A(FP4_YYY *r,const FP4_YYY *w,const FP4_YYY *x,FP4_YYY *y,const FP4_YYY *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_YYY_xtr_D(FP4_YYY *r,FP4_YYY *x);
+extern void FP4_YYY_xtr_D(FP4_YYY *r,const FP4_YYY *x);
 /**	@brief Calculates FP4 trace of an FP12 raised to the power of a BIG number
  *
 	XTR single exponentiation
@@ -243,7 +243,7 @@ extern void FP4_YYY_xtr_D(FP4_YYY *r,FP4_YYY *x);
 	@param x FP4 instance, trace of an FP12 w
 	@param b BIG number
  */
-extern void FP4_YYY_xtr_pow(FP4_YYY *r,FP4_YYY *x,BIG_XXX b);
+extern void FP4_YYY_xtr_pow(FP4_YYY *r,const FP4_YYY *x,const BIG_XXX b);
 /**	@brief Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP12s
  *
 	XTR double exponentiation
@@ -256,7 +256,7 @@ extern void FP4_YYY_xtr_pow(FP4_YYY *r,FP4_YYY *x,BIG_XXX b);
 	@param a BIG number
 	@param b BIG number
  */
-extern void FP4_YYY_xtr_pow2(FP4_YYY *r,FP4_YYY *c,FP4_YYY *d,FP4_YYY *e,FP4_YYY *f,BIG_XXX a,BIG_XXX b);
+extern void FP4_YYY_xtr_pow2(FP4_YYY *r,const FP4_YYY *c,const FP4_YYY *d,const FP4_YYY *e,const FP4_YYY *f,const BIG_XXX a,const BIG_XXX b);
 
 /**	@brief Conditional copy of FP4 number
  *
@@ -265,7 +265,7 @@ extern void FP4_YYY_xtr_pow2(FP4_YYY *r,FP4_YYY *c,FP4_YYY *d,FP4_YYY *e,FP4_YYY
 	@param y another FP4 instance
 	@param s copy only takes place if not equal to 0
  */
-extern void FP4_YYY_cmove(FP4_YYY *x,FP4_YYY *y,int s);
+extern void FP4_YYY_cmove(FP4_YYY *x,const FP4_YYY *y,int s);
 
 
 /**	@brief Calculate square root of an FP4
@@ -299,7 +299,7 @@ extern void FP4_YYY_div_2i(FP4_YYY *x);
 	@param x FP4 instance, on exit = y/2
 	@param y FP4 instance
  */
-extern void FP4_YYY_div2(FP4_YYY *x,FP4_YYY *y);
+extern void FP4_YYY_div2(FP4_YYY *x,const FP4_YYY *y);
 
 #endif
 
diff --git a/include/fp8.h.in b/include/fp8.h.in
index a7f040a..b891d47 100644
--- a/include/fp8.h.in
+++ b/include/fp8.h.in
@@ -157,7 +157,7 @@ extern void FP8_YYY_qmul(FP8_YYY *x,FP8_YYY *y,FP2_YYY *a);
 	@param y FP8 instance
 	@param a FP multiplier
  */
-extern void FP8_YYY_tmul(FP8_YYY *x,FP8_YYY *y,FP_YYY *a);
+extern void FP8_YYY_tmul(FP8_YYY *x,const FP8_YYY *y,FP_YYY *a);
 
 /**	@brief Multiplication of an FP8 by a small integer
  *
@@ -165,7 +165,7 @@ extern void FP8_YYY_tmul(FP8_YYY *x,FP8_YYY *y,FP_YYY *a);
 	@param y FP8 instance
 	@param i an integer
  */
-extern void FP8_YYY_imul(FP8_YYY *x,FP8_YYY *y,int i);
+extern void FP8_YYY_imul(FP8_YYY *x,const FP8_YYY *y,int i);
 /**	@brief Squaring an FP8
  *
 	@param x FP8 instance, on exit = y^2
diff --git a/include/hash_to_field.h.in b/include/hash_to_field.h.in
new file mode 100644
index 0000000..3ad449e
--- /dev/null
+++ b/include/hash_to_field.h.in
@@ -0,0 +1,56 @@
+/*
+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 hash_to_field.h
+ * 
+ * @author Alexandre Adomnicai
+ * 
+ * @brief Header file for implementation of standard hash to curve functions according to https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/
+ */
+#ifndef HASH_TO_FIELD_ZZZ_H
+#define HASH_TO_FIELD_ZZZ_H
+
+#include "fp_YYY.h"
+#include "config_curve_ZZZ.h"
+
+#define SUCCESS                    0x00000000
+#define ERR_NULLPOINTER_HASH2FIELD 0x00000401
+#define ERR_BADARGLEN_HASH2FIELD   0x00000402
+
+/** 
+ * @brief Hash a byte string msg of arbitrary length into one or more finite
+ * field elements according to the draft-irtf-cfrg-hash-to-curve-16 spec.
+ * Relies on expand_message_xmd function with SHA-256.
+ * 
+ * @param elems Output finite field elements
+ * @param nelems Number of finite field elements (is 'count * m' from spec)
+ * @param m Extension degree of finite field (m >= 1)
+ * @param msg Input byte string
+ * @param msglen Byte string length (in bytes)
+ * @param DST Domain separation tag
+ * @param DSTlen Domain separation tag length (in bytes)
+ * 
+ * @return 0 if successful, error code otherwise
+ */
+extern int hash_to_field_YYY(BIG_XXX elems[], unsigned int nelems, unsigned int m,
+  const char *msg, unsigned int msglen,
+  const char *DST, unsigned int DSTlen);
+
+#endif
diff --git a/include/mpin.h.in b/include/mpin.h.in
index e0c7227..b96ffa2 100644
--- a/include/mpin.h.in
+++ b/include/mpin.h.in
@@ -35,7 +35,6 @@ under the License.
 
 #define PGS_ZZZ MODBYTES_XXX  /**< MPIN Group Size */
 #define PFS_ZZZ MODBYTES_XXX  /**< MPIN Field Size */
-//#define PAS_ZZZ 16            /**< MPIN Symmetric Key Size */
 
 #define MPIN_OK             0   /**< Function completed without error */
 #define MPIN_INVALID_POINT  -14	/**< Point is NOT on the curve */
@@ -45,7 +44,6 @@ under the License.
 #define MAXPIN 10000         /**< max PIN */
 #define PBLEN 14             /**< max length of PIN in bits */
 
-//#define HASH_TYPE_MPIN_ZZZ SHA256   /**< Choose Hash function */
 
 #define MESSAGE_SIZE 256        /**< Signature message size  */
 #define M_SIZE_ZZZ (MESSAGE_SIZE+2*PFS_ZZZ+1)   /**< Signature message size and G1 size */
@@ -62,7 +60,7 @@ under the License.
 	@param O is an input octet
 	@param Y is the output octet
 */
-void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y);
+void MPIN_ZZZ_GET_Y(int h,int t,const octet *O,octet *Y);
 
 /**	@brief Extract a PIN number from a client secret
  *
@@ -73,7 +71,7 @@ void MPIN_ZZZ_GET_Y(int h,int t,octet *O,octet *Y);
 	@param CS is the client secret from which the factor is to be extracted
 	@return 0 or an error code
  */
-int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+int MPIN_ZZZ_EXTRACT_FACTOR(int h,const octet *ID,int factor,int facbits,octet *CS);
 
 /**	@brief Extract a PIN number from a client secret
  *
@@ -84,7 +82,7 @@ int MPIN_ZZZ_EXTRACT_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
 	@param CS is the client secret to which the factor is to be added
 	@return 0 or an error code
  */
-int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
+int MPIN_ZZZ_RESTORE_FACTOR(int h,const octet *ID,int factor,int facbits,octet *CS);
 
 
 /**	@brief Extract a PIN number from a client secret
@@ -95,7 +93,7 @@ int MPIN_ZZZ_RESTORE_FACTOR(int h,octet *ID,int factor,int facbits,octet *CS);
 	@param CS is the client secret from which the PIN is to be extracted
 	@return 0 or an error code
  */
-int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
+int MPIN_ZZZ_EXTRACT_PIN(int h,const octet *ID,int pin,octet *CS);
 
 
 
@@ -120,7 +118,7 @@ int MPIN_ZZZ_EXTRACT_PIN(int h,octet *ID,int pin,octet *CS);
 	@param y is output H(t|U) or H(t|UT) if Time Permits enabled
 	@return 0 or an error code
  */
-int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *V,octet *U,octet *UT,octet *TP, octet* MESSAGE, int t, octet *y);
+int MPIN_ZZZ_CLIENT(int h,int d,const octet *ID,csprng *R,octet *x,int pin,const octet *T,octet *V,octet *U,octet *UT,const octet *TP,const octet* MESSAGE, int t, octet *y);
 /**	@brief Perform first pass of the client side of the 3-pass version of the M-Pin protocol
  *
 	If Time Permits are disabled, set d = 0, and UT is not generated and can be set to NULL.
@@ -139,7 +137,7 @@ int MPIN_ZZZ_CLIENT(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,oc
 	@param TP is the input time permit
 	@return 0 or an error code
  */
-int MPIN_ZZZ_CLIENT_1(int h,int d,octet *ID,csprng *R,octet *x,int pin,octet *T,octet *S,octet *U,octet *UT,octet *TP);
+int MPIN_ZZZ_CLIENT_1(int h,int d,const octet *ID,csprng *R,octet *x,int pin,const octet *T,octet *S,octet *U,octet *UT,const octet *TP);
 /**	@brief Generate a random group element
  *
 	@param R is a pointer to a cryptographically secure random number generator
@@ -154,7 +152,7 @@ int MPIN_ZZZ_RANDOM_GENERATE(csprng *R,octet *S);
 	@param V on output = -(x+y).V
 	@return 0 or an error code
  */
-int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V);
+int MPIN_ZZZ_CLIENT_2(const octet *x,const octet *y,octet *V);
 /**	@brief Perform server side of the one-pass version of the M-Pin protocol
  *
 	If Time Permits are disabled, set d = 0, and UT and HTID are not generated and can be set to NULL.
@@ -177,7 +175,7 @@ int MPIN_ZZZ_CLIENT_2(octet *x,octet *y,octet *V);
 	@param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
 	@return 0 or an error code
  */
-int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *ID,octet *MESSAGE, int t, octet *Pa);
+int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,const octet *SS,const octet *U,const octet *UT,const octet *V,octet *E,octet *F,const octet *ID,const octet *MESSAGE, int t,const octet *Pa);
 /**	@brief Perform first pass of the server side of the 3-pass version of the M-Pin protocol
  *
  	@param h is the hash type
@@ -187,7 +185,7 @@ int MPIN_ZZZ_SERVER(int h,int d,octet *HID,octet *HTID,octet *y,octet *SS,octet
 	@param HTID is output H(ID)+H(d|H(ID))
 	@return 0 or an error code
  */
-void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
+void MPIN_ZZZ_SERVER_1(int h,int d,const octet *ID,octet *HID,octet *HTID);
 /**	@brief Perform third pass on the server side of the 3-pass version of the M-Pin protocol
  *
 	If Time Permits are disabled, set d = 0, and UT and HTID are not needed and can be set to NULL.
@@ -206,7 +204,7 @@ void MPIN_ZZZ_SERVER_1(int h,int d,octet *ID,octet *HID,octet *HTID);
 	@param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
 	@return 0 or an error code
  */
-int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,octet *UT,octet *V,octet *E,octet *F,octet *Pa);
+int MPIN_ZZZ_SERVER_2(int d,const octet *HID,const octet *HTID,const octet *y,const octet *SS,const octet *U,const octet *UT,const octet *V,octet *E,octet *F,const octet *Pa);
 /**	@brief Add two members from the group G1
  *
 	@param Q1 an input member of G1
@@ -214,7 +212,7 @@ int MPIN_ZZZ_SERVER_2(int d,octet *HID,octet *HTID,octet *y,octet *SS,octet *U,o
 	@param Q an output member of G1 = Q1+Q2
 	@return 0 or an error code
  */
-int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
+int MPIN_ZZZ_RECOMBINE_G1(const octet *Q1,const octet *Q2,octet *Q);
 /**	@brief Add two members from the group G2
  *
 	@param P1 an input member of G2
@@ -222,14 +220,14 @@ int MPIN_ZZZ_RECOMBINE_G1(octet *Q1,octet *Q2,octet *Q);
 	@param P an output member of G2 = P1+P2
 	@return 0 or an error code
  */
-int MPIN_ZZZ_RECOMBINE_G2(octet *P1,octet *P2,octet *P);
+int MPIN_ZZZ_RECOMBINE_G2(const octet *P1,const octet *P2,octet *P);
 /**	@brief Use Kangaroos to find PIN error
  *
 	@param E a member of the group GT
 	@param F a member of the group GT =  E^e
 	@return 0 if Kangaroos failed, or the PIN error e
  */
-int MPIN_ZZZ_KANGAROO(octet *E,octet *F);
+int MPIN_ZZZ_KANGAROO(const octet *E,const octet *F);
 /**	@brief Encoding of a Time Permit to make it indistinguishable from a random string
  *
 	@param R is a pointer to a cryptographically secure random number generator
@@ -253,7 +251,7 @@ int MPIN_ZZZ_DECODING(octet *TP);
 	@param W the output =x.G or x.M(G), where M(.) is a mapping
 	@return 0 or an error code
  */
-int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,const octet *G,octet *W);
 /**	@brief Find a random multiple of a point in G1
  *
 	@param R is a pointer to a cryptographically secure random number generator
@@ -263,7 +261,7 @@ int MPIN_ZZZ_GET_G1_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
 	@param W the output =x.G or (1/x).G
 	@return 0 or an error code
  */
-int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
+int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,const octet *G,octet *W);
 
 /**	@brief Create a client secret in G1 from a master secret and the client ID
  *
@@ -272,7 +270,7 @@ int MPIN_ZZZ_GET_G2_MULTIPLE(csprng *R,int type,octet *x,octet *G,octet *W);
 	@param CS is the full client secret = s.H(ID)
 	@return 0 or an error code
  */
-int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
+int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,const octet *ID,octet *CS);
 /**	@brief Create a Time Permit in G1 from a master secret and the client ID
  *
   	@param h is the hash type
@@ -282,15 +280,14 @@ int MPIN_ZZZ_GET_CLIENT_SECRET(octet *S,octet *ID,octet *CS);
 	@param TP is a Time Permit for the given date = s.H(d|H(ID))
 	@return 0 or an error code
  */
-int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,octet *S,octet *ID,octet *TP);
+int MPIN_ZZZ_GET_CLIENT_PERMIT(int h,int d,const octet *S,const octet *ID,octet *TP);
 /**	@brief Create a server secret in G2 from a master secret
  *
 	@param S is an input master secret
 	@param SS is the server secret = s.Q where Q is a fixed generator of G2
 	@return 0 or an error code
  */
-int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS);
-/* int MPIN_TEST_PAIRING(octet *,octet *); */
+int MPIN_ZZZ_GET_SERVER_SECRET(const octet *S,octet *SS);
 
 /* For M-Pin Full */
 /**	@brief Precompute values for use by the client side of M-Pin Full
@@ -302,7 +299,7 @@ int MPIN_ZZZ_GET_SERVER_SECRET(octet *S,octet *SS);
 	@param g2 precomputed output
 	@return 0 or an error code
  */
-int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
+int MPIN_ZZZ_PRECOMPUTE(const octet *T,const octet *ID,const octet *CP,octet *g1,octet *g2);
 /**	@brief Calculate Key on Server side for M-Pin Full
  *
 	Uses UT internally for the key calculation, unless not available in which case U is used
@@ -317,7 +314,7 @@ int MPIN_ZZZ_PRECOMPUTE(octet *T,octet *ID,octet *CP,octet *g1,octet *g2);
 	@param K is the output calculated shared key
 	@return 0 or an error code
  */
-int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octet *U,octet *UT,octet *K);
+int MPIN_ZZZ_SERVER_KEY(int h,const octet *Z,const octet *SS,const octet *w,const octet *p,const octet *I,const octet *U,const octet *UT,octet *K);
 /**	@brief Calculate Key on Client side for M-Pin Full
  *
   	@param h is the hash type
@@ -331,7 +328,7 @@ int MPIN_ZZZ_SERVER_KEY(int h,octet *Z,octet *SS,octet *w,octet *p,octet *I,octe
 	@param K is the output calculated shared key
 	@return 0 or an error code
  */
-int MPIN_ZZZ_CLIENT_KEY(int h,octet *g1,octet *g2,int pin,octet *r,octet *x,octet *p,octet *T,octet *K);
+int MPIN_ZZZ_CLIENT_KEY(int h,const octet *g1,const octet *g2,int pin,const octet *r,const octet *x,const octet *p,const octet *T,octet *K);
 
 /** @brief Generates a random public key for the client z.Q
  *
diff --git a/include/paillier.h b/include/paillier.h
index 7ce3a72..992751b 100644
--- a/include/paillier.h
+++ b/include/paillier.h
@@ -94,7 +94,7 @@ typedef struct
  *  @param  PUB              Public key
  *  @param  PRIV             Private key
  */
-void PAILLIER_KEY_PAIR(csprng *RNG, octet *P, octet* Q, PAILLIER_public_key *PUB, PAILLIER_private_key *PRIV);
+void PAILLIER_KEY_PAIR(csprng *RNG, const octet *P, const octet* Q, PAILLIER_public_key *PUB, PAILLIER_private_key *PRIV);
 
 /*! \brief Clear private key
  *
@@ -118,7 +118,7 @@ void PAILLIER_PRIVATE_KEY_KILL(PAILLIER_private_key *PRIV);
  *  @param  CT               Ciphertext
  *  @param  R                R value for testing. If RNG is NULL then this value is read.
  */
-void PAILLIER_ENCRYPT(csprng *RNG, PAILLIER_public_key *PUB, octet* PT, octet* CT, octet* R);
+void PAILLIER_ENCRYPT(csprng *RNG, PAILLIER_public_key *PUB, const octet* PT, octet* CT, octet* R);
 
 /*! \brief Decrypt ciphertext
  *
@@ -136,7 +136,7 @@ void PAILLIER_ENCRYPT(csprng *RNG, PAILLIER_public_key *PUB, octet* PT, octet* C
  *  @param   CT               Ciphertext
  *  @param   PT               Plaintext
  */
-void PAILLIER_DECRYPT(PAILLIER_private_key *PRIV, octet* CT, octet* PT);
+void PAILLIER_DECRYPT(PAILLIER_private_key *PRIV, const octet* CT, octet* PT);
 
 /*! \brief Homomorphic addition of plaintexts
  *
@@ -150,9 +150,8 @@ void PAILLIER_DECRYPT(PAILLIER_private_key *PRIV, octet* CT, octet* PT);
  *  @param   CT1              Ciphertext one
  *  @param   CT2              Ciphertext two
  *  @param   CT               Ciphertext
- *  @return                   Returns 0 or else error code
  */
-void PAILLIER_ADD(PAILLIER_public_key *PUB, octet* CT1, octet* CT2, octet* CT);
+void PAILLIER_ADD(PAILLIER_public_key *PUB, const octet* CT1, const octet* CT2, octet* CT);
 
 /*! \brief Homomorphic multipication of plaintexts
  *
@@ -167,14 +166,14 @@ void PAILLIER_ADD(PAILLIER_public_key *PUB, octet* CT1, octet* CT2, octet* CT);
  *  @param   PT               Plaintext constant
  *  @param   CT               Ciphertext
  */
-void PAILLIER_MULT(PAILLIER_public_key *PUB, octet* CT1, octet* PT, octet* CT);
+void PAILLIER_MULT(PAILLIER_public_key *PUB, const octet* CT1, const octet* PT, octet* CT);
 
 /*! \brief Read a public key from its octet representation
  *
  * @param   PUB   Public key
  * @param   PK    Octet representation of the public key
  */
-void PAILLIER_PK_fromOctet(PAILLIER_public_key *PUB, octet *PK);
+void PAILLIER_PK_fromOctet(PAILLIER_public_key *PUB, const octet *PK);
 
 /*! \brief Write a public key to an octet
  *
diff --git a/include/pair.h.in b/include/pair.h.in
index a7350bd..bd70b1f 100644
--- a/include/pair.h.in
+++ b/include/pair.h.in
@@ -50,7 +50,7 @@ extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposi
 	@param QV ECP instance, an element of G1
 
  */
-extern void PAIR_ZZZ_another(FP12_YYY r[],ECP2_ZZZ* PV,ECP_ZZZ* QV);
+extern void PAIR_ZZZ_another(FP12_YYY r[],const ECP2_ZZZ* PV,const ECP_ZZZ* QV);
 
 /**	@brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
  *
@@ -59,7 +59,7 @@ extern void PAIR_ZZZ_another(FP12_YYY r[],ECP2_ZZZ* PV,ECP_ZZZ* QV);
 	@param Q ECP instance, an element of G1
 
  */
-extern void PAIR_ZZZ_ate(FP12_YYY *r,ECP2_ZZZ *P,ECP_ZZZ *Q);
+extern void PAIR_ZZZ_ate(FP12_YYY *r,const ECP2_ZZZ *P,const ECP_ZZZ *Q);
 /**	@brief Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
  *
 	Faster than calculating two separate pairings
@@ -69,7 +69,7 @@ extern void PAIR_ZZZ_ate(FP12_YYY *r,ECP2_ZZZ *P,ECP_ZZZ *Q);
 	@param R ECP2 instance, an element of G2
 	@param S ECP instance, an element of G1
  */
-extern void PAIR_ZZZ_double_ate(FP12_YYY *r,ECP2_ZZZ *P,ECP_ZZZ *Q,ECP2_ZZZ *R,ECP_ZZZ *S);
+extern void PAIR_ZZZ_double_ate(FP12_YYY *r,const ECP2_ZZZ *P,const ECP_ZZZ *Q,const ECP2_ZZZ *R,const ECP_ZZZ *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
@@ -83,7 +83,7 @@ extern void PAIR_ZZZ_fexp(FP12_YYY *x);
 	@param b BIG multiplier
 
  */
-extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,BIG_XXX b);
+extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,const BIG_XXX b);
 /**	@brief Fast point multiplication of a member of the group G2 by a BIG number
  *
 	May exploit endomorphism for speed.
@@ -91,7 +91,7 @@ extern void PAIR_ZZZ_G1mul(ECP_ZZZ *Q,BIG_XXX b);
 	@param b BIG multiplier
 
  */
-extern void PAIR_ZZZ_G2mul(ECP2_ZZZ *P,BIG_XXX b);
+extern void PAIR_ZZZ_G2mul(ECP2_ZZZ *P,const BIG_XXX b);
 /**	@brief Fast raising of a member of GT to a BIG power
  *
 	May exploit endomorphism for speed.
@@ -99,7 +99,7 @@ extern void PAIR_ZZZ_G2mul(ECP2_ZZZ *P,BIG_XXX b);
 	@param b BIG exponent
 
  */
-extern void PAIR_ZZZ_GTpow(FP12_YYY *x,BIG_XXX b);
+extern void PAIR_ZZZ_GTpow(FP12_YYY *x,const BIG_XXX b);
 /**	@brief Tests FP12 for membership of GT
  *
 	@param x FP12 instance
@@ -131,6 +131,6 @@ extern void PAIR_ZZZ_initmp(FP12_YYY r[]);
 	@param r FP12 precomputed array of accumulated line functions
 
  */
-extern void PAIR_ZZZ_miller(FP12_YYY *res,FP12_YYY r[]);
+extern void PAIR_ZZZ_miller(FP12_YYY *res,const FP12_YYY r[]);
 
 #endif
diff --git a/include/pbc_support.h b/include/pbc_support.h
index 4fe82d9..1b94648 100644
--- a/include/pbc_support.h
+++ b/include/pbc_support.h
@@ -39,7 +39,7 @@ under the License.
 	@param x octect involved in the h ash
 	@param w output
  */
-extern void mhashit(int sha,int n,octet *x,octet *w);
+extern void mhashit(int sha,int n,const octet *x,octet *w);
 
 /**	@brief Supply today's date as days from the epoch
  *
@@ -57,14 +57,14 @@ unsign32 today(void);
 	@param W is the server part response
 	@param H the output is the hash of all of the above that apply
 */
-void HASH_ALL(int h,octet *I,octet *U,octet *CU,octet *Y,octet *V,octet *R,octet *W,octet *H);
+void HASH_ALL(int h,const octet *I,const octet *U,const octet *CU,const octet *Y,const octet *V,const octet *R,const octet *W,octet *H);
 /**	@brief Hash an M-Pin Identity to an octet string
  *
  	@param h is the hash type
 	@param ID an octet containing the identity
 	@param HID an octet containing the hashed identity
  */
-void HASH_ID(int h,octet *ID,octet *HID);
+void HASH_ID(int h,const octet *ID,octet *HID);
 /**	@brief Get epoch time as unsigned integer
  *
 	@return current epoch time in seconds
@@ -79,7 +79,7 @@ unsign32 GET_TIME(void);
 	@param C Ciphertext
 	@param T Checksum
  */
-void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
+void AES_GCM_ENCRYPT(octet *K,const octet *IV,const octet *H,const octet *P,octet *C,octet *T);
 
 /**	@brief AES-GCM Decryption
  *
@@ -90,7 +90,7 @@ void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
 	@param C Ciphertext
 	@param T Checksum
  */
-void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
+void AES_GCM_DECRYPT(octet *K,const octet *IV,const octet *H,const octet *C,octet *P,octet *T);
 
 
 #endif
diff --git a/include/randapi.h b/include/randapi.h
index 9a6807e..c40b04f 100644
--- a/include/randapi.h
+++ b/include/randapi.h
@@ -34,7 +34,7 @@
 	@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);
+extern void CREATE_CSPRNG(csprng *R,const octet *S);
 /**	@brief Kill a random number generator
  *
 	Deletes all internal state
diff --git a/include/rsa.h.in b/include/rsa.h.in
index 08a744f..947f3a2 100644
--- a/include/rsa.h.in
+++ b/include/rsa.h.in
@@ -57,11 +57,11 @@ typedef struct
 
 typedef struct
 {
-    BIG_XXX p[FFLEN_WWW/2];  /**< secret prime p  */
-    BIG_XXX q[FFLEN_WWW/2];  /**< secret prime q  */
-    BIG_XXX dp[FFLEN_WWW/2]; /**< decrypting exponent mod (p-1)  */
-    BIG_XXX dq[FFLEN_WWW/2]; /**< decrypting exponent mod (q-1)  */
-    BIG_XXX c[FFLEN_WWW/2];  /**< 1/p mod q */
+    BIG_XXX p[HFLEN_WWW];  /**< secret prime p  */
+    BIG_XXX q[HFLEN_WWW];  /**< secret prime q  */
+    BIG_XXX dp[HFLEN_WWW]; /**< decrypting exponent mod (p-1)  */
+    BIG_XXX dq[HFLEN_WWW]; /**< decrypting exponent mod (q-1)  */
+    BIG_XXX c[HFLEN_WWW];  /**< 1/p mod q */
 } rsa_private_key_WWW;
 
 /* RSA Auxiliary Functions */
@@ -72,10 +72,10 @@ typedef struct
 	@param e the encryption exponent
 	@param PRIV the output RSA private key
 	@param PUB the output RSA public key
-        @param P Input prime number. Used when R is equal to NULL for testing
-        @param Q Inpuy prime number. Used when R is equal to NULL for testing
+    @param P Input prime number. Used when R is equal to NULL for testing
+    @param Q Inpuy prime number. Used when R is equal to NULL for testing
  */
-extern void RSA_WWW_KEY_PAIR(csprng *R,sign32 e,rsa_private_key_WWW* PRIV,rsa_public_key_WWW* PUB,octet *P, octet* Q);
+extern void RSA_WWW_KEY_PAIR(csprng *R,sign32 e,rsa_private_key_WWW* PRIV,rsa_public_key_WWW* PUB,const octet *P, const octet* Q);
 
 /**	@brief RSA encryption of suitably padded plaintext
  *
@@ -83,7 +83,7 @@ extern void RSA_WWW_KEY_PAIR(csprng *R,sign32 e,rsa_private_key_WWW* PRIV,rsa_pu
 	@param F is input padded message
 	@param G is the output ciphertext
  */
-extern void RSA_WWW_ENCRYPT(rsa_public_key_WWW* PUB,octet *F,octet *G);
+extern void RSA_WWW_ENCRYPT(rsa_public_key_WWW* PUB,const octet *F,octet *G);
 /**	@brief RSA decryption of ciphertext
  *
 	@param PRIV the input RSA private key
@@ -91,7 +91,7 @@ extern void RSA_WWW_ENCRYPT(rsa_public_key_WWW* PUB,octet *F,octet *G);
 	@param F is output plaintext (requires unpadding)
 
  */
-extern void RSA_WWW_DECRYPT(rsa_private_key_WWW* PRIV,octet *G,octet *F);
+extern void RSA_WWW_DECRYPT(rsa_private_key_WWW* PRIV,const octet *G,octet *F);
 /**	@brief Destroy an RSA private Key
  *
 	@param PRIV the input RSA private key. Destroyed on output.
@@ -103,7 +103,7 @@ extern void RSA_WWW_PRIVATE_KEY_KILL(rsa_private_key_WWW *PRIV);
 	@param x FF instance to be created from an octet string
 	@param S input octet string
  */
-extern void RSA_WWW_fromOctet(BIG_XXX *x,octet *S);
+extern void RSA_WWW_fromOctet(BIG_XXX *x,const octet *S);
 
 
 
diff --git a/include/rsa_support.h b/include/rsa_support.h
index 519d012..2a21729 100644
--- a/include/rsa_support.h
+++ b/include/rsa_support.h
@@ -38,7 +38,7 @@
 	@param W is the output encoding, ready for RSA signature
 	@return 1 if OK, else 0
  */
-extern int PKCS15(int h,octet *M,octet *W);
+extern int PKCS15(int h,const octet *M,octet *W);
 /**	@brief OAEP padding of a message prior to RSA encryption
  *
 	@param h is the hash type
@@ -48,7 +48,7 @@ extern int PKCS15(int h,octet *M,octet *W);
 	@param F is the output encoding, ready for RSA encryption
 	@return 0 if OK, else 1
  */
-extern int	OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
+extern int	OAEP_ENCODE(int h,const octet *M,csprng *R,const octet *P,octet *F);
 /**	@brief OAEP unpadding of a message after RSA decryption
  *
 	Unpadding is done in-place
@@ -57,6 +57,6 @@ extern int	OAEP_ENCODE(int h,octet *M,csprng *R,octet *P,octet *F);
 	@param F is input padded message, unpadded on output
 	@return 0 if OK, else 1
  */
-extern int  OAEP_DECODE(int h,octet *P,octet *F);
+extern int  OAEP_DECODE(int h,const octet *P,octet *F);
 
 #endif
diff --git a/include/utils.h b/include/utils.h
index 34c05ae..ad8f47b 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -52,7 +52,7 @@ void amcl_hex2bin(const char *src, char *dst, size_t src_len);
  * @param src_len length binary string
  * @param dst_len length hex encoded string
  */
-void amcl_bin2hex(char *src, char *dst, size_t src_len, size_t dst_len);
+void amcl_bin2hex(const char *src, char *dst, size_t src_len, size_t dst_len);
 
 /**
  * @brief Print encoded binary string in hex
@@ -62,7 +62,7 @@ void amcl_bin2hex(char *src, char *dst, size_t src_len, size_t dst_len);
  * @param src     Binary string
  * @param src_len length binary string
  */
-void amcl_print_hex(char *src, size_t src_len);
+void amcl_print_hex(const char *src, size_t src_len);
 
 /**
  * @brief Generate a random Octet
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 05d8ba2..df8065e 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -19,6 +19,8 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
 
 include(PythonSiteDirs)
 
+add_subdirectory(benchmark)
+
 foreach(curve ${AMCL_CURVE})
   amcl_curve_field(PF "${curve}")
   amcl_curve_field(TC "${curve}")
@@ -29,7 +31,7 @@ foreach(curve ${AMCL_CURVE})
     amcl_configure_file_curve(TestMPINInstall_ZZZ.py.in TestMPINInstall_${TC}.py ${curve} __no_install)
 
     install(FILES "${amcl_mpin_${TC}_GEN_PYS}" DESTINATION ${PYTHON3_SITE_PACKAGES})
-  
+
     add_test(test_python_mpin_install_${TC} python3 TestMPINInstall_${TC}.py)
 
     # Set the LD_LIBRARY_PATH or equivalent to the libraries can be
@@ -53,8 +55,8 @@ foreach(curve ${AMCL_CURVE})
 
   if(TARGET amcl_bls_${TC})
     amcl_configure_file_curve(bls_ZZZ.py.in bls_${TC}.py ${curve} amcl_bls_${TC}_GEN_PYS)
-    amcl_configure_file_curve(run_bls_ZZZ.py.in run_bls_${TC}.py ${curve} __no_install)    
+    amcl_configure_file_curve(run_bls_ZZZ.py.in run_bls_${TC}.py ${curve} __no_install)
     install(FILES "${amcl_bls_${TC}_GEN_PYS}" DESTINATION ${PYTHON3_SITE_PACKAGES})
   endif()
-  
+
 endforeach()
diff --git a/python/run_bls_ZZZ.py.in b/python/run_bls_ZZZ.py.in
index bf6c86b..25c540f 100755
--- a/python/run_bls_ZZZ.py.in
+++ b/python/run_bls_ZZZ.py.in
@@ -22,7 +22,6 @@ under the License.
 
 """
 example for using bls
-
 """
 
 import cffi
diff --git a/scripts/build.sh b/scripts/build.sh
new file mode 100755
index 0000000..432402d
--- /dev/null
+++ b/scripts/build.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+#
+# build.sh
+#
+# Build AMCL
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+set -Cue -o pipefail
+
+PROJECT_HOME="$(cd "$(dirname "${0}")/.." && pwd)"
+cd "$PROJECT_HOME"
+
+declare -a arr=("Release" "Debug" "Coverage" "ASan")
+
+for i in "${arr[@]}"
+do
+    (
+	echo "$i"
+        rm -rf target/$i
+        mkdir -p target/$i
+        cd target/$i
+
+        cmake -D CMAKE_BUILD_TYPE=$i \
+              -D BUILD_SHARED_LIBS=ON \
+              -D DEBUG_NORM=OFF \
+              -D AMCL_CHUNK=64 \
+              -D AMCL_CURVE="BLS381,SECP256K1,ED25519" \
+              -D AMCL_RSA="2048,4096" \
+              -D BUILD_PAILLIER=ON \
+              -D BUILD_PYTHON=ON \
+              -D BUILD_BLS=ON \
+              -D BUILD_BLS_IETF=ON \
+              -D BUILD_WCC=OFF \
+              -D BUILD_MPIN=ON \
+              -D BUILD_X509=OFF \
+              -D CMAKE_INSTALL_PREFIX=/usr/local ../..
+
+        make
+  )
+done
diff --git a/scripts/coverage.sh b/scripts/coverage.sh
new file mode 100755
index 0000000..6a23063
--- /dev/null
+++ b/scripts/coverage.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# coverage.sh
+#
+# Generate coverage figures
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+CURRENTDIR=${PWD}
+
+function coverage()
+{
+  echo "coverage"
+  cd $CURRENTDIR/target/Coverage
+  mkdir coverage
+  lcov --capture --initial --directory . --output-file coverage/libamcl.info
+  lcov --no-checksum --directory . --capture --output-file coverage/libamcl.info
+  lcov --remove coverage/libamcl.info "*/test_*" --output-file coverage/libamcl.info
+  genhtml -o coverage -t "AMCL Test Coverage" coverage/libamcl.info
+}
+
+coverage
diff --git a/scripts/delete.sh b/scripts/delete.sh
new file mode 100755
index 0000000..b521ab6
--- /dev/null
+++ b/scripts/delete.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# delete.sh
+#
+# Delete build files
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+function delete()
+{
+  echo "remove build files"
+  rm -rf target
+  rm -rf build
+  rm -rf coverage
+}
+
+delete
diff --git a/scripts/docker.sh b/scripts/docker.sh
new file mode 100755
index 0000000..a44fe26
--- /dev/null
+++ b/scripts/docker.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+#
+# docker.sh
+#
+# Build and test code in docker
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+set -Cue -o pipefail
+
+SCRIPT_HOME="$(cd "$(dirname "${0}")" && pwd)"
+cd "$SCRIPT_HOME/.."
+
+usage()
+{
+cat << EOF
+usage: $0 options
+
+OPTIONS:
+   -b      Build docker image
+   -t      Run tests
+   -c      Get coverage figures
+   -i      Login to containerAdd docker images to microk8s
+   -k      Stop and remove containers
+   -h      Print usage
+
+EXAMPLE:
+
+   ./docker.sh -b -t -c -i -k -h
+EOF
+}
+
+function build()
+{
+  echo "echo docker build -t libamcl ."
+  docker build -t libamcl .
+}
+
+function test()
+{
+  echo "docker run --cap-add SYS_PTRACE --rm libamcl"
+  docker run --cap-add SYS_PTRACE --rm libamcl
+}
+
+function coverage()
+{
+  echo "docker run --cap-add SYS_PTRACE libamcl ./scripts/coverage.sh"
+  docker run --cap-add SYS_PTRACE libamcl ./scripts/coverage.sh
+}
+
+function login()
+{
+  echo "docker run -it --rm libamcl bash"
+  docker run -it --rm libamcl bash
+}
+
+function kill()
+{
+    CONTAINER_ID=`docker ps -a | grep libamcl | cut -c1-12`
+
+    if [ "${CONTAINER_ID}" ];
+    then
+	echo "docker stop $CONTAINER_ID"
+	docker stop "$CONTAINER_ID"
+	docker rm  "$CONTAINER_ID"
+    fi
+}
+
+while getopts "btcikh" OPTION
+do
+     case $OPTION in
+         b)
+             build
+             ;;
+         t)
+	     test
+             ;;
+         c)
+             coverage
+             ;;
+         i)
+             login
+             ;;
+         k)
+             kill
+             ;;
+         h)
+             usage
+             exit 1
+             ;;
+         :)
+             echo "Missing required argument" 1>&2
+             usage
+             exit 1
+             ;;
+         \?)
+             echo "Invalid option: -$OPTARG" 1>&2
+             usage
+             exit 1
+             ;;
+     esac
+done
+
+if [ "$1" == "" ]
+then
+    usage
+    exit 1
+fi
diff --git a/scripts/format.sh b/scripts/format.sh
new file mode 100755
index 0000000..6924503
--- /dev/null
+++ b/scripts/format.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+# format.sh
+#
+# Format the source code
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+astyle --style=allman --recursive --suffix=none '*.c'
+astyle --style=allman --recursive --suffix=none '*.c.in'
+astyle --style=allman --recursive --suffix=none '*.h'
diff --git a/scripts/gitleaks.sh b/scripts/gitleaks.sh
new file mode 100755
index 0000000..8f3ba92
--- /dev/null
+++ b/scripts/gitleaks.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# gitleaks.sh
+#
+# Detect secrets
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+#
+# https://qredo.atlassian.net/wiki/spaces/SEC/pages/1002340428/Secret+Detection#Running-the-Secret-detection-locally
+# https://github.com/zricethezav/gitleaks
+
+# EXAMPLE USAGE:
+#
+# ./gitleaks.sh
+
+set -Cue -o pipefail
+
+PROJECT_HOME="$(cd "$(dirname "${0}")/.." && pwd)"
+cd "$PROJECT_HOME"
+
+function detect_secrets()
+{
+  # Check gitleaks image exists
+  if [ ! "$(docker images | grep "^zricethezav/gitleaks .*latest")" ];
+  then
+      echo "docker pull ghcr.io/zricethezav/gitleaks:latest"
+      docker pull ghcr.io/zricethezav/gitleaks:latest
+  else
+      echo "zricethezav/gitleaks:latest downloaded"
+  fi
+
+  # Get config file
+  git clone git@gitlab.qredo.com:security/security-ci-cd-templates.git
+  cp security-ci-cd-templates/secret-detection/qredo-secret-detection-config.toml  .
+
+  # Run gitleaks
+  docker run -v $PWD:/path zricethezav/gitleaks:latest detect --source="/path"  --verbose --config /path/qredo-secret-detection-config.toml --report-format json --report-path /path/gitleaks_report.json
+}
+
+detect_secrets
diff --git a/scripts/test.sh b/scripts/test.sh
new file mode 100755
index 0000000..9773dbd
--- /dev/null
+++ b/scripts/test.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# test.sh
+#
+# Test all the library build configurations
+#
+# @author Kealan McCusker <ke...@gmail.com>
+# ------------------------------------------------------------------------------
+
+# NOTES:
+
+set -Cue -o pipefail
+
+PROJECT_HOME="$(cd "$(dirname "${0}")/.." && pwd)"
+cd "$PROJECT_HOME"
+
+declare -a arr=("Release" "Debug" "Coverage" "ASan")
+
+for i in "${arr[@]}"
+do
+    (
+	echo "$i"
+        cd target/$i
+        make test ARGS=-j8
+    )
+done
diff --git a/src/aes.c b/src/aes.c
index 656a031..c96f143 100644
--- a/src/aes.c
+++ b/src/aes.c
@@ -256,7 +256,8 @@ static unsign32 SubByte(unsign32 a)
 static uchar product(unsign32 x,unsign32 y)
 {
     /* dot product of two 4-byte arrays */
-    uchar xb[4],yb[4];
+    uchar xb[4];
+    uchar 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]);
@@ -265,7 +266,8 @@ static uchar product(unsign32 x,unsign32 y)
 static unsign32 InvMixCol(unsign32 x)
 {
     /* matrix Multiplication */
-    unsign32 y,m;
+    unsign32 y;
+    unsign32 m;
     uchar b[4];
 
     m=pack(InCo);
@@ -282,7 +284,7 @@ static unsign32 InvMixCol(unsign32 x)
 
 /* SU= 8 */
 /* reset cipher */
-void AES_reset(amcl_aes *a,int mode,char *iv)
+void AES_reset(amcl_aes *a,int mode,const char *iv)
 {
     /* reset mode, or reset iv */
     int i;
@@ -296,19 +298,22 @@ void AES_reset(amcl_aes *a,int mode,char *iv)
     }
 }
 
-void AES_getreg(amcl_aes *a,char *ir)
+void AES_getreg(const amcl_aes *a,char *ir)
 {
-    int i;
-    for (i=0; i<4*NB; i++) ir[i]=a->f[i];
+    for (int i=0; i<4*NB; i++) ir[i]=a->f[i];
 }
 
 /* SU= 72 */
 /* Initialise cipher */
-int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
+int AES_init(amcl_aes* a,int mode,int nk,char *key,const char *iv)
 {
     /* Key length Nk=16, 24 or 32 bytes */
     /* Key Scheduler. Create expanded encryption key */
-    int i,j,k,N,nr;
+    int i;
+    int j;
+    int k;
+    int N;
+    int nr;
     unsign32 CipherKey[8];
 
     nk/=4;
@@ -327,8 +332,8 @@ int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
     for (i=j=0; i<nk; i++,j+=4)
     {
         CipherKey[i]=pack((uchar *)&key[j]);
+        a->fkey[i]=CipherKey[i];
     }
-    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];
@@ -361,14 +366,20 @@ int AES_init(amcl_aes* a,int mode,int nk,char *key,char *iv)
 
 /* SU= 80 */
 /* Encrypt a single block */
-void AES_ecb_encrypt(amcl_aes *a,uchar *buff)
+void AES_ecb_encrypt(const amcl_aes *a,uchar *buff)
 {
-    int i,j,k;
-    unsign32 p[4],q[4],*x,*y,*t;
+    int i;
+    int j;
+    int k;
+    unsign32 p[4];
+    unsign32 q[4];
+    unsign32 *x;
+    unsign32 *y;
+    unsign32 *t;
 
     for (i=j=0; i<NB; i++,j+=4)
     {
-        p[i]=pack((uchar *)&buff[j]);
+        p[i]=pack(&buff[j]);
         p[i]^=a->fkey[i];
     }
 
@@ -424,21 +435,27 @@ void AES_ecb_encrypt(amcl_aes *a,uchar *buff)
 
     for (i=j=0; i<NB; i++,j+=4)
     {
-        unpack(y[i],(uchar *)&buff[j]);
+        unpack(y[i],&buff[j]);
         x[i]=y[i]=0;   /* clean up stack */
     }
 }
 
 /* SU= 80 */
 /* Decrypt a single block */
-void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
+void AES_ecb_decrypt(const amcl_aes *a,uchar *buff)
 {
-    int i,j,k;
-    unsign32 p[4],q[4],*x,*y,*t;
+    int i;
+    int j;
+    int k;
+    unsign32 p[4];
+    unsign32 q[4];
+    unsign32 *x;
+    unsign32 *y;
+    unsign32 *t;
 
     for (i=j=0; i<NB; i++,j+=4)
     {
-        p[i]=pack((uchar *)&buff[j]);
+        p[i]=pack(&buff[j]);
         p[i]^=a->rkey[i];
     }
 
@@ -495,7 +512,7 @@ void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
 
     for (i=j=0; i<NB; i++,j+=4)
     {
-        unpack(y[i],(uchar *)&buff[j]);
+        unpack(y[i],&buff[j]);
         x[i]=y[i]=0;   /* clean up stack */
     }
 
@@ -504,8 +521,7 @@ void AES_ecb_decrypt(amcl_aes *a,uchar *buff)
 /* simple default increment function */
 static void increment(char *f)
 {
-    int i;
-    for (i=0; i<16; i++)
+    for (int i=0; i<16; i++)
     {
         f[i]++;
         if (f[i]!=0) break;
@@ -516,7 +532,8 @@ static void increment(char *f)
 /* Encrypt using selected mode of operation */
 unsign32 AES_encrypt(amcl_aes* a,char *buff)
 {
-    int j,bytes;
+    int j;
+    int bytes;
     char st[16];
     unsign32 fell_off;
 
@@ -582,7 +599,8 @@ unsign32 AES_encrypt(amcl_aes* a,char *buff)
 /* Decrypt using selected mode of operation */
 unsign32 AES_decrypt(amcl_aes *a,char *buff)
 {
-    int j,bytes;
+    int j;
+    int bytes;
     char st[16];
     unsign32 fell_off;
 
@@ -658,47 +676,3 @@ void AES_end(amcl_aes *a)
     for (i=0; i<4*NB; i++)
         a->f[i]=0;
 }
-
-
-/*
-#include <stdio.h>
-
-#define KK 32
-
-int main()
-{
-    int i;
-    amcl_aes a;
-	unsign32 t;
-	uchar x,y;
-
-    char key[KK];
-    char block[16];
-    char iv[16];
-    for (i=0;i<KK;i++) key[i]=5;
-    key[0]=1;
-    for (i=0;i<16;i++) iv[i]=i;
-    for (i=0;i<16;i++) block[i]=i;
-
-    AES_init(&a,CTR16,KK,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,CTR16,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/src/big.c.in b/src/big.c.in
index 3358ae1..4aa7214 100644
--- a/src/big.c.in
+++ b/src/big.c.in
@@ -24,16 +24,15 @@
 
 /* test a=0? */
 /* libsodium constant time implementation */
-int BIG_XXX_iszilch(BIG_XXX a)
+int BIG_XXX_iszilch(const BIG_XXX a)
 {
-    int i;
     chunk d = 0;
 
 #ifdef DEBUG_NORM
     if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("Input to iszilch not normed\n");
 #endif
 
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         d |= a[i];
 
     return (1 & ((d-1)>>BASEBITS_XXX));
@@ -44,16 +43,15 @@ int BIG_XXX_iszilch(BIG_XXX a)
    comparison to zero of a[1],..,a[NLEN_XXX-1]
    then checking if a[0] == 1
  */
-int BIG_XXX_isunity(BIG_XXX a)
+int BIG_XXX_isunity(const BIG_XXX a)
 {
-    int i;
     chunk d = 0;
 
 #ifdef DEBUG_NORM
     if ((a[MPV_XXX]!=1 && a[MPV_XXX]!=0) || a[MNV_XXX]!=0) printf("Input to isunity not normed\n");
 #endif
 
-    for(i=1; i<NLEN_XXX; i++)
+    for(int i=1; i<NLEN_XXX; i++)
         d |= a[i];
 
     return (1 & ((d-1)>>BASEBITS_XXX) & ((a[0]^1)-1)>>BASEBITS_XXX);
@@ -61,16 +59,15 @@ int BIG_XXX_isunity(BIG_XXX a)
 
 /* test a=0? */
 /* libsodium constant time implementation */
-int BIG_XXX_diszilch(DBIG_XXX a)
+int BIG_XXX_diszilch(const DBIG_XXX a)
 {
-    int i;
     chunk d = 0;
 
 #ifdef DEBUG_NORM
     if ((a[DMPV_XXX]!=1 && a[DMPV_XXX]!=0) || a[DMNV_XXX]!=0) printf("Input to diszilch not normed\n");
 #endif
 
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
         d |= a[i];
 
     return (1 & ((d-1)>>BASEBITS_XXX));
@@ -78,10 +75,10 @@ int BIG_XXX_diszilch(DBIG_XXX a)
 
 /* SU= 56 */
 /* output a */
-void BIG_XXX_output(BIG_XXX a)
+void BIG_XXX_output(const BIG_XXX a)
 {
     BIG_XXX b;
-    int i,len;
+    int len;
     len=BIG_XXX_nbits(a);
     if (len%4==0) len/=4;
     else
@@ -91,7 +88,7 @@ void BIG_XXX_output(BIG_XXX a)
     }
     if (len<MODBYTES_XXX*2) len=MODBYTES_XXX*2;
 
-    for (i=len-1; i>=0; i--)
+    for (int i=len-1; i>=0; i--)
     {
         BIG_XXX_copy(b,a);
         BIG_XXX_shr(b,i*4);
@@ -100,11 +97,10 @@ void BIG_XXX_output(BIG_XXX a)
 }
 
 /* SU= 16 */
-void BIG_XXX_rawoutput(BIG_XXX a)
+void BIG_XXX_rawoutput(const BIG_XXX a)
 {
-    int i;
     printf("(");
-    for (i=0; i<NLEN_XXX-1; i++)
+    for (int i=0; i<NLEN_XXX-1; i++)
 #if CHUNK==64
         printf("%"PRIxMAX",",(uintmax_t) a[i]);
     printf("%"PRIxMAX")",(uintmax_t) a[NLEN_XXX-1]);
@@ -117,13 +113,13 @@ void BIG_XXX_rawoutput(BIG_XXX a)
 /* Swap a and b if d=1 */
 void BIG_XXX_cswap(BIG_XXX a,BIG_XXX b,int d)
 {
-    int i;
-    chunk t,c=d;
+    chunk t;
+    chunk c=d;
     c=~(c-1);
 #ifdef DEBUG_NORM
     for (i=0; i<NLEN_XXX+2; i++)
 #else
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
 #endif
     {
         t=c&(a[i]^b[i]);
@@ -133,14 +129,13 @@ void BIG_XXX_cswap(BIG_XXX a,BIG_XXX b,int d)
 }
 
 /* Move b to a if d=1 */
-void BIG_XXX_cmove(BIG_XXX f,BIG_XXX g,int d)
+void BIG_XXX_cmove(BIG_XXX f,const BIG_XXX g,int d)
 {
-    int i;
     chunk b=(chunk)-d;
 #ifdef DEBUG_NORM
     for (i=0; i<NLEN_XXX+2; i++)
 #else
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
 #endif
     {
         f[i]^=(f[i]^g[i])&b;
@@ -148,14 +143,13 @@ void BIG_XXX_cmove(BIG_XXX f,BIG_XXX g,int d)
 }
 
 /* Move g to f if d=1 */
-void BIG_XXX_dcmove(DBIG_XXX f,DBIG_XXX g,int d)
+void BIG_XXX_dcmove(DBIG_XXX f,const DBIG_XXX g,int d)
 {
-    int i;
     chunk b=(chunk)-d;
 #ifdef DEBUG_NORM
     for (i=0; i<DNLEN_XXX+2; i++)
 #else
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
 #endif
     {
         f[i]^=(f[i]^g[i])&b;
@@ -164,13 +158,12 @@ void BIG_XXX_dcmove(DBIG_XXX f,DBIG_XXX g,int d)
 
 /* convert BIG to/from bytes */
 /* SU= 64 */
-void BIG_XXX_toBytes(char *b,BIG_XXX a)
+void BIG_XXX_toBytes(char *b,const BIG_XXX a)
 {
-    int i;
     BIG_XXX c;
     BIG_XXX_copy(c,a);
     BIG_XXX_norm(c);
-    for (i=MODBYTES_XXX-1; i>=0; i--)
+    for (int i=MODBYTES_XXX-1; i>=0; i--)
     {
         b[i]=c[0]&0xff;
         BIG_XXX_fshr(c,8);
@@ -178,11 +171,10 @@ void BIG_XXX_toBytes(char *b,BIG_XXX a)
 }
 
 /* SU= 16 */
-void BIG_XXX_fromBytes(BIG_XXX a,char *b)
+void BIG_XXX_fromBytes(BIG_XXX a,const char *b)
 {
-    int i;
     BIG_XXX_zero(a);
-    for (i=0; i<MODBYTES_XXX; i++)
+    for (int i=0; i<MODBYTES_XXX; i++)
     {
         BIG_XXX_fshl(a,8);
         a[0]+=(int)(unsigned char)b[i];
@@ -193,13 +185,13 @@ void BIG_XXX_fromBytes(BIG_XXX a,char *b)
 #endif
 }
 
-void BIG_XXX_fromBytesLen(BIG_XXX a,char *b,int s)
+void BIG_XXX_fromBytesLen(BIG_XXX a,const char *b,int s)
 {
-    int i,len=s;
+    int len=s;
     BIG_XXX_zero(a);
 
     if (len>MODBYTES_XXX) len=MODBYTES_XXX;
-    for (i=0; i<len; i++)
+    for (int i=0; i<len; i++)
     {
         BIG_XXX_fshl(a,8);
         a[0]+=(int)(unsigned char)b[i];
@@ -216,7 +208,7 @@ void BIG_XXX_fromBytesLen(BIG_XXX a,char *b,int s)
 void BIG_XXX_doutput(DBIG_XXX a)
 {
     DBIG_XXX b;
-    int i,len;
+    int len;
     BIG_XXX_dnorm(a);
     len=BIG_XXX_dnbits(a);
     if (len%4==0) len/=4;
@@ -226,7 +218,7 @@ void BIG_XXX_doutput(DBIG_XXX a)
         len++;
     }
 
-    for (i=len-1; i>=0; i--)
+    for (int i=len-1; i>=0; i--)
     {
         BIG_XXX_dcopy(b,a);
         BIG_XXX_dshr(b,i*4);
@@ -235,11 +227,10 @@ void BIG_XXX_doutput(DBIG_XXX a)
 }
 
 
-void BIG_XXX_drawoutput(DBIG_XXX a)
+void BIG_XXX_drawoutput(const DBIG_XXX a)
 {
-    int i;
     printf("(");
-    for (i=0; i<DNLEN_XXX-1; i++)
+    for (int i=0; i<DNLEN_XXX-1; i++)
 #if CHUNK==64
         printf("%"PRIxMAX",",(uintmax_t) a[i]);
     printf("%"PRIxMAX")",(uintmax_t) a[DNLEN_XXX-1]);
@@ -250,10 +241,9 @@ void BIG_XXX_drawoutput(DBIG_XXX a)
 }
 
 /* Copy b=a */
-void BIG_XXX_copy(BIG_XXX b,BIG_XXX a)
+void BIG_XXX_copy(BIG_XXX b,const BIG_XXX a)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         b[i]=a[i];
 #ifdef DEBUG_NORM
     b[MPV_XXX]=a[MPV_XXX];
@@ -264,8 +254,7 @@ void BIG_XXX_copy(BIG_XXX b,BIG_XXX a)
 /* Copy from ROM b=a */
 void BIG_XXX_rcopy(BIG_XXX b,const BIG_XXX a)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         b[i]=a[i];
 #ifdef DEBUG_NORM
     b[MPV_XXX]=1;
@@ -274,10 +263,9 @@ void BIG_XXX_rcopy(BIG_XXX b,const BIG_XXX a)
 }
 
 /* double length DBIG copy b=a */
-void BIG_XXX_dcopy(DBIG_XXX b,DBIG_XXX a)
+void BIG_XXX_dcopy(DBIG_XXX b,const DBIG_XXX a)
 {
-    int i;
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
         b[i]=a[i];
 #ifdef DEBUG_NORM
     b[DMPV_XXX]=a[DMPV_XXX];
@@ -286,7 +274,7 @@ void BIG_XXX_dcopy(DBIG_XXX b,DBIG_XXX a)
 }
 
 /* Copy BIG to bottom half of DBIG */
-void BIG_XXX_dscopy(DBIG_XXX b,BIG_XXX a)
+void BIG_XXX_dscopy(DBIG_XXX b,const BIG_XXX a)
 {
     int i;
     for (i=0; i<NLEN_XXX-1; i++)
@@ -303,7 +291,7 @@ void BIG_XXX_dscopy(DBIG_XXX b,BIG_XXX a)
 }
 
 /* Copy BIG to top half of DBIG */
-void BIG_XXX_dsucopy(DBIG_XXX b,BIG_XXX a)
+void BIG_XXX_dsucopy(DBIG_XXX b,const BIG_XXX a)
 {
     int i;
     for (i=0; i<NLEN_XXX; i++)
@@ -317,22 +305,20 @@ void BIG_XXX_dsucopy(DBIG_XXX b,BIG_XXX a)
 }
 
 /* Copy bottom half of DBIG to BIG */
-void BIG_XXX_sdcopy(BIG_XXX b,DBIG_XXX a)
+void BIG_XXX_sdcopy(BIG_XXX a,const DBIG_XXX b)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
-        b[i]=a[i];
+    for (int i=0; i<NLEN_XXX; i++)
+        a[i]=b[i];
 #ifdef DEBUG_NORM
-    b[MPV_XXX]=a[DMPV_XXX];
-    b[MNV_XXX]=a[DMNV_XXX];
+    a[MPV_XXX]=b[DMPV_XXX];
+    a[MNV_XXX]=b[DMNV_XXX];
 #endif
 }
 
 /* Copy top half of DBIG to BIG */
-void BIG_XXX_sducopy(BIG_XXX b,DBIG_XXX a)
+void BIG_XXX_sducopy(BIG_XXX b,const DBIG_XXX a)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         b[i]=a[i+NLEN_XXX];
 #ifdef DEBUG_NORM
     b[MPV_XXX]=a[DMPV_XXX];
@@ -344,8 +330,7 @@ void BIG_XXX_sducopy(BIG_XXX b,DBIG_XXX a)
 /* Set a=0 */
 void BIG_XXX_zero(BIG_XXX a)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         a[i]=0;
 #ifdef DEBUG_NORM
     a[MPV_XXX]=a[MNV_XXX]=0;
@@ -354,8 +339,7 @@ void BIG_XXX_zero(BIG_XXX a)
 
 void BIG_XXX_dzero(DBIG_XXX a)
 {
-    int i;
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
         a[i]=0;
 #ifdef DEBUG_NORM
     a[DMPV_XXX]=a[DMNV_XXX]=0;
@@ -365,9 +349,8 @@ void BIG_XXX_dzero(DBIG_XXX a)
 /* set a=1 */
 void BIG_XXX_one(BIG_XXX a)
 {
-    int i;
     a[0]=1;
-    for (i=1; i<NLEN_XXX; i++)
+    for (int i=1; i<NLEN_XXX; i++)
         a[i]=0;
 #ifdef DEBUG_NORM
     a[MPV_XXX]=1;
@@ -379,10 +362,9 @@ void BIG_XXX_one(BIG_XXX a)
 
 /* Set c=a+b */
 /* SU= 8 */
-void BIG_XXX_add(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+void BIG_XXX_add(BIG_XXX c,const BIG_XXX a,const BIG_XXX b)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         c[i]=a[i]+b[i];
 #ifdef DEBUG_NORM
     c[MPV_XXX]=a[MPV_XXX]+b[MPV_XXX];
@@ -396,10 +378,9 @@ void BIG_XXX_add(BIG_XXX c,BIG_XXX a,BIG_XXX b)
 /* Set c=a or b */
 void BIG_XXX_or(BIG_XXX c,BIG_XXX a,BIG_XXX b)
 {
-    int i;
     BIG_XXX_norm(a);
     BIG_XXX_norm(b);
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         c[i]=a[i]|b[i];
 #ifdef DEBUG_NORM
     c[MPV_XXX]=1;
@@ -420,10 +401,9 @@ void BIG_XXX_inc(BIG_XXX c,int d)
 
 /* Set c=a-b */
 /* SU= 8 */
-void BIG_XXX_sub(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+void BIG_XXX_sub(BIG_XXX c,const BIG_XXX a,const BIG_XXX b)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
         c[i]=a[i]-b[i];
 #ifdef DEBUG_NORM
     c[MPV_XXX]=a[MPV_XXX]+b[MNV_XXX];
@@ -436,10 +416,9 @@ void BIG_XXX_sub(BIG_XXX c,BIG_XXX a,BIG_XXX b)
 
 /* SU= 8 */
 
-void BIG_XXX_dsub(DBIG_XXX c,DBIG_XXX a,DBIG_XXX b)
+void BIG_XXX_dsub(DBIG_XXX c,const DBIG_XXX a,const DBIG_XXX b)
 {
-    int i;
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
         c[i]=a[i]-b[i];
 #ifdef DEBUG_NORM
     c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
@@ -449,10 +428,9 @@ void BIG_XXX_dsub(DBIG_XXX c,DBIG_XXX a,DBIG_XXX b)
 #endif
 }
 
-void BIG_XXX_dadd(DBIG_XXX c,DBIG_XXX a,DBIG_XXX b)
+void BIG_XXX_dadd(DBIG_XXX c,const DBIG_XXX a,const DBIG_XXX b)
 {
-    int i;
-    for (i=0; i<DNLEN_XXX; i++)
+    for (int i=0; i<DNLEN_XXX; i++)
         c[i]=a[i]+b[i];
 #ifdef DEBUG_NORM
     c[DMPV_XXX]=a[DMPV_XXX]+b[DMNV_XXX];
@@ -473,10 +451,9 @@ void BIG_XXX_dec(BIG_XXX c,int d)
 }
 
 /* multiplication r=a*c by c<=NEXCESS_XXX */
-void BIG_XXX_imul(BIG_XXX r,BIG_XXX a,int c)
+void BIG_XXX_imul(BIG_XXX r,const BIG_XXX a,int c)
 {
-    int i;
-    for (i=0; i<NLEN_XXX; i++) r[i]=a[i]*c;
+    for (int i=0; i<NLEN_XXX; i++) r[i]=a[i]*c;
 #ifdef DEBUG_NORM
     r[MPV_XXX]=a[MPV_XXX]*c;
     r[MNV_XXX]=a[MNV_XXX]*c;
@@ -488,11 +465,11 @@ void BIG_XXX_imul(BIG_XXX r,BIG_XXX a,int c)
 
 /* multiplication r=a*c by larger integer - c<=FEXCESS */
 /* SU= 24 */
-chunk BIG_XXX_pmul(BIG_XXX r,BIG_XXX a,int c)
+chunk BIG_XXX_pmul(BIG_XXX r,const BIG_XXX a,int c)
 {
-    int i;
-    chunk ak,carry=0;
-    for (i=0; i<NLEN_XXX; i++)
+    chunk ak;
+    chunk carry=0;
+    for (int i=0; i<NLEN_XXX; i++)
     {
         ak=a[i];
         r[i]=0;
@@ -509,11 +486,12 @@ chunk BIG_XXX_pmul(BIG_XXX r,BIG_XXX a,int c)
 /* SU= 16 */
 int BIG_XXX_div3(BIG_XXX r)
 {
-    int i;
-    chunk ak,base,carry=0;
+    chunk ak;
+    chunk base;
+    chunk carry=0;
     BIG_XXX_norm(r);
     base=((chunk)1<<BASEBITS_XXX);
-    for (i=NLEN_XXX-1; i>=0; i--)
+    for (int i=NLEN_XXX-1; i>=0; i--)
     {
         ak=(carry*base+r[i]);
         r[i]=ak/3;
@@ -524,13 +502,12 @@ int BIG_XXX_div3(BIG_XXX r)
 
 /* multiplication c=a*b by even larger integer b>FEXCESS, resulting in DBIG */
 /* SU= 24 */
-void BIG_XXX_pxmul(DBIG_XXX c,BIG_XXX a,int b)
+void BIG_XXX_pxmul(DBIG_XXX c,const BIG_XXX a,int b)
 {
-    int j;
     chunk carry;
     BIG_XXX_dzero(c);
     carry=0;
-    for (j=0; j<NLEN_XXX; j++)
+    for (int j=0; j<NLEN_XXX; j++)
         carry=muladd_XXX(a[j],(chunk)b,carry,&c[j]);
     c[NLEN_XXX]=carry;
 #ifdef DEBUG_NORM
@@ -541,16 +518,15 @@ void BIG_XXX_pxmul(DBIG_XXX c,BIG_XXX a,int b)
 
 /* .. if you know the result will fit in a BIG, c must be distinct from a and b */
 /* SU= 40 */
-void BIG_XXX_smul(BIG_XXX c,BIG_XXX a,BIG_XXX b)
+void BIG_XXX_smul(BIG_XXX c,const BIG_XXX a,const BIG_XXX b)
 {
-    int i,j;
     chunk carry;
 
     BIG_XXX_zero(c);
-    for (i=0; i<NLEN_XXX; i++)
+    for (int i=0; i<NLEN_XXX; i++)
     {
         carry=0;
-        for (j=0; j<NLEN_XXX; j++)
+        for (int j=0; j<NLEN_XXX; j++)
         {
             if (i+j<NLEN_XXX)
                 carry=muladd_XXX(a[i],b[j],carry,&c[i+j]);
@@ -565,11 +541,12 @@ void BIG_XXX_smul(BIG_XXX c,BIG_XXX a,BIG_XXX b)
 
 /* Set c=a*b */
 /* SU= 72 */
-void BIG_XXX_mul(DBIG_XXX c,BIG_XXX a,BIG_XXX b)
+void BIG_XXX_mul(DBIG_XXX c,const BIG_XXX a,const BIG_XXX b)
 {
     int i;
 #ifdef dchunk
-    dchunk t,co;
+    dchunk t;
+    dchunk co;
     dchunk s;
     dchunk d[NLEN_XXX];
     int k;
@@ -619,13 +596,12 @@ void BIG_XXX_mul(DBIG_XXX c,BIG_XXX a,BIG_XXX b)
 #endif
 
 #else
-    int j;
     chunk carry;
     BIG_XXX_dzero(c);
     for (i=0; i<NLEN_XXX; i++)
     {
         carry=0;
-        for (j=0; j<NLEN_XXX; j++)
+        for (int j=0; j<NLEN_XXX; j++)
             carry=muladd_XXX(a[i],b[j],carry,&c[i+j]);
 
         c[NLEN_XXX+i]=carry;
@@ -641,11 +617,13 @@ void BIG_XXX_mul(DBIG_XXX c,BIG_XXX a,BIG_XXX b)
 
 /* Set c=a*a */
 /* SU= 80 */
-void BIG_XXX_sqr(DBIG_XXX c,BIG_XXX a)
+void BIG_XXX_sqr(DBIG_XXX c,const BIG_XXX a)
 {
-    int i,j;
+    int i;
+    int j;
 #ifdef dchunk
-    dchunk t,co;
+    dchunk t;
+    dchunk co;
 #endif
 
 #ifdef DEBUG_NORM
@@ -758,12 +736,15 @@ void BIG_XXX_sqr(DBIG_XXX c,BIG_XXX a)
 }
 
 /* Montgomery reduction */
-void BIG_XXX_monty(BIG_XXX a,BIG_XXX md,chunk MC,DBIG_XXX d)
+void BIG_XXX_monty(BIG_XXX a,const BIG_XXX md,chunk MC,const DBIG_XXX d)
 {
-    int i,k;
+    int i;
+    int k;
 
 #ifdef dchunk
-    dchunk t,c,s;
+    dchunk t;
+    dchunk c;
+    dchunk s;
     dchunk dd[NLEN_XXX];
     chunk v[NLEN_XXX];
 #endif
@@ -807,13 +788,13 @@ void BIG_XXX_monty(BIG_XXX a,BIG_XXX md,chunk MC,DBIG_XXX d)
 
 
 #else
-    int j;
-    chunk m,carry;
+    chunk m;
+    chunk carry;
     for (i=0; i<NLEN_XXX; i++)
     {
         m = (MC*d[i])&BMASK_XXX;
         carry=0;
-        for (j=0; j<NLEN_XXX; j++)
+        for (int j=0; j<NLEN_XXX; j++)
             carry=muladd_XXX(m,md[j],carry,&d[i+j]);
         d[NLEN_XXX+i]+=carry;
     }
@@ -837,7 +818,7 @@ void BIG_XXX_shl(BIG_XXX a,int k)
     int n=k%BASEBITS_XXX;
     int m=k/BASEBITS_XXX;
 
-    a[NLEN_XXX-1]=((a[NLEN_XXX-1-m]<<n));
+    a[NLEN_XXX-1]=(a[NLEN_XXX-1-m]<<n);
     if (NLEN_XXX>=m+2) a[NLEN_XXX-1]|=(a[NLEN_XXX-m-2]>>(BASEBITS_XXX-n));
 
     for (i=NLEN_XXX-2; i>m; i--)
@@ -852,10 +833,8 @@ void BIG_XXX_shl(BIG_XXX a,int k)
 /* SU= 16 */
 int BIG_XXX_fshl(BIG_XXX a,int n)
 {
-    int i;
-
-    a[NLEN_XXX-1]=((a[NLEN_XXX-1]<<n))|(a[NLEN_XXX-2]>>(BASEBITS_XXX-n)); /* top word not masked */
-    for (i=NLEN_XXX-2; i>0; i--)
+    a[NLEN_XXX-1]=(a[NLEN_XXX-1]<<n)|(a[NLEN_XXX-2]>>(BASEBITS_XXX-n)); /* top word not masked */
+    for (int i=NLEN_XXX-2; i>0; i--)
         a[i]=((a[i]<<n)&BMASK_XXX)|(a[i-1]>>(BASEBITS_XXX-n));
     a[0]=(a[0]<<n)&BMASK_XXX;
 
@@ -870,7 +849,7 @@ void BIG_XXX_dshl(DBIG_XXX a,int k)
     int n=k%BASEBITS_XXX;
     int m=k/BASEBITS_XXX;
 
-    a[DNLEN_XXX-1]=((a[DNLEN_XXX-1-m]<<n))|(a[DNLEN_XXX-m-2]>>(BASEBITS_XXX-n));
+    a[DNLEN_XXX-1]=(a[DNLEN_XXX-1-m]<<n)|(a[DNLEN_XXX-m-2]>>(BASEBITS_XXX-n));
 
     for (i=DNLEN_XXX-2; i>m; i--)
         a[i]=((a[i-m]<<n)&BMASK_XXX)|(a[i-m-1]>>(BASEBITS_XXX-n));
@@ -895,16 +874,16 @@ void BIG_XXX_shr(BIG_XXX a,int k)
 }
 
 /* Fast combined shift, subtract and norm. Return sign of result */
-int BIG_XXX_ssn(BIG_XXX r,BIG_XXX a,BIG_XXX m)
+int BIG_XXX_ssn(BIG_XXX r,const BIG_XXX a,BIG_XXX m)
 {
-    int i,n=NLEN_XXX-1;
+    int n=NLEN_XXX-1;
     chunk carry;
     m[0]=(m[0]>>1)|((m[1]<<(BASEBITS_XXX-1))&BMASK_XXX);
     r[0]=a[0]-m[0];
     carry=r[0]>>BASEBITS_XXX;
     r[0]&=BMASK_XXX;
 
-    for (i=1; i<n; i++)
+    for (int i=1; i<n; i++)
     {
         m[i]=(m[i]>>1)|((m[i+1]<<(BASEBITS_XXX-1))&BMASK_XXX);
         r[i]=a[i]-m[i]+carry;
@@ -926,9 +905,8 @@ int BIG_XXX_ssn(BIG_XXX r,BIG_XXX a,BIG_XXX m)
 /* SU= 16 */
 int BIG_XXX_fshr(BIG_XXX a,int k)
 {
-    int i;
     chunk r=a[0]&(((chunk)1<<k)-1); /* shifted out part */
-    for (i=0; i<NLEN_XXX-1; i++)
+    for (int i=0; i<NLEN_XXX-1; i++)
         a[i]=(a[i]>>k)|((a[i+1]<<(BASEBITS_XXX-k))&BMASK_XXX);
     a[NLEN_XXX-1]=a[NLEN_XXX-1]>>k;
     return (int)r;
@@ -950,10 +928,11 @@ void BIG_XXX_dshr(DBIG_XXX a,int k)
 /* 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 */
-chunk BIG_XXX_split(BIG_XXX t,BIG_XXX b,DBIG_XXX d,int n)
+chunk BIG_XXX_split(BIG_XXX t,BIG_XXX b,const DBIG_XXX d,int n)
 {
     int i;
-    chunk nw,carry=0;
+    chunk nw;
+    chunk carry=0;
     int m=n%BASEBITS_XXX;
 
     if (m==0)
@@ -996,9 +975,9 @@ chunk BIG_XXX_split(BIG_XXX t,BIG_XXX b,DBIG_XXX d,int n)
 /* normalise BIG - force all digits < 2^BASEBITS */
 chunk BIG_XXX_norm(BIG_XXX a)
 {
-    int i;
-    chunk d,carry=0;
-    for (i=0; i<NLEN_XXX-1; i++)
+    chunk d;
+    chunk carry=0;
+    for (int i=0; i<NLEN_XXX-1; i++)
     {
         d=a[i]+carry;
         a[i]=d&BMASK_XXX;
@@ -1015,9 +994,9 @@ chunk BIG_XXX_norm(BIG_XXX a)
 
 void BIG_XXX_dnorm(DBIG_XXX a)
 {
-    int i;
-    chunk d,carry=0;
-    for (i=0; i<DNLEN_XXX-1; i++)
+    chunk d;
+    chunk carry=0;
+    for (int i=0; i<DNLEN_XXX-1; i++)
     {
         d=a[i]+carry;
         a[i]=d&BMASK_XXX;
@@ -1033,9 +1012,8 @@ void BIG_XXX_dnorm(DBIG_XXX a)
 /* 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 */
 /* libsodium constant time implementation */
-int BIG_XXX_comp(BIG_XXX b1,BIG_XXX b2)
+int BIG_XXX_comp(const BIG_XXX b1,const BIG_XXX b2)
 {
-    int i;
     chunk gt = 0;
     chunk eq = 1;
 
@@ -1044,7 +1022,7 @@ int BIG_XXX_comp(BIG_XXX b1,BIG_XXX b2)
     if ((b2[MPV_XXX]!=1 && b2[MPV_XXX]!=0) || b2[MNV_XXX]!=0) printf("Second input to comp not normed\n");
 #endif
 
-    for (i = NLEN_XXX-1; i>=0; i--)
+    for (int i = NLEN_XXX-1; i>=0; i--)
     {
         gt |= ((b2[i]-b1[i]) >> BASEBITS_XXX) & eq;
         eq &= ((b2[i]^b1[i])-1) >> BASEBITS_XXX;
@@ -1056,9 +1034,8 @@ int BIG_XXX_comp(BIG_XXX b1,BIG_XXX b2)
 /* Compare b1 and b2. Return 1 for b1>b2, -1 for a<b, 0 for a==b */
 /* a and b MUST be normalised before call */
 /* libsodium constant time implementation */
-int BIG_XXX_dcomp(DBIG_XXX b1,DBIG_XXX b2)
+int BIG_XXX_dcomp(const DBIG_XXX b1,const DBIG_XXX b2)
 {
-    int i;
     chunk gt = 0;
     chunk eq = 1;
 
@@ -1067,7 +1044,7 @@ int BIG_XXX_dcomp(DBIG_XXX b1,DBIG_XXX b2)
     if ((b2[DMPV_XXX]!=1 && b2[DMPV_XXX]!=0) || b2[DMNV_XXX]!=0) printf("Second input to dcomp not normed\n");
 #endif
 
-    for (i=DNLEN_XXX-1; i>=0; i--)
+    for (int i=DNLEN_XXX-1; i>=0; i--)
     {
         gt |= ((b2[i]-b1[i]) >> BASEBITS_XXX) & eq;
         eq &= ((b2[i]^b1[i])-1) >> BASEBITS_XXX;
@@ -1078,9 +1055,10 @@ int BIG_XXX_dcomp(DBIG_XXX b1,DBIG_XXX b2)
 
 /* return number of bits in a */
 /* SU= 8 */
-int BIG_XXX_nbits(BIG_XXX a)
+int BIG_XXX_nbits(const BIG_XXX a)
 {
-    int bts,k=NLEN_XXX-1;
+    int bts;
+    int k=NLEN_XXX-1;
     BIG_XXX t;
     chunk c;
     BIG_XXX_copy(t,a);
@@ -1098,9 +1076,10 @@ int BIG_XXX_nbits(BIG_XXX a)
 }
 
 /* SU= 8, Calculate number of bits in a DBIG - output normalised */
-int BIG_XXX_dnbits(DBIG_XXX a)
+int BIG_XXX_dnbits(const DBIG_XXX a)
 {
-    int bts,k=DNLEN_XXX-1;
+    int bts;
+    int k=DNLEN_XXX-1;
     DBIG_XXX t;
     chunk c;
     BIG_XXX_dcopy(t,a);
@@ -1120,7 +1099,7 @@ int BIG_XXX_dnbits(DBIG_XXX a)
 
 /* Set b=b mod c */
 /* SU= 16 */
-void BIG_XXX_mod(BIG_XXX b,BIG_XXX c1)
+void BIG_XXX_mod(BIG_XXX b,const BIG_XXX c1)
 {
     int k=0;
     BIG_XXX r; /**/
@@ -1151,10 +1130,11 @@ void BIG_XXX_mod(BIG_XXX b,BIG_XXX c1)
 
 /* Set a=b mod c, b is destroyed. Slow but rarely used. */
 /* SU= 96 */
-void BIG_XXX_dmod(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
+void BIG_XXX_dmod(BIG_XXX a,DBIG_XXX b,const BIG_XXX c)
 {
     int k=0;
-    DBIG_XXX m,r;
+    DBIG_XXX m;
+    DBIG_XXX r;
     BIG_XXX_dnorm(b);
     BIG_XXX_dscopy(m,c);
 
@@ -1187,11 +1167,14 @@ void BIG_XXX_dmod(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
 /* Set a=b/c,  b is destroyed. Slow but rarely used. */
 /* SU= 136 */
 
-void BIG_XXX_ddiv(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
+void BIG_XXX_ddiv(BIG_XXX a,DBIG_XXX b,const BIG_XXX c)
 {
-    int d,k=0;
-    DBIG_XXX m,dr;
-    BIG_XXX e,r;
+    int d;
+    int k=0;
+    DBIG_XXX m;
+    DBIG_XXX dr;
+    BIG_XXX e;
+    BIG_XXX r;
     BIG_XXX_dnorm(b);
     BIG_XXX_dscopy(m,c);
 
@@ -1226,10 +1209,14 @@ void BIG_XXX_ddiv(BIG_XXX a,DBIG_XXX b,BIG_XXX c)
 
 /* SU= 136 */
 
-void BIG_XXX_sdiv(BIG_XXX a,BIG_XXX c)
+void BIG_XXX_sdiv(BIG_XXX a,const BIG_XXX c)
 {
-    int d,k=0;
-    BIG_XXX m,e,b,r;
+    int d;
+    int k=0;
+    BIG_XXX m;
+    BIG_XXX e;
+    BIG_XXX b;
+    BIG_XXX r;
     BIG_XXX_norm(a);
     BIG_XXX_copy(b,a);
     BIG_XXX_copy(m,c);
@@ -1263,24 +1250,24 @@ void BIG_XXX_sdiv(BIG_XXX a,BIG_XXX c)
 }
 
 /* return LSB of a */
-int BIG_XXX_parity(BIG_XXX a)
+int BIG_XXX_parity(const BIG_XXX a)
 {
     return a[0]%2;
 }
 
 /* return n-th bit of a */
 /* SU= 16 */
-int BIG_XXX_bit(BIG_XXX a,int n)
+int BIG_XXX_bit(const BIG_XXX a,int n)
 {
     return ((int)(a[n/BASEBITS_XXX]>>(n%BASEBITS_XXX))) & 1;
 }
 
 /* return w bits of a starting from the n-th */
-int BIG_XXX_bits(BIG_XXX a, int n, int w)
+int BIG_XXX_bits(const BIG_XXX a, int n, int w)
 {
-    int i, b = 0;
+    int b = 0;
 
-    for (i=n+w-1; i>=n; i--)
+    for (int i=n+w-1; i>=n; i--)
     {
         b <<=1;
         b |= ((int)(a[i/BASEBITS_XXX]>>(i%BASEBITS_XXX))) & 1;
@@ -1301,12 +1288,14 @@ int BIG_XXX_lastbits(BIG_XXX a,int n)
 /* get 8*MODBYTES size random number */
 void BIG_XXX_random(BIG_XXX m,csprng *rng)
 {
-    int i,b,j=0,r=0;
+    int b;
+    int j=0;
+    int r=0;
     int len=8*MODBYTES_XXX;
 
     BIG_XXX_zero(m);
     /* generate random BIG */
-    for (i=0; i<len; i++)
+    for (int i=0; i<len; i++)
     {
         if (j==0) r=RAND_byte(rng);
         else r>>=1;
@@ -1325,13 +1314,15 @@ void BIG_XXX_random(BIG_XXX m,csprng *rng)
 
 /* get random BIG from rng, modulo q. Done one bit at a time, so its portable */
 
-void BIG_XXX_randomnum(BIG_XXX m,BIG_XXX q,csprng *rng)
+void BIG_XXX_randomnum(BIG_XXX m,const BIG_XXX q,csprng *rng)
 {
-    int i,b,j=0,r=0;
+    int b;
+    int j=0;
+    int r=0;
     DBIG_XXX d;
     BIG_XXX_dzero(d);
     /* generate random DBIG */
-    for (i=0; i<2*BIG_XXX_nbits(q); i++)
+    for (int i=0; i<2*BIG_XXX_nbits(q); i++)
     {
         if (j==0) r=RAND_byte(rng);
         else r>>=1;
@@ -1351,10 +1342,11 @@ void BIG_XXX_randomnum(BIG_XXX m,BIG_XXX q,csprng *rng)
 
 /* Set r=a*b mod m */
 /* SU= 96 */
-void BIG_XXX_modmul(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
+void BIG_XXX_modmul(BIG_XXX r,const BIG_XXX a1,const BIG_XXX b1,const BIG_XXX m)
 {
     DBIG_XXX d;
-    BIG_XXX a,b;
+    BIG_XXX a;
+    BIG_XXX b;
     BIG_XXX_copy(a,a1);
     BIG_XXX_copy(b,b1);
     BIG_XXX_mod(a,m);
@@ -1366,7 +1358,7 @@ void BIG_XXX_modmul(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
 
 /* Set a=a*a mod m */
 /* SU= 88 */
-void BIG_XXX_modsqr(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
+void BIG_XXX_modsqr(BIG_XXX r,const BIG_XXX a1,const BIG_XXX m)
 {
     DBIG_XXX d;
     BIG_XXX a;
@@ -1378,7 +1370,7 @@ void BIG_XXX_modsqr(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
 
 /* Set r=-a mod m */
 /* SU= 16 */
-void BIG_XXX_modneg(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
+void BIG_XXX_modneg(BIG_XXX r,const BIG_XXX a1,const BIG_XXX m)
 {
     BIG_XXX a;
     BIG_XXX_copy(a,a1);
@@ -1388,11 +1380,12 @@ void BIG_XXX_modneg(BIG_XXX r,BIG_XXX a1,BIG_XXX m)
 
 /* Set a=a/b mod m */
 /* SU= 136 */
-void BIG_XXX_moddiv(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
+void BIG_XXX_moddiv(BIG_XXX r,const BIG_XXX a1,const BIG_XXX b1,const BIG_XXX m)
 {
     DBIG_XXX d;
     BIG_XXX z;
-    BIG_XXX a,b;
+    BIG_XXX a;
+    BIG_XXX b;
     BIG_XXX_copy(a,a1);
     BIG_XXX_copy(b,b1);
 
@@ -1406,10 +1399,16 @@ void BIG_XXX_moddiv(BIG_XXX r,BIG_XXX a1,BIG_XXX b1,BIG_XXX m)
 
 /* Get jacobi Symbol (a/p). Returns 0, 1 or -1 */
 /* SU= 216 */
-int BIG_XXX_jacobi(BIG_XXX a,BIG_XXX p)
+int BIG_XXX_jacobi(BIG_XXX a,const BIG_XXX p)
 {
-    int n8,k,m=0;
-    BIG_XXX t,x,n,zilch,one;
+    int n8;
+    int k;
+    int m=0;
+    BIG_XXX t;
+    BIG_XXX x;
+    BIG_XXX n;
+    BIG_XXX zilch;
+    BIG_XXX one;
     BIG_XXX_one(one);
     BIG_XXX_zero(zilch);
     if (BIG_XXX_parity(p)==0 || BIG_XXX_comp(a,zilch)==0 || BIG_XXX_comp(p,one)<=0) return 0;
@@ -1445,7 +1444,11 @@ int BIG_XXX_jacobi(BIG_XXX a,BIG_XXX p)
 /* Arazi and Qi inversion mod 256 */
 static int invmod256(int a)
 {
-    int U,t1,t2,b,c;
+    int U;
+    int t1;
+    int t2;
+    int b;
+    int c;
     t1=0;
     c=(a>>1)&1;
     t1+=c;
@@ -1486,11 +1489,13 @@ static int invmod256(int a)
 /* a=1/a mod 2^BIGBITS. This is very fast! */
 void BIG_XXX_invmod2m(BIG_XXX a)
 {
-    int i;
-    BIG_XXX U,t1,b,c;
+    BIG_XXX U;
+    BIG_XXX t1;
+    BIG_XXX b;
+    BIG_XXX c;
     BIG_XXX_zero(U);
     BIG_XXX_inc(U,invmod256(BIG_XXX_lastbits(a,8)));
-    for (i=8; i<BIGBITS_XXX; i<<=1)
+    for (int i=8; i<BIGBITS_XXX; i<<=1)
     {
         BIG_XXX_norm(U);
         BIG_XXX_copy(b,a);
@@ -1527,10 +1532,18 @@ void BIG_XXX_invmod2m(BIG_XXX a)
 }
 
 /* Set r=1/a mod p. Kaliski method - on entry a < p*/
-void BIG_XXX_invmodp(BIG_XXX r,BIG_XXX a,BIG_XXX p)
+void BIG_XXX_invmodp(BIG_XXX r,const BIG_XXX a,const BIG_XXX p)
 {
-    int k, p1, pu, pv, psw, pmv;
-    BIG_XXX u, v, s, w;
+    int k;
+    int p1;
+    int pu;
+    int pv;
+    int psw;
+    int pmv;
+    BIG_XXX u;
+    BIG_XXX v;
+    BIG_XXX s;
+    BIG_XXX w;
 
     BIG_XXX_copy(u, p);
     BIG_XXX_copy(v, a);
@@ -1609,7 +1622,8 @@ void BIG_XXX_invmodp(BIG_XXX r,BIG_XXX a,BIG_XXX p)
 /* set x = x mod 2^m */
 void BIG_XXX_mod2m(BIG_XXX x,int m)
 {
-    int i,wd,bt;
+    int wd;
+    int bt;
     chunk msk;
     BIG_XXX_norm(x);
 
@@ -1617,13 +1631,14 @@ void BIG_XXX_mod2m(BIG_XXX x,int m)
     bt=m%BASEBITS_XXX;
     msk=((chunk)1<<bt)-1;
     x[wd]&=msk;
-    for (i=wd+1; i<NLEN_XXX; i++) x[i]=0;
+    for (int i=wd+1; i<NLEN_XXX; i++) x[i]=0;
 }
 
 /* set x = x mod 2^m */
 void BIG_XXX_dmod2m(DBIG_XXX x,int m)
 {
-    int i,wd,bt;
+    int wd;
+    int bt;
     chunk msk;
     BIG_XXX_norm(x);
 
@@ -1631,17 +1646,17 @@ void BIG_XXX_dmod2m(DBIG_XXX x,int m)
     bt=m%BASEBITS_XXX;
     msk=((chunk)1<<bt)-1;
     x[wd]&=msk;
-    for (i=wd+1; i<DNLEN_XXX; i++) x[i]=0;
+    for (int i=wd+1; i<DNLEN_XXX; i++) x[i]=0;
 }
 
 // new
 /* Convert to DBIG number from byte array of given length */
-void BIG_XXX_dfromBytesLen(DBIG_XXX a,char *b,int s)
+void BIG_XXX_dfromBytesLen(DBIG_XXX a,const char *b,int s)
 {
-    int i,len=s;
+    int len=s;
     BIG_XXX_dzero(a);
 
-    for (i=0; i<len; i++)
+    for (int i=0; i<len; i++)
     {
         BIG_XXX_dshl(a,8);
         a[0]+=(int)(unsigned char)b[i];
diff --git a/src/bls.c.in b/src/bls.c.in
index 94e6061..623622e 100644
--- a/src/bls.c.in
+++ b/src/bls.c.in
@@ -26,7 +26,7 @@ under the License.
 #include "bls_ZZZ.h"
 
 // Polynomial interpolation coefficients
-static void recover_coefficients(int k, octet* X, BIG_XXX* coefs)
+static void recover_coefficients(int k, const octet* X, BIG_XXX* coefs)
 {
     BIG_XXX r;
     BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
@@ -93,15 +93,14 @@ static void recover_coefficients(int k, octet* X, BIG_XXX* coefs)
 }
 
 /* hash a message, M, to an ECP point, using SHA3 */
-static void BLS_HASHIT(ECP_ZZZ *P,octet *M)
+static void BLS_HASHIT(ECP_ZZZ *P,const octet *M)
 {
-    int i;
     int j;
     sha3 hs;
     char h[MODBYTES_XXX];
     octet HM= {0,sizeof(h),h};
     SHA3_init(&hs,SHAKE256);
-    for (i=0; i<M->len; i++)
+    for (int i=0; i<M->len; i++)
     {
         j = (unsigned char) M->val[i];
         SHA3_process(&hs,j);
@@ -115,7 +114,8 @@ static void BLS_HASHIT(ECP_ZZZ *P,octet *M)
 int BLS_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
 {
     ECP2_ZZZ G;
-    BIG_XXX s,q;
+    BIG_XXX s;
+    BIG_XXX q;
     BIG_XXX_rcopy(q,CURVE_Order_ZZZ);
     ECP2_ZZZ_generator(&G);
 
@@ -138,7 +138,7 @@ int BLS_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
 }
 
 /* Sign message M using private key S to produce signature SIG */
-int BLS_ZZZ_SIGN(octet *SIG,octet *M,octet *S)
+int BLS_ZZZ_SIGN(octet *SIG,const octet *M,const octet *S)
 {
     BIG_XXX s;
     ECP_ZZZ D;
@@ -152,11 +152,13 @@ int BLS_ZZZ_SIGN(octet *SIG,octet *M,octet *S)
 }
 
 /* Verify signature of message M, the signature SIG, and the public key W */
-int BLS_ZZZ_VERIFY(octet *SIG,octet *M,octet *W)
+int BLS_ZZZ_VERIFY(const octet *SIG,const octet *M,const octet *W)
 {
     FP12_YYY v;
-    ECP2_ZZZ G,PK;
-    ECP_ZZZ D,HM;
+    ECP2_ZZZ G;
+    ECP2_ZZZ PK;
+    ECP_ZZZ D;
+    ECP_ZZZ HM;
     BLS_HASHIT(&HM,M);
 
     if (!ECP_ZZZ_fromOctet(&D,SIG))
@@ -183,7 +185,7 @@ int BLS_ZZZ_VERIFY(octet *SIG,octet *M,octet *W)
 }
 
 /* R=R1+R2 in group G1 */
-int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R)
+int BLS_ZZZ_ADD_G1(const octet *R1,const octet *R2,octet *R)
 {
     ECP_ZZZ P;
     ECP_ZZZ T;
@@ -205,7 +207,7 @@ int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R)
 }
 
 /* W=W1+W2 in group G2 */
-int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W)
+int BLS_ZZZ_ADD_G2(const octet *W1,const octet *W2,octet *W)
 {
     ECP2_ZZZ Q;
     ECP2_ZZZ T;
@@ -226,7 +228,7 @@ int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W)
     return BLS_OK;
 }
 
-int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO)
+int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, const octet* SKI, octet* SKO)
 {
     BIG_XXX r;
     BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
@@ -287,7 +289,7 @@ int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SK
     return BLS_OK;
 }
 
-int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK)
+int BLS_ZZZ_RECOVER_SECRET(int k,const octet* X, const octet* Y, octet* SK)
 {
     BIG_XXX r;
     BIG_XXX_rcopy(r,CURVE_Order_ZZZ);
@@ -323,7 +325,7 @@ int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK)
     return BLS_OK;
 }
 
-int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG)
+int BLS_ZZZ_RECOVER_SIGNATURE(int k, const octet* X, const octet* Y, octet* SIG)
 {
     BIG_XXX coefs[k];
     ECP_ZZZ y;
diff --git a/src/bls_ietf.c.in b/src/bls_ietf.c.in
new file mode 100644
index 0000000..1f42936
--- /dev/null
+++ b/src/bls_ietf.c.in
@@ -0,0 +1,1275 @@
+/*
+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.
+*/
+
+/* Boneh-Lynn-Shacham signature 128-bit API */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "config_curve_ZZZ.h"
+#include "hash_to_field_YYY.h"
+
+#if CURVE_SECURITY_ZZZ == 128
+#include "bls_ietf_ZZZ.h"
+#else
+#error "IETF-compliant BLS currently only supports 128-bit security level (i.e. BLS12-381)"
+#endif
+
+int BLS_IETF_ZZZ_keygen(char sk[SK_LEN],
+    const char *ikm,  unsigned int ikmlen,
+    const char *salt, unsigned int saltlen,
+    const char *info, unsigned int infolen)
+{
+
+    if (ikm == NULL || salt == NULL || (info == NULL && infolen))
+        return ERR_NULLPOINTER_BLS;
+    if (ikmlen < 32 || saltlen < SHA256_HASH_SIZE)
+        return ERR_BADARGLEN_BLS;
+
+    int ret;
+    // L = ceil((3 * ceil(log2(r))) / 16) as defined in RFC
+    unsigned int L = (3*(unsigned int)BIG_XXX_nbits(CURVE_Order_ZZZ) + 15) / 16; // 15 is added to ensure ceiling-division
+    char okm[L];
+    char prk[SHA256_HASH_SIZE];
+    char ikm_prime[ikmlen + 1];
+    char info_prime[infolen + 2];
+    char salt_prime[saltlen];
+    BIG_XXX s;
+
+    for(unsigned int i = 0; i < saltlen; i++)
+        salt_prime[i] = salt[i];
+
+    for(unsigned int i = 0; i < ikmlen; i++)
+        ikm_prime[i] = ikm[i];
+    // ikm_prime = ikm || I2OSP(0, 1)
+    ikm_prime[ikmlen] = 0x00;
+
+    for(unsigned int i = 0; i < infolen; i++)
+        info_prime[i] = info[i];
+    // info_prime = info || I2OSP(L, 2)
+    info_prime[infolen]     = (char)(L >> 8);   // most significant byte
+    info_prime[infolen + 1] = (char)(L & 0xff); // least significant byte
+
+    while (1) {
+        // PRK = HKDF-Extract(salt, IKM || I2OSP(0, 1))
+        ret = HKDF_SHA256_extract(prk, salt_prime, saltlen, ikm_prime, ikmlen + 1);
+        // OKM = HKDF-Expand(PRK, key_info || I2OSP(L, 2), L)
+        ret |= HKDF_SHA256_expand(okm, L, prk, SHA256_HASH_SIZE, info_prime, infolen + 2);
+        if (ret != SUCCESS)
+            return ret;
+        // SK = OS2IP(OKM) mod r
+        BIG_XXX_fromBytesLen(s, okm, L);
+        BIG_XXX_mod(s, CURVE_Order_ZZZ);
+        // if SK != 0
+        if (!BIG_XXX_iszilch(s)) {
+            // return SK
+            BIG_XXX_toBytes(okm, s);
+            // SK is only 32-byte long and requires BE encoding
+            for(unsigned int i = 0; i < SK_LEN; i++)
+                sk[i] = okm[L - SK_LEN + i];
+            break;
+        }
+        // salt = H(salt)
+        HASH256_oneshot(salt_prime, salt_prime, saltlen);
+        // the initial saltlen may be greater than the hash size
+        saltlen = SHA256_HASH_SIZE;
+    }
+
+    // zeroize pseudo-random key
+    for(unsigned int i = 0; i < SHA256_HASH_SIZE; i++)
+        prk[i] = 0x00;
+    // zeroize output keying material
+    for(unsigned int i = 0; i < L; i++)
+        okm[i] = 0x00;
+    // zeroize big variable
+    BIG_XXX_zero(s);
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_sk_to_pk_G1(ECP_ZZZ *pk, const char *sk)
+{
+    if (pk == NULL || sk == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX s;
+
+    // s <- SK
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // PK <- G
+    ECP_ZZZ_generator(pk);
+    // PK <- s*G
+    ECP_ZZZ_mul(pk, s);
+    // zeroize big variable
+    BIG_XXX_zero(s);
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_sk_to_pk_G2(ECP2_ZZZ *pk, const char *sk)
+{
+    if (pk == NULL || sk == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX s;
+
+    // s <- SK
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // PK <- G
+    ECP2_ZZZ_generator(pk);
+    // PK <- s*G
+    ECP2_ZZZ_mul(pk, s);
+    // zeroize big variable
+    BIG_XXX_zero(s);
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_serialize_G1(octet *bytes, const ECP_ZZZ *point)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX x;
+    BIG_XXX y;
+
+    if (ECP_ZZZ_get(x, y, point) == -1)
+        return ERR_NOTONCURVE_BLS;
+
+    BIG_XXX_toBytes(bytes->val, x);
+    BIG_XXX_toBytes(bytes->val + BFS_ZZZ, y);
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_deserialize_G1(ECP_ZZZ *point, const octet *bytes)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX x;
+    BIG_XXX y;
+
+    BIG_XXX_fromBytes(x, bytes->val);
+    BIG_XXX_fromBytes(y, bytes->val + BFS_ZZZ);
+
+    if (ECP_ZZZ_set(point, x, y) == 0)
+        return ERR_NOTONCURVE_BLS;
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_serialize_G2(octet *bytes, const ECP2_ZZZ *point)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX b;
+    FP2_YYY qx;
+    FP2_YYY qy;
+
+    if (ECP2_ZZZ_get(&qx, &qy, point) == -1)
+        return ERR_NOTONCURVE_BLS;
+
+    FP_YYY_redc(b, &(qx.b));
+    BIG_XXX_toBytes(bytes->val, b);
+    bytes->len = BFS_ZZZ;
+
+    FP_YYY_redc(b, &(qx.a));
+    BIG_XXX_toBytes(bytes->val + BFS_ZZZ, b);
+    bytes->len += BFS_ZZZ;
+
+    FP_YYY_redc(b, &(qy.b));
+    BIG_XXX_toBytes(bytes->val + 2*BFS_ZZZ, b);
+    bytes->len += BFS_ZZZ;
+
+    FP_YYY_redc(b, &(qy.a));
+    BIG_XXX_toBytes(bytes->val + 3*BFS_ZZZ, b);
+    bytes->len += BFS_ZZZ;
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_deserialize_G2(ECP2_ZZZ *point, const octet *bytes)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX re;
+    BIG_XXX im;
+    FP2_YYY x;
+    FP2_YYY y;
+
+    // First FP2 element
+    BIG_XXX_fromBytes(im, bytes->val);
+    BIG_XXX_fromBytes(re, bytes->val + BFS_ZZZ);
+    FP2_YYY_from_BIGs(&x, re, im);
+
+    // Second FP2 element
+    BIG_XXX_fromBytes(im, bytes->val + 2*BFS_ZZZ);
+    BIG_XXX_fromBytes(re, bytes->val + 3*BFS_ZZZ);
+    FP2_YYY_from_BIGs(&y, re, im);
+
+    if (ECP2_ZZZ_set(point, &x, &y) == 0)
+        return ERR_NOTONCURVE_BLS;
+
+    return SUCCESS;
+}
+
+/**
+ * @brief Indicates if given a y-coordinate is the lexicographically greatest
+ * as well as its parity.
+ *
+ * @param y y-coordinate
+ *
+ * @return A 2-bit value where:
+ * - the most-significant bit is set to 1 if the y-coordinate is the
+ * lexicographically largest of the two associated with its x-coordinate.
+ * - the least-significant bit is set to 1 if the y-coordinate is odd.
+ */
+static int sgn0_big(const BIG_XXX y)
+{
+    int i;
+    int carry;
+    int ret;
+    chunk borrow;
+    chunk chunkx;
+    BIG_XXX tmp;
+
+    ret = y[0] & 1;
+
+    for (carry=0, i=0; i<NLEN_XXX; i++) {
+        tmp[i] = (y[i] << 1) | carry;
+        carry = y[i] >> (BASEBITS_XXX - 1);
+    }
+
+    for (borrow=0, i=0; i<NLEN_XXX; i++) {
+        chunkx = tmp[i] - (Modulus_ZZZ[i] + borrow);
+        borrow = (chunkx >> BASEBITS_XXX) & 1;
+    }
+
+    ret |= ((carry - (int)borrow) & 2) ^ 2;
+
+    return ret;
+}
+
+/**
+ * @brief Indicates if given a y-coordinate (FP2 element) is the
+ * lexicographically greatest as well as its parity.
+ *
+ * @param y y-coordinate
+ *
+ * @return A 2-bit value where:
+ * - the most-significant bit is set to 1 if the y-coordinate is the
+ * lexicographically largest of the two associated with its x-coordinate.
+ * - the least-significant bit is set to 1 if the y-coordinate is odd.
+ */
+static int sgn0_fp2(const FP2_YYY y)
+{
+    int re;
+    int im;
+    int sign;
+    int prty;
+
+    BIG_XXX a;
+    BIG_XXX b;
+
+    FP_YYY_redc(a, &(y.a));
+    FP_YYY_redc(b, &(y.b));
+
+    re = sgn0_big(a);
+    im = sgn0_big(b);
+
+    // y->b != 0 ? sgn0_big(y->b) : sgn0_big(a->a)
+    sign = 0 - BIG_XXX_iszilch(b);
+    sign = (re & sign) | (im & ~sign);
+
+    // y->a == 0 ? prty(y->b) : prty(a->a)
+    prty = 0 - BIG_XXX_iszilch(a);
+    prty = (im & prty) | (re & ~prty);
+
+    return (sign & 2) | (prty & 1);
+}
+
+int BLS_IETF_ZZZ_compress_G1(octet *bytes, const ECP_ZZZ *point)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int sign;
+    BIG_XXX x;
+    BIG_XXX y;
+
+    if (ECP_ZZZ_isinf(point)) {
+        for(int i = 0; i < BFS_ZZZ; i++)
+            bytes->val[i] = 0x00;
+        bytes->val[0] = 0xc0; // compressed and infinity bits
+    } else {
+        if (ECP_ZZZ_get(x, y, point) == -1)
+            return ERR_NOTONCURVE_BLS;
+        BIG_XXX_toBytes(bytes->val, x);
+        sign = sgn0_big(y);
+        bytes->val[0] |= (unsigned char)(0x80 | ((sign & 2) << 4)); // compressed and not infinity
+    }
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_uncompress_G1(ECP_ZZZ *point, const octet *bytes)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if ((bytes->val[0] & 0x80) == 0x00)
+        return ERR_BADENCODING_BLS;
+
+    int sign;
+    BIG_XXX a;
+    BIG_XXX b;
+    FP_YYY x;
+    FP_YYY y;
+    char bytes_prime[BFS_ZZZ];
+
+    if (bytes->val[0] & 0x40) {
+        /**
+         * Ensure that all bytes are equal to zero
+         */
+        if ((bytes->val[0] & 0x3f) != 0x00)
+            return ERR_BADENCODING_BLS;
+        for(int i = 1; i < BFS_ZZZ; i++) {
+            if ((bytes->val[i]) != 0x00)
+                return ERR_BADENCODING_BLS;
+        }
+        ECP_ZZZ_inf(point);
+        return SUCCESS;
+    }
+
+    for(int i = 0; i < BFS_ZZZ; i++)
+        bytes_prime[i] = bytes->val[i];
+    bytes_prime[0] &= 0x1f; //discard top 3 bits
+
+    BIG_XXX_fromBytes(a, bytes_prime);
+    FP_YYY_nres(&x, a);
+
+    ECP_ZZZ_rhs(&y, &x);
+    FP_YYY_sqrt(&y, &y);
+    FP_YYY_redc(b, &y);
+
+    sign = sgn0_big(b);
+    sign >>= 1; // discard parity bit
+    if (sign != ((bytes->val[0] & 0x20) >> 5)) {
+        FP_YYY_neg(&y, &y);
+        FP_YYY_redc(b, &y);
+    }
+
+    if (ECP_ZZZ_set(point, a, b) == 0)
+        return ERR_NOTONCURVE_BLS;
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_compress_G2(octet *bytes, const ECP2_ZZZ *point)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int sign;
+    BIG_XXX b;
+    FP2_YYY x;
+    FP2_YYY y;
+
+    if (ECP2_ZZZ_isinf(point)) {
+        for(int i = 1; i < 2*BFS_ZZZ; i++)
+            bytes->val[i] = 0x00;
+        bytes->val[0] = 0xc0; // compressed and infinity bits
+    } else {
+        if (ECP2_ZZZ_get(&x, &y, point) == -1)
+            return ERR_NOTONCURVE_BLS;
+
+        FP_YYY_redc(b, &(x.b));
+        BIG_XXX_toBytes(bytes->val, b);
+
+        FP_YYY_redc(b, &(x.a));
+        BIG_XXX_toBytes(bytes->val + BFS_ZZZ, b);
+
+        sign = sgn0_fp2(y);
+        bytes->val[0] |= (unsigned char)(0x80 | ((sign & 2) << 4)); // compressed and not infinity
+    }
+
+    return SUCCESS;
+}
+
+int BLS_IETF_ZZZ_uncompress_G2(ECP2_ZZZ *point, const octet *bytes)
+{
+    if (bytes == NULL || point == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if ((bytes->val[0] & 0x80) == 0x00)
+        return ERR_BADENCODING_BLS;
+
+    int sign;
+    BIG_XXX re;
+    BIG_XXX im;
+    FP2_YYY x;
+    FP2_YYY y;
+    char bytes_prime[2*BFS_ZZZ];
+
+    if (bytes->val[0] & 0x40) {
+        /**
+         * Ensure that all bytes are equal to zero
+         */
+        if ((bytes->val[0] & 0x3f) != 0x00)
+            return ERR_BADENCODING_BLS;
+        for(int i = 1; i < 2*BFS_ZZZ; i++) {
+            if ((bytes->val[i]) != 0x00)
+                return ERR_BADENCODING_BLS;
+        }
+        ECP2_ZZZ_inf(point);
+        return SUCCESS;
+    }
+
+    for(int i = 0; i < 2*BFS_ZZZ; i++)
+        bytes_prime[i] = bytes->val[i];
+    bytes_prime[0] &= 0x1f; //discard top 3 bits
+
+    BIG_XXX_fromBytes(im, bytes_prime);
+    BIG_XXX_fromBytes(re, bytes_prime + BFS_ZZZ);
+    FP2_YYY_from_BIGs(&x, re, im);
+
+    ECP2_ZZZ_rhs(&y, &x);
+    FP2_YYY_sqrt(&y, &y);
+
+    sign = sgn0_fp2(y);
+    sign >>= 1; // discard parity bit
+    if (sign != ((bytes->val[0] & 0x20) >> 5))
+        FP2_YYY_neg(&y, &y);
+
+    if (ECP2_ZZZ_set(point, &x, &y) == 0)
+        return ERR_NOTONCURVE_BLS;
+
+    return SUCCESS;
+}
+
+/**
+ * @brief Calculates the 11-isogeny mapping for BLS12-381 G1.
+ *
+ * @param P Output point
+ * @param x_prime x-coordinate of input point
+ * @param y_prime y-coordinate of input point
+ *
+ * @return 0 if successful, error code otherwise
+ */
+static int iso11_to_ecp(ECP_ZZZ *P, FP_YYY x_prime, FP_YYY y_prime)
+{
+    if (P == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX x;
+    BIG_XXX y;
+    FP_YYY k;
+    FP_YYY xnum;
+    FP_YYY xden;
+    FP_YYY ynum;
+    FP_YYY yden;
+
+    FP_YYY_zero(&xnum);
+    FP_YYY_zero(&ynum);
+    FP_YYY_copy(&xden, &x_prime);
+    FP_YYY_copy(&yden, &x_prime);
+
+    // x_num = k_(1,11) * x'^11 + k_(1,10) * x'^10 + k_(1,9) * x'^9 + ... + k_(1,0)
+    for(int i = 11; i > 0; i--) {
+        FP_YYY_nres(&k, ISO11_XNUM_BLS381[i]);
+        FP_YYY_add(&xnum, &xnum, &k);
+        FP_YYY_mul(&xnum, &xnum, &x_prime);
+    }
+    FP_YYY_nres(&k, ISO11_XNUM_BLS381[0]);
+    FP_YYY_add(&xnum, &xnum, &k);
+
+    // x_den = x'^10 + k_(2,9) * x'^9 + k_(2,8) * x'^8 + ... + k_(2,0)
+    for(int i = 9; i > 0; i--) {
+        FP_YYY_nres(&k, ISO11_XDEN_BLS381[i]);
+        FP_YYY_add(&xden, &xden, &k);
+        FP_YYY_mul(&xden, &xden, &x_prime);
+    }
+    FP_YYY_nres(&k, ISO11_XDEN_BLS381[0]);
+    FP_YYY_add(&xden, &xden, &k);
+
+    // y_num = k_(3,15) * x'^15 + k_(3,14) * x'^14 + k_(3,13) * x'^13 + ... + k_(3,0)
+    for(int i = 15; i > 0; i--) {
+        FP_YYY_nres(&k, ISO11_YNUM_BLS381[i]);
+        FP_YYY_add(&ynum, &ynum, &k);
+        FP_YYY_mul(&ynum, &ynum, &x_prime);
+    }
+    FP_YYY_nres(&k, ISO11_YNUM_BLS381[0]);
+    FP_YYY_add(&ynum, &ynum, &k);
+
+    // y_den = x'^15 + k_(4,14) * x'^14 + k_(4,13) * x'^13 + ... + k_(4,0)
+    for(int i = 14; i > 0; i--) {
+        FP_YYY_nres(&k, ISO11_YDEN_BLS381[i]);
+        FP_YYY_add(&yden, &yden, &k);
+        FP_YYY_mul(&yden, &yden, &x_prime);
+    }
+    FP_YYY_nres(&k, ISO11_YDEN_BLS381[0]);
+    FP_YYY_add(&yden, &yden, &k);
+
+    // x = x_num / x_den
+    FP_YYY_inv(&xden, &xden);
+    FP_YYY_mul(&xnum, &xnum, &xden);
+    // y = y' * y_num / y_den
+    FP_YYY_inv(&yden, &yden);
+    FP_YYY_mul(&ynum, &ynum, &yden);
+    FP_YYY_mul(&ynum, &ynum, &y_prime);
+    // P = (x, y)
+    FP_YYY_redc(x, &xnum);
+    FP_YYY_redc(y, &ynum);
+    if (ECP_ZZZ_set(P, x, y) == 0)
+        return ERR_NOTONCURVE_BLS;
+
+    return SUCCESS;
+}
+
+/**
+ * @brief Calculates the 3-isogeny mapping for BLS12-381 G2.
+ *
+ * @param P Output point
+ * @param x_prime x-coordinate of input point
+ * @param y_prime y-coordinate of input point
+ *
+ * @return 0 if successful, error code otherwise
+ */
+static int iso3_to_ecp(ECP2_ZZZ *P, FP2_YYY x_prime, FP2_YYY y_prime)
+{
+    if (P == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    FP2_YYY k;
+    FP2_YYY xnum;
+    FP2_YYY xden;
+    FP2_YYY ynum;
+    FP2_YYY yden;
+
+    FP2_YYY_zero(&xnum);
+    FP2_YYY_zero(&ynum);
+    FP2_YYY_copy(&yden, &x_prime);
+
+    // x_num = k_(1,3) * x'^3 + k_(1,2) * x'^2 + k_(1,1) * x' + k_(1,0)
+    for(int i = 3; i > 0; i--) {
+        FP2_YYY_from_BIGs(&k, ISO3_XNUMre_BLS381[i], ISO3_XNUMim_BLS381[i]);
+        FP2_YYY_add(&xnum, &xnum, &k);
+        FP2_YYY_mul(&xnum, &xnum, &x_prime);
+    }
+    FP2_YYY_from_BIGs(&k, ISO3_XNUMre_BLS381[0], ISO3_XNUMim_BLS381[0]);
+    FP2_YYY_add(&xnum, &xnum, &k);
+
+    // x_den = x'^2 + k_(2,1) * x' + k_(2,0)
+    FP2_YYY_from_BIGs(&k, ISO3_XDENre_BLS381[1], ISO3_XDENim_BLS381[1]);
+    FP2_YYY_add(&xden, &x_prime, &k);
+    FP2_YYY_mul(&xden, &xden, &x_prime);
+    FP2_YYY_from_BIGs(&k, ISO3_XDENre_BLS381[0], ISO3_XDENim_BLS381[0]);
+    FP2_YYY_add(&xden, &xden, &k);
+
+    // y_num = k_(3,3) * x'^3 + k_(3,2) * x'^2 + k_(3,1) * x' + k_(3,0)
+    for(int i = 3; i > 0; i--) {
+        FP2_YYY_from_BIGs(&k, ISO3_YNUMre_BLS381[i], ISO3_YNUMim_BLS381[i]);
+        FP2_YYY_add(&ynum, &ynum, &k);
+        FP2_YYY_mul(&ynum, &ynum, &x_prime);
+    }
+    FP2_YYY_from_BIGs(&k, ISO3_YNUMre_BLS381[0], ISO3_YNUMim_BLS381[0]);
+    FP2_YYY_add(&ynum, &ynum, &k);
+
+    // y_den = x'^3 + k_(4,2) * x'^2 + k_(4,1) * x' + k_(4,0)
+    for(int i = 2; i > 0; i--) {
+        FP2_YYY_from_BIGs(&k, ISO3_YDENre_BLS381[i], ISO3_YDENim_BLS381[i]);
+        FP2_YYY_add(&yden, &yden, &k);
+        FP2_YYY_mul(&yden, &yden, &x_prime);
+    }
+    FP2_YYY_from_BIGs(&k, ISO3_YDENre_BLS381[0], ISO3_YDENim_BLS381[0]);
+    FP2_YYY_add(&yden, &yden, &k);
+
+    // x = x_num / x_den
+    FP2_YYY_inv(&xden, &xden);
+    FP2_YYY_mul(&xnum, &xnum, &xden);
+    // y = y' * y_num / y_den
+    FP2_YYY_inv(&yden, &yden);
+    FP2_YYY_mul(&ynum, &ynum, &yden);
+    FP2_YYY_mul(&ynum, &ynum, &y_prime);
+    // P = (x, y)
+    ECP2_ZZZ_set(P, &xnum, &ynum);
+
+    return SUCCESS;
+}
+
+/**
+ * @brief Calculates a point on the elliptic curve E from an element of the finite field F over which E is defined.
+ * Follows the Simplified SWU for AB == 0 method as defined at
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-for-ab-0 (ยง 6.6.3)
+ *
+ * @param P Output EC point
+ * @param u Input finite field element
+ *
+ * @return 0 if successful, error code otherwise
+ */
+static int map_to_curve_G1(ECP_ZZZ *P, FP_YYY u)
+{
+    if (P == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    FP_YYY x;
+    FP_YYY y;
+    int ret = SUCCESS;
+
+    // (x, y) = map_to_curve_simple_swu(u)
+    ret |= ECP_ZZZ_sswu(&x, &y, u);
+    // P = (x, y) = iso_map(x, y)
+    ret |= iso11_to_ecp(P, x, y);
+
+    return ret;
+}
+
+/**
+ * @brief Calculates a point on the elliptic curve from a quadratic extension field element.
+ * Follows the Simplified SWU for AB == 0 method as defined at
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-simplified-swu-for-ab-0
+ *
+ * @param P Output EC point
+ * @param u Input finite field element
+ *
+ * @return 0 if successful, error code otherwise
+ */
+static int map_to_curve_G2(ECP2_ZZZ *P, FP2_YYY u)
+{
+    if (P == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    FP2_YYY x;
+    FP2_YYY y;
+
+    // (x, y) = map_to_curve_simple_swu(u)
+    ret |= ECP2_ZZZ_sswu(&x, &y, u);
+    // P = (x, y) = iso_map(x, y)
+    ret |= iso3_to_ecp(P, x, y);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_hash2curve_G1(ECP_ZZZ *P, const octet *msg, const octet *dst)
+{
+    if (P == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX elems[2];
+    FP_YYY u;
+    ECP_ZZZ Q;
+    int ret = SUCCESS;
+
+    // u = hash_to_field(msg, 2)
+    ret |= hash_to_field_YYY(elems, 2, 1, msg->val, msg->len, dst->val, dst->len);
+    // P = map_to_curve(u[0])
+    FP_YYY_nres(&u, elems[0]);
+    ret |= map_to_curve_G1(P, u);
+    // Q = map_to_curve(u[1])
+    FP_YYY_nres(&u, elems[1]);
+    ret |= map_to_curve_G1(&Q, u);
+    // P = P + Q
+    ECP_ZZZ_add(P, &Q);
+    // P = clear_cofactor(P)
+    ECP_ZZZ_mul(P, H_EFF_G1);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_encode2curve_G1(ECP_ZZZ *P, const octet *msg, const octet *dst)
+{
+    if (P == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX elems;
+    FP_YYY u;
+    int ret = SUCCESS;
+
+    // u = hash_to_field(msg, 1)
+    ret |= hash_to_field_YYY(&elems, 1, 1, msg->val, msg->len, dst->val, dst->len);
+    //P = map_to_curve(u[0])
+    FP_YYY_nres(&u, elems);
+    ret |= map_to_curve_G1(P, u);
+    // P = P = clear_cofactor(P)
+    ECP_ZZZ_mul(P, H_EFF_G1);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_hash2curve_G2(ECP2_ZZZ *P, const octet *msg, const octet *dst)
+{
+    if (P == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    BIG_XXX elems[4];
+    FP2_YYY u;
+    ECP2_ZZZ Q;
+
+    // u = hash_to_field(msg, 2)
+    ret |= hash_to_field_YYY(elems, 2, 2, msg->val, msg->len, dst->val, dst->len);
+    // P = map_to_curve(u[0])
+    FP2_YYY_from_BIGs(&u, elems[0], elems[1]);
+    ret |= map_to_curve_G2(P, u);
+    // Q = map_to_curve(u[1])
+    FP2_YYY_from_BIGs(&u, elems[2], elems[3]);
+    ret |= map_to_curve_G2(&Q, u);
+    // P = P + Q
+    ECP2_ZZZ_add(P, &Q);
+    // P = clear_cofactor(P)
+    ret |= ECP2_ZZZ_clearcofactor(P);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_encode2curve_G2(ECP2_ZZZ *P, const octet *msg, const octet *dst)
+{
+    if (P == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    BIG_XXX elems[2];
+    FP2_YYY u;
+
+    // u = hash_to_field(msg, 1)
+    ret |= hash_to_field_YYY(elems, 1, 2, msg->val, msg->len, dst->val, dst->len);
+    // P = map_to_curve(u[0])
+    FP2_YYY_from_BIGs(&u, elems[0], elems[1]);
+    ret |= map_to_curve_G2(P, u);
+    // P = clear_cofactor(P)
+    ret |= ECP2_ZZZ_clearcofactor(P);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_core_sign_G1(octet *sig, const char *sk, const octet *msg, const octet *dst)
+{
+    if (sig == NULL || sk == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX s;
+    ECP_ZZZ Q;
+    int ret = SUCCESS;
+
+    // s <- SK
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // Q <- hash_to_point(msg)
+    ret |= BLS_IETF_ZZZ_hash2curve_G1(&Q, msg, dst);
+    // Q <- s*Q
+    PAIR_ZZZ_G1mul(&Q, s);
+    // sig <- point_to_signature(Q)
+    ret |= BLS_IETF_ZZZ_compress_G1(sig, &Q);
+    // zeroization
+    BIG_XXX_zero(s);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_core_sign_G2(octet *sig, const char *sk, const octet *msg, const octet *dst)
+{
+    if (sig == NULL || sk == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    BIG_XXX s;
+    ECP2_ZZZ Q;
+    int ret = SUCCESS;
+
+    // s <- SK
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // Q <- hash_to_point(msg)
+    ret |= BLS_IETF_ZZZ_hash2curve_G2(&Q, msg, dst);
+    // Q <- s*Q
+    PAIR_ZZZ_G2mul(&Q, s);
+    // sig <- point_to_signature(Q)
+    ret |= BLS_IETF_ZZZ_compress_G2(sig, &Q);
+    // zeroization
+    BIG_XXX_zero(s);
+
+    return ret;
+}
+
+// TODO: Implement a faster variant based on https://eprint.iacr.org/2019/814
+static inline int subgroup_check_G1(ECP_ZZZ P)
+{
+    ECP_ZZZ_mul(&P, CURVE_Order_ZZZ);
+    return ECP_ZZZ_isinf(&P);
+}
+
+// TODO: Implement a faster variant based on https://eprint.iacr.org/2019/814
+static inline int subgroup_check_G2(ECP2_ZZZ P)
+{
+    ECP2_ZZZ_mul(&P, CURVE_Order_ZZZ);
+    return ECP2_ZZZ_isinf(&P);
+}
+
+int BLS_IETF_ZZZ_core_verify_G1(const octet *sig, const ECP2_ZZZ *PK, const octet *msg, const octet *dst)
+{
+    if (sig == NULL || PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    ECP_ZZZ  Q;
+    ECP_ZZZ  R;
+    ECP2_ZZZ P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+
+    // R <- signature_to_point(sig)
+    ret |= BLS_IETF_ZZZ_uncompress_G1(&R, sig);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+
+    if (!subgroup_check_G1(R))
+        return ERR_NOTONCURVE_BLS;
+
+    if(ECP2_ZZZ_isinf(PK) || !subgroup_check_G2(*PK))
+        return ERR_INVALIDPUBKEY_BLS;
+
+    // Q <- hash_to_point(msg)
+    ret |= BLS_IETF_ZZZ_hash2curve_G1(&Q, msg, dst);
+
+    // pairing protocol according to https://eprint.iacr.org/2019/077.pdf
+    ECP2_ZZZ_generator(&P);
+    ECP2_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    PAIR_ZZZ_another(acc, &P, &R);
+    PAIR_ZZZ_another(acc, PK, &Q);
+    PAIR_ZZZ_miller(&f, acc);
+    PAIR_ZZZ_fexp(&f);
+
+    // ensure that pairing(Q, PK) * pairing(R, -P) == 1
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADSIGNATURE_BLS;
+
+    return ret;
+}
+
+
+int BLS_IETF_ZZZ_core_verify_G2(const octet *sig, const ECP_ZZZ *PK, const octet *msg, const octet *dst)
+{
+    if (sig == NULL || PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    ECP2_ZZZ Q;
+    ECP2_ZZZ R;
+    ECP_ZZZ  P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+
+    // R <- signature_to_point(sig)
+    ret |= BLS_IETF_ZZZ_uncompress_G2(&R, sig);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+
+    if (!subgroup_check_G2(R))
+        return ERR_NOTONCURVE_BLS;
+
+    if(ECP_ZZZ_isinf(PK) || !subgroup_check_G1(*PK))
+        return ERR_INVALIDPUBKEY_BLS;
+
+    // Q <- hash_to_point(msg)
+    ret |= BLS_IETF_ZZZ_hash2curve_G2(&Q, msg, dst);
+
+    // pairing protocol according to https://eprint.iacr.org/2019/077.pdf
+    ECP_ZZZ_generator(&P);
+    ECP_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    PAIR_ZZZ_another(acc, &R, &P);
+    PAIR_ZZZ_another(acc, &Q, PK);
+    PAIR_ZZZ_miller(&f, acc);
+    PAIR_ZZZ_fexp(&f);
+
+    // ensure that pairing(Q, PK) * pairing(R, -P) == 1
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADSIGNATURE_BLS;
+
+    return ret;
+}
+
+
+int BLS_IETF_ZZZ_aggregate_G1(octet *out, const octet *in, unsigned int n)
+{
+    if (out == NULL || in == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    int ret = SUCCESS;
+    ECP_ZZZ  A;
+    ECP_ZZZ  B;
+
+    // A <- signature_to_point(in)
+    ret |= BLS_IETF_ZZZ_uncompress_G1(&A, in);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+
+    for (unsigned int i = 1; i < n; i++) {
+        // B <- signature_to_point(in + i)
+        ret |= BLS_IETF_ZZZ_uncompress_G1(&B, in + i);
+        if (ret != SUCCESS)
+            return ERR_BADSIGNATURE_BLS;
+        // A <- A + B
+        ECP_ZZZ_add(&A, &B);
+    }
+
+    // out <- point_to_signature(A)
+    ret |= BLS_IETF_ZZZ_compress_G1(out, &A);
+    return ret;
+}
+
+int BLS_IETF_ZZZ_aggregate_G2(octet *out, const octet *in, unsigned int n)
+{
+    if (out == NULL || in == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    int ret = SUCCESS;
+    ECP2_ZZZ  A;
+    ECP2_ZZZ  B;
+
+    // A <- signature_to_point(in)
+    ret |= BLS_IETF_ZZZ_uncompress_G2(&A, in);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+    for (unsigned int i = 1; i < n; i++) {
+        // B <- signature_to_point(in + i)
+        ret |= BLS_IETF_ZZZ_uncompress_G2(&B, in + i);
+        if (ret != SUCCESS)
+            return ERR_BADSIGNATURE_BLS;
+        // A <- A + B
+        ECP2_ZZZ_add(&A, &B);
+    }
+
+    // out <- point_to_signature(A)
+    ret |= BLS_IETF_ZZZ_compress_G2(out, &A);
+    return ret;
+}
+
+int BLS_IETF_ZZZ_core_aggregate_verify_G1(const octet *sig, const ECP2_ZZZ PK[], const octet msg[], unsigned int n, const octet *dst)
+{
+    if (sig == NULL || PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    int ret = SUCCESS;
+    ECP_ZZZ  Q;
+    ECP_ZZZ  R;
+    ECP2_ZZZ P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+
+    // R <- signature_to_point(sig)
+    ret |= BLS_IETF_ZZZ_uncompress_G1(&R, sig);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+
+    if (!subgroup_check_G1(R))
+        return ERR_NOTONCURVE_BLS;
+
+    // initialize the pairing protocol
+    ECP2_ZZZ_generator(&P);
+    ECP2_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    PAIR_ZZZ_another(acc, &P, &R);
+
+    for (unsigned int i = 0; i < n; i++) {
+        if(ECP2_ZZZ_isinf(PK + i) || !subgroup_check_G2(PK[i]))
+            return ERR_INVALIDPUBKEY_BLS;
+        if (ret != SUCCESS)
+            return ERR_BADSIGNATURE_BLS;
+        // Q <- hash_to_point(msg)
+        ret |= BLS_IETF_ZZZ_hash2curve_G1(&Q, msg + i, dst);
+        PAIR_ZZZ_another(acc, PK + i, &Q);
+
+    }
+
+    PAIR_ZZZ_miller(&f, acc);
+    PAIR_ZZZ_fexp(&f);
+
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADSIGNATURE_BLS;
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_core_aggregate_verify_G2(const octet *sig, const ECP_ZZZ PK[], const octet msg[], unsigned int n, const octet *dst)
+{
+    if (sig == NULL || PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    int ret = SUCCESS;
+    ECP2_ZZZ Q;
+    ECP2_ZZZ R;
+    ECP_ZZZ  P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+
+    // R <- signature_to_point(sig)
+    ret |= BLS_IETF_ZZZ_uncompress_G2(&R, sig);
+    if (ret != SUCCESS)
+        return ERR_BADSIGNATURE_BLS;
+
+    if (!subgroup_check_G2(R))
+        return ERR_NOTONCURVE_BLS;
+
+    // initialize the pairing protocol
+    ECP_ZZZ_generator(&P);
+    ECP_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    PAIR_ZZZ_another(acc, &R, &P);
+
+    for (unsigned int i = 0; i < n; i++) {
+        if(ECP_ZZZ_isinf(PK + i) || !subgroup_check_G1(PK[i]))
+            return ERR_INVALIDPUBKEY_BLS;
+        if (ret != SUCCESS)
+            return ERR_BADSIGNATURE_BLS;
+        // Q <- hash_to_point(msg)
+        ret |= BLS_IETF_ZZZ_hash2curve_G2(&Q, msg + i, dst);
+        PAIR_ZZZ_another(acc, &Q, PK + i);
+
+    }
+
+    PAIR_ZZZ_miller(&f, acc);
+    PAIR_ZZZ_fexp(&f);
+
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADSIGNATURE_BLS;
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_pop_prove_G1(octet *proof, const char *sk)
+{
+    if (proof == NULL || sk == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    BIG_XXX s;
+    ECP_ZZZ Q;
+    ECP2_ZZZ PK;
+    char dst[43]  = "BLS_POP_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_";
+    octet dst_oct = {43, 43, dst};
+    char pubkey[2*BFS_ZZZ];
+    octet pk_oct  = {2*BFS_ZZZ, 2*BFS_ZZZ, pubkey};
+
+    // s <- sk
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // PK <- SkToPk(sk)
+    ret |= BLS_IETF_ZZZ_sk_to_pk_G2(&PK, sk);
+    ret |= BLS_IETF_ZZZ_compress_G2(&pk_oct, &PK);
+    // Q <- hash_pubkey_to_point(PK)
+    ret |= BLS_IETF_ZZZ_hash2curve_G1(&Q, &pk_oct, &dst_oct);
+    // Q <- s*Q
+    ECP_ZZZ_mul(&Q, s);
+    // proof <- point_to_signature(Q)
+    ret |= BLS_IETF_ZZZ_compress_G1(proof, &Q);
+    // zeroize big variable
+    BIG_XXX_zero(s);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_pop_prove_G2(octet *proof, const char *sk)
+{
+    if (proof == NULL || sk == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    BIG_XXX s;
+    ECP2_ZZZ Q;
+    ECP_ZZZ PK;
+    char dst[43]  = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
+    octet dst_oct = {43, 43, dst};
+    char pubkey[BFS_ZZZ];
+    octet pk_oct  = {BFS_ZZZ, BFS_ZZZ, pubkey};
+
+    // s <- sk
+    BIG_XXX_fromBytesLen(s, sk, SK_LEN);
+    // PK <- SkToPk(sk)
+    ret |= BLS_IETF_ZZZ_sk_to_pk_G1(&PK, sk);
+    ret |= BLS_IETF_ZZZ_compress_G1(&pk_oct, &PK);
+    // Q <- hash_pubkey_to_point(PK)
+    ret |= BLS_IETF_ZZZ_hash2curve_G2(&Q, &pk_oct, &dst_oct);
+    // Q <- s*Q
+    ECP2_ZZZ_mul(&Q, s);
+    // proof <- point_to_signature(Q)
+    ret |= BLS_IETF_ZZZ_compress_G2(proof, &Q);
+    // zeroize big variable
+    BIG_XXX_zero(s);
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_pop_verify_G1(const octet *proof, const ECP2_ZZZ *PK)
+{
+    if (proof == NULL || PK == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    ECP_ZZZ  Q;
+    ECP_ZZZ  R;
+    ECP2_ZZZ P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+    char dst[43]  = "BLS_POP_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_";
+    octet dst_oct = {43, 43, dst};
+    char pubkey[2*BFS_ZZZ];
+    octet pk_oct  = {2*BFS_ZZZ, 2*BFS_ZZZ, pubkey};
+
+    // R <- signature_to_point(proof)
+    ret |= BLS_IETF_ZZZ_uncompress_G1(&R, proof);
+    if (ret != SUCCESS)
+        return ERR_BADPOP_BLS;
+
+    if (!subgroup_check_G1(R))
+        return ERR_NOTONCURVE_BLS;
+
+    if(ECP2_ZZZ_isinf(PK) || !subgroup_check_G2(*PK))
+        return ERR_INVALIDPUBKEY_BLS;
+
+    // Q <- hash_pubkey_to_point(PK)
+    ret |= BLS_IETF_ZZZ_compress_G2(&pk_oct, PK);
+    ret |= BLS_IETF_ZZZ_hash2curve_G1(&Q, &pk_oct, &dst_oct);
+
+    // pairing protocol according to https://eprint.iacr.org/2019/077.pdf
+    ECP2_ZZZ_generator(&P);
+    ECP2_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    // accumulate 1st pairing(R, -P)
+    PAIR_ZZZ_another(acc, &P, &R);
+    // accumulate 2nd pairing(Q, PK)
+    PAIR_ZZZ_another(acc, PK, &Q);
+    // combined Miller loop calculation
+    PAIR_ZZZ_miller(&f, acc);
+    // final exponentiation
+    PAIR_ZZZ_fexp(&f);
+
+    // ensure that pairing(Q, PK) * pairing(R, -P) == 1
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADPOP_BLS;
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_pop_verify_G2(const octet *proof, const ECP_ZZZ *PK)
+{
+    if (proof == NULL || PK == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    int ret = SUCCESS;
+    ECP2_ZZZ Q;
+    ECP2_ZZZ R;
+    ECP_ZZZ  P;
+    FP12_YYY f;
+    FP12_YYY acc[ATE_BITS_ZZZ];
+    char dst[43]  = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
+    octet dst_oct = {43, 43, dst};
+    char pubkey[BFS_ZZZ];
+    octet pk_oct  = {BFS_ZZZ, BFS_ZZZ, pubkey};
+
+    // R <- signature_to_point(proof)
+    ret |= BLS_IETF_ZZZ_uncompress_G2(&R, proof);
+    if (ret != SUCCESS)
+        return ERR_BADPOP_BLS;
+
+    if (!subgroup_check_G2(R))
+        return ERR_NOTONCURVE_BLS;
+
+    if(ECP_ZZZ_isinf(PK) || !subgroup_check_G1(*PK))
+        return ERR_INVALIDPUBKEY_BLS;
+
+    // Q <- hash_pubkey_to_point(PK)
+    ret |= BLS_IETF_ZZZ_compress_G1(&pk_oct, PK);
+    ret |= BLS_IETF_ZZZ_hash2curve_G2(&Q, &pk_oct, &dst_oct);
+
+    // pairing protocol according to https://eprint.iacr.org/2019/077.pdf
+    ECP_ZZZ_generator(&P);
+    ECP_ZZZ_neg(&P);
+    PAIR_ZZZ_initmp(acc);
+    // accumulate 1st pairing(R, -P)
+    PAIR_ZZZ_another(acc, &R, &P);
+    // accumulate 2nd pairing(Q, PK)
+    PAIR_ZZZ_another(acc, &Q, PK);
+    // combined Miller loop calculation
+    PAIR_ZZZ_miller(&f, acc);
+    // final exponentiation
+    PAIR_ZZZ_fexp(&f);
+
+    // ensure that pairing(Q, PK) * pairing(R, -P) == 1
+    if (!FP12_YYY_isunity(&f))
+        return ERR_BADPOP_BLS;
+
+    return ret;
+}
+
+int BLS_IETF_ZZZ_fast_aggregate_verify_G1(const octet *sig, const ECP2_ZZZ PK[], const octet *msg, unsigned int n, const octet *dst)
+{
+    if (PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    ECP2_ZZZ A;
+
+    // aggregate <- pubkey_to_point(PK_1)
+    ECP2_ZZZ_copy(&A, PK);
+
+    // aggregate <- aggregate + pubkey_to_point(PK_i)
+    for (unsigned int i = 1; i < n; i++)
+        ECP2_ZZZ_add(&A, PK + i);
+
+    // return CoreVerify(A, message, signature)
+    return BLS_IETF_ZZZ_core_verify_G1(sig, &A, msg, dst);
+}
+
+int BLS_IETF_ZZZ_fast_aggregate_verify_G2(const octet *sig, const ECP_ZZZ PK[], const octet *msg, unsigned int n, const octet *dst)
+{
+    if (PK == NULL || msg == NULL || dst == NULL)
+        return ERR_NULLPOINTER_BLS;
+
+    if (n == 0)
+        return ERR_BADARGLEN_BLS;
+
+    ECP_ZZZ A;
+
+    // aggregate <- pubkey_to_point(PK_1)
+    ECP_ZZZ_copy(&A, PK);
+
+    // aggregate <- aggregate + pubkey_to_point(PK_i)
+    for (unsigned int i = 1; i < n; i++)
+        ECP_ZZZ_add(&A, PK + i);
+
+    // return CoreVerify(A, message, signature)
+    return BLS_IETF_ZZZ_core_verify_G2(sig, &A, msg, dst);
+}
diff --git a/src/ecdh.c.in b/src/ecdh.c.in
index 216c509..5b86ada 100644
--- a/src/ecdh.c.in
+++ b/src/ecdh.c.in
@@ -33,7 +33,8 @@ under the License.
  * otherwise it is generated randomly internally */
 int ECP_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
 {
-    BIG_XXX r,s;
+    BIG_XXX r;
+    BIG_XXX s;
     ECP_ZZZ G;
     int res=0;
 
@@ -65,11 +66,14 @@ int ECP_ZZZ_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W)
 }
 
 /* Validate public key */
-int ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W)
+int ECP_ZZZ_PUBLIC_KEY_VALIDATE(const octet *W)
 {
-    BIG_XXX q,r,k;
+    BIG_XXX q;
+    BIG_XXX r;
+    BIG_XXX k;
     ECP_ZZZ WP;
-    int valid,nb;
+    int valid;
+    int nb;
     int res=0;
 
     BIG_XXX_rcopy(q,Modulus_YYY);
@@ -101,9 +105,11 @@ int ECP_ZZZ_PUBLIC_KEY_VALIDATE(octet *W)
 }
 
 /* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */
-int ECP_ZZZ_SVDP_DH(octet *S,octet *WD,octet *Z)
+int ECP_ZZZ_SVDP_DH(const octet *S,const octet *WD,octet *Z)
 {
-    BIG_XXX r,s,wx;
+    BIG_XXX r;
+    BIG_XXX s;
+    BIG_XXX wx;
     int valid;
     ECP_ZZZ W;
     int res=0;
@@ -137,13 +143,21 @@ int ECP_ZZZ_SVDP_DH(octet *S,octet *WD,octet *Z)
 #if CURVETYPE_ZZZ!=MONTGOMERY
 
 /* IEEE ECDSA Signature, C and D are signature on F using private key S */
-int ECP_ZZZ_SP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet *D)
+int ECP_ZZZ_SP_DSA(int sha,csprng *RNG,const octet *K,const octet *S,const octet *F,octet *C,octet *D)
 {
     char h[128];
     octet H= {0,sizeof(h),h};
 
-    BIG_XXX r,s,f,c,d,u,vx,w;
-    ECP_ZZZ G,V;
+    BIG_XXX r;
+    BIG_XXX s;
+    BIG_XXX f;
+    BIG_XXX c;
+    BIG_XXX d;
+    BIG_XXX u;
+    BIG_XXX vx;
+    BIG_XXX w;
+    ECP_ZZZ G;
+    ECP_ZZZ V;
 
     ehashit(sha,F,-1,NULL,&H,sha);
 
@@ -225,14 +239,19 @@ int ECP_ZZZ_SP_DSA(int sha,csprng *RNG,octet *K,octet *S,octet *F,octet *C,octet
 }
 
 /* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
-int ECP_ZZZ_VP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
+int ECP_ZZZ_VP_DSA(int sha,const octet *W,const octet *F, octet *C,octet *D)
 {
     char h[128];
     octet H= {0,sizeof(h),h};
 
-    BIG_XXX r,f,c,d,h2;
+    BIG_XXX r;
+    BIG_XXX f;
+    BIG_XXX c;
+    BIG_XXX d;
+    BIG_XXX h2;
     int res=0;
-    ECP_ZZZ G,WP;
+    ECP_ZZZ G;
+    ECP_ZZZ WP;
     int valid;
 
     ehashit(sha,F,-1,NULL,&H,sha);
@@ -252,8 +271,6 @@ int ECP_ZZZ_VP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
 
     BIG_XXX_fromBytesLen(f,H.val,hlen);
 
-    //BIG_fromBytes(f,H.val);
-
     if (BIG_XXX_iszilch(c) || BIG_XXX_comp(c,r)>=0 || BIG_XXX_iszilch(d) || BIG_XXX_comp(d,r)>=0)
         res=ECDH_INVALID;
 
@@ -284,11 +301,17 @@ int ECP_ZZZ_VP_DSA(int sha,octet *W,octet *F, octet *C,octet *D)
 }
 
 /* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */
-void ECP_ZZZ_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octet *M,int tlen,octet *V,octet *C,octet *T)
+void ECP_ZZZ_ECIES_ENCRYPT(int sha,const octet *P1,const octet *P2,csprng *RNG,const octet *W,const octet *M,int tlen,octet *V,octet *C,octet *T)
 {
 
-    int i,len;
-    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],u[EFS_ZZZ];
+    int len;
+    char z[EFS_ZZZ];
+    char vz[3*EFS_ZZZ+1];
+    char k[2*AESKEY_ZZZ];
+    char k1[AESKEY_ZZZ];
+    char k2[AESKEY_ZZZ];
+    char l2[8];
+    char u[EFS_ZZZ];
     octet Z= {0,sizeof(z),z};
     octet VZ= {0,sizeof(vz),vz};
     octet K= {0,sizeof(k),k};
@@ -306,7 +329,7 @@ void ECP_ZZZ_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octe
     KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
 
     K1.len=K2.len=AESKEY_ZZZ;
-    for (i=0; i<AESKEY_ZZZ; i++)
+    for (int i=0; i<AESKEY_ZZZ; i++)
     {
         K1.val[i]=K.val[i];
         K2.val[i]=K.val[AESKEY_ZZZ+i];
@@ -324,11 +347,17 @@ void ECP_ZZZ_ECIES_ENCRYPT(int sha,octet *P1,octet *P2,csprng *RNG,octet *W,octe
 }
 
 /* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */
-int ECP_ZZZ_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T,octet *U,octet *M)
+int ECP_ZZZ_ECIES_DECRYPT(int sha,const octet *P1,const octet *P2,const octet *V,octet *C,const octet *T,const octet *U,octet *M)
 {
 
-    int i,len;
-    char z[EFS_ZZZ],vz[3*EFS_ZZZ+1],k[2*AESKEY_ZZZ],k1[AESKEY_ZZZ],k2[AESKEY_ZZZ],l2[8],tag[32];
+    int len;
+    char z[EFS_ZZZ];
+    char vz[3*EFS_ZZZ+1];
+    char k[2*AESKEY_ZZZ];
+    char k1[AESKEY_ZZZ];
+    char k2[AESKEY_ZZZ];
+    char l2[8];
+    char tag[32];
     octet Z= {0,sizeof(z),z};
     octet VZ= {0,sizeof(vz),vz};
     octet K= {0,sizeof(k),k};
@@ -345,7 +374,7 @@ int ECP_ZZZ_ECIES_DECRYPT(int sha,octet *P1,octet *P2,octet *V,octet *C,octet *T
     KDF2(sha,&VZ,P1,2*AESKEY_ZZZ,&K);
 
     K1.len=K2.len=AESKEY_ZZZ;
-    for (i=0; i<AESKEY_ZZZ; i++)
+    for (int i=0; i<AESKEY_ZZZ; i++)
     {
         K1.val[i]=K.val[i];
         K2.val[i]=K.val[AESKEY_ZZZ+i];
diff --git a/src/ecdh_support.c b/src/ecdh_support.c
index ee9397b..eec01de 100644
--- a/src/ecdh_support.c
+++ b/src/ecdh_support.c
@@ -19,20 +19,18 @@ under the License.
 
 /* Symmetric crypto support functions Functions  */
 
-#include <stdio.h>
 #include <string.h>
-#include <stdlib.h>
-#include <time.h>
-
 #include "ecdh_support.h"
 
 #define ROUNDUP(a,b) ((a)-1)/(b)+1
 
 /* general purpose hash function w=hash(p|n|x|y) */
-/* pad or truncate ouput to length pad if pad!=0 */
-void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
+/* pad or truncate output to length pad if pad!=0 */
+void ehashit(int sha,const octet *p,int n,const octet *x,octet *w,int pad)
 {
-    int i,c[4],hlen;
+    int i;
+    int c[4];
+    int hlen;
     hash256 sha256;
     hash512 sha512;
     char hh[64];
@@ -48,6 +46,8 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
     case SHA512:
         HASH512_init(&sha512);
         break;
+    default:
+        break;
     }
 
     hlen=sha;
@@ -65,6 +65,8 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
         case SHA512:
             HASH512_process(&sha512,p->val[i]);
             break;
+        default:
+            break;
         }
     }
     if (n>0)
@@ -72,7 +74,7 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
         c[0]=(n>>24)&0xff;
         c[1]=(n>>16)&0xff;
         c[2]=(n>>8)&0xff;
-        c[3]=(n)&0xff;
+        c[3]=n&0xff;
         for (i=0; i<4; i++)
         {
             switch(sha)
@@ -86,6 +88,8 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
             case SHA512:
                 HASH512_process(&sha512,c[i]);
                 break;
+            default:
+                break;
             }
         }
     }
@@ -102,6 +106,8 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
             case SHA512:
                 HASH512_process(&sha512,x->val[i]);
                 break;
+            default:
+                break;
             }
         }
 
@@ -116,6 +122,8 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
     case SHA512:
         HASH512_hash(&sha512,hh);
         break;
+    default:
+        break;
     }
 
     OCT_empty(w);
@@ -129,28 +137,27 @@ void ehashit(int sha,octet *p,int n,octet *x,octet *w,int pad)
         {
             OCT_jbyte(w,0,pad-hlen);
             OCT_jbytes(w,hh,hlen);
-
-//            OCT_jbytes(w,hh,hlen);
-//            OCT_jbyte(w,0,pad-hlen);
         }
     }
     return;
 }
 
 /* Hash octet p to octet w */
-void HASH(int sha,octet *p,octet *w)
+void HASH(int sha,const octet *p,octet *w)
 {
     ehashit(sha,p,-1,NULL,w,0);
 }
 
 /* Calculate HMAC of m using key k. HMAC is tag of length olen */
-int HMAC(int sha,octet *m,octet *k,int olen,octet *tag)
+int HMAC(int sha,const octet *m,const 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[128],k0[128];
+    int hlen;
+    int b;
+    char h[128];
+    char k0[128];
     octet H= {0,sizeof(h),h};
     octet K0= {0,sizeof(k0),k0};
 
@@ -179,19 +186,19 @@ int HMAC(int sha,octet *m,octet *k,int olen,octet *tag)
     return 1;
 }
 
-void KDF2(int sha,octet *z,octet *p,int olen,octet *key)
+void KDF2(int sha,const octet *z,const octet *p,int olen,octet *key)
 {
     /* NOTE: the parameter olen is the length of the output k in bytes */
     char h[64];
     octet H= {0,sizeof(h),h};
-    int counter,cthreshold;
+    int cthreshold;
     int hlen=sha;
 
     OCT_empty(key);
 
     cthreshold=ROUNDUP(olen,hlen);
 
-    for (counter=1; counter<=cthreshold; counter++)
+    for (int counter=1; counter<=cthreshold; counter++)
     {
         ehashit(sha,z,counter,p,&H,0);
         if (key->len+hlen>olen)  OCT_jbytes(key,H.val,olen%hlen);
@@ -203,15 +210,17 @@ void KDF2(int sha,octet *z,octet *p,int olen,octet *key)
 /* Password based Key Derivation Function */
 /* Input password p, salt s, and repeat count */
 /* Output key of length olen */
-void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
+void PBKDF2(int sha,const octet *p,octet *s,int rep,int olen,octet *key)
 {
-    int i,j,len,d=ROUNDUP(olen,sha);
-    char f[64],u[64];
+    int len;
+    int d=ROUNDUP(olen,sha);
+    char f[64];
+    char u[64];
     octet F= {0,sizeof(f),f};
     octet U= {0,sizeof(u),u};
     OCT_empty(key);
 
-    for (i=1; i<=d; i++)
+    for (int i=1; i<=d; i++)
     {
         len=s->len;
         OCT_jint(s,i,4);
@@ -220,7 +229,7 @@ void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
 
         s->len=len;
         OCT_copy(&U,&F);
-        for (j=2; j<=rep; j++)
+        for (int j=2; j<=rep; j++)
         {
             HMAC(sha,&U,p,sha,&U);
             OCT_xor(&F,&U);
@@ -233,14 +242,16 @@ void PBKDF2(int sha,octet *p,octet *s,int rep,int olen,octet *key)
 }
 
 /* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */
-void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
+void AES_CBC_IV0_ENCRYPT(octet *k,const 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 */
     amcl_aes a;
     int fin;
-    int i,j,ipt,opt;
+    int i;
+    int ipt;
+    int opt;
     char buff[16];
     int padlen;
 
@@ -270,7 +281,7 @@ void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
     /* last block, filled up to i-th index */
 
     padlen=16-i;
-    for (j=i; j<16; j++) buff[j]=padlen;
+    for (int j=i; j<16; j++) buff[j]=(char)padlen;
     AES_encrypt(&a,buff);
     for (i=0; i<16; i++)
         if (opt<c->max) c->val[opt++]=buff[i];
@@ -279,13 +290,17 @@ void AES_CBC_IV0_ENCRYPT(octet *k,octet *m,octet *c)
 }
 
 /* decrypts and returns TRUE if all consistent, else returns FALSE */
-int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
+int AES_CBC_IV0_DECRYPT(octet *k,const octet *c,octet *m)
 {
     /* padding is removed */
     amcl_aes a;
-    int i,ipt,opt,ch;
+    int i;
+    int ipt;
+    int opt;
+    int ch;
     char buff[16];
-    int fin,bad;
+    int fin;
+    int bad;
     int padlen;
     ipt=opt=0;
 
@@ -300,7 +315,7 @@ int AES_CBC_IV0_DECRYPT(octet *k,octet *c,octet *m)
     {
         for (i=0; i<16; i++)
         {
-            buff[i]=ch;
+            buff[i]=(char)ch;
             if (ipt>=c->len)
             {
                 fin=1;
diff --git a/src/ecp.c.in b/src/ecp.c.in
index 8b1d938..ca54939 100644
--- a/src/ecp.c.in
+++ b/src/ecp.c.in
@@ -25,7 +25,7 @@ under the License.
 #include "ecp_ZZZ.h"
 
 /* test for P=O point-at-infinity */
-int ECP_ZZZ_isinf(ECP_ZZZ *P)
+int ECP_ZZZ_isinf(const ECP_ZZZ *P)
 {
 
 #if CURVETYPE_ZZZ==EDWARDS
@@ -52,7 +52,7 @@ static void ECP_ZZZ_cswap(ECP_ZZZ *P,ECP_ZZZ *Q,int d)
 
 #if CURVETYPE_ZZZ!=MONTGOMERY
 /* Conditional move Q to P dependant on d */
-static void ECP_ZZZ_cmove(ECP_ZZZ *P,ECP_ZZZ *Q,int d)
+static void ECP_ZZZ_cmove(ECP_ZZZ *P,const ECP_ZZZ *Q,int d)
 {
     FP_YYY_cmove(&(P->x),&(Q->x),d);
 #if CURVETYPE_ZZZ!=MONTGOMERY
@@ -66,13 +66,13 @@ static int teq(sign32 b,sign32 c)
 {
     sign32 x=b^c;
     x-=1;  // if x=0, x now -1
-    return (int)((x>>31)&1);
+    return (x>>31)&1;
 }
 #endif // CURVETYPE_ZZZ!=MONTGOMERY
 
 #if CURVETYPE_ZZZ!=MONTGOMERY
 /* Constant time select from pre-computed table */
-static void ECP_ZZZ_select(ECP_ZZZ *P,ECP_ZZZ W[],sign32 b)
+static void ECP_ZZZ_select(ECP_ZZZ *P,const ECP_ZZZ W[],sign32 b)
 {
     ECP_ZZZ MP;
     sign32 m=b>>31;
@@ -91,15 +91,16 @@ static void ECP_ZZZ_select(ECP_ZZZ *P,ECP_ZZZ W[],sign32 b)
 
     ECP_ZZZ_copy(&MP,P);
     ECP_ZZZ_neg(&MP);  // minus P
-    ECP_ZZZ_cmove(P,&MP,(int)(m&1));
+    ECP_ZZZ_cmove(P,&MP,m&1);
 }
 #endif
 
 /* Test P == Q */
 /* SU=168 */
-int ECP_ZZZ_equals(ECP_ZZZ *P,ECP_ZZZ *Q)
+int ECP_ZZZ_equals(const ECP_ZZZ *P,const ECP_ZZZ *Q)
 {
-    FP_YYY a,b;
+    FP_YYY a;
+    FP_YYY b;
 
     FP_YYY_mul(&a,&(P->x),&(Q->z));
     FP_YYY_mul(&b,&(Q->x),&(P->z));
@@ -117,7 +118,7 @@ int ECP_ZZZ_equals(ECP_ZZZ *P,ECP_ZZZ *Q)
 
 /* Set P=Q */
 /* SU=16 */
-void ECP_ZZZ_copy(ECP_ZZZ *P,ECP_ZZZ *Q)
+void ECP_ZZZ_copy(ECP_ZZZ *P,const ECP_ZZZ *Q)
 {
     FP_YYY_copy(&(P->x),&(Q->x));
 #if CURVETYPE_ZZZ!=MONTGOMERY
@@ -184,7 +185,8 @@ void ECP_ZZZ_rhs(FP_YYY *v,FP_YYY *x)
 
 #if CURVETYPE_ZZZ==EDWARDS
     /* (Ax^2-1)/(Bx^2-1) */
-    FP_YYY t,one;
+    FP_YYY t;
+    FP_YYY one;
     FP_YYY_sqr(v,x);
     FP_YYY_one(&one);
     FP_YYY_rcopy(&t,CURVE_B_ZZZ);
@@ -246,7 +248,7 @@ int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x)
 }
 
 /* Extract x coordinate as BIG */
-int ECP_ZZZ_get(BIG_XXX x,ECP_ZZZ *P)
+int ECP_ZZZ_get(BIG_XXX x,const ECP_ZZZ *P)
 {
     ECP_ZZZ W;
     ECP_ZZZ_copy(&W,P);
@@ -260,7 +262,7 @@ int ECP_ZZZ_get(BIG_XXX x,ECP_ZZZ *P)
 #else
 /* Extract (x,y) and return sign of y. If x and y are the same return only x */
 /* SU=16 */
-int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,ECP_ZZZ *P)
+int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,const ECP_ZZZ *P)
 {
     ECP_ZZZ W;
     int s;
@@ -279,9 +281,10 @@ int ECP_ZZZ_get(BIG_XXX x,BIG_XXX y,ECP_ZZZ *P)
 
 /* Set P=(x,{y}) */
 /* SU=96 */
-int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y)
+int ECP_ZZZ_set(ECP_ZZZ *P,const BIG_XXX x,const BIG_XXX y)
 {
-    FP_YYY rhs,y2;
+    FP_YYY rhs;
+    FP_YYY y2;
 
     FP_YYY_nres(&y2,y);
     FP_YYY_sqr(&y2,&y2);
@@ -304,10 +307,11 @@ int ECP_ZZZ_set(ECP_ZZZ *P,BIG_XXX x,BIG_XXX y)
 
 /* Set P=(x,y), where y is calculated from x with sign s */
 /* SU=136 */
-int ECP_ZZZ_setx(ECP_ZZZ *P,BIG_XXX x,int s)
+int ECP_ZZZ_setx(ECP_ZZZ *P,const BIG_XXX x,int s)
 {
     FP_YYY rhs;
-    BIG_XXX t,m;
+    BIG_XXX t;
+    BIG_XXX m;
     BIG_XXX_rcopy(m,Modulus_YYY);
 
     FP_YYY_nres(&rhs,x);
@@ -362,9 +366,10 @@ void ECP_ZZZ_cfp(ECP_ZZZ *P)
 /* map BIG to point on curve of correct order */
 /* The BIG should be the output of some hash function */
 
-void ECP_ZZZ_mapit(ECP_ZZZ *P,octet *W)
+void ECP_ZZZ_mapit(ECP_ZZZ *P,const octet *W)
 {
-    BIG_XXX q,x;
+    BIG_XXX q;
+    BIG_XXX x;
     BIG_XXX_fromBytes(x,W->val);
     BIG_XXX_rcopy(q,Modulus_YYY);
     BIG_XXX_mod(x,q);
@@ -391,7 +396,8 @@ void ECP_ZZZ_mapit(ECP_ZZZ *P,octet *W)
 /* SU=160 */
 void ECP_ZZZ_affine(ECP_ZZZ *P)
 {
-    FP_YYY one,iz;
+    FP_YYY one;
+    FP_YYY iz;
     if (ECP_ZZZ_isinf(P)) return;
     FP_YYY_one(&one);
     if (FP_YYY_equals(&(P->z),&one)) return;
@@ -413,7 +419,8 @@ void ECP_ZZZ_affine(ECP_ZZZ *P)
 /* SU=120 */
 void ECP_ZZZ_outputxyz(ECP_ZZZ *P)
 {
-    BIG_XXX x,z;
+    BIG_XXX x;
+    BIG_XXX z;
     if (ECP_ZZZ_isinf(P))
     {
         printf("Infinity\n");
@@ -475,9 +482,10 @@ void ECP_ZZZ_output(ECP_ZZZ *P)
 
 /* SU=16 */
 /* Output point P */
-void ECP_ZZZ_rawoutput(ECP_ZZZ *P)
+void ECP_ZZZ_rawoutput(const ECP_ZZZ *P)
 {
-    BIG_XXX x,z;
+    BIG_XXX x;
+    BIG_XXX z;
 
 #if CURVETYPE_ZZZ!=MONTGOMERY
     BIG_XXX y;
@@ -504,7 +512,7 @@ void ECP_ZZZ_rawoutput(ECP_ZZZ *P)
 
 /* SU=88 */
 /* Convert P to octet string */
-void ECP_ZZZ_toOctet(octet *W,ECP_ZZZ *P,bool compress)
+void ECP_ZZZ_toOctet(octet *W,const ECP_ZZZ *P,bool compress)
 {
 #if CURVETYPE_ZZZ==MONTGOMERY
     BIG_XXX x;
@@ -513,7 +521,8 @@ void ECP_ZZZ_toOctet(octet *W,ECP_ZZZ *P,bool compress)
     W->val[0]=6;
     BIG_XXX_toBytes(&(W->val[1]),x);
 #else
-    BIG_XXX x,y;
+    BIG_XXX x;
+    BIG_XXX y;
     ECP_ZZZ_get(x,y,P);
     if (compress)
     {
@@ -534,7 +543,7 @@ void ECP_ZZZ_toOctet(octet *W,ECP_ZZZ *P,bool compress)
 
 /* SU=88 */
 /* Restore P from octet string */
-int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *W)
+int ECP_ZZZ_fromOctet(ECP_ZZZ *P,const octet *W)
 {
 #if CURVETYPE_ZZZ==MONTGOMERY
     BIG_XXX x;
@@ -542,7 +551,8 @@ int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *W)
     if (ECP_ZZZ_set(P,x)) return 1;
     return 0;
 #else
-    BIG_XXX x,y;
+    BIG_XXX x;
+    BIG_XXX y;
     int typ=W->val[0];
     BIG_XXX_fromBytes(x,&(W->val[1]));
     if (typ==0x04)
@@ -550,10 +560,8 @@ int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *W)
         BIG_XXX_fromBytes(y,&(W->val[MODBYTES_XXX+1]));
         if (ECP_ZZZ_set(P,x,y)) return 1;
     }
-    if (typ==0x02 || typ==0x03)
-    {
-        if (ECP_ZZZ_setx(P,x,typ&1)) return 1;
-    }
+    if ((typ==0x02 || typ==0x03) && (ECP_ZZZ_setx(P,x,typ&1)))
+        return 1;
     return 0;
 #endif
 }
@@ -564,145 +572,155 @@ int ECP_ZZZ_fromOctet(ECP_ZZZ *P,octet *W)
 void ECP_ZZZ_dbl(ECP_ZZZ *P)
 {
 #if CURVETYPE_ZZZ==WEIERSTRASS
-    FP_YYY t0,t1,t2,t3,x3,y3,z3,b;
+    FP_YYY t0;
+    FP_YYY t1;
+    FP_YYY t2;
+    FP_YYY t3;
+    FP_YYY x3;
+    FP_YYY y3;
+    FP_YYY z3;
+    FP_YYY b;
 
     if (CURVE_A_ZZZ==0)
     {
-        FP_YYY_sqr(&t0,&(P->y));					//t0.sqr();
-        FP_YYY_mul(&t1,&(P->y),&(P->z));			//t1.mul(z);
-
-        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr();
-        FP_YYY_add(&(P->z),&t0,&t0);		//z.add(t0);
-        FP_YYY_norm(&(P->z));					//z.norm();
-        FP_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
-        FP_YYY_add(&(P->z),&(P->z),&(P->z));	//z.add(z);
-        FP_YYY_norm(&(P->z));					//z.norm();
-
-        FP_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);		//t2.imul(3*ROM.CURVE_B_I);
-        FP_YYY_mul(&x3,&t2,&(P->z));			//x3.mul(z);
-
-        FP_YYY_add(&y3,&t0,&t2);				//y3.add(t2);
-        FP_YYY_norm(&y3);						//y3.norm();
-        FP_YYY_mul(&(P->z),&(P->z),&t1);		//z.mul(t1);
-
-        FP_YYY_add(&t1,&t2,&t2);				//t1.add(t2);
-        FP_YYY_add(&t2,&t2,&t1);				//t2.add(t1);
-        FP_YYY_sub(&t0,&t0,&t2);				//t0.sub(t2);
-        FP_YYY_norm(&t0);						//t0.norm();
-        FP_YYY_mul(&y3,&y3,&t0);				//y3.mul(t0);
-        FP_YYY_add(&y3,&y3,&x3);				//y3.add(x3);
-        FP_YYY_mul(&t1,&(P->x),&(P->y));			//t1.mul(y);
-
-        FP_YYY_norm(&t0);					//x.norm();
-        FP_YYY_mul(&(P->x),&t0,&t1);		//x.mul(t1);
-        FP_YYY_add(&(P->x),&(P->x),&(P->x));	//x.add(x);
-        FP_YYY_norm(&(P->x));					//x.norm();
-        FP_YYY_copy(&(P->y),&y3);				//y.copy(y3);
-        FP_YYY_norm(&(P->y));					//y.norm();
+        FP_YYY_sqr(&t0,&(P->y));					//t0.sqr()
+        FP_YYY_mul(&t1,&(P->y),&(P->z));			//t1.mul(z)
+
+        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr()
+        FP_YYY_add(&(P->z),&t0,&t0);		        //z.add(t0)
+        FP_YYY_norm(&(P->z));					    //z.norm()
+        FP_YYY_add(&(P->z),&(P->z),&(P->z));	    //z.add(z)
+        FP_YYY_add(&(P->z),&(P->z),&(P->z));	    //z.add(z)
+        FP_YYY_norm(&(P->z));					    //z.norm()
+
+        FP_YYY_imul(&t2,&t2,3*CURVE_B_I_ZZZ);		//t2.imul(3*ROM.CURVE_B_I)
+        FP_YYY_mul(&x3,&t2,&(P->z));			    //x3.mul(z)
+
+        FP_YYY_add(&y3,&t0,&t2);				    //y3.add(t2)
+        FP_YYY_norm(&y3);						    //y3.norm()
+        FP_YYY_mul(&(P->z),&(P->z),&t1);		    //z.mul(t1)
+
+        FP_YYY_add(&t1,&t2,&t2);				    //t1.add(t2)
+        FP_YYY_add(&t2,&t2,&t1);				    //t2.add(t1)
+        FP_YYY_sub(&t0,&t0,&t2);				    //t0.sub(t2)
+        FP_YYY_norm(&t0);						    //t0.norm()
+        FP_YYY_mul(&y3,&y3,&t0);				    //y3.mul(t0)
+        FP_YYY_add(&y3,&y3,&x3);				    //y3.add(x3)
+        FP_YYY_mul(&t1,&(P->x),&(P->y));			//t1.mul(y)
+
+        FP_YYY_norm(&t0);					        //x.norm()
+        FP_YYY_mul(&(P->x),&t0,&t1);		        //x.mul(t1)
+        FP_YYY_add(&(P->x),&(P->x),&(P->x));	    //x.add(x)
+        FP_YYY_norm(&(P->x));					    //x.norm()
+        FP_YYY_copy(&(P->y),&y3);				    //y.copy(y3)
+        FP_YYY_norm(&(P->y));					    //y.norm()
     }
     else // its -3
     {
 
-        if (CURVE_B_I_ZZZ==0)					//if (ROM.CURVE_B_I==0)
-            FP_YYY_rcopy(&b,CURVE_B_ZZZ);		//b.copy(new FP(new BIG(ROM.CURVE_B)));
+        if (CURVE_B_I_ZZZ==0)					    //if ROM.CURVE_B_I = 0
+            FP_YYY_rcopy(&b,CURVE_B_ZZZ);           //b.copy(new FP(new BIG(ROM.CURVE_B)))
 
-        FP_YYY_sqr(&t0,&(P->x));					//t0.sqr();  //1    x^2
-        FP_YYY_sqr(&t1,&(P->y));					//t1.sqr();  //2    y^2
-        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr();  //3
+        FP_YYY_sqr(&t0,&(P->x));					//t0.sqr()  //1    x^2
+        FP_YYY_sqr(&t1,&(P->y));					//t1.sqr()  //2    y^2
+        FP_YYY_sqr(&t2,&(P->z));					//t2.sqr()  //3
 
-        FP_YYY_mul(&t3,&(P->x),&(P->y));			//t3.mul(y); //4
-        FP_YYY_add(&t3,&t3,&t3);				//t3.add(t3);
-        FP_YYY_norm(&t3);						//t3.norm();//5
+        FP_YYY_mul(&t3,&(P->x),&(P->y));			//t3.mul(y) //4
+        FP_YYY_add(&t3,&t3,&t3);				    //t3.add(t3)
+        FP_YYY_norm(&t3);						    //t3.norm() //5
 
-        FP_YYY_mul(&z3,&(P->z),&(P->x));			//z3.mul(x);   //6
-        FP_YYY_add(&z3,&z3,&z3);				//z3.add(z3);
-        FP_YYY_norm(&z3);						//z3.norm();//7
+        FP_YYY_mul(&z3,&(P->z),&(P->x));			//z3.mul(x)   //6
+        FP_YYY_add(&z3,&z3,&z3);				    //z3.add(z3)
+        FP_YYY_norm(&z3);						    //z3.norm() //7
 
-        if (CURVE_B_I_ZZZ==0)						//if (ROM.CURVE_B_I==0)
-            FP_YYY_mul(&y3,&t2,&b);				//y3.mul(b); //8
+        if (CURVE_B_I_ZZZ==0)						//if ROM.CURVE_B_I = 0
+            FP_YYY_mul(&y3,&t2,&b);				    //y3.mul(b) //8
         else
-            FP_YYY_imul(&y3,&t2,CURVE_B_I_ZZZ);	//y3.imul(ROM.CURVE_B_I);
-
-        FP_YYY_sub(&y3,&y3,&z3);				//y3.sub(z3); //y3.norm(); //9  ***
-        FP_YYY_add(&x3,&y3,&y3);				//x3.add(y3);
-        FP_YYY_norm(&x3);						//x3.norm();//10
-
-        FP_YYY_add(&y3,&y3,&x3);				//y3.add(x3); //y3.norm();//11
-        FP_YYY_sub(&x3,&t1,&y3);				//x3.sub(y3);
-        FP_YYY_norm(&x3);						//x3.norm();//12
-        FP_YYY_add(&y3,&y3,&t1);				//y3.add(t1);
-        FP_YYY_norm(&y3);						//y3.norm();//13
-        FP_YYY_mul(&y3,&y3,&x3);				//y3.mul(x3); //14
-        FP_YYY_mul(&x3,&x3,&t3);				//x3.mul(t3); //15
-        FP_YYY_add(&t3,&t2,&t2);				//t3.add(t2);  //16
-        FP_YYY_add(&t2,&t2,&t3);				//t2.add(t3); //17
-
-        if (CURVE_B_I_ZZZ==0)					//if (ROM.CURVE_B_I==0)
-            FP_YYY_mul(&z3,&z3,&b);				//z3.mul(b); //18
+            FP_YYY_imul(&y3,&t2,CURVE_B_I_ZZZ);	    //y3.imul(ROM.CURVE_B_I)
+
+        FP_YYY_sub(&y3,&y3,&z3);				    //y3.sub(z3) //y3.norm() //9  ***
+        FP_YYY_add(&x3,&y3,&y3);				    //x3.add(y3)
+        FP_YYY_norm(&x3);						    //x3.norm() //10
+
+        FP_YYY_add(&y3,&y3,&x3);				    //y3.add(x3) //y3.norm() //11
+        FP_YYY_sub(&x3,&t1,&y3);				    //x3.sub(y3)
+        FP_YYY_norm(&x3);						    //x3.norm()//12
+        FP_YYY_add(&y3,&y3,&t1);				    //y3.add(t1)
+        FP_YYY_norm(&y3);						    //y3.norm() //13
+        FP_YYY_mul(&y3,&y3,&x3);				    //y3.mul(x3) //14
+        FP_YYY_mul(&x3,&x3,&t3);				    //x3.mul(t3) //15
+        FP_YYY_add(&t3,&t2,&t2);				    //t3.add(t2)  //16
+        FP_YYY_add(&t2,&t2,&t3);				    //t2.add(t3) //17
+
+        if (CURVE_B_I_ZZZ==0)					    //if ROM.CURVE_B_I = 0
+            FP_YYY_mul(&z3,&z3,&b);				    //z3.mul(b) //18
         else
-            FP_YYY_imul(&z3,&z3,CURVE_B_I_ZZZ);	//z3.imul(ROM.CURVE_B_I);
-
-        FP_YYY_sub(&z3,&z3,&t2);				//z3.sub(t2); //z3.norm();//19
-        FP_YYY_sub(&z3,&z3,&t0);				//z3.sub(t0);
-        FP_YYY_norm(&z3);						//z3.norm();//20  ***
-        FP_YYY_add(&t3,&z3,&z3);				//t3.add(z3); //t3.norm();//21
-
-        FP_YYY_add(&z3,&z3,&t3);				//z3.add(t3);
-        FP_YYY_norm(&z3);						//z3.norm(); //22
-        FP_YYY_add(&t3,&t0,&t0);				//t3.add(t0); //t3.norm(); //23
-        FP_YYY_add(&t0,&t0,&t3);				//t0.add(t3); //t0.norm();//24
-        FP_YYY_sub(&t0,&t0,&t2);				//t0.sub(t2);
-        FP_YYY_norm(&t0);						//t0.norm();//25
-
-        FP_YYY_mul(&t0,&t0,&z3);				//t0.mul(z3);//26
-        FP_YYY_add(&y3,&y3,&t0);				//y3.add(t0); //y3.norm();//27
-        FP_YYY_mul(&t0,&(P->y),&(P->z));			//t0.mul(z);//28
-        FP_YYY_add(&t0,&t0,&t0);				//t0.add(t0);
-        FP_YYY_norm(&t0);						//t0.norm(); //29
-        FP_YYY_mul(&z3,&z3,&t0);				//z3.mul(t0);//30
-        FP_YYY_sub(&(P->x),&x3,&z3);				//x3.sub(z3); //x3.norm();//31
-        FP_YYY_add(&t0,&t0,&t0);				//t0.add(t0);
-        FP_YYY_norm(&t0);						//t0.norm();//32
-        FP_YYY_add(&t1,&t1,&t1);				//t1.add(t1);
-        FP_YYY_norm(&t1);						//t1.norm();//33
-        FP_YYY_mul(&(P->z),&t0,&t1);				//z3.mul(t1);//34
-
-        FP_YYY_norm(&(P->x));					//x.norm();
-        FP_YYY_copy(&(P->y),&y3);				//y.copy(y3);
-        FP_YYY_norm(&(P->y));					//y.norm();
-        FP_YYY_norm(&(P->z));					//z.norm();
+            FP_YYY_imul(&z3,&z3,CURVE_B_I_ZZZ);	    //z3.imul(ROM.CURVE_B_I)
+
+        FP_YYY_sub(&z3,&z3,&t2);				    //z3.sub(t2) //z3.norm() //19
+        FP_YYY_sub(&z3,&z3,&t0);				    //z3.sub(t0)
+        FP_YYY_norm(&z3);						    //z3.norm() //20  ***
+        FP_YYY_add(&t3,&z3,&z3);				    //t3.add(z3) //t3.norm() //21
+
+        FP_YYY_add(&z3,&z3,&t3);				    //z3.add(t3)
+        FP_YYY_norm(&z3);						    //z3.norm() //22
+        FP_YYY_add(&t3,&t0,&t0);				    //t3.add(t0) //t3.norm() //23
+        FP_YYY_add(&t0,&t0,&t3);				    //t0.add(t3) //t0.norm() //24
+        FP_YYY_sub(&t0,&t0,&t2);				    //t0.sub(t2)
+        FP_YYY_norm(&t0);						    //t0.norm() //25
+
+        FP_YYY_mul(&t0,&t0,&z3);				    //t0.mul(z3) //26
+        FP_YYY_add(&y3,&y3,&t0);				    //y3.add(t0) //y3.norm() //27
+        FP_YYY_mul(&t0,&(P->y),&(P->z));			//t0.mul(z) //28
+        FP_YYY_add(&t0,&t0,&t0);				    //t0.add(t0)
+        FP_YYY_norm(&t0);						    //t0.norm() //29
+        FP_YYY_mul(&z3,&z3,&t0);				    //z3.mul(t0) //30
+        FP_YYY_sub(&(P->x),&x3,&z3);				//x3.sub(z3) //x3.norm() //31
+        FP_YYY_add(&t0,&t0,&t0);				    //t0.add(t0)
+        FP_YYY_norm(&t0);						    //t0.norm() //32
+        FP_YYY_add(&t1,&t1,&t1);				    //t1.add(t1)
+        FP_YYY_norm(&t1);						    //t1.norm() //33
+        FP_YYY_mul(&(P->z),&t0,&t1);				//z3.mul(t1) //34
+
+        FP_YYY_norm(&(P->x));					    //x.norm()
+        FP_YYY_copy(&(P->y),&y3);				    //y.copy(y3)
+        FP_YYY_norm(&(P->y));					    //y.norm()
+        FP_YYY_norm(&(P->z));					    //z.norm()
     }
 #endif
 
 #if CURVETYPE_ZZZ==EDWARDS
     /* Not using square for multiplication swap, as (1) it needs more adds, and (2) it triggers more reductions */
 
-    FP_YYY C,D,H,J;
+    FP_YYY C;
+    FP_YYY D;
+    FP_YYY H;
+    FP_YYY J;
 
-    FP_YYY_sqr(&C,&(P->x));							//C.sqr();
+    FP_YYY_sqr(&C,&(P->x));							//C.sqr()
 
-    FP_YYY_mul(&(P->x),&(P->x),&(P->y));		//x.mul(y);
-    FP_YYY_add(&(P->x),&(P->x),&(P->x));		//x.add(x);
-    FP_YYY_norm(&(P->x));						//x.norm();
+    FP_YYY_mul(&(P->x),&(P->x),&(P->y));		    //x.mul(y)
+    FP_YYY_add(&(P->x),&(P->x),&(P->x));	    	//x.add(x)
+    FP_YYY_norm(&(P->x));					    	//x.norm()
 
-    FP_YYY_sqr(&D,&(P->y));							//D.sqr();
+    FP_YYY_sqr(&D,&(P->y));							//D.sqr()
 
-    if (CURVE_A_ZZZ==-1)				//if (ROM.CURVE_A==-1)
-        FP_YYY_neg(&C,&C);				//	C.neg();
+    if (CURVE_A_ZZZ==-1)			            	//if ROM.CURVE_A = -1
+        FP_YYY_neg(&C,&C);			             	//C.neg()
 
-    FP_YYY_add(&(P->y),&C,&D);		//y.add(D);
-    FP_YYY_norm(&(P->y));				//y.norm();
-    FP_YYY_sqr(&H,&(P->z));				//H.sqr();
-    FP_YYY_add(&H,&H,&H);				//H.add(H);
+    FP_YYY_add(&(P->y),&C,&D);		                //y.add(D)
+    FP_YYY_norm(&(P->y));				            //y.norm()
+    FP_YYY_sqr(&H,&(P->z));				            //H.sqr()
+    FP_YYY_add(&H,&H,&H);				            //H.add(H)
 
-    FP_YYY_sub(&J,&(P->y),&H);			//J.sub(H);
-    FP_YYY_norm(&J);					//J.norm();
+    FP_YYY_sub(&J,&(P->y),&H);		               	//J.sub(H)
+    FP_YYY_norm(&J);				            	//J.norm()
 
-    FP_YYY_mul(&(P->x),&(P->x),&J);		//x.mul(J);
-    FP_YYY_sub(&C,&C,&D);				//C.sub(D);
-    FP_YYY_norm(&C);					//C.norm();
-    FP_YYY_mul(&(P->z),&(P->y),&J);		//z.mul(J);
-    FP_YYY_mul(&(P->y),&(P->y),&C);		//y.mul(C);
+    FP_YYY_mul(&(P->x),&(P->x),&J);		            //x.mul(J)
+    FP_YYY_sub(&C,&C,&D);			            	//C.sub(D)
+    FP_YYY_norm(&C);				            	//C.norm()
+    FP_YYY_mul(&(P->z),&(P->y),&J);		            //z.mul(J)
+    FP_YYY_mul(&(P->y),&(P->y),&C);		            //y.mul(C)
 
 
 #endif
@@ -710,21 +728,21 @@ void ECP_ZZZ_dbl(ECP_ZZZ *P)
 #if CURVETYPE_ZZZ==MONTGOMERY
     FP_YYY A,B,AA,BB,C;
 
-    FP_YYY_add(&A,&(P->x),&(P->z));			//A.add(z);
-    FP_YYY_norm(&A);					//A.norm();
-    FP_YYY_sqr(&AA,&A);				//AA.sqr();
-    FP_YYY_sub(&B,&(P->x),&(P->z));			//B.sub(z);
-    FP_YYY_norm(&B);					//B.norm();
+    FP_YYY_add(&A,&(P->x),&(P->z));		        	//A.add(z)
+    FP_YYY_norm(&A);				            	//A.norm()
+    FP_YYY_sqr(&AA,&A);				                //AA.sqr()
+    FP_YYY_sub(&B,&(P->x),&(P->z));		        	//B.sub(z)
+    FP_YYY_norm(&B);					            //B.norm()
 
-    FP_YYY_sqr(&BB,&B);				//BB.sqr();
-    FP_YYY_sub(&C,&AA,&BB);				//C.sub(BB);
-    FP_YYY_norm(&C);					//C.norm();
-    FP_YYY_mul(&(P->x),&AA,&BB);	//x.mul(BB);
-    FP_YYY_imul(&A,&C,(CURVE_A_ZZZ+2)/4);	//A.imul((ROM.CURVE_A+2)/4);
+    FP_YYY_sqr(&BB,&B);			                	//BB.sqr()
+    FP_YYY_sub(&C,&AA,&BB);			            	//C.sub(BB)
+    FP_YYY_norm(&C);				            	//C.norm()
+    FP_YYY_mul(&(P->x),&AA,&BB);                	//x.mul(BB)
+    FP_YYY_imul(&A,&C,(CURVE_A_ZZZ+2)/4);       	//A.imul((ROM.CURVE_A+2)/4)
 
-    FP_YYY_add(&BB,&BB,&A);				//BB.add(A);
-    FP_YYY_norm(&BB);					//BB.norm();
-    FP_YYY_mul(&(P->z),&BB,&C);		//z.mul(C);
+    FP_YYY_add(&BB,&BB,&A);			            	//BB.add(A)
+    FP_YYY_norm(&BB);				            	//BB.norm()
+    FP_YYY_mul(&(P->z),&BB,&C);		                //z.mul(C)
 
 #endif
 }
@@ -736,29 +754,29 @@ void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q,ECP_ZZZ *W)
 {
     FP_YYY A,B,C,D,DA,CB;
 
-    FP_YYY_add(&A,&(P->x),&(P->z));	//A.add(z);
-    FP_YYY_sub(&B,&(P->x),&(P->z));	//B.sub(z);
+    FP_YYY_add(&A,&(P->x),&(P->z));             	//A.add(z)
+    FP_YYY_sub(&B,&(P->x),&(P->z));	                //B.sub(z)
 
-    FP_YYY_add(&C,&(Q->x),&(Q->z));	//C.add(Q.z);
+    FP_YYY_add(&C,&(Q->x),&(Q->z));             	//C.add(Q.z)
 
-    FP_YYY_sub(&D,&(Q->x),&(Q->z));	//D.sub(Q.z);
-    FP_YYY_norm(&A);			//A.norm();
+    FP_YYY_sub(&D,&(Q->x),&(Q->z));             	//D.sub(Q.z)
+    FP_YYY_norm(&A);			                    //A.norm()
 
-    FP_YYY_norm(&D);			//D.norm();
-    FP_YYY_mul(&DA,&D,&A);			//DA.mul(A);
+    FP_YYY_norm(&D);			                    //D.norm()
+    FP_YYY_mul(&DA,&D,&A);		                	//DA.mul(A)
 
-    FP_YYY_norm(&C);			//C.norm();
-    FP_YYY_norm(&B);			//B.norm();
-    FP_YYY_mul(&CB,&C,&B);		//CB.mul(B);
+    FP_YYY_norm(&C);			                    //C.norm()
+    FP_YYY_norm(&B);		                    	//B.norm()
+    FP_YYY_mul(&CB,&C,&B);		                    //CB.mul(B)
 
-    FP_YYY_add(&A,&DA,&CB);		//A.add(CB);
-    FP_YYY_norm(&A);			//A.norm();
-    FP_YYY_sqr(&(P->x),&A);			//A.sqr();
-    FP_YYY_sub(&B,&DA,&CB);		//B.sub(CB);
-    FP_YYY_norm(&B);			//B.norm();
-    FP_YYY_sqr(&B,&B);			//B.sqr();
+    FP_YYY_add(&A,&DA,&CB);		                    //A.add(CB)
+    FP_YYY_norm(&A);		                    	//A.norm()
+    FP_YYY_sqr(&(P->x),&A);		                	//A.sqr()
+    FP_YYY_sub(&B,&DA,&CB);		                    //B.sub(CB)
+    FP_YYY_norm(&B);		                    	//B.norm()
+    FP_YYY_sqr(&B,&B);			                    //B.sqr()
 
-    FP_YYY_mul(&(P->z),&(W->x),&B);	//z.mul(B);
+    FP_YYY_mul(&(P->z),&(W->x),&B);             	//z.mul(B)
 
 }
 
@@ -766,221 +784,236 @@ void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q,ECP_ZZZ *W)
 
 /* Set P+=Q */
 /* SU=248 */
-void ECP_ZZZ_add(ECP_ZZZ *P,ECP_ZZZ *Q)
+void ECP_ZZZ_add(ECP_ZZZ *P,const ECP_ZZZ *Q)
 {
 #if CURVETYPE_ZZZ==WEIERSTRASS
 
     int b3;
-    FP_YYY t0,t1,t2,t3,t4,x3,y3,z3,b;
+    FP_YYY t0;
+    FP_YYY t1;
+    FP_YYY t2;
+    FP_YYY t3;
+    FP_YYY t4;
+    FP_YYY x3;
+    FP_YYY y3;
+    FP_YYY z3;
+    FP_YYY b;
 
     if (CURVE_A_ZZZ==0)
     {
-        b3=3*CURVE_B_I_ZZZ;					//int b=3*ROM.CURVE_B_I;
-        FP_YYY_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x);
-        FP_YYY_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y);
-        FP_YYY_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z);
-        FP_YYY_add(&t3,&(P->x),&(P->y));		//t3.add(y);
-        FP_YYY_norm(&t3);					//t3.norm();
-
-        FP_YYY_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y);
-        FP_YYY_norm(&t4);					//t4.norm();
-        FP_YYY_mul(&t3,&t3,&t4);			//t3.mul(t4);
-        FP_YYY_add(&t4,&t0,&t1);			//t4.add(t1);
-
-        FP_YYY_sub(&t3,&t3,&t4);			//t3.sub(t4);
-        FP_YYY_norm(&t3);					//t3.norm();
-        FP_YYY_add(&t4,&(P->y),&(P->z));		//t4.add(z);
-        FP_YYY_norm(&t4);					//t4.norm();
-        FP_YYY_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z);
-        FP_YYY_norm(&x3);					//x3.norm();
-
-        FP_YYY_mul(&t4,&t4,&x3);			//t4.mul(x3);
-        FP_YYY_add(&x3,&t1,&t2);			//x3.add(t2);
-
-        FP_YYY_sub(&t4,&t4,&x3);			//t4.sub(x3);
-        FP_YYY_norm(&t4);					//t4.norm();
-        FP_YYY_add(&x3,&(P->x),&(P->z));		//x3.add(z);
-        FP_YYY_norm(&x3);					//x3.norm();
-        FP_YYY_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z);
-        FP_YYY_norm(&y3);					//y3.norm();
-        FP_YYY_mul(&x3,&x3,&y3);			//x3.mul(y3);
-
-        FP_YYY_add(&y3,&t0,&t2);			//y3.add(t2);
-        FP_YYY_sub(&y3,&x3,&y3);			//y3.rsub(x3);
-        FP_YYY_norm(&y3);					//y3.norm();
-        FP_YYY_add(&x3,&t0,&t0);			//x3.add(t0);
-        FP_YYY_add(&t0,&t0,&x3);			//t0.add(x3);
-        FP_YYY_norm(&t0);					//t0.norm();
-        FP_YYY_imul(&t2,&t2,b3);				//t2.imul(b);
-
-        FP_YYY_add(&z3,&t1,&t2);			//z3.add(t2);
-        FP_YYY_norm(&z3);					//z3.norm();
-        FP_YYY_sub(&t1,&t1,&t2);			//t1.sub(t2);
-        FP_YYY_norm(&t1);					//t1.norm();
-        FP_YYY_imul(&y3,&y3,b3);				//y3.imul(b);
-
-        FP_YYY_mul(&x3,&y3,&t4);			//x3.mul(t4);
-        FP_YYY_mul(&t2,&t3,&t1);			//t2.mul(t1);
-        FP_YYY_sub(&(P->x),&t2,&x3);			//x3.rsub(t2);
-        FP_YYY_mul(&y3,&y3,&t0);			//y3.mul(t0);
-        FP_YYY_mul(&t1,&t1,&z3);			//t1.mul(z3);
-        FP_YYY_add(&(P->y),&y3,&t1);			//y3.add(t1);
-        FP_YYY_mul(&t0,&t0,&t3);			//t0.mul(t3);
-        FP_YYY_mul(&z3,&z3,&t4);			//z3.mul(t4);
-        FP_YYY_add(&(P->z),&z3,&t0);			//z3.add(t0);
-
-        FP_YYY_norm(&(P->x));				//x.norm();
-        FP_YYY_norm(&(P->y));				//y.norm();
-        FP_YYY_norm(&(P->z));				//z.norm();
+        b3=3*CURVE_B_I_ZZZ;					        //int b=3*ROM.CURVE_B_I
+        FP_YYY_mul(&t0,&(P->x),&(Q->x));	    	//t0.mul(Q.x)
+        FP_YYY_mul(&t1,&(P->y),&(Q->y));	    	//t1.mul(Q.y)
+        FP_YYY_mul(&t2,&(P->z),&(Q->z));	    	//t2.mul(Q.z)
+        FP_YYY_add(&t3,&(P->x),&(P->y));	    	//t3.add(y)
+        FP_YYY_norm(&t3);					        //t3.norm()
+
+        FP_YYY_add(&t4,&(Q->x),&(Q->y));	    	//t4.add(Q.y)
+        FP_YYY_norm(&t4);				          	//t4.norm()
+        FP_YYY_mul(&t3,&t3,&t4);		           	//t3.mul(t4)
+        FP_YYY_add(&t4,&t0,&t1);		        	//t4.add(t1)
+
+        FP_YYY_sub(&t3,&t3,&t4);		        	//t3.sub(t4)
+        FP_YYY_norm(&t3);				        	//t3.norm()
+        FP_YYY_add(&t4,&(P->y),&(P->z));    		//t4.add(z)
+        FP_YYY_norm(&t4);					        //t4.norm()
+        FP_YYY_add(&x3,&(Q->y),&(Q->z));	    	//x3.add(Q.z)
+        FP_YYY_norm(&x3);					        //x3.norm()
+
+        FP_YYY_mul(&t4,&t4,&x3);		   	        //t4.mul(x3)
+        FP_YYY_add(&x3,&t1,&t2);		        	//x3.add(t2)
+
+        FP_YYY_sub(&t4,&t4,&x3);		        	//t4.sub(x3)
+        FP_YYY_norm(&t4);				        	//t4.norm()
+        FP_YYY_add(&x3,&(P->x),&(P->z));	    	//x3.add(z)
+        FP_YYY_norm(&x3);				        	//x3.norm()
+        FP_YYY_add(&y3,&(Q->x),&(Q->z));	    	//y3.add(Q.z)
+        FP_YYY_norm(&y3);				        	//y3.norm()
+        FP_YYY_mul(&x3,&x3,&y3);		        	//x3.mul(y3)
+
+        FP_YYY_add(&y3,&t0,&t2);		        	//y3.add(t2)
+        FP_YYY_sub(&y3,&x3,&y3);	        		//y3.rsub(x3)
+        FP_YYY_norm(&y3);			        		//y3.norm()
+        FP_YYY_add(&x3,&t0,&t0);	        		//x3.add(t0)
+        FP_YYY_add(&t0,&t0,&x3);	        		//t0.add(x3)
+        FP_YYY_norm(&t0);				        	//t0.norm()
+        FP_YYY_imul(&t2,&t2,b3);	        		//t2.imul(b)
+
+        FP_YYY_add(&z3,&t1,&t2);		        	//z3.add(t2)
+        FP_YYY_norm(&z3);				        	//z3.norm()
+        FP_YYY_sub(&t1,&t1,&t2);		        	//t1.sub(t2)
+        FP_YYY_norm(&t1);				        	//t1.norm()
+        FP_YYY_imul(&y3,&y3,b3);		       		//y3.imul(b)
+
+        FP_YYY_mul(&x3,&y3,&t4);			        //x3.mul(t4)
+        FP_YYY_mul(&t2,&t3,&t1);		        	//t2.mul(t1)
+        FP_YYY_sub(&(P->x),&t2,&x3);	    		//x3.rsub(t2)
+        FP_YYY_mul(&y3,&y3,&t0);		        	//y3.mul(t0)
+        FP_YYY_mul(&t1,&t1,&z3);		        	//t1.mul(z3)
+        FP_YYY_add(&(P->y),&y3,&t1);	    		//y3.add(t1)
+        FP_YYY_mul(&t0,&t0,&t3);		        	//t0.mul(t3)
+        FP_YYY_mul(&z3,&z3,&t4);		        	//z3.mul(t4)
+        FP_YYY_add(&(P->z),&z3,&t0);	    		//z3.add(t0)
+
+        FP_YYY_norm(&(P->x));			        	//x.norm()
+        FP_YYY_norm(&(P->y));			        	//y.norm()
+        FP_YYY_norm(&(P->z));			        	//z.norm()
     }
     else
     {
 
-        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
-            FP_YYY_rcopy(&b,CURVE_B_ZZZ);	//b.copy(new FP(new BIG(ROM.CURVE_B)));
-
-        FP_YYY_mul(&t0,&(P->x),&(Q->x));		//t0.mul(Q.x); //1
-        FP_YYY_mul(&t1,&(P->y),&(Q->y));		//t1.mul(Q.y); //2
-        FP_YYY_mul(&t2,&(P->z),&(Q->z));		//t2.mul(Q.z); //3
-
-        FP_YYY_add(&t3,&(P->x),&(P->y));		//t3.add(y);
-        FP_YYY_norm(&t3);					//t3.norm(); //4
-        FP_YYY_add(&t4,&(Q->x),&(Q->y));		//t4.add(Q.y);
-        FP_YYY_norm(&t4);					//t4.norm();//5
-        FP_YYY_mul(&t3,&t3,&t4);			//t3.mul(t4);//6
-
-        FP_YYY_add(&t4,&t0,&t1);			//t4.add(t1); //t4.norm(); //7
-        FP_YYY_sub(&t3,&t3,&t4);			//t3.sub(t4);
-        FP_YYY_norm(&t3);					//t3.norm(); //8
-        FP_YYY_add(&t4,&(P->y),&(P->z));		//t4.add(z);
-        FP_YYY_norm(&t4);					//t4.norm();//9
-        FP_YYY_add(&x3,&(Q->y),&(Q->z));		//x3.add(Q.z);
-        FP_YYY_norm(&x3);					//x3.norm();//10
-        FP_YYY_mul(&t4,&t4,&x3);			//t4.mul(x3); //11
-        FP_YYY_add(&x3,&t1,&t2);			//x3.add(t2); //x3.norm();//12
-
-        FP_YYY_sub(&t4,&t4,&x3);			//t4.sub(x3);
-        FP_YYY_norm(&t4);					//t4.norm();//13
-        FP_YYY_add(&x3,&(P->x),&(P->z));		//x3.add(z);
-        FP_YYY_norm(&x3);					//x3.norm(); //14
-        FP_YYY_add(&y3,&(Q->x),&(Q->z));		//y3.add(Q.z);
-        FP_YYY_norm(&y3);					//y3.norm();//15
-
-        FP_YYY_mul(&x3,&x3,&y3);			//x3.mul(y3); //16
-        FP_YYY_add(&y3,&t0,&t2);			//y3.add(t2); //y3.norm();//17
-
-        FP_YYY_sub(&y3,&x3,&y3);			//y3.rsub(x3);
-        FP_YYY_norm(&y3);					//y3.norm(); //18
-
-        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
-            FP_YYY_mul(&z3,&t2,&b);			//z3.mul(b); //18
+        if (CURVE_B_I_ZZZ==0)			        	//if ROM.CURVE_B_I = 0
+            FP_YYY_rcopy(&b,CURVE_B_ZZZ);	        //b.copy(new FP(new BIG(ROM.CURVE_B)))
+
+        FP_YYY_mul(&t0,&(P->x),&(Q->x));	    	//t0.mul(Q.x) //1
+        FP_YYY_mul(&t1,&(P->y),&(Q->y));	    	//t1.mul(Q.y) //2
+        FP_YYY_mul(&t2,&(P->z),&(Q->z));	    	//t2.mul(Q.z) //3
+
+        FP_YYY_add(&t3,&(P->x),&(P->y));	    	//t3.add(y)
+        FP_YYY_norm(&t3);					        //t3.norm() //4
+        FP_YYY_add(&t4,&(Q->x),&(Q->y));	    	//t4.add(Q.y)
+        FP_YYY_norm(&t4);					        //t4.norm() //5
+        FP_YYY_mul(&t3,&t3,&t4);		        	//t3.mul(t4) //6
+
+        FP_YYY_add(&t4,&t0,&t1);		        	//t4.add(t1) //t4.norm() //7
+        FP_YYY_sub(&t3,&t3,&t4);		        	//t3.sub(t4)
+        FP_YYY_norm(&t3);			        		//t3.norm() //8
+        FP_YYY_add(&t4,&(P->y),&(P->z));	    	//t4.add(z)
+        FP_YYY_norm(&t4);				        	//t4.norm()//9
+        FP_YYY_add(&x3,&(Q->y),&(Q->z));    		//x3.add(Q.z)
+        FP_YYY_norm(&x3);				        	//x3.norm()//10
+        FP_YYY_mul(&t4,&t4,&x3);		        	//t4.mul(x3) //11
+        FP_YYY_add(&x3,&t1,&t2);		        	//x3.add(t2) //x3.norm() //12
+
+        FP_YYY_sub(&t4,&t4,&x3);			        //t4.sub(x3)
+        FP_YYY_norm(&t4);					        //t4.norm() //13
+        FP_YYY_add(&x3,&(P->x),&(P->z));	    	//x3.add(z)
+        FP_YYY_norm(&x3);				        	//x3.norm() //14
+        FP_YYY_add(&y3,&(Q->x),&(Q->z));	    	//y3.add(Q.z)
+        FP_YYY_norm(&y3);				        	//y3.norm() //15
+
+        FP_YYY_mul(&x3,&x3,&y3);		        	//x3.mul(y3) //16
+        FP_YYY_add(&y3,&t0,&t2);		        	//y3.add(t2) //y3.norm()//17
+
+        FP_YYY_sub(&y3,&x3,&y3);		        	//y3.rsub(x3)
+        FP_YYY_norm(&y3);				        	//y3.norm() //18
+
+        if (CURVE_B_I_ZZZ==0)			        	//if ROM.CURVE_B_I = 0
+            FP_YYY_mul(&z3,&t2,&b);		        	//z3.mul(b) //18
         else
-            FP_YYY_imul(&z3,&t2,CURVE_B_I_ZZZ);	//z3.imul(ROM.CURVE_B_I);
+            FP_YYY_imul(&z3,&t2,CURVE_B_I_ZZZ); 	//z3.imul(ROM.CURVE_B_I)
 
-        FP_YYY_sub(&x3,&y3,&z3);			//x3.sub(z3);
-        FP_YYY_norm(&x3);					//x3.norm(); //20
-        FP_YYY_add(&z3,&x3,&x3);			//z3.add(x3); //z3.norm(); //21
+        FP_YYY_sub(&x3,&y3,&z3);			        //x3.sub(z3)
+        FP_YYY_norm(&x3);				        	//x3.norm() //20
+        FP_YYY_add(&z3,&x3,&x3);		        	//z3.add(x3) //z3.norm() //21
 
-        FP_YYY_add(&x3,&x3,&z3);			//x3.add(z3); //x3.norm(); //22
-        FP_YYY_sub(&z3,&t1,&x3);			//z3.sub(x3);
-        FP_YYY_norm(&z3);					//z3.norm(); //23
-        FP_YYY_add(&x3,&x3,&t1);			//x3.add(t1);
-        FP_YYY_norm(&x3);					//x3.norm(); //24
+        FP_YYY_add(&x3,&x3,&z3);		        	//x3.add(z3) //x3.norm() //22
+        FP_YYY_sub(&z3,&t1,&x3);		        	//z3.sub(x3)
+        FP_YYY_norm(&z3);				        	//z3.norm() //23
+        FP_YYY_add(&x3,&x3,&t1);		        	//x3.add(t1)
+        FP_YYY_norm(&x3);				        	//x3.norm() //24
 
-        if (CURVE_B_I_ZZZ==0)				//if (ROM.CURVE_B_I==0)
-            FP_YYY_mul(&y3,&y3,&b);			//y3.mul(b); //18
+        if (CURVE_B_I_ZZZ==0)			        	//if ROM.CURVE_B_I = 0
+            FP_YYY_mul(&y3,&y3,&b);		        	//y3.mul(b) //18
         else
-            FP_YYY_imul(&y3,&y3,CURVE_B_I_ZZZ);	//y3.imul(ROM.CURVE_B_I);
-
-        FP_YYY_add(&t1,&t2,&t2);			//t1.add(t2); //t1.norm();//26
-        FP_YYY_add(&t2,&t2,&t1);			//t2.add(t1); //t2.norm();//27
-
-        FP_YYY_sub(&y3,&y3,&t2);			//y3.sub(t2); //y3.norm(); //28
-
-        FP_YYY_sub(&y3,&y3,&t0);			//y3.sub(t0);
-        FP_YYY_norm(&y3);					//y3.norm(); //29
-        FP_YYY_add(&t1,&y3,&y3);			//t1.add(y3); //t1.norm();//30
-        FP_YYY_add(&y3,&y3,&t1);			//y3.add(t1);
-        FP_YYY_norm(&y3);					//y3.norm(); //31
-
-        FP_YYY_add(&t1,&t0,&t0);			//t1.add(t0); //t1.norm(); //32
-        FP_YYY_add(&t0,&t0,&t1);			//t0.add(t1); //t0.norm();//33
-        FP_YYY_sub(&t0,&t0,&t2);			//t0.sub(t2);
-        FP_YYY_norm(&t0);					//t0.norm();//34
-
-        FP_YYY_mul(&t1,&t4,&y3);			//t1.mul(y3);//35
-        FP_YYY_mul(&t2,&t0,&y3);			//t2.mul(y3);//36
-        FP_YYY_mul(&y3,&x3,&z3);			//y3.mul(z3);//37
-        FP_YYY_add(&(P->y),&y3,&t2);			//y3.add(t2); //y3.norm();//38
-        FP_YYY_mul(&x3,&x3,&t3);			//x3.mul(t3);//39
-        FP_YYY_sub(&(P->x),&x3,&t1);			//x3.sub(t1);//40
-        FP_YYY_mul(&z3,&z3,&t4);			//z3.mul(t4);//41
-
-        FP_YYY_mul(&t1,&t3,&t0);			//t1.mul(t0);//42
-        FP_YYY_add(&(P->z),&z3,&t1);			//z3.add(t1);
-        FP_YYY_norm(&(P->x));				//x.norm();
-
-        FP_YYY_norm(&(P->y));				//y.norm();
-        FP_YYY_norm(&(P->z));				//z.norm();
+            FP_YYY_imul(&y3,&y3,CURVE_B_I_ZZZ); 	//y3.imul(ROM.CURVE_B_I)
+
+        FP_YYY_add(&t1,&t2,&t2);		        	//t1.add(t2) //t1.norm() //26
+        FP_YYY_add(&t2,&t2,&t1);		        	//t2.add(t1) //t2.norm() //27
+
+        FP_YYY_sub(&y3,&y3,&t2);		        	//y3.sub(t2) //y3.norm() //28
+
+        FP_YYY_sub(&y3,&y3,&t0);		        	//y3.sub(t0)
+        FP_YYY_norm(&y3);				        	//y3.norm() //29
+        FP_YYY_add(&t1,&y3,&y3);		        	//t1.add(y3) //t1.norm() //30
+        FP_YYY_add(&y3,&y3,&t1);		        	//y3.add(t1)
+        FP_YYY_norm(&y3);				        	//y3.norm() //31
+
+        FP_YYY_add(&t1,&t0,&t0);		        	//t1.add(t0) //t1.norm() //32
+        FP_YYY_add(&t0,&t0,&t1);		        	//t0.add(t1) //t0.norm() //33
+        FP_YYY_sub(&t0,&t0,&t2);		        	//t0.sub(t2)
+        FP_YYY_norm(&t0);				        	//t0.norm() //34
+
+        FP_YYY_mul(&t1,&t4,&y3);		        	//t1.mul(y3) //35
+        FP_YYY_mul(&t2,&t0,&y3);			        //t2.mul(y3) //36
+        FP_YYY_mul(&y3,&x3,&z3);		        	//y3.mul(z3) //37
+        FP_YYY_add(&(P->y),&y3,&t2);	       		//y3.add(t2) //y3.norm() //38
+        FP_YYY_mul(&x3,&x3,&t3);		        	//x3.mul(t3) //39
+        FP_YYY_sub(&(P->x),&x3,&t1);		    	//x3.sub(t1) //40
+        FP_YYY_mul(&z3,&z3,&t4);			        //z3.mul(t4) //41
+
+        FP_YYY_mul(&t1,&t3,&t0);		        	//t1.mul(t0) //42
+        FP_YYY_add(&(P->z),&z3,&t1);		    	//z3.add(t1)
+        FP_YYY_norm(&(P->x));			        	//x.norm()
+
+        FP_YYY_norm(&(P->y));			        	//y.norm()
+        FP_YYY_norm(&(P->z));			        	//z.norm()
     }
 
 #else
-    FP_YYY A,B,C,D,E,F,G,b;
-
-    FP_YYY_mul(&A,&(P->z),&(Q->z));		//A.mul(Q.z);
-    FP_YYY_sqr(&B,&A);					//B.sqr();
-    FP_YYY_mul(&C,&(P->x),&(Q->x));		//C.mul(Q.x);
-    FP_YYY_mul(&D,&(P->y),&(Q->y));		//D.mul(Q.y);
-    FP_YYY_mul(&E,&C,&D);				//E.mul(D);
-
-    if (CURVE_B_I_ZZZ==0)			//if (ROM.CURVE_B_I==0)
+    FP_YYY A;
+    FP_YYY B;
+    FP_YYY C;
+    FP_YYY D;
+    FP_YYY E;
+    FP_YYY F;
+    FP_YYY G;
+    FP_YYY b;
+
+    FP_YYY_mul(&A,&(P->z),&(Q->z));		            //A.mul(Q.z)
+    FP_YYY_sqr(&B,&A);				            	//B.sqr()
+    FP_YYY_mul(&C,&(P->x),&(Q->x));	            	//C.mul(Q.x)
+    FP_YYY_mul(&D,&(P->y),&(Q->y));	            	//D.mul(Q.y)
+    FP_YYY_mul(&E,&C,&D);			            	//E.mul(D)
+
+    if (CURVE_B_I_ZZZ==0)			                //if ROM.CURVE_B_I = 0
     {
-        FP_YYY_rcopy(&b,CURVE_B_ZZZ);	//FP b=new FP(new BIG(ROM.CURVE_B));
-        FP_YYY_mul(&E,&E,&b);			//E.mul(b);
+        FP_YYY_rcopy(&b,CURVE_B_ZZZ);	            //FP b=new FP(new BIG(ROM.CURVE_B))
+        FP_YYY_mul(&E,&E,&b);		            	//E.mul(b)
     }
     else
-        FP_YYY_imul(&E,&E,CURVE_B_I_ZZZ);	//E.imul(ROM.CURVE_B_I);
+        FP_YYY_imul(&E,&E,CURVE_B_I_ZZZ);	        //E.imul(ROM.CURVE_B_I)
 
-    FP_YYY_sub(&F,&B,&E);			//F.sub(E);
-    FP_YYY_add(&G,&B,&E);			//G.add(E);
+    FP_YYY_sub(&F,&B,&E);		                	//F.sub(E)
+    FP_YYY_add(&G,&B,&E);		                	//G.add(E)
 
-    if (CURVE_A_ZZZ==1)				//if (ROM.CURVE_A==1)
+    if (CURVE_A_ZZZ==1)			                	//if ROM.CURVE_A = 1
     {
-        FP_YYY_sub(&E,&D,&C);		//E.sub(C);
+        FP_YYY_sub(&E,&D,&C);		                //E.sub(C)
     }
-    FP_YYY_add(&C,&C,&D);			//C.add(D);
-    FP_YYY_add(&B,&(P->x),&(P->y));		//B.add(y);
-
-    FP_YYY_add(&D,&(Q->x),&(Q->y));		//D.add(Q.y);
-    FP_YYY_norm(&B);				//B.norm();
-    FP_YYY_norm(&D);				//D.norm();
-    FP_YYY_mul(&B,&B,&D);			//B.mul(D);
-    FP_YYY_sub(&B,&B,&C);			//B.sub(C);
-    FP_YYY_norm(&B);				//B.norm();
-    FP_YYY_norm(&F);				//F.norm();
-    FP_YYY_mul(&B,&B,&F);			//B.mul(F);
-    FP_YYY_mul(&(P->x),&A,&B); //x.mul(B);
-    FP_YYY_norm(&G);				//G.norm();
-
-    if (CURVE_A_ZZZ==1)				//if (ROM.CURVE_A==1)
+FP_YYY_add(&C,&C,&D);                               //C.add(D)
+    FP_YYY_add(&B,&(P->x),&(P->y));	            	//B.add(y)
+
+    FP_YYY_add(&D,&(Q->x),&(Q->y));	            	//D.add(Q.y)
+    FP_YYY_norm(&B);				                //B.norm()
+    FP_YYY_norm(&D);			                	//D.norm()
+    FP_YYY_mul(&B,&B,&D);			                //B.mul(D)
+    FP_YYY_sub(&B,&B,&C);		                	//B.sub(C)
+    FP_YYY_norm(&B);			                	//B.norm()
+    FP_YYY_norm(&F);			                	//F.norm()
+    FP_YYY_mul(&B,&B,&F);		                	//B.mul(F)
+    FP_YYY_mul(&(P->x),&A,&B);                      //x.mul(B)
+    FP_YYY_norm(&G);			                   	//G.norm()
+
+    if (CURVE_A_ZZZ==1)			                	//if ROM.CURVE_A = 1
     {
-        FP_YYY_norm(&E);			//E.norm();
-        FP_YYY_mul(&C,&E,&G);		//C.mul(G);
+        FP_YYY_norm(&E);		                	//E.norm()
+        FP_YYY_mul(&C,&E,&G);		                //C.mul(G)
     }
-    if (CURVE_A_ZZZ==-1)			//if (ROM.CURVE_A==-1)
+    if (CURVE_A_ZZZ==-1)			                //if ROM.CURVE_A = -1
     {
-        FP_YYY_norm(&C);			//C.norm();
-        FP_YYY_mul(&C,&C,&G);		//C.mul(G);
+        FP_YYY_norm(&C);		                	//C.norm()
+        FP_YYY_mul(&C,&C,&G);	                   	//C.mul(G)
     }
-    FP_YYY_mul(&(P->y),&A,&C);	//y.mul(C);
-    FP_YYY_mul(&(P->z),&F,&G);	//z.mul(G);
+    FP_YYY_mul(&(P->y),&A,&C);	                    //y.mul(C)
+    FP_YYY_mul(&(P->z),&F,&G);                  	//z.mul(G)
 
 #endif
 }
 
 /* Set P-=Q */
 /* SU=16 */
-void  ECP_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q)
+void  ECP_ZZZ_sub(ECP_ZZZ *P,const ECP_ZZZ *Q)
 {
     ECP_ZZZ NQ;
     ECP_ZZZ_copy(&NQ,Q);
@@ -994,14 +1027,15 @@ void  ECP_ZZZ_sub(ECP_ZZZ *P,ECP_ZZZ *Q)
 /* constant time multiply by small integer of length bts - use ladder */
 void ECP_ZZZ_pinmul(ECP_ZZZ *P,int e,int bts)
 {
-    int i,b;
-    ECP_ZZZ R0,R1;
+    int b;
+    ECP_ZZZ R0;
+    ECP_ZZZ R1;
 
     ECP_ZZZ_affine(P);
     ECP_ZZZ_inf(&R0);
     ECP_ZZZ_copy(&R1,P);
 
-    for (i=bts-1; i>=0; i--)
+    for (int i=bts-1; i>=0; i--)
     {
         b=(e>>i)&1;
         ECP_ZZZ_copy(P,&R1);
@@ -1018,12 +1052,14 @@ void ECP_ZZZ_pinmul(ECP_ZZZ *P,int e,int bts)
 
 /* Set P=r*P */
 /* SU=424 */
-void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
+void ECP_ZZZ_mul(ECP_ZZZ *P,const BIG_XXX e)
 {
 #if CURVETYPE_ZZZ==MONTGOMERY
     /* Montgomery ladder */
-    int nb,i,b;
-    ECP_ZZZ R0,R1,D;
+    int b;
+    ECP_ZZZ R0;
+    ECP_ZZZ R1;
+    ECP_ZZZ D;
     if (ECP_ZZZ_isinf(P)) return;
     if (BIG_XXX_iszilch(e))
     {
@@ -1038,8 +1074,7 @@ void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
     ECP_ZZZ_copy(&D,P);
     ECP_ZZZ_affine(&D);
 
-    nb=BIG_XXX_nbits(e);
-    for (i=nb-2; i>=0; i--)
+    for (int i=BIGBITS_XXX-2; i>=0; i--)
     {
         b=BIG_XXX_bit(e,i);
         ECP_ZZZ_copy(P,&R1);
@@ -1055,9 +1090,15 @@ void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
 
 #else
     /* fixed size windows */
-    int i,nb,s,ns;
-    BIG_XXX mt,t;
-    ECP_ZZZ Q,W[8],C;
+    int i;
+    int nb;
+    int s;
+    int ns;
+    BIG_XXX mt;
+    BIG_XXX t;
+    ECP_ZZZ Q;
+    ECP_ZZZ W[8];
+    ECP_ZZZ C;
     sign8 w[1+(NLEN_XXX*BASEBITS_XXX+3)/4];
 
     if (ECP_ZZZ_isinf(P)) return;
@@ -1082,8 +1123,6 @@ void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
         ECP_ZZZ_add(&W[i],&Q);
     }
 
-//printf("W[1]= ");ECP_output(&W[1]); printf("\n");
-
     /* make exponent odd - add 2P if even, P if odd */
     BIG_XXX_copy(t,e);
     s=BIG_XXX_parity(t);
@@ -1097,17 +1136,17 @@ void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
     ECP_ZZZ_cmove(&Q,P,ns);
     ECP_ZZZ_copy(&C,&Q);
 
-    nb=1+(BIG_XXX_nbits(t)+3)/4;
+    nb=1+(BIGBITS_XXX+3)/4;
 
     /* convert exponent to signed 4-bit window */
     for (i=0; i<nb; i++)
     {
-        w[i]=BIG_XXX_lastbits(t,5)-16;
+        w[i]=(signed char)(BIG_XXX_lastbits(t,5)-16);
         BIG_XXX_dec(t,w[i]);
         BIG_XXX_norm(t);
         BIG_XXX_fshr(t,4);
     }
-    w[nb]=BIG_XXX_lastbits(t,5);
+    w[nb]=(signed char)BIG_XXX_lastbits(t,5);
 
     ECP_ZZZ_copy(P,&W[(w[nb]-1)/2]);
     for (i=nb-1; i>=0; i--)
@@ -1129,12 +1168,22 @@ void ECP_ZZZ_mul(ECP_ZZZ *P,BIG_XXX e)
 /* constant time - as useful for GLV method in pairings */
 /* SU=456 */
 
-void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f)
+void ECP_ZZZ_mul2(ECP_ZZZ *P,const ECP_ZZZ *Q,const BIG_XXX e,const BIG_XXX f)
 {
-    BIG_XXX te,tf,mt;
-    ECP_ZZZ S,T,W[8],C;
+    BIG_XXX te;
+    BIG_XXX tf;
+    BIG_XXX mt;
+    ECP_ZZZ S;
+    ECP_ZZZ T;
+    ECP_ZZZ W[8];
+    ECP_ZZZ C;
     sign8 w[1+(NLEN_XXX*BASEBITS_XXX+1)/2];
-    int i,a,b,s,ns,nb;
+    int i;
+    int a;
+    int b;
+    int s;
+    int ns;
+    int nb;
 
     BIG_XXX_copy(te,e);
     BIG_XXX_copy(tf,f);
@@ -1187,7 +1236,7 @@ void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f)
 
     BIG_XXX_add(mt,te,tf);
     BIG_XXX_norm(mt);
-    nb=1+(BIG_XXX_nbits(mt)+1)/2;
+    nb=1+(BIGBITS_XXX+1)/2;
 
     /* convert exponent to signed 2-bit window */
     for (i=0; i<nb; i++)
@@ -1200,9 +1249,9 @@ void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f)
         BIG_XXX_dec(tf,b);
         BIG_XXX_norm(tf);
         BIG_XXX_fshr(tf,2);
-        w[i]=4*a+b;
+        w[i]=(signed char)(4*a+b);
     }
-    w[nb]=(4*BIG_XXX_lastbits(te,3)+BIG_XXX_lastbits(tf,3));
+    w[nb]=(signed char)(4*BIG_XXX_lastbits(te,3)+BIG_XXX_lastbits(tf,3));
 
     ECP_ZZZ_copy(P,&W[(w[nb]-1)/2]);
     for (i=nb-1; i>=0; i--)
@@ -1220,7 +1269,8 @@ void ECP_ZZZ_mul2(ECP_ZZZ *P,ECP_ZZZ *Q,BIG_XXX e,BIG_XXX f)
 
 void ECP_ZZZ_generator(ECP_ZZZ *G)
 {
-    BIG_XXX x,y;
+    BIG_XXX x;
+    BIG_XXX y;
     BIG_XXX_rcopy(x,CURVE_Gx_ZZZ);
 #if CURVETYPE_ZZZ!=MONTGOMERY
     BIG_XXX_rcopy(y,CURVE_Gy_ZZZ);
@@ -1230,60 +1280,85 @@ void ECP_ZZZ_generator(ECP_ZZZ *G)
 #endif
 }
 
-#ifdef HAS_MAIN
-
-int main()
-{
-    int i;
-    ECP_ZZZ G,P;
-    csprng RNG;
-    BIG_XXX r,s,x,y,b,m,w,q;
-    BIG_XXX_rcopy(x,CURVE_Gx);
-#if CURVETYPE_ZZZ!=MONTGOMERY
-    BIG_XXX_rcopy(y,CURVE_Gy);
-#endif
-    BIG_XXX_rcopy(m,Modulus_YYY);
-
-    printf("x= ");
-    BIG_XXX_output(x);
-    printf("\n");
-#if CURVETYPE_ZZZ!=MONTGOMERY
-    printf("y= ");
-    BIG_XXX_output(y);
-    printf("\n");
-#endif
-    RNG_seed(&RNG,3,"abc");
-
-#if CURVETYPE_ZZZ!=MONTGOMERY
-    ECP_ZZZ_set(&G,x,y);
-#else
-    ECP_ZZZ_set(&G,x);
-#endif
-    if (ECP_ZZZ_isinf(&G)) printf("Failed to set - point not on curve\n");
-    else printf("set success\n");
-
-    ECP_ZZZ_output(&G);
 
-    BIG_XXX_rcopy(r,CURVE_Order); //BIG_dec(r,7);
-    printf("r= ");
-    BIG_XXX_output(r);
-    printf("\n");
+#if (PAIRING_FRIENDLY_ZZZ == BLS && CURVE_SECURITY_ZZZ == 128)
 
-    ECP_ZZZ_copy(&P,&G);
-
-    ECP_ZZZ_mul(&P,r);
+/**
+ * @brief Implemenst the sgn0 function as defined at
+ * https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-the-sgn0-function (ยง 4.1)
+ * 
+ * @param a Finite field element
+ * 
+ * @return either 0 or 1 indicating the "sign" of a
+ */
+static inline int sgn0_fp(FP_YYY a)
+{
+    BIG_XXX b;
+    FP_YYY_redc(b, &a);
+    return BIG_XXX_parity(b);
+}
 
-    ECP_ZZZ_output(&P);
-//exit(0);
-    BIG_XXX_randomnum(w,&RNG);
-    BIG_XXX_mod(w,r);
+int ECP_ZZZ_sswu(FP_YYY *x, FP_YYY *y, FP_YYY u)
+{
+    if (x == NULL || y == NULL)
+        return -1;
+
+    FP_YYY a;
+    FP_YYY b;
+    FP_YYY z;
+    FP_YYY gx;
+    FP_YYY tv1;
+    FP_YYY tmp;
+
+    FP_YYY_nres(&a, SSWU_A1_ZZZ);
+    FP_YYY_nres(&b, SSWU_B1_ZZZ);
+    FP_YYY_nres(&z, SSWU_Z1_ZZZ);
+    FP_YYY_one(&gx);
+
+    // tv1 = 1 / (Z^2 * u^4 + Z * u^2)
+    FP_YYY_sqr(&tmp, &u);
+    FP_YYY_mul(&tmp, &tmp, &z);
+    FP_YYY_sqr(&tv1, &tmp);
+    FP_YYY_add(&tv1, &tv1, &tmp);
+    FP_YYY_inv(&tv1, &tv1);
+
+    // x = (-B / A) * (1 + tv1)
+    FP_YYY_add(x, &tv1, &gx);
+    FP_YYY_mul(x, x, &b);
+    FP_YYY_neg(x, x);
+    FP_YYY_inv(&gx, &a);
+    FP_YYY_mul(x, x, &gx);
+
+    // if tv1 == 0, set x = B / (Z * A)
+    if (FP_YYY_iszilch(&tv1)) {
+        FP_YYY_mul(x, &b, &gx);
+        FP_YYY_inv(&gx, &z);
+        FP_YYY_mul(x, x, &gx);
+    }
 
-    ECP_ZZZ_copy(&P,&G);
-    ECP_ZZZ_mul(&P,w);
+    // gx = x^3 + A * x + B
+    FP_YYY_sqr(&gx, x);
+    FP_YYY_add(&gx, &gx, &a);
+    FP_YYY_mul(&gx, &gx, x);
+    FP_YYY_add(&gx, &gx, &b);
+    // y = sqrt(gx)
+    FP_YYY_sqrt(y, &gx);
+    // tv1 = y^2
+    FP_YYY_sqr(&tv1, y);
+
+    // If !(is_square(gx)), set x = Z * u^2 * x1 and y = sqrt(x2^3 + A * x2 + B)
+    if (!FP_YYY_equals(&gx, &tv1)) {
+        FP_YYY_mul(x, x, &tmp);
+        FP_YYY_sqr(&gx, x);
+        FP_YYY_add(&gx, &gx, &a);
+        FP_YYY_mul(&gx, &gx, x);
+        FP_YYY_add(&gx, &gx, &b);
+        FP_YYY_sqrt(y, &gx);
+    }
 
-    ECP_ZZZ_output(&P);
+    if (sgn0_fp(*y) != sgn0_fp(u))
+        FP_YYY_neg(y, y);
 
-    return 0;
+    return SUCCESS;
 }
-
 #endif
diff --git a/src/ecp2.c.in b/src/ecp2.c.in
index 6061d98..586c1fb 100644
--- a/src/ecp2.c.in
+++ b/src/ecp2.c.in
@@ -22,14 +22,14 @@ under the License.
 
 #include "ecp2_ZZZ.h"
 
-int ECP2_ZZZ_isinf(ECP2_ZZZ *P)
+int ECP2_ZZZ_isinf(const ECP2_ZZZ *P)
 {
     return (FP2_YYY_iszilch(&(P->x)) & FP2_YYY_iszilch(&(P->z)));
 }
 
 /* Set P=Q */
 /* SU= 16 */
-void ECP2_ZZZ_copy(ECP2_ZZZ *P,ECP2_ZZZ *Q)
+void ECP2_ZZZ_copy(ECP2_ZZZ *P,const ECP2_ZZZ *Q)
 {
     FP2_YYY_copy(&(P->x),&(Q->x));
     FP2_YYY_copy(&(P->y),&(Q->y));
@@ -46,7 +46,7 @@ void ECP2_ZZZ_inf(ECP2_ZZZ *P)
 }
 
 /* Conditional move Q to P dependant on d */
-static void ECP2_ZZZ_cmove(ECP2_ZZZ *P,ECP2_ZZZ *Q,int d)
+static void ECP2_ZZZ_cmove(ECP2_ZZZ *P,const ECP2_ZZZ *Q,int d)
 {
     FP2_YYY_cmove(&(P->x),&(Q->x),d);
     FP2_YYY_cmove(&(P->y),&(Q->y),d);
@@ -58,11 +58,11 @@ static int teq(sign32 b,sign32 c)
 {
     sign32 x=b^c;
     x-=1;  // if x=0, x now -1
-    return (int)((x>>31)&1);
+    return (x>>31)&1;
 }
 
 /* Constant time select from pre-computed table */
-static void ECP2_ZZZ_select(ECP2_ZZZ *P,ECP2_ZZZ W[],sign32 b)
+static void ECP2_ZZZ_select(ECP2_ZZZ *P,const ECP2_ZZZ W[],sign32 b)
 {
     ECP2_ZZZ MP;
     sign32 m=b>>31;
@@ -81,14 +81,15 @@ static void ECP2_ZZZ_select(ECP2_ZZZ *P,ECP2_ZZZ W[],sign32 b)
 
     ECP2_ZZZ_copy(&MP,P);
     ECP2_ZZZ_neg(&MP);  // minus P
-    ECP2_ZZZ_cmove(P,&MP,(int)(m&1));
+    ECP2_ZZZ_cmove(P,&MP,m&1);
 }
 
 /* return 1 if P==Q, else 0 */
 /* SU= 312 */
 int ECP2_ZZZ_equals(ECP2_ZZZ *P,ECP2_ZZZ *Q)
 {
-    FP2_YYY a,b;
+    FP2_YYY a;
+    FP2_YYY b;
 
     FP2_YYY_mul(&a,&(P->x),&(Q->z));
     FP2_YYY_mul(&b,&(Q->x),&(P->z));
@@ -104,7 +105,8 @@ int ECP2_ZZZ_equals(ECP2_ZZZ *P,ECP2_ZZZ *Q)
 /* SU= 232 */
 void ECP2_ZZZ_affine(ECP2_ZZZ *P)
 {
-    FP2_YYY one,iz;
+    FP2_YYY one;
+    FP2_YYY iz;
     if (ECP2_ZZZ_isinf(P)) return;
 
     FP2_YYY_one(&one);
@@ -126,7 +128,7 @@ void ECP2_ZZZ_affine(ECP2_ZZZ *P)
 
 /* extract x, y from point P */
 /* SU= 16 */
-int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,ECP2_ZZZ *P)
+int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,const ECP2_ZZZ *P)
 {
     ECP2_ZZZ W;
     ECP2_ZZZ_copy(&W,P);
@@ -139,9 +141,10 @@ int ECP2_ZZZ_get(FP2_YYY *x,FP2_YYY *y,ECP2_ZZZ *P)
 
 /* SU= 152 */
 /* Output point P */
-void ECP2_ZZZ_output(ECP2_ZZZ *P)
+void ECP2_ZZZ_output(const ECP2_ZZZ *P)
 {
-    FP2_YYY x,y;
+    FP2_YYY x;
+    FP2_YYY y;
     if (ECP2_ZZZ_isinf(P))
     {
         printf("Infinity\n");
@@ -156,7 +159,7 @@ void ECP2_ZZZ_output(ECP2_ZZZ *P)
 }
 
 /* SU= 232 */
-void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P)
+void ECP2_ZZZ_outputxyz(const ECP2_ZZZ *P)
 {
     ECP2_ZZZ Q;
     if (ECP2_ZZZ_isinf(P))
@@ -176,10 +179,11 @@ void ECP2_ZZZ_outputxyz(ECP2_ZZZ *P)
 
 /* SU= 168 */
 /* Convert Q to octet string */
-void ECP2_ZZZ_toOctet(octet *W,ECP2_ZZZ *Q)
+void ECP2_ZZZ_toOctet(octet *W,const ECP2_ZZZ *Q)
 {
     BIG_XXX b;
-    FP2_YYY qx,qy;
+    FP2_YYY qx;
+    FP2_YYY qy;
     ECP2_ZZZ_get(&qx,&qy,Q);
 
     FP_YYY_redc(b,&(qx.a));
@@ -197,10 +201,11 @@ void ECP2_ZZZ_toOctet(octet *W,ECP2_ZZZ *Q)
 
 /* SU= 176 */
 /* restore Q from octet string */
-int ECP2_ZZZ_fromOctet(ECP2_ZZZ *Q,octet *W)
+int ECP2_ZZZ_fromOctet(ECP2_ZZZ *Q,const octet *W)
 {
     BIG_XXX b;
-    FP2_YYY qx,qy;
+    FP2_YYY qx;
+    FP2_YYY qy;
     BIG_XXX_fromBytes(b,&(W->val[0]));
     FP_YYY_nres(&(qx.a),b);
     BIG_XXX_fromBytes(b,&(W->val[MODBYTES_XXX]));
@@ -216,7 +221,7 @@ int ECP2_ZZZ_fromOctet(ECP2_ZZZ *Q,octet *W)
 
 /* SU= 128 */
... 16196 lines suppressed ...