[Cryptech-Commits] [user/sra/libhal] 02/15: Add csprng and hash modules. Add real error codes instead of magic numbers, and propegate error codes up from lower layers. Whack C++-isms, add parenthesese to a lot of macro expressions for evaluation safety, other minor cleanup.

git at cryptech.is git at cryptech.is
Mon May 25 21:04:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

sra at hactrn.net pushed a commit to branch master
in repository user/sra/libhal.

commit fa13a8485ce07aecfbfa481baccfc33565f0be0d
Author: Rob Austein <sra at hactrn.net>
Date:   Wed May 20 16:57:33 2015 -0400

    Add csprng and hash modules.  Add real error codes instead of magic
    numbers, and propegate error codes up from lower layers.  Whack
    C++-isms, add parenthesese to a lot of macro expressions for
    evaluation safety, other minor cleanup.
---
 Makefile.in  |  40 ++--
 configure.ac |  20 +-
 cryptech.h   | 740 +++++++++++++++++++++++++++++++----------------------------
 csprng.c     |  93 ++++++++
 hal_io_eim.c |  65 +++---
 hal_io_i2c.c | 211 ++++++++++-------
 hash.c       | 376 ++++++++++++++++++++++++++++++
 7 files changed, 1043 insertions(+), 502 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index 02ce7c7..b03924b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,46 +1,36 @@
 # @configure_input@
 
-INC = cryptech.h
-LIB = libcryptech.a
+INC		= cryptech.h
+LIB		= libcryptech.a
+OBJ		= ${IO_OBJ} csprng.o hash.o
 
-BIN = hash hash_tester trng_extractor trng_tester aes_tester modexp_tester
-
-HAL_IO_OBJ_EIM	= hal_io_eim.o novena-eim.o
-HAL_IO_OBJ_I2C 	= hal_io_i2c.o
-HAL_IO_OBJ	= $(HAL_IO_OBJ_ at FPGA_BUS@)
-
-LIB_OBJ		= $(HAL_IO_OBJ)
+IO_OBJ		= ${IO_OBJ_ at FPGA_BUS@}
+IO_OBJ_EIM	= hal_io_eim.o novena-eim.o
+IO_OBJ_I2C 	= hal_io_i2c.o
 
 CC		= @CC@
 CFLAGS		= @CFLAGS@
 LDFLAGS		= @LDFLAGS@
-LIBS		= @LIBS@
 
 prefix		= @prefix@
 exec_prefix	= @exec_prefix@
-bindir		= @bindir@
 includedir	= @includedir@
 libdir		= @libdir@
-sysconfdir	= @sysconfdir@
-
-all: $(LIB) $(BIN)
 
-*.o: $(INC)
+all: ${LIB}
 
-$(BIN): $(LIB)
+${OBJ}: ${INC}
 
-${LIB}: $(LIB_OBJ)
+${LIB}: ${OBJ}
 	ar rcs $@ $^
 
-install: $(LIB) $(BIN) $(INC)
-	install $(LIB) $(libdir)
-	install $(BIN) $(bindir)
-	install $(INC) $(includedir)
+install: ${LIB} ${INC}
+	install ${LIB} ${libdir}
+	install ${INC} ${includedir}
 
 uninstall:
-	cd $(libdir); rm -f $(LIB)
-	cd $(bindir); rm -f ${BIN}
-	cd $(includedir); rm -f $(INC)
+	cd ${libdir}; rm -f ${LIB}
+	cd ${includedir}; rm -f ${INC}
 
 clean:
-	rm -f *.o $(LIB) $(BIN)
+	rm -f ${OBJ} ${LIB}
diff --git a/configure.ac b/configure.ac
index 43db468..07cd236 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,23 +17,13 @@ AC_ARG_VAR([CC],	[C compiler command])
 AC_ARG_VAR([CFLAGS],	[C compiler flags])
 AC_ARG_VAR([LDFLAGS],	[Linker flags])
 
-AS_CASE($FPGA_BUS,
-	[""],[FPGA_BUS=EIM],
-	[EIM|I2C],[],
+AS_CASE($FPGA_BUS, [""],[FPGA_BUS=EIM], [EIM|I2C],[],
 	[AC_MSG_ERROR([Invalid setting of FPGA_BUS, must be "EIM" or "I2C"])])
-
-AS_CASE($CC,
-	[""],[CC="cc"],
-	[])
-	
-AS_CASE($CFLAGS,
-	[""],[CFLAGS="-g -Wall -fPIC"],
-	[])
-	
-AS_CASE($LDFLAGS,
-	[""],[LDFLAGS="-g"],
-	[])
 	
+AS_CASE($CC,      [""],[CC="cc"],		  [])
+AS_CASE($CFLAGS,  [""],[CFLAGS="-g -Wall -fPIC"], [])
+AS_CASE($LDFLAGS, [""],[LDFLAGS="-g"],		  [])
+
 AC_MSG_NOTICE([FPGA bus: $FPGA_BUS])
 AC_MSG_NOTICE([C compiler: $CC])
 AC_MSG_NOTICE([C compiler flags: $CFLAGS])
diff --git a/cryptech.h b/cryptech.h
index 9a10c58..903fbd4 100644
--- a/cryptech.h
+++ b/cryptech.h
@@ -1,124 +1,122 @@
-//======================================================================
-//
-// cryptech.h
-// ----------
-// Memory map and access functions for Cryptech cores.
-//
-//
-// Authors: Joachim Strombergson, Paul Selkirk
-// Copyright (c) 2015, NORDUnet A/S All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-// - Redistributions of source code must retain the above copyright notice,
-//   this list of conditions and the following disclaimer.
-//
-// - Redistributions in binary form must reproduce the above copyright
-//   notice, this list of conditions and the following disclaimer in the
-//   documentation and/or other materials provided with the distribution.
-//
-// - Neither the name of the NORDUnet nor the names of its contributors may
-//   be used to endorse or promote products derived from this software
-//   without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-//======================================================================
-
 /*
+ * cryptech.h
+ * ----------
+ * Memory map and access functions for Cryptech cores.
+ *
+ * Authors: Joachim Strombergson, Paul Selkirk
+ * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
-Each Cryptech core has a set of 4-byte registers, which are accessed
-through a 16-bit address. The address space is divided as follows:
-  3 bits segment selector       | up to 8 segments
-  5 bits core selector          | up to 32 cores/segment (see note below)
-  8 bits register selector      | up to 256 registers/core (see modexp below)
-
-i.e, the address is structured as:
-sss ccccc rrrrrrrr
-
-The I2C and UART communication channels use this 16-bit address format
-directly in their read and write commands.
-
-The EIM communications channel translates this 16-bit address into a
-32-bit memory-mapped address in the range 0x08000000..807FFFF:
-00001000000000 sss 0 ccccc rrrrrrrr 00
-
-EIM, as implemented on the Novena, uses a 19-bit address space:
-  Bits 18..16 are the semgent selector.
-  Bits 15..10 are the core selector.
-  Bits 9..2 are the register selector.
-  Bits 1..0 are zero, because reads and writes are always word aligned.
-
-Note that EIM can support 64 cores per segment, but we sacrifice one bit
-in order to map it into a 16-bit address space.
-
-*/
-
-
-//------------------------------------------------------------------
-// Default sizes
-//------------------------------------------------------------------
-#define CORE_SIZE               0x100
-#define SEGMENT_SIZE            0x20 * CORE_SIZE
+/*
+ * Each Cryptech core has a set of 4-byte registers, which are accessed
+ * through a 16-bit address. The address space is divided as follows:
+ *   3 bits segment selector       | up to 8 segments
+ *   5 bits core selector          | up to 32 cores/segment (see note below)
+ *   8 bits register selector      | up to 256 registers/core (see modexp below)
+ * 
+ * i.e, the address is structured as:
+ * sss ccccc rrrrrrrr
+ * 
+ * The I2C and UART communication channels use this 16-bit address format
+ * directly in their read and write commands.
+ * 
+ * The EIM communications channel translates this 16-bit address into a
+ * 32-bit memory-mapped address in the range 0x08000000..807FFFF:
+ * 00001000000000 sss 0 ccccc rrrrrrrr 00
+ * 
+ * EIM, as implemented on the Novena, uses a 19-bit address space:
+ *   Bits 18..16 are the semgent selector.
+ *   Bits 15..10 are the core selector.
+ *   Bits 9..2 are the register selector.
+ *   Bits 1..0 are zero, because reads and writes are always word aligned.
+ * 
+ * Note that EIM can support 64 cores per segment, but we sacrifice one bit
+ * in order to map it into a 16-bit address space.
+ */
+
+#ifndef _CRYPTECH_H_
+#define _CRYPTECH_H_
 
 
-//------------------------------------------------------------------
-// Segments
-//------------------------------------------------------------------
-#define SEGMENT_OFFSET_GLOBALS  0 * SEGMENT_SIZE
-#define SEGMENT_OFFSET_HASHES   1 * SEGMENT_SIZE
-#define SEGMENT_OFFSET_RNGS     2 * SEGMENT_SIZE
-#define SEGMENT_OFFSET_CIPHERS  3 * SEGMENT_SIZE
-#define SEGMENT_OFFSET_MATH     4 * SEGMENT_SIZE
+/*
+ * Default sizes.
+ */
+#define CORE_SIZE               (0x100)
+#define SEGMENT_SIZE            (0x20 * CORE_SIZE)
 
 
-//------------------------------------------------------------------
-// Addresses and codes common to all cores
-//------------------------------------------------------------------
-#define ADDR_NAME0              0x00
-#define ADDR_NAME1              0x01
-#define ADDR_VERSION            0x02
-#define ADDR_CTRL               0x08
-#define CTRL_INIT               1
-#define CTRL_NEXT               2
-#define ADDR_STATUS             0x09
-#define STATUS_READY            1
-#define STATUS_VALID            2
+/*
+ * Segments.
+ */
+#define SEGMENT_OFFSET_GLOBALS  (0 * SEGMENT_SIZE)
+#define SEGMENT_OFFSET_HASHES   (1 * SEGMENT_SIZE)
+#define SEGMENT_OFFSET_RNGS     (2 * SEGMENT_SIZE)
+#define SEGMENT_OFFSET_CIPHERS  (3 * SEGMENT_SIZE)
+#define SEGMENT_OFFSET_MATH     (4 * SEGMENT_SIZE)
 
 
-// a handy macro from cryptlib
+/*
+ * Addresses and codes common to all cores.
+ */
+#define ADDR_NAME0              (0x00)
+#define ADDR_NAME1              (0x01)
+#define ADDR_VERSION            (0x02)
+#define ADDR_CTRL               (0x08)
+#define CTRL_INIT               (1)
+#define CTRL_NEXT               (2)
+#define ADDR_STATUS             (0x09)
+#define STATUS_READY            (1)
+#define STATUS_VALID            (2)
+
+
+/* A handy macro from cryptlib */
 #ifndef bitsToBytes
 #define bitsToBytes(x)          (x / 8)
 #endif
 
 
-//------------------------------------------------------------------
-// Board segment.
-// Board-level registers and communication channel registers
-//------------------------------------------------------------------
-#define BOARD_ADDR_BASE         SEGMENT_OFFSET_GLOBALS + (0 * CORE_SIZE)
-#define BOARD_ADDR_NAME0        BOARD_ADDR_BASE + ADDR_NAME0
-#define BOARD_ADDR_NAME1        BOARD_ADDR_BASE + ADDR_NAME1
-#define BOARD_ADDR_VERSION      BOARD_ADDR_BASE + ADDR_VERSION
-#define BOARD_ADDR_DUMMY        BOARD_ADDR_BASE + 0xFF
-
-#define COMM_ADDR_BASE          SEGMENT_OFFSET_GLOBALS + (1 * CORE_SIZE)
-#define COMM_ADDR_NAME0         COMM_ADDR_BASE + ADDR_NAME0
-#define COMM_ADDR_NAME1         COMM_ADDR_BASE + ADDR_NAME1
-#define COMM_ADDR_VERSION       COMM_ADDR_BASE + ADDR_VERSION
-
-// current name and version values
+/*
+ * Board segment.
+ * Board-level registers and communication channel registers.
+ */
+#define BOARD_ADDR_BASE         (SEGMENT_OFFSET_GLOBALS + (0 * CORE_SIZE))
+#define BOARD_ADDR_NAME0        (BOARD_ADDR_BASE + ADDR_NAME0)
+#define BOARD_ADDR_NAME1        (BOARD_ADDR_BASE + ADDR_NAME1)
+#define BOARD_ADDR_VERSION      (BOARD_ADDR_BASE + ADDR_VERSION)
+#define BOARD_ADDR_DUMMY        (BOARD_ADDR_BASE + 0xFF)
+
+#define COMM_ADDR_BASE          (SEGMENT_OFFSET_GLOBALS + (1 * CORE_SIZE))
+#define COMM_ADDR_NAME0         (COMM_ADDR_BASE + ADDR_NAME0)
+#define COMM_ADDR_NAME1         (COMM_ADDR_BASE + ADDR_NAME1)
+#define COMM_ADDR_VERSION       (COMM_ADDR_BASE + ADDR_VERSION)
+
+/* Current name and version values */
 #define NOVENA_BOARD_NAME0      "PVT1"
 #define NOVENA_BOARD_NAME1      "    "
 #define NOVENA_BOARD_VERSION    "0.10"
@@ -132,58 +130,59 @@ in order to map it into a 16-bit address space.
 #define I2C_INTERFACE_VERSION   "0.10"
 
 
-//------------------------------------------------------------------
-// Hashes segment.
-//------------------------------------------------------------------
-// addresses common to all hash cores
-#define ADDR_BLOCK              0x10
-#define ADDR_DIGEST             0x20      // except SHA512
-
-// addresses and codes for the specific hash cores.
-#define SHA1_ADDR_BASE          SEGMENT_OFFSET_HASHES + (0 * CORE_SIZE)
-#define SHA1_ADDR_NAME0         SHA1_ADDR_BASE + ADDR_NAME0
-#define SHA1_ADDR_NAME1         SHA1_ADDR_BASE + ADDR_NAME1
-#define SHA1_ADDR_VERSION       SHA1_ADDR_BASE + ADDR_VERSION
-#define SHA1_ADDR_CTRL          SHA1_ADDR_BASE + ADDR_CTRL
-#define SHA1_ADDR_STATUS        SHA1_ADDR_BASE + ADDR_STATUS
-#define SHA1_ADDR_BLOCK         SHA1_ADDR_BASE + ADDR_BLOCK
-#define SHA1_ADDR_DIGEST        SHA1_ADDR_BASE + ADDR_DIGEST
+/*
+ * Hashes segment.
+ */
+
+/* Addresses common to all hash cores */
+#define ADDR_BLOCK              (0x10)
+#define ADDR_DIGEST             (0x20)      /* except SHA512 */
+
+/* Addresses and codes for the specific hash cores */
+#define SHA1_ADDR_BASE          (SEGMENT_OFFSET_HASHES + (0 * CORE_SIZE))
+#define SHA1_ADDR_NAME0         (SHA1_ADDR_BASE + ADDR_NAME0)
+#define SHA1_ADDR_NAME1         (SHA1_ADDR_BASE + ADDR_NAME1)
+#define SHA1_ADDR_VERSION       (SHA1_ADDR_BASE + ADDR_VERSION)
+#define SHA1_ADDR_CTRL          (SHA1_ADDR_BASE + ADDR_CTRL)
+#define SHA1_ADDR_STATUS        (SHA1_ADDR_BASE + ADDR_STATUS)
+#define SHA1_ADDR_BLOCK         (SHA1_ADDR_BASE + ADDR_BLOCK)
+#define SHA1_ADDR_DIGEST        (SHA1_ADDR_BASE + ADDR_DIGEST)
 #define SHA1_BLOCK_LEN          bitsToBytes(512)
 #define SHA1_LENGTH_LEN         bitsToBytes(64)
 #define SHA1_DIGEST_LEN         bitsToBytes(160)
 
-#define SHA256_ADDR_BASE        SEGMENT_OFFSET_HASHES + (1 * CORE_SIZE)
-#define SHA256_ADDR_NAME0       SHA256_ADDR_BASE + ADDR_NAME0
-#define SHA256_ADDR_NAME1       SHA256_ADDR_BASE + ADDR_NAME1
-#define SHA256_ADDR_VERSION     SHA256_ADDR_BASE + ADDR_VERSION
-#define SHA256_ADDR_CTRL        SHA256_ADDR_BASE + ADDR_CTRL
-#define SHA256_ADDR_STATUS      SHA256_ADDR_BASE + ADDR_STATUS
-#define SHA256_ADDR_BLOCK       SHA256_ADDR_BASE + ADDR_BLOCK
-#define SHA256_ADDR_DIGEST      SHA256_ADDR_BASE + ADDR_DIGEST
+#define SHA256_ADDR_BASE        (SEGMENT_OFFSET_HASHES + (1 * CORE_SIZE))
+#define SHA256_ADDR_NAME0       (SHA256_ADDR_BASE + ADDR_NAME0)
+#define SHA256_ADDR_NAME1       (SHA256_ADDR_BASE + ADDR_NAME1)
+#define SHA256_ADDR_VERSION     (SHA256_ADDR_BASE + ADDR_VERSION)
+#define SHA256_ADDR_CTRL        (SHA256_ADDR_BASE + ADDR_CTRL)
+#define SHA256_ADDR_STATUS      (SHA256_ADDR_BASE + ADDR_STATUS)
+#define SHA256_ADDR_BLOCK       (SHA256_ADDR_BASE + ADDR_BLOCK)
+#define SHA256_ADDR_DIGEST      (SHA256_ADDR_BASE + ADDR_DIGEST)
 #define SHA256_BLOCK_LEN        bitsToBytes(512)
 #define SHA256_LENGTH_LEN       bitsToBytes(64)
 #define SHA256_DIGEST_LEN       bitsToBytes(256)
 
-#define SHA512_ADDR_BASE        SEGMENT_OFFSET_HASHES + (2 * CORE_SIZE)
-#define SHA512_ADDR_NAME0       SHA512_ADDR_BASE + ADDR_NAME0
-#define SHA512_ADDR_NAME1       SHA512_ADDR_BASE + ADDR_NAME1
-#define SHA512_ADDR_VERSION     SHA512_ADDR_BASE + ADDR_VERSION
-#define SHA512_ADDR_CTRL        SHA512_ADDR_BASE + ADDR_CTRL
-#define SHA512_ADDR_STATUS      SHA512_ADDR_BASE + ADDR_STATUS
-#define SHA512_ADDR_BLOCK       SHA512_ADDR_BASE + ADDR_BLOCK
-#define SHA512_ADDR_DIGEST      SHA512_ADDR_BASE + 0x40
+#define SHA512_ADDR_BASE        (SEGMENT_OFFSET_HASHES + (2 * CORE_SIZE))
+#define SHA512_ADDR_NAME0       (SHA512_ADDR_BASE + ADDR_NAME0)
+#define SHA512_ADDR_NAME1       (SHA512_ADDR_BASE + ADDR_NAME1)
+#define SHA512_ADDR_VERSION     (SHA512_ADDR_BASE + ADDR_VERSION)
+#define SHA512_ADDR_CTRL        (SHA512_ADDR_BASE + ADDR_CTRL)
+#define SHA512_ADDR_STATUS      (SHA512_ADDR_BASE + ADDR_STATUS)
+#define SHA512_ADDR_BLOCK       (SHA512_ADDR_BASE + ADDR_BLOCK)
+#define SHA512_ADDR_DIGEST      (SHA512_ADDR_BASE + 0x40)
 #define SHA512_BLOCK_LEN        bitsToBytes(1024)
 #define SHA512_LENGTH_LEN       bitsToBytes(128)
 #define SHA512_224_DIGEST_LEN   bitsToBytes(224)
 #define SHA512_256_DIGEST_LEN   bitsToBytes(256)
 #define SHA384_DIGEST_LEN       bitsToBytes(384)
 #define SHA512_DIGEST_LEN       bitsToBytes(512)
-#define MODE_SHA_512_224        0 << 2
-#define MODE_SHA_512_256        1 << 2
-#define MODE_SHA_384            2 << 2
-#define MODE_SHA_512            3 << 2
+#define MODE_SHA_512_224        (0 << 2)
+#define MODE_SHA_512_256        (1 << 2)
+#define MODE_SHA_384            (2 << 2)
+#define MODE_SHA_512            (3 << 2)
 
-// current name and version values
+/* Current name and version values */
 #define SHA1_NAME0              "sha1"
 #define SHA1_NAME1              "    "
 #define SHA1_VERSION            "0.50"
@@ -197,72 +196,73 @@ in order to map it into a 16-bit address space.
 #define SHA512_VERSION          "0.80"
 
 
-//-----------------------------------------------------------------
-// TRNG segment.
-//-----------------------------------------------------------------
-// addresses and codes for the TRNG cores */
-#define TRNG_ADDR_BASE          SEGMENT_OFFSET_RNGS + (0x00 * CORE_SIZE)
-#define TRNG_ADDR_NAME0         TRNG_ADDR_BASE + ADDR_NAME0
-#define TRNG_ADDR_NAME1         TRNG_ADDR_BASE + ADDR_NAME1
-#define TRNG_ADDR_VERSION       TRNG_ADDR_BASE + ADDR_VERSION
-#define TRNG_ADDR_CTRL          TRNG_ADDR_BASE + 0x10
-#define TRNG_CTRL_DISCARD       1
-#define TRNG_CTRL_TEST_MODE     2
-#define TRNG_ADDR_STATUS        TRNG_ADDR_BASE + 0x11
-// no status bits defined (yet)
-#define TRNG_ADDR_DELAY         TRNG_ADDR_BASE + 0x13
-
-#define ENTROPY1_ADDR_BASE      SEGMENT_OFFSET_RNGS + (0x05 * CORE_SIZE)
-#define ENTROPY1_ADDR_NAME0     ENTROPY1_ADDR_BASE + ADDR_NAME0
-#define ENTROPY1_ADDR_NAME1     ENTROPY1_ADDR_BASE + ADDR_NAME1
-#define ENTROPY1_ADDR_VERSION   ENTROPY1_ADDR_BASE + ADDR_VERSION
-#define ENTROPY1_ADDR_CTRL      ENTROPY1_ADDR_BASE + 0x10
-#define ENTROPY1_CTRL_ENABLE    1
-#define ENTROPY1_ADDR_STATUS    ENTROPY1_ADDR_BASE + 0x11
-#define ENTROPY1_STATUS_VALID   1
-#define ENTROPY1_ADDR_ENTROPY   ENTROPY1_ADDR_BASE + 0x20
-#define ENTROPY1_ADDR_DELTA     ENTROPY1_ADDR_BASE + 0x30
-
-#define ENTROPY2_ADDR_BASE      SEGMENT_OFFSET_RNGS + (0x06 * CORE_SIZE)
-#define ENTROPY2_ADDR_NAME0     ENTROPY2_ADDR_BASE + ADDR_NAME0
-#define ENTROPY2_ADDR_NAME1     ENTROPY2_ADDR_BASE + ADDR_NAME1
-#define ENTROPY2_ADDR_VERSION   ENTROPY2_ADDR_BASE + ADDR_VERSION
-#define ENTROPY2_ADDR_CTRL      ENTROPY2_ADDR_BASE + 0x10
-#define ENTROPY2_CTRL_ENABLE    1
-#define ENTROPY2_ADDR_STATUS    ENTROPY2_ADDR_BASE + 0x11
-#define ENTROPY2_STATUS_VALID   1
-#define ENTROPY2_ADDR_OPA       ENTROPY2_ADDR_BASE + 0x18
-#define ENTROPY2_ADDR_OPB       ENTROPY2_ADDR_BASE + 0x19
-#define ENTROPY2_ADDR_ENTROPY   ENTROPY2_ADDR_BASE + 0x20
-#define ENTROPY2_ADDR_RAW       ENTROPY2_ADDR_BASE + 0x21
-#define ENTROPY2_ADDR_ROSC      ENTROPY2_ADDR_BASE + 0x22
-
-#define MIXER_ADDR_BASE         SEGMENT_OFFSET_RNGS + (0x0a * CORE_SIZE)
-#define MIXER_ADDR_NAME0        MIXER_ADDR_BASE + ADDR_NAME0
-#define MIXER_ADDR_NAME1        MIXER_ADDR_BASE + ADDR_NAME1
-#define MIXER_ADDR_VERSION      MIXER_ADDR_BASE + ADDR_VERSION
-#define MIXER_ADDR_CTRL         MIXER_ADDR_BASE + 0x10
-#define MIXER_CTRL_ENABLE       1
-#define MIXER_CTRL_RESTART      2
-#define MIXER_ADDR_STATUS       MIXER_ADDR_BASE + 0x11
-// no status bits defined (yet)
-#define MIXER_ADDR_TIMEOUT      MIXER_ADDR_BASE + 0x20
-
-#define CSPRNG_ADDR_BASE        SEGMENT_OFFSET_RNGS + (0x0b * CORE_SIZE)
-#define CSPRNG_ADDR_NAME0       CSPRNG_ADDR_BASE + ADDR_NAME0
-#define CSPRNG_ADDR_NAME1       CSPRNG_ADDR_BASE + ADDR_NAME1
-#define CSPRNG_ADDR_VERSION     CSPRNG_ADDR_BASE + ADDR_VERSION
-#define CSPRNG_ADDR_CTRL        CSPRNG_ADDR_BASE + 0x10
-#define CSPRNG_CTRL_ENABLE      1
-#define CSPRNG_CTRL_SEED        2
-#define CSPRNG_ADDR_STATUS      CSPRNG_ADDR_BASE + 0x11
-#define CSPRNG_STATUS_VALID     1
-#define CSPRNG_ADDR_RANDOM      CSPRNG_ADDR_BASE + 0x20
-#define CSPRNG_ADDR_NROUNDS     CSPRNG_ADDR_BASE + 0x40
-#define CSPRNG_ADDR_NBLOCKS_LO  CSPRNG_ADDR_BASE + 0x41
-#define CSPRNG_ADDR_NBLOCKS_HI  CSPRNG_ADDR_BASE + 0x42
-
-// current name and version values
+/*
+ * TRNG segment.
+ */
+
+/* addresses and codes for the TRNG cores */
+#define TRNG_ADDR_BASE          (SEGMENT_OFFSET_RNGS + (0x00 * CORE_SIZE))
+#define TRNG_ADDR_NAME0         (TRNG_ADDR_BASE + ADDR_NAME0)
+#define TRNG_ADDR_NAME1         (TRNG_ADDR_BASE + ADDR_NAME1)
+#define TRNG_ADDR_VERSION       (TRNG_ADDR_BASE + ADDR_VERSION)
+#define TRNG_ADDR_CTRL          (TRNG_ADDR_BASE + 0x10)
+#define TRNG_CTRL_DISCARD       (1)
+#define TRNG_CTRL_TEST_MODE     (2)
+#define TRNG_ADDR_STATUS        (TRNG_ADDR_BASE + 0x11)
+/* No status bits defined (yet) */
+#define TRNG_ADDR_DELAY         (TRNG_ADDR_BASE + 0x13)
+
+#define ENTROPY1_ADDR_BASE      (SEGMENT_OFFSET_RNGS + (0x05 * CORE_SIZE))
+#define ENTROPY1_ADDR_NAME0     (ENTROPY1_ADDR_BASE + ADDR_NAME0)
+#define ENTROPY1_ADDR_NAME1     (ENTROPY1_ADDR_BASE + ADDR_NAME1)
+#define ENTROPY1_ADDR_VERSION   (ENTROPY1_ADDR_BASE + ADDR_VERSION)
+#define ENTROPY1_ADDR_CTRL      (ENTROPY1_ADDR_BASE + 0x10)
+#define ENTROPY1_CTRL_ENABLE    (1)
+#define ENTROPY1_ADDR_STATUS    (ENTROPY1_ADDR_BASE + 0x11)
+#define ENTROPY1_STATUS_VALID   (1)
+#define ENTROPY1_ADDR_ENTROPY   (ENTROPY1_ADDR_BASE + 0x20)
+#define ENTROPY1_ADDR_DELTA     (ENTROPY1_ADDR_BASE + 0x30)
+
+#define ENTROPY2_ADDR_BASE      (SEGMENT_OFFSET_RNGS + (0x06 * CORE_SIZE))
+#define ENTROPY2_ADDR_NAME0     (ENTROPY2_ADDR_BASE + ADDR_NAME0)
+#define ENTROPY2_ADDR_NAME1     (ENTROPY2_ADDR_BASE + ADDR_NAME1)
+#define ENTROPY2_ADDR_VERSION   (ENTROPY2_ADDR_BASE + ADDR_VERSION)
+#define ENTROPY2_ADDR_CTRL      (ENTROPY2_ADDR_BASE + 0x10)
+#define ENTROPY2_CTRL_ENABLE    (1)
+#define ENTROPY2_ADDR_STATUS    (ENTROPY2_ADDR_BASE + 0x11)
+#define ENTROPY2_STATUS_VALID   (1)
+#define ENTROPY2_ADDR_OPA       (ENTROPY2_ADDR_BASE + 0x18)
+#define ENTROPY2_ADDR_OPB       (ENTROPY2_ADDR_BASE + 0x19)
+#define ENTROPY2_ADDR_ENTROPY   (ENTROPY2_ADDR_BASE + 0x20)
+#define ENTROPY2_ADDR_RAW       (ENTROPY2_ADDR_BASE + 0x21)
+#define ENTROPY2_ADDR_ROSC      (ENTROPY2_ADDR_BASE + 0x22)
+
+#define MIXER_ADDR_BASE         (SEGMENT_OFFSET_RNGS + (0x0a * CORE_SIZE))
+#define MIXER_ADDR_NAME0        (MIXER_ADDR_BASE + ADDR_NAME0)
+#define MIXER_ADDR_NAME1        (MIXER_ADDR_BASE + ADDR_NAME1)
+#define MIXER_ADDR_VERSION      (MIXER_ADDR_BASE + ADDR_VERSION)
+#define MIXER_ADDR_CTRL         (MIXER_ADDR_BASE + 0x10)
+#define MIXER_CTRL_ENABLE       (1)
+#define MIXER_CTRL_RESTART      (2)
+#define MIXER_ADDR_STATUS       (MIXER_ADDR_BASE + 0x11)
+/* No status bits defined (yet) */
+#define MIXER_ADDR_TIMEOUT      (MIXER_ADDR_BASE + 0x20)
+
+#define CSPRNG_ADDR_BASE        (SEGMENT_OFFSET_RNGS + (0x0b * CORE_SIZE))
+#define CSPRNG_ADDR_NAME0       (CSPRNG_ADDR_BASE + ADDR_NAME0)
+#define CSPRNG_ADDR_NAME1       (CSPRNG_ADDR_BASE + ADDR_NAME1)
+#define CSPRNG_ADDR_VERSION     (CSPRNG_ADDR_BASE + ADDR_VERSION)
+#define CSPRNG_ADDR_CTRL        (CSPRNG_ADDR_BASE + 0x10)
+#define CSPRNG_CTRL_ENABLE      (1)
+#define CSPRNG_CTRL_SEED        (2)
+#define CSPRNG_ADDR_STATUS      (CSPRNG_ADDR_BASE + 0x11)
+#define CSPRNG_STATUS_VALID     (1)
+#define CSPRNG_ADDR_RANDOM      (CSPRNG_ADDR_BASE + 0x20)
+#define CSPRNG_ADDR_NROUNDS     (CSPRNG_ADDR_BASE + 0x40)
+#define CSPRNG_ADDR_NBLOCKS_LO  (CSPRNG_ADDR_BASE + 0x41)
+#define CSPRNG_ADDR_NBLOCKS_HI  (CSPRNG_ADDR_BASE + 0x42)
+
+/* Current name and version values */
 #define TRNG_NAME0              "trng"
 #define TRNG_NAME1              "    "
 #define TRNG_VERSION            "0.50"
@@ -280,162 +280,208 @@ in order to map it into a 16-bit address space.
 #define CSPRNG_VERSION          "0.50"
 
 
-// -----------------------------------------------------------------
-// CIPHERS segment.
-// -----------------------------------------------------------------
-// aes core.
-#define AES_ADDR_BASE           SEGMENT_OFFSET_CIPHERS + (0 * CORE_SIZE)
-#define AES_ADDR_NAME0          AES_ADDR_BASE + ADDR_NAME0
-#define AES_ADDR_NAME1          AES_ADDR_BASE + ADDR_NAME1
-#define AES_ADDR_VERSION        AES_ADDR_BASE + ADDR_VERSION
-#define AES_ADDR_CTRL           AES_ADDR_BASE + ADDR_CTRL
-#define AES_ADDR_STATUS         AES_ADDR_BASE + ADDR_STATUS
-
-#define AES_ADDR_CONFIG         AES_ADDR_BASE + 0x0a
-#define AES_CONFIG_ENCDEC       1
-#define AES_CONFIG_KEYLEN       2
-
-#define AES_ADDR_KEY0           AES_ADDR_BASE + 0x10
-#define AES_ADDR_KEY1           AES_ADDR_BASE + 0x11
-#define AES_ADDR_KEY2           AES_ADDR_BASE + 0x12
-#define AES_ADDR_KEY3           AES_ADDR_BASE + 0x13
-#define AES_ADDR_KEY4           AES_ADDR_BASE + 0x14
-#define AES_ADDR_KEY5           AES_ADDR_BASE + 0x15
-#define AES_ADDR_KEY6           AES_ADDR_BASE + 0x16
-#define AES_ADDR_KEY7           AES_ADDR_BASE + 0x17
-
-#define AES_ADDR_BLOCK0         AES_ADDR_BASE + 0x20
-#define AES_ADDR_BLOCK1         AES_ADDR_BASE + 0x21
-#define AES_ADDR_BLOCK2         AES_ADDR_BASE + 0x22
-#define AES_ADDR_BLOCK3         AES_ADDR_BASE + 0x23
-
-#define AES_ADDR_RESULT0        AES_ADDR_BASE + 0x30
-#define AES_ADDR_RESULT1        AES_ADDR_BASE + 0x31
-#define AES_ADDR_RESULT2        AES_ADDR_BASE + 0x32
-#define AES_ADDR_RESULT3        AES_ADDR_BASE + 0x33
-
-// current name and version values
+/*
+ * CIPHERS segment.
+ */
+
+/* AES core */
+#define AES_ADDR_BASE           (SEGMENT_OFFSET_CIPHERS + (0 * CORE_SIZE))
+#define AES_ADDR_NAME0          (AES_ADDR_BASE + ADDR_NAME0)
+#define AES_ADDR_NAME1          (AES_ADDR_BASE + ADDR_NAME1)
+#define AES_ADDR_VERSION        (AES_ADDR_BASE + ADDR_VERSION)
+#define AES_ADDR_CTRL           (AES_ADDR_BASE + ADDR_CTRL)
+#define AES_ADDR_STATUS         (AES_ADDR_BASE + ADDR_STATUS)
+
+#define AES_ADDR_CONFIG         (AES_ADDR_BASE + 0x0a)
+#define AES_CONFIG_ENCDEC       (1)
+#define AES_CONFIG_KEYLEN       (2)
+
+#define AES_ADDR_KEY0           (AES_ADDR_BASE + 0x10)
+#define AES_ADDR_KEY1           (AES_ADDR_BASE + 0x11)
+#define AES_ADDR_KEY2           (AES_ADDR_BASE + 0x12)
+#define AES_ADDR_KEY3           (AES_ADDR_BASE + 0x13)
+#define AES_ADDR_KEY4           (AES_ADDR_BASE + 0x14)
+#define AES_ADDR_KEY5           (AES_ADDR_BASE + 0x15)
+#define AES_ADDR_KEY6           (AES_ADDR_BASE + 0x16)
+#define AES_ADDR_KEY7           (AES_ADDR_BASE + 0x17)
+
+#define AES_ADDR_BLOCK0         (AES_ADDR_BASE + 0x20)
+#define AES_ADDR_BLOCK1         (AES_ADDR_BASE + 0x21)
+#define AES_ADDR_BLOCK2         (AES_ADDR_BASE + 0x22)
+#define AES_ADDR_BLOCK3         (AES_ADDR_BASE + 0x23)
+
+#define AES_ADDR_RESULT0        (AES_ADDR_BASE + 0x30)
+#define AES_ADDR_RESULT1        (AES_ADDR_BASE + 0x31)
+#define AES_ADDR_RESULT2        (AES_ADDR_BASE + 0x32)
+#define AES_ADDR_RESULT3        (AES_ADDR_BASE + 0x33)
+
+/* Current name and version values */
 #define AES_CORE_NAME0          "aes "
 #define AES_CORE_NAME1          "    "
 #define AES_CORE_VERSION        "0.80"
 
 
-// Chacha core
-#define CHACHA_ADDR_BASE        SEGMENT_OFFSET_CIPHERS + (1 * CORE_SIZE)
-#define CHACHA_ADDR_NAME0       CHACHA_ADDR_BASE + ADDR_NAME0
-#define CHACHA_ADDR_NAME1       CHACHA_ADDR_BASE + ADDR_NAME1
-#define CHACHA_ADDR_VERSION     CHACHA_ADDR_BASE + ADDR_VERSION
-#define CHACHA_ADDR_CTRL        CHACHA_ADDR_BASE + ADDR_CTRL
-#define CHACHA_ADDR_STATUS      CHACHA_ADDR_BASE + ADDR_STATUS
-
-#define CHACHA_ADDR_KEYLEN      CHACHA_ADDR_BASE + 0x0a
-#define CHACHA_KEYLEN           1
-
-#define CHACHA_ADDR_ROUNDS      CHACHA_ADDR_BASE + 0x0b
-
-#define CHACHA_ADDR_KEY0        CHACHA_ADDR_BASE + 0x10
-#define CHACHA_ADDR_KEY1        CHACHA_ADDR_BASE + 0x11
-#define CHACHA_ADDR_KEY2        CHACHA_ADDR_BASE + 0x12
-#define CHACHA_ADDR_KEY3        CHACHA_ADDR_BASE + 0x13
-#define CHACHA_ADDR_KEY4        CHACHA_ADDR_BASE + 0x14
-#define CHACHA_ADDR_KEY5        CHACHA_ADDR_BASE + 0x15
-#define CHACHA_ADDR_KEY6        CHACHA_ADDR_BASE + 0x16
-#define CHACHA_ADDR_KEY7        CHACHA_ADDR_BASE + 0x17
-
-#define CHACHA_ADDR_IV0         CHACHA_ADDR_BASE + 0x20
-#define CHACHA_ADDR_IV1         CHACHA_ADDR_BASE + 0x21
-
-#define CHACHA_ADDR_DATA_IN0    CHACHA_ADDR_BASE + 0x40
-#define CHACHA_ADDR_DATA_IN1    CHACHA_ADDR_BASE + 0x41
-#define CHACHA_ADDR_DATA_IN2    CHACHA_ADDR_BASE + 0x42
-#define CHACHA_ADDR_DATA_IN3    CHACHA_ADDR_BASE + 0x43
-#define CHACHA_ADDR_DATA_IN4    CHACHA_ADDR_BASE + 0x44
-#define CHACHA_ADDR_DATA_IN5    CHACHA_ADDR_BASE + 0x45
-#define CHACHA_ADDR_DATA_IN6    CHACHA_ADDR_BASE + 0x46
-#define CHACHA_ADDR_DATA_IN7    CHACHA_ADDR_BASE + 0x47
-#define CHACHA_ADDR_DATA_IN8    CHACHA_ADDR_BASE + 0x48
-#define CHACHA_ADDR_DATA_IN9    CHACHA_ADDR_BASE + 0x49
-#define CHACHA_ADDR_DATA_IN10   CHACHA_ADDR_BASE + 0x4a
-#define CHACHA_ADDR_DATA_IN11   CHACHA_ADDR_BASE + 0x4b
-#define CHACHA_ADDR_DATA_IN12   CHACHA_ADDR_BASE + 0x4c
-#define CHACHA_ADDR_DATA_IN13   CHACHA_ADDR_BASE + 0x4d
-#define CHACHA_ADDR_DATA_IN14   CHACHA_ADDR_BASE + 0x4e
-#define CHACHA_ADDR_DATA_IN15   CHACHA_ADDR_BASE + 0x4f
-
-#define CHACHA_ADDR_DATA_OUT0   CHACHA_ADDR_BASE + 0x80
-#define CHACHA_ADDR_DATA_OUT1   CHACHA_ADDR_BASE + 0x81
-#define CHACHA_ADDR_DATA_OUT2   CHACHA_ADDR_BASE + 0x82
-#define CHACHA_ADDR_DATA_OUT3   CHACHA_ADDR_BASE + 0x83
-#define CHACHA_ADDR_DATA_OUT4   CHACHA_ADDR_BASE + 0x84
-#define CHACHA_ADDR_DATA_OUT5   CHACHA_ADDR_BASE + 0x85
-#define CHACHA_ADDR_DATA_OUT6   CHACHA_ADDR_BASE + 0x86
-#define CHACHA_ADDR_DATA_OUT7   CHACHA_ADDR_BASE + 0x87
-#define CHACHA_ADDR_DATA_OUT8   CHACHA_ADDR_BASE + 0x88
-#define CHACHA_ADDR_DATA_OUT9   CHACHA_ADDR_BASE + 0x89
-#define CHACHA_ADDR_DATA_OUT10  CHACHA_ADDR_BASE + 0x8a
-#define CHACHA_ADDR_DATA_OUT11  CHACHA_ADDR_BASE + 0x8b
-#define CHACHA_ADDR_DATA_OUT12  CHACHA_ADDR_BASE + 0x8c
-#define CHACHA_ADDR_DATA_OUT13  CHACHA_ADDR_BASE + 0x8d
-#define CHACHA_ADDR_DATA_OUT14  CHACHA_ADDR_BASE + 0x8e
-#define CHACHA_ADDR_DATA_OUT15  CHACHA_ADDR_BASE + 0x8f
-
-// current name and version values
+/* Chacha core */
+#define CHACHA_ADDR_BASE        (SEGMENT_OFFSET_CIPHERS + (1 * CORE_SIZE))
+#define CHACHA_ADDR_NAME0       (CHACHA_ADDR_BASE + ADDR_NAME0)
+#define CHACHA_ADDR_NAME1       (CHACHA_ADDR_BASE + ADDR_NAME1)
+#define CHACHA_ADDR_VERSION     (CHACHA_ADDR_BASE + ADDR_VERSION)
+#define CHACHA_ADDR_CTRL        (CHACHA_ADDR_BASE + ADDR_CTRL)
+#define CHACHA_ADDR_STATUS      (CHACHA_ADDR_BASE + ADDR_STATUS)
+
+#define CHACHA_ADDR_KEYLEN      (CHACHA_ADDR_BASE + 0x0a)
+#define CHACHA_KEYLEN           (1)
+
+#define CHACHA_ADDR_ROUNDS      (CHACHA_ADDR_BASE + 0x0b)
+
+#define CHACHA_ADDR_KEY0        (CHACHA_ADDR_BASE + 0x10)
+#define CHACHA_ADDR_KEY1        (CHACHA_ADDR_BASE + 0x11)
+#define CHACHA_ADDR_KEY2        (CHACHA_ADDR_BASE + 0x12)
+#define CHACHA_ADDR_KEY3        (CHACHA_ADDR_BASE + 0x13)
+#define CHACHA_ADDR_KEY4        (CHACHA_ADDR_BASE + 0x14)
+#define CHACHA_ADDR_KEY5        (CHACHA_ADDR_BASE + 0x15)
+#define CHACHA_ADDR_KEY6        (CHACHA_ADDR_BASE + 0x16)
+#define CHACHA_ADDR_KEY7        (CHACHA_ADDR_BASE + 0x17)
+
+#define CHACHA_ADDR_IV0         (CHACHA_ADDR_BASE + 0x20)
+#define CHACHA_ADDR_IV1         (CHACHA_ADDR_BASE + 0x21)
+
+#define CHACHA_ADDR_DATA_IN0    (CHACHA_ADDR_BASE + 0x40)
+#define CHACHA_ADDR_DATA_IN1    (CHACHA_ADDR_BASE + 0x41)
+#define CHACHA_ADDR_DATA_IN2    (CHACHA_ADDR_BASE + 0x42)
+#define CHACHA_ADDR_DATA_IN3    (CHACHA_ADDR_BASE + 0x43)
+#define CHACHA_ADDR_DATA_IN4    (CHACHA_ADDR_BASE + 0x44)
+#define CHACHA_ADDR_DATA_IN5    (CHACHA_ADDR_BASE + 0x45)
+#define CHACHA_ADDR_DATA_IN6    (CHACHA_ADDR_BASE + 0x46)
+#define CHACHA_ADDR_DATA_IN7    (CHACHA_ADDR_BASE + 0x47)
+#define CHACHA_ADDR_DATA_IN8    (CHACHA_ADDR_BASE + 0x48)
+#define CHACHA_ADDR_DATA_IN9    (CHACHA_ADDR_BASE + 0x49)
+#define CHACHA_ADDR_DATA_IN10   (CHACHA_ADDR_BASE + 0x4a)
+#define CHACHA_ADDR_DATA_IN11   (CHACHA_ADDR_BASE + 0x4b)
+#define CHACHA_ADDR_DATA_IN12   (CHACHA_ADDR_BASE + 0x4c)
+#define CHACHA_ADDR_DATA_IN13   (CHACHA_ADDR_BASE + 0x4d)
+#define CHACHA_ADDR_DATA_IN14   (CHACHA_ADDR_BASE + 0x4e)
+#define CHACHA_ADDR_DATA_IN15   (CHACHA_ADDR_BASE + 0x4f)
+
+#define CHACHA_ADDR_DATA_OUT0   (CHACHA_ADDR_BASE + 0x80)
+#define CHACHA_ADDR_DATA_OUT1   (CHACHA_ADDR_BASE + 0x81)
+#define CHACHA_ADDR_DATA_OUT2   (CHACHA_ADDR_BASE + 0x82)
+#define CHACHA_ADDR_DATA_OUT3   (CHACHA_ADDR_BASE + 0x83)
+#define CHACHA_ADDR_DATA_OUT4   (CHACHA_ADDR_BASE + 0x84)
+#define CHACHA_ADDR_DATA_OUT5   (CHACHA_ADDR_BASE + 0x85)
+#define CHACHA_ADDR_DATA_OUT6   (CHACHA_ADDR_BASE + 0x86)
+#define CHACHA_ADDR_DATA_OUT7   (CHACHA_ADDR_BASE + 0x87)
+#define CHACHA_ADDR_DATA_OUT8   (CHACHA_ADDR_BASE + 0x88)
+#define CHACHA_ADDR_DATA_OUT9   (CHACHA_ADDR_BASE + 0x89)
+#define CHACHA_ADDR_DATA_OUT10  (CHACHA_ADDR_BASE + 0x8a)
+#define CHACHA_ADDR_DATA_OUT11  (CHACHA_ADDR_BASE + 0x8b)
+#define CHACHA_ADDR_DATA_OUT12  (CHACHA_ADDR_BASE + 0x8c)
+#define CHACHA_ADDR_DATA_OUT13  (CHACHA_ADDR_BASE + 0x8d)
+#define CHACHA_ADDR_DATA_OUT14  (CHACHA_ADDR_BASE + 0x8e)
+#define CHACHA_ADDR_DATA_OUT15  (CHACHA_ADDR_BASE + 0x8f)
+
+/* Current name and version values */
 #define CHACHA_NAME0            "chac"
 #define CHACHA_NAME1            "ha  "
 #define CHACHA_VERSION          "0.80"
 
 
-// -----------------------------------------------------------------
-// MATH segment.
-// -----------------------------------------------------------------
-// Modexp core.
-#define MODEXP_ADDR_BASE        SEGMENT_OFFSET_MATH + (0x00 * CORE_SIZE)
-#define MODEXP_ADDR_NAME0       MODEXP_ADDR_BASE + ADDR_NAME0
-#define MODEXP_ADDR_NAME1       MODEXP_ADDR_BASE + ADDR_NAME1
-#define MODEXP_ADDR_VERSION     MODEXP_ADDR_BASE + ADDR_VERSION
-#define MODEXP_ADDR_CTRL        MODEXP_ADDR_BASE + ADDR_CTRL
-#define MODEXP_CTRL_INIT_BIT    1
-#define MODEXP_CTRL_NEXT_BIT    2
-#define MODEXP_ADDR_STATUS      MODEXP_ADDR_BASE + ADDR_STATUS
+/*
+ * MATH segment.
+ */
+
+/* Modexp core */
+#define MODEXP_ADDR_BASE        (SEGMENT_OFFSET_MATH + (0x00 * CORE_SIZE))
+#define MODEXP_ADDR_NAME0       (MODEXP_ADDR_BASE + ADDR_NAME0)
+#define MODEXP_ADDR_NAME1       (MODEXP_ADDR_BASE + ADDR_NAME1)
+#define MODEXP_ADDR_VERSION     (MODEXP_ADDR_BASE + ADDR_VERSION)
+#define MODEXP_ADDR_CTRL        (MODEXP_ADDR_BASE + ADDR_CTRL)
+#define MODEXP_CTRL_INIT_BIT    (1)
+#define MODEXP_CTRL_NEXT_BIT    (2)
+#define MODEXP_ADDR_STATUS      (MODEXP_ADDR_BASE + ADDR_STATUS)
 
-#define MODEXP_ADDR_DELAY       MODEXP_ADDR_BASE + 0x13
-#define MODEXP_STATUS_READY     1
+#define MODEXP_ADDR_DELAY       (MODEXP_ADDR_BASE + 0x13)
+#define MODEXP_STATUS_READY     (1)
 
-#define MODEXP_MODULUS_LENGTH   MODEXP_ADDR_BASE + 0x20
-#define MODEXP_EXPONENT_LENGTH  MODEXP_ADDR_BASE + 0x21
-#define MODEXP_LENGTH           MODEXP_ADDR_BASE + 0x22
+#define MODEXP_MODULUS_LENGTH   (MODEXP_ADDR_BASE + 0x20)
+#define MODEXP_EXPONENT_LENGTH  (MODEXP_ADDR_BASE + 0x21)
+#define MODEXP_LENGTH           (MODEXP_ADDR_BASE + 0x22)
 
-#define MODEXP_MODULUS_PTR_RST  MODEXP_ADDR_BASE + 0x30
-#define MODEXP_MODULUS_DATA     MODEXP_ADDR_BASE + 0x31
+#define MODEXP_MODULUS_PTR_RST  (MODEXP_ADDR_BASE + 0x30)
+#define MODEXP_MODULUS_DATA     (MODEXP_ADDR_BASE + 0x31)
 
-#define MODEXP_EXPONENT_PTR_RST MODEXP_ADDR_BASE + 0x40
-#define MODEXP_EXPONENT_DATA    MODEXP_ADDR_BASE + 0x41
+#define MODEXP_EXPONENT_PTR_RST (MODEXP_ADDR_BASE + 0x40)
+#define MODEXP_EXPONENT_DATA    (MODEXP_ADDR_BASE + 0x41)
 
-#define MODEXP_MESSAGE_PTR_RST  MODEXP_ADDR_BASE + 0x50
-#define MODEXP_MESSAGE_DATA     MODEXP_ADDR_BASE + 0x51
+#define MODEXP_MESSAGE_PTR_RST  (MODEXP_ADDR_BASE + 0x50)
+#define MODEXP_MESSAGE_DATA     (MODEXP_ADDR_BASE + 0x51)
 
-#define MODEXP_RESULT_PTR_RST   MODEXP_ADDR_BASE + 0x60
-#define MODEXP_RESULT_DATA      MODEXP_ADDR_BASE + 0x61
+#define MODEXP_RESULT_PTR_RST   (MODEXP_ADDR_BASE + 0x60)
+#define MODEXP_RESULT_DATA      (MODEXP_ADDR_BASE + 0x61)
 
 #define MODEXP_NAME0            "mode"
 #define MODEXP_NAME1            "xp  "
 #define MODEXP_VERSION          "0.51"
 
 
-//------------------------------------------------------------------
-// Public I/O functions
-//------------------------------------------------------------------
+/*
+ * C API error codes.
+ */
+
+typedef enum {
+  HAL_OK,			/* All's well */
+  HAL_ERROR_MEMORY,		/* malloc() failure or similar */
+  HAL_ERROR_INCONSISTENT_ARGS,	/* Inconsistent arguments given */
+  HAL_ERROR_IO_SETUP_FAILED,	/* Could not set up I/O with FPGA */
+  HAL_ERROR_IO_TIMEOUT,		/* I/O with FPGA timed out */
+  HAL_ERROR_IO_UNEXPECTED,	/* Unexpected response from FPGA */
+  HAL_ERROR_IO_OS_ERROR,	/* Operating system error talking to FPGA */
+  HAL_ERROR_CSPRNG_ZEROED,	/* CSPRNG is returning zeros (perhaps core not present?) */
+  N_HAL_ERRORS			/* Number of error codes (must be last) */
+} hal_error_t;
+
+
+/*
+ * Public functions.
+ */
+
+/*
+ * Public I/O functions.
+ */
+
 void hal_io_set_debug(int onoff);
-int hal_io_write(off_t offset, const uint8_t *buf, size_t len);
-int hal_io_read(off_t offset, uint8_t *buf, size_t len);
-int hal_io_expected(off_t offset, const uint8_t *expected, size_t len);
-int hal_io_init(off_t offset);
-int hal_io_next(off_t offset);
-int hal_io_wait(off_t offset, uint8_t status, int *count);
-int hal_io_wait_ready(off_t offset);
-int hal_io_wait_valid(off_t offset);
-
-
-//======================================================================
-// EOF cryptech.h
-//======================================================================
+hal_error_t hal_io_write(off_t offset, const uint8_t *buf, size_t len);
+hal_error_t hal_io_read(off_t offset, uint8_t *buf, size_t len);
+hal_error_t hal_io_expected(off_t offset, const uint8_t *expected, size_t len);
+hal_error_t hal_io_init(off_t offset);
+hal_error_t hal_io_next(off_t offset);
+hal_error_t hal_io_wait(off_t offset, uint8_t status, int *count);
+hal_error_t hal_io_wait_ready(off_t offset);
+hal_error_t hal_io_wait_valid(off_t offset);
+
+/*
+ * Higher level public API.
+ */
+
+hal_error_t hal_random(void *buffer, const size_t length);
+
+void hal_hash_set_debug(int onoff);
+hal_error_t hash_sha1_core_present(void);
+hal_error_t hash_sha256_core_present(void);
+hal_error_t hash_sha512_core_present(void);
+size_t hal_hash_state_size(void);
+void hal_hash_state_initialize(void *state);
+hal_error_t hal_hash_sha1(void *state, const uint8_t * data_buffer, const size_t data_buffer_length,
+			  		    uint8_t *digest_buffer, const size_t digest_buffer_length);
+hal_error_t hal_hash_sha256(void *state, const uint8_t *data_buffer, const size_t data_buffer_length,
+					     uint8_t *digest_buffer, const size_t digest_buffer_length);
+hal_error_t hal_hash_sha512_224(void *state, const uint8_t *data_buffer, const size_t data_buffer_length,
+                                		 uint8_t *digest_buffer, const size_t digest_buffer_length);
+hal_error_t hal_hash_sha512_256(void *state, const uint8_t *data_buffer, const size_t data_buffer_length,
+                                		 uint8_t *digest_buffer, const size_t digest_buffer_length);
+hal_error_t hal_hash_sha384(void *state, const uint8_t *data_buffer, const size_t data_buffer_length,
+                            		     uint8_t *digest_buffer, const size_t digest_buffer_length);
+hal_error_t hal_hash_sha512(void *state, const uint8_t *data_buffer, const size_t data_buffer_length,
+                            		     uint8_t *digest_buffer, const size_t digest_buffer_length);
+
+#endif /* _CRYPTECH_H_ */
diff --git a/csprng.c b/csprng.c
new file mode 100644
index 0000000..f4f835d
--- /dev/null
+++ b/csprng.c
@@ -0,0 +1,93 @@
+/* 
+ * csprng.c
+ * ------------------------------
+ *
+ * HAL interface to Cryptech CSPRNG/TRNG.
+ * 
+ * Authors: Joachim Strömbergson, Paul Selkirk, Rob Austein
+ * Copyright (c) 2014-2015, SUNET
+ * 
+ * Redistribution and use in source and binary forms, with or 
+ * without modification, are permitted provided that the following 
+ * conditions are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#if 0
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#endif
+
+#include "cryptech.h"
+
+#ifndef WAIT_FOR_CSPRNG_VALID
+#define WAIT_FOR_CSPRNG_VALID	1
+#endif
+
+hal_error_t hal_random(void *buffer, const size_t length)
+{
+  uint8_t temp[4], *buf = buffer;
+  hal_error_t err;
+  size_t i;
+
+  for (i = 0; i < length; i += 4) {
+    const int last = (length - i) < 4;
+
+    if (WAIT_FOR_CSPRNG_VALID && (err = hal_io_wait_valid(CSPRNG_ADDR_STATUS)) != HAL_OK)
+      return err;
+
+    if ((err = hal_io_read(CSPRNG_ADDR_RANDOM, (last ? temp : &buf[i]), 4)) != HAL_OK)
+      return err;
+
+    if (last)
+      for (; i < length; i++)
+        buf[i] = temp[i&3];
+  }
+
+  for (i = 0, buf = buffer; i < length; i++, buf++)
+    if (*buf != 0)
+      return HAL_OK;
+
+  return HAL_ERROR_CSPRNG_ZEROED;
+}
+
+/*
+ * "Any programmer who fails to comply with the standard naming, formatting,
+ *  or commenting conventions should be shot.  If it so happens that it is
+ *  inconvenient to shoot him, then he is to be politely requested to recode
+ *  his program in adherence to the above standard."
+ *                      -- Michael Spier, Digital Equipment Corporation
+ *
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/hal_io_eim.c b/hal_io_eim.c
index ebffd24..6f9e159 100644
--- a/hal_io_eim.c
+++ b/hal_io_eim.c
@@ -49,18 +49,19 @@ static int inited = 0;
 
 /* ---------------- EIM low-level code ---------------- */
 
-static int init(void)
+static hal_error_t init(void)
 {
     if (inited)
-        return 0;
+        return HAL_OK;
 
     if (eim_setup() != 0) {
-        fprintf(stderr, "EIM setup failed\n");
-        return -1;
+        if (debug)
+            fprintf(stderr, "[ EIM setup failed ]\n");
+        return HAL_ERROR_IO_SETUP_FAILED;
     }
 
     inited = 1;
-    return 0;
+    return HAL_OK;
 }
 
 /* translate cryptech register number to EIM address
@@ -95,10 +96,12 @@ static void dump(char *label, const uint8_t *buf, size_t len)
     }
 }
 
-int hal_io_write(off_t offset, const uint8_t *buf, size_t len)
+hal_error_t hal_io_write(off_t offset, const uint8_t *buf, size_t len)
 {
-    if (init() != 0)
-        return -1;
+    hal_error_t err;
+
+    if ((err = init()) != HAL_OK)
+        return err;
 
     dump("write ", buf, len);
 
@@ -109,16 +112,17 @@ int hal_io_write(off_t offset, const uint8_t *buf, size_t len)
         eim_write_32(offset, &val);
     }
 
-    return 0;
+    return HAL_OK;
 }
 
-int hal_io_read(off_t offset, uint8_t *buf, size_t len)
+hal_error_t hal_io_read(off_t offset, uint8_t *buf, size_t len)
 {
     uint8_t *rbuf = buf;
     int rlen = len;
+    hal_error_t err;
 
-    if (init() != 0)
-        return -1;
+    if ((err = init()) != HAL_OK)
+        return err;
 
     offset = eim_offset(offset);
     for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
@@ -129,79 +133,84 @@ int hal_io_read(off_t offset, uint8_t *buf, size_t len)
 
     dump("read  ", buf, len);
 
-    return 0;
+    return HAL_OK;
 }
 
-int hal_io_expected(off_t offset, const uint8_t *expected, size_t len)
+hal_error_t hal_io_expected(off_t offset, const uint8_t *expected, size_t len)
 {
+    hal_error_t err;
     uint8_t *buf;
     int i;
 
     buf = malloc(len);
     if (buf == NULL) {
         perror("malloc");
-        return 1;
+        return HAL_ERROR_MEMORY;
     }
     dump("expect", expected, len);
 
-    if (hal_io_read(offset, buf, len) != 0)
+    if ((err = hal_io_read(offset, buf, len)) != HAL_OK)
         goto errout;
 
-    for (i = 0; i < len; ++i)
+    for (i = 0; i < len; ++i) {
         if (buf[i] != expected[i]) {
             fprintf(stderr, "response byte %d: expected 0x%02x, got 0x%02x\n",
                     i, expected[i], buf[i]);
+	    err = HAL_ERROR_IO_UNEXPECTED;
             goto errout;
         }
+    }
 
     free(buf);
-    return 0;
+    return HAL_OK;
+
 errout:
     free(buf);
-    return 1;
+    return err;
 }
 
-int hal_io_init(off_t offset)
+hal_error_t hal_io_init(off_t offset)
 {
     uint8_t buf[4] = { 0, 0, 0, CTRL_INIT };
 
     return hal_io_write(offset, buf, 4);
 }
 
-int hal_io_next(off_t offset)
+hal_error_t hal_io_next(off_t offset)
 {
     uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT };
 
     return hal_io_write(offset, buf, 4);
 }
 
-int hal_io_wait(off_t offset, uint8_t status, int *count)
+hal_error_t hal_io_wait(off_t offset, uint8_t status, int *count)
 {
+    hal_error_t err;
     uint8_t buf[4];
     int i;
 
     for (i = 1; ; ++i) {
         if (count && (*count > 0) && (i >= *count)) {
             fprintf(stderr, "hal_io_wait timed out\n");
-            return 1;
+            return HAL_ERROR_IO_TIMEOUT;
         }
-        if (hal_io_read(offset, buf, 4) != 0)
-            return -1;
+        if ((err = hal_io_read(offset, buf, 4)) != HAL_OK)
+            return err;
         if (buf[3] & status) {
             if (count)
                 *count = i;
-            return 0;
+            return HAL_OK;
         }
     }
 }
 
-int hal_io_wait_ready(off_t offset)
+hal_error_t hal_io_wait_ready(off_t offset)
 {
     int limit = 256;
     return hal_io_wait(offset, STATUS_READY, &limit);
 }
 
-int hal_io_wait_valid(off_t offset)
+hal_error_t hal_io_wait_valid(off_t offset)
 {
     int limit = 256;
     return hal_io_wait(offset, STATUS_VALID, &limit);
diff --git a/hal_io_i2c.c b/hal_io_i2c.c
index f521e73..54b54fb 100644
--- a/hal_io_i2c.c
+++ b/hal_io_i2c.c
@@ -69,62 +69,82 @@ static void dump(char *label, const uint8_t *buf, size_t len)
 
 static void i2c_close(void)
 {
-    close(i2cfd);
+    (void) close(i2cfd);
 }
 
-static int i2c_open(void)
+static hal_error_t i2c_open(void)
 {
+    int fd = -1;
+
     if (i2cfd >= 0)
-        return 0;
-
-    i2cfd = open(I2C_dev, O_RDWR);
-    if (i2cfd < 0) {
-        fprintf(stderr, "Unable to open %s: ", I2C_dev);
-        perror("");
-        i2cfd = 0;
-        return 1;
+        return HAL_OK;
+
+    /* It's dead, Jim, you can stop kicking it now */
+    if (i2cfd < -1)
+	return HAL_ERROR_IO_SETUP_FAILED;
+
+    fd = open(I2C_dev, O_RDWR);
+    if (fd < 0) {
+        if (debug)
+            perror("Unable to open %s: " I2C_dev);
+	goto fail;
     }
 
-    if (ioctl(i2cfd, I2C_SLAVE, I2C_addr) < 0) {
-        fprintf(stderr, "Unable to set I2C slave device 0x%02x: ", I2C_addr);
-        perror("");
-        return 1;
+    if (ioctl(fd, I2C_SLAVE, I2C_addr) < 0) {
+        if (debug)
+	    perror("Unable to set I2C slave device");
+        goto fail;
     }
 
-    if (atexit(i2c_close) != 0) {
-        fprintf(stderr, "Unable to set I2C atexit handler.");
-        return 1;
+    if (atexit(i2c_close) < 0) {
+	if (debug)
+	    perror("Unable to set I2C atexit handler");
+        goto fail;
     }
 
-    return 0;
+    i2cfd = fd;
+    return HAL_OK;
+
+ fail:
+    if (fd >= 0)
+        close(fd);
+    i2cfd = -2;
+    return HAL_ERROR_IO_SETUP_FAILED;
 }
 
-static int i2c_write(const uint8_t *buf, size_t len)
+static hal_error_t i2c_write(const uint8_t *buf, size_t len)
 {
-    if (i2c_open() != 0)
-        return 1;
+    hal_error_t err;
+
+    if ((err = i2c_open()) != HAL_OK)
+        return err;
 
     dump("write ", buf, len);
 
     if (write(i2cfd, buf, len) != len) {
-        perror("i2c write failed");
-        return 1;
+	if (debug)
+	      perror("i2c write failed");
+        return HAL_ERROR_IO_OS_ERROR;
     }
 
-    return 0;
+    return HAL_OK;
 }
 
-static int i2c_read(uint8_t *b)
+static hal_error_t i2c_read(uint8_t *b)
 {
-    if (i2c_open() != 0)
-        return 1;
+    hal_error_t err;
+
+    if ((err = i2c_open()) != HAL_OK)
+        return err;
 
-    /* read() on the i2c device only returns one byte at a time,
+    /*
+     * read() on the i2c device only returns one byte at a time,
      * and hal_io_get_resp() needs to parse the response one byte at a time
      */
     if (read(i2cfd, b, 1) != 1) {
-        perror("i2c read failed");
-        return 1;
+	if (debug)
+            perror("i2c read failed");
+        return HAL_ERROR_IO_OS_ERROR;
     }
 
     return 0;
@@ -148,7 +168,7 @@ static int i2c_read(uint8_t *b)
 #define UNKNOWN   0xfe
 #define ERROR     0xfd
 
-static int hal_io_send_write_cmd(off_t offset, const uint8_t *data)
+static hal_error_t hal_io_send_write_cmd(off_t offset, const uint8_t *data)
 {
     uint8_t buf[9] = { SOC, WRITE_CMD, (offset >> 8) & 0xff, offset & 0xff,
                        data[0], data[1], data[2], data[3], EOC };
@@ -156,25 +176,27 @@ static int hal_io_send_write_cmd(off_t offset, const uint8_t *data)
     return i2c_write(buf, sizeof(buf));
 }
 
-static int hal_io_send_read_cmd(off_t offset)
+static hal_error_t hal_io_send_read_cmd(off_t offset)
 {
     uint8_t buf[5] = { SOC, READ_CMD, (offset >> 8) & 0xff, offset & 0xff, EOC };
 
     return i2c_write(buf, sizeof(buf));
 }
 
-static int hal_io_get_resp(uint8_t *buf, size_t len)
+static hal_error_t hal_io_get_resp(uint8_t *buf, size_t len)
 {
+    hal_error_t err;
     int i;
 
     for (i = 0; i < len; ++i) {
-        if (i2c_read(&buf[i]) != 0)
-            return 1;
+        if ((err = i2c_read(&buf[i])) != HAL_OK)
+            return err;
         if ((i == 0) && (buf[i] != SOR)) {
             /* we've gotten out of sync, and there's probably nothing we can do */
-            fprintf(stderr, "response byte 0: expected 0x%02x (SOR), got 0x%02x\n",
-                    SOR, buf[0]);
-            return 1;
+	    if (debug)
+		fprintf(stderr, "response byte 0: expected 0x%02x (SOR), got 0x%02x\n",
+			SOR, buf[0]);
+            return HAL_ERROR_IO_UNEXPECTED;
         }
         else if (i == 1) {      /* response code */
             switch (buf[i]) {
@@ -193,18 +215,19 @@ static int hal_io_get_resp(uint8_t *buf, size_t len)
                 break;
             default:
                 /* we've gotten out of sync, and there's probably nothing we can do */
-                fprintf(stderr, "unknown response code 0x%02x\n", buf[i]);
-                return 1;
+		if (debug)
+		    fprintf(stderr, "unknown response code 0x%02x\n", buf[i]);
+                return HAL_ERROR_IO_UNEXPECTED;
             }
         }
     }
 
     dump("read  ", buf, len);
 
-    return 0;
+    return HAL_OK;
 }
 
-static int hal_io_compare(uint8_t *buf, const uint8_t *expected, size_t len)
+static hal_error_t hal_io_compare(uint8_t *buf, const uint8_t *expected, size_t len)
 {
     int i;
 
@@ -213,126 +236,140 @@ static int hal_io_compare(uint8_t *buf, const uint8_t *expected, size_t len)
         if (buf[i] != expected[i]) {
             fprintf(stderr, "response byte %d: expected 0x%02x, got 0x%02x\n",
                     i, expected[i], buf[i]);
-            return 1;
+            return HAL_ERROR_IO_UNEXPECTED;
         }
     }
 
-    return 0;
+    return HAL_OK;
 }
 
-static int hal_io_get_write_resp(off_t offset)
+static hal_error_t hal_io_get_write_resp(off_t offset)
 {
     uint8_t buf[5];
     uint8_t expected[5] = { SOR, WRITE_OK, (offset >> 8) & 0xff, offset & 0xff, EOR };
+    hal_error_t err;
+
+    if ((err = hal_io_get_resp(buf, sizeof(buf))) != HAL_OK)
+	return err;
 
-    return
-        hal_io_get_resp(buf, sizeof(buf)) ||
-        hal_io_compare(buf, expected, sizeof(expected));
+    return hal_io_compare(buf, expected, sizeof(expected));
 }
 
-static int hal_io_get_read_resp(off_t offset, uint8_t *data)
+static hal_error_t hal_io_get_read_resp(off_t offset, uint8_t *data)
 {
     uint8_t buf[9];
     uint8_t expected[4] = { SOR, READ_OK, (offset >> 8) & 0xff, offset & 0xff };
+    hal_error_t err;
+
+    if ((err = hal_io_get_resp(buf, sizeof(buf))) != HAL_OK ||
+        (err = hal_io_compare(buf, expected, 4))  != HAL_OK)
+	return err;
 
-    if ((hal_io_get_resp(buf, sizeof(buf)) != 0) ||
-        (hal_io_compare(buf, expected, 4) != 0) || buf[8] != EOR)
-        return 1;
+    if (buf[8] != EOR)
+        return HAL_ERROR_IO_UNEXPECTED;
 
     data[0] = buf[4];
     data[1] = buf[5];
     data[2] = buf[6];
     data[3] = buf[7];
 
-    return 0;
+    return HAL_OK;
 }
 
-static int hal_io_get_read_resp_expected(off_t offset, const uint8_t *data)
+static hal_error_t hal_io_get_read_resp_expected(off_t offset, const uint8_t *data)
 {
     uint8_t buf[9];
     uint8_t expected[9] = { SOR, READ_OK, (offset >> 8) & 0xff, offset & 0xff,
                             data[0], data[1], data[2], data[3], EOR };
+    hal_error_t err;
 
     dump("expect", expected, 9);
 
-    return (hal_io_get_resp(buf, sizeof(buf)) ||
-            hal_io_compare(buf, expected, sizeof(buf)));
+    if ((err = hal_io_get_resp(buf, sizeof(buf))) != HAL_OK)
+	return err;
+
+    return hal_io_compare(buf, expected, sizeof(buf));
 }
 
-int hal_io_write(off_t offset, const uint8_t *buf, size_t len)
+hal_error_t hal_io_write(off_t offset, const uint8_t *buf, size_t len)
 {
-    for (; len > 0; offset++, buf += 4, len -= 4) {
-        if (hal_io_send_write_cmd(offset, buf) ||
-            hal_io_get_write_resp(offset))
-            return 1;
-    }
+    hal_error_t err;
 
-    return 0;
+    for (; len > 0; offset++, buf += 4, len -= 4)
+	if ((err = hal_io_send_write_cmd(offset, buf)) != HAL_OK ||
+	    (err = hal_io_get_write_resp(offset))      != HAL_OK)
+            return err;
+
+    return HAL_OK;
 }
 
-int hal_io_read(off_t offset, uint8_t *buf, size_t len)
+hal_error_t hal_io_read(off_t offset, uint8_t *buf, size_t len)
 {
-    for (; len > 0; offset++, buf += 4, len -= 4) {
-        if (hal_io_send_read_cmd(offset) ||
-            hal_io_get_read_resp(offset, buf))
-            return 1;
-    }
+    hal_error_t err;
 
-    return 0;
+    for (; len > 0; offset++, buf += 4, len -= 4)
+	if ((err = hal_io_send_read_cmd(offset))      != HAL_OK ||
+	    (err = hal_io_get_read_resp(offset, buf)) != HAL_OK)
+            return err;
+
+    return HAL_OK;
 }
 
-int hal_io_expected(off_t offset, const uint8_t *buf, size_t len)
+hal_error_t hal_io_expected(off_t offset, const uint8_t *buf, size_t len)
 {
-    for (; len > 0; offset++, buf += 4, len -= 4) {
-        if (hal_io_send_read_cmd(offset) ||
-            hal_io_get_read_resp_expected(offset, buf))
-            return 1;
-    }
+    hal_error_t err;
 
-    return 0;
+    for (; len > 0; offset++, buf += 4, len -= 4)
+	if ((err = hal_io_send_read_cmd(offset))	       != HAL_OK ||
+	    (err = hal_io_get_read_resp_expected(offset, buf)) != HAL_OK)
+            return err;
+
+    return HAL_OK;
 }
 
-int hal_io_init(off_t offset)
+hal_error_t hal_io_init(off_t offset)
 {
     uint8_t buf[4] = { 0, 0, 0, CTRL_INIT };
 
     return hal_io_write(offset, buf, 4);
 }
 
-int hal_io_next(off_t offset)
+hal_error_t hal_io_next(off_t offset)
 {
     uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT };
 
     return hal_io_write(offset, buf, 4);
 }
 
-int hal_io_wait(off_t offset, uint8_t status, int *count)
+hal_error_t hal_io_wait(off_t offset, uint8_t status, int *count)
 {
+    hal_error_t err;
     uint8_t buf[4];
     int i;
 
     for (i = 1; ; ++i) {
         if (count && (*count > 0) && (i >= *count)) {
-            fprintf(stderr, "hal_io_wait timed out\n");
-            return 1;
+	    if (debug)
+	        fprintf(stderr, "hal_io_wait timed out\n");
+            return HAL_ERROR_IO_TIMEOUT;
         }
-        if (hal_io_read(offset, buf, 4) != 0)
-            return -1;
+        if ((err = hal_io_read(offset, buf, 4)) != HAL_OK)
+            return err;
         if (buf[3] & status) {
             if (count)
                 *count = i;
-            return 0;
+            return HAL_OK;
         }
     }
 }
 
-int hal_io_wait_ready(off_t offset)
+hal_error_t hal_io_wait_ready(off_t offset)
 {
     int limit = 10;
     return hal_io_wait(offset, STATUS_READY, &limit);
 }
 
-int hal_io_wait_valid(off_t offset)
+hal_error_t hal_io_wait_valid(off_t offset)
 {
     int limit = 10;
     return hal_io_wait(offset, STATUS_VALID, &limit);
diff --git a/hash.c b/hash.c
new file mode 100644
index 0000000..e41bf20
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,376 @@
+/* 
+ * hashes.c
+ * --------
+ *
+ * HAL interface to Cryptech hash cores.
+ * 
+ * Authors: Joachim Strömbergson, Paul Selkirk, Rob Austein
+ * Copyright (c) 2014-2015, SUNET
+ * 
+ * Redistribution and use in source and binary forms, with or 
+ * without modification, are permitted provided that the following 
+ * conditions are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include "cryptech.h"
+
+/* Longest digest block we support at the moment */
+#define MAX_BLOCK_LEN           SHA512_BLOCK_LEN
+
+/* Hash state */
+typedef struct {
+  uint64_t msg_length_high;             /* Total data hashed in this message */
+  uint64_t msg_length_low;              /* (128 bits in SHA-512 cases) */
+  size_t block_length;                  /* Block length for this algorithm */
+  uint8_t block[MAX_BLOCK_LEN];         /* Block we're accumulating */
+  size_t block_used;                    /* How much of the block we've used */
+  unsigned block_count;                 /* Blocks sent */
+} hash_state_t;
+
+static int debug = 0;
+
+/*
+ * Debugging control.
+ */
+
+void hal_hash_set_debug(int onoff)
+{
+  debug = onoff;
+}
+
+/*
+ * Tell caller how much space to allocate for a hash_state_t.  This
+ * lets us hide details that are nobody else's business while letting
+ * somebody else deal with memory allocation (and is the way
+ * Cryptlib's HAL code works, not by coincidence).
+ */
+
+size_t hal_hash_state_size(void)
+{
+  return sizeof(hash_state_t);
+}
+
+void hal_hash_state_initialize(void *_state)
+{
+  hash_state_t *state = _state;
+  assert(state != NULL);
+  memset(state, 0, sizeof(*state));
+}
+
+/*
+ * Report whether cores are present.
+ */
+
+hal_error_t hash_sha1_core_present(void)
+{
+  return hal_io_expected(SHA1_ADDR_NAME0, (const uint8_t *) (SHA1_NAME0 SHA1_NAME1), 8);
+}
+
+hal_error_t hash_sha256_core_present(void)
+{
+  return hal_io_expected(SHA256_ADDR_NAME0, (const uint8_t *) (SHA256_NAME0 SHA256_NAME1), 8);
+}
+
+hal_error_t hash_sha512_core_present(void)
+{
+  return hal_io_expected(SHA512_ADDR_NAME0, (const uint8_t *) (SHA512_NAME0 SHA512_NAME1), 8);
+}
+
+/*
+ * Send one block to a core.
+ */
+
+static hal_error_t hash_write_block(const off_t block_addr,
+                                    const off_t ctrl_addr,
+                                    const off_t status_addr,
+                                    const uint8_t ctrl_mode,
+                                    const hash_state_t * const state)
+{
+  uint8_t ctrl_cmd[4];
+  hal_error_t err;
+
+  assert(state != NULL && state->block_length % 4 == 0);
+
+  if (debug)
+    fprintf(stderr, "[ %s ]\n", state->block_count == 0 ? "init" : "next");
+
+  if ((err = hal_io_write(block_addr, state->block, state->block_length)) != HAL_OK)
+    return err;
+
+  ctrl_cmd[0] = ctrl_cmd[1] = ctrl_cmd[2] = 0;
+  ctrl_cmd[3] = state->block_count == 0 ? CTRL_INIT : CTRL_NEXT;  
+  ctrl_cmd[3] |= ctrl_mode;
+
+  /*
+   * Not sure why we're waiting for ready here, but it's what the old
+   * (read: tested) code did, so keep that behavior for now.
+   */
+
+  if ((err = hal_io_write(ctrl_addr, ctrl_cmd, sizeof(ctrl_cmd))) != HAL_OK)
+    return err;
+
+  return hal_io_wait_valid(status_addr);
+}
+
+/*
+ * Read hash result from core.
+ */
+
+static hal_error_t hash_read_digest(const uint8_t digest_addr,
+                                    const uint8_t status_addr,
+                                    uint8_t *digest,
+                                    const size_t digest_length)
+{
+  hal_error_t err;
+
+  assert(digest != NULL && digest_length % 4 == 0);
+
+  if ((err = hal_io_wait_valid(status_addr)) != HAL_OK)
+    return err;
+
+  return hal_io_read(digest_addr, digest, digest_length);
+}
+
+/*
+ * Hash data.  All supported hash algorithms use similar block
+ * manipulations and padding algorithms, so all can use this method
+ * with a few parameters which we handle via closures below.
+ */
+
+static hal_error_t hash_do_hash(hash_state_t *state,                    /* Opaque state block */
+                                const uint8_t * const data_buffer,	/* Data to be hashed */
+                                size_t data_buffer_length,              /* Length of data_buffer */
+                                uint8_t *digest_buffer,                 /* Returned digest */
+                                const size_t digest_buffer_length,      /* Length of digest_buffer */
+                                const size_t block_length,              /* Length of a block */
+                                const size_t digest_length,             /* Length of resulting digest */
+                                const size_t length_length,             /* Length of the length field */
+                                const off_t block_addr,                 /* Where to write hash blocks */
+                                const off_t ctrl_addr,                  /* Control register */
+                                const off_t status_addr,                /* Status register */
+                                const off_t digest_addr,                /* Where to read digest */
+                                const uint8_t ctrl_mode)                /* Digest mode, for cores that have modes */
+{
+  hal_error_t err;
+  size_t n;
+  int i;
+
+  if (state == NULL ||
+      (state->block_length != 0 && state->block_length != block_length) ||
+      (data_buffer_length > 0 && data_buffer == NULL) ||
+      (data_buffer_length == 0 && digest_buffer == NULL) ||
+      (digest_buffer != NULL && digest_buffer_length < digest_length))
+    return HAL_ERROR_INCONSISTENT_ARGS;
+
+  if (state->block_length == 0)
+    state->block_length = block_length;
+
+  assert(block_length <= sizeof(state->block));
+
+  if (data_buffer_length > 0) {                            /* We have data to hash */
+
+    const uint8_t *p = data_buffer;
+
+    while ((n = state->block_length - state->block_used) <= data_buffer_length) {
+      /*
+       * We have enough data for another complete block.
+       */
+      if (debug)
+        fprintf(stderr, "[ Full block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n",
+                (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, state->msg_length_low);
+      memcpy(state->block + state->block_used, p, n);
+      if ((state->msg_length_low += n) < n)
+        state->msg_length_high++;
+      state->block_used = 0;
+      data_buffer_length -= n;
+      p += n;
+      if ((err = hash_write_block(block_addr, ctrl_addr, status_addr, ctrl_mode, state)) != HAL_OK)
+        return err;
+      state->block_count++;
+    }
+
+    if (data_buffer_length > 0) {
+      /*
+       * Data left over, but not enough for a full block, stash it.
+       */
+      if (debug)
+        fprintf(stderr, "[ Partial block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n",
+                (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, state->msg_length_low);
+      assert(data_buffer_length < n);
+      memcpy(state->block + state->block_used, p, data_buffer_length);
+      if ((state->msg_length_low += data_buffer_length) < data_buffer_length)
+        state->msg_length_high++;
+      state->block_used += data_buffer_length;
+    }
+  }
+
+  else {           /* Done: add padding, then pull result from the core */
+
+    uint64_t bit_length_low  = (state->msg_length_low  << 3);
+    uint64_t bit_length_high = (state->msg_length_high << 3) | (state->msg_length_low >> 61);
+    uint8_t *p;
+
+    /* Initial pad byte */
+    assert(state->block_used < state->block_length);
+    state->block[state->block_used++] = 0x80;
+
+    /* If not enough room for bit count, zero and push current block */
+    if ((n = state->block_length - state->block_used) < length_length) {
+      if (debug)
+        fprintf(stderr, "[ Overflow block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n",
+                (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, state->msg_length_low);
+      if (n > 0)
+        memset(state->block + state->block_used, 0, n);
+      if ((err = hash_write_block(block_addr, ctrl_addr, status_addr, ctrl_mode, state)) != HAL_OK)
+        return err;
+      state->block_count++;
+      state->block_used = 0;
+    }
+
+    /* Pad final block */
+    n = state->block_length - state->block_used;
+    assert(n >= length_length);
+    if (n > 0)
+      memset(state->block + state->block_used, 0, n);
+    if (debug)
+      fprintf(stderr, "[ Final block, data_buffer_length %lu, used %lu, n %lu, msg_length %llu ]\n",
+              (unsigned long) data_buffer_length, (unsigned long) state->block_used, (unsigned long) n, state->msg_length_low);
+    p = state->block + state->block_length;
+    for (i = 0; (bit_length_low || bit_length_high) && i < length_length; i++) {
+      *--p = (uint8_t) (bit_length_low & 0xFF);
+      bit_length_low >>= 8;
+      if (bit_length_high) {
+        bit_length_low |= ((bit_length_high & 0xFF) << 56);
+        bit_length_high >>= 8;
+      }
+    }
+
+    /* Push final block */
+    if ((err = hash_write_block(block_addr, ctrl_addr, status_addr, ctrl_mode, state)) != HAL_OK)
+      return err;
+    state->block_count++;
+
+    /* All data pushed to core, now we just need to read back the result */
+    if ((err = hash_read_digest(digest_addr, status_addr, digest_buffer, digest_length)) != HAL_OK)
+      return err;
+  }
+
+  return HAL_OK;
+}
+
+/*
+ * Closures to provide the public API.
+ */
+
+hal_error_t hal_hash_sha1(void *state,
+                          const uint8_t *data_buffer,
+                          const size_t data_buffer_length,
+                          uint8_t *digest_buffer,
+                          const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA1_BLOCK_LEN, SHA1_DIGEST_LEN, SHA1_LENGTH_LEN,
+                      SHA1_ADDR_BLOCK, SHA1_ADDR_CTRL, SHA1_ADDR_STATUS, SHA1_ADDR_DIGEST, 0);
+}
+
+hal_error_t hal_hash_sha256(void *state,
+                            const uint8_t *data_buffer,
+                            const size_t data_buffer_length,
+                            uint8_t *digest_buffer,
+                            const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA256_BLOCK_LEN, SHA256_DIGEST_LEN, SHA256_LENGTH_LEN,
+                      SHA256_ADDR_BLOCK, SHA256_ADDR_CTRL, SHA256_ADDR_STATUS, SHA256_ADDR_DIGEST, 0);
+}
+
+hal_error_t hal_hash_sha512_224(void *state,
+                                const uint8_t *data_buffer,
+                                const size_t data_buffer_length,
+                                uint8_t *digest_buffer,
+                                const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA512_BLOCK_LEN, SHA512_DIGEST_LEN, SHA512_LENGTH_LEN,
+                      SHA512_ADDR_BLOCK, SHA512_ADDR_CTRL, SHA512_ADDR_STATUS, SHA512_ADDR_DIGEST,
+                      MODE_SHA_512_224);
+}
+
+hal_error_t hal_hash_sha512_256(void *state,
+                                const uint8_t *data_buffer,
+                                const size_t data_buffer_length,
+                                uint8_t *digest_buffer,
+                                const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA512_BLOCK_LEN, SHA512_DIGEST_LEN, SHA512_LENGTH_LEN,
+                      SHA512_ADDR_BLOCK, SHA512_ADDR_CTRL, SHA512_ADDR_STATUS, SHA512_ADDR_DIGEST,
+                      MODE_SHA_512_256);
+}
+
+hal_error_t hal_hash_sha384(void *state,
+                            const uint8_t *data_buffer,
+                            const size_t data_buffer_length,
+                            uint8_t *digest_buffer,
+                            const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA512_BLOCK_LEN, SHA512_DIGEST_LEN, SHA512_LENGTH_LEN,
+                      SHA512_ADDR_BLOCK, SHA512_ADDR_CTRL, SHA512_ADDR_STATUS, SHA512_ADDR_DIGEST,
+                      MODE_SHA_384);
+}
+
+hal_error_t hal_hash_sha512(void *state,
+                            const uint8_t *data_buffer,
+                            const size_t data_buffer_length,
+                            uint8_t *digest_buffer,
+                            const size_t digest_buffer_length)
+{
+  return hash_do_hash(state, data_buffer, data_buffer_length, digest_buffer, digest_buffer_length,
+                      SHA512_BLOCK_LEN, SHA512_DIGEST_LEN, SHA512_LENGTH_LEN,
+                      SHA512_ADDR_BLOCK, SHA512_ADDR_CTRL, SHA512_ADDR_STATUS, SHA512_ADDR_DIGEST,
+                      MODE_SHA_512);
+}
+
+/*
+ * "Any programmer who fails to comply with the standard naming, formatting,
+ *  or commenting conventions should be shot.  If it so happens that it is
+ *  inconvenient to shoot him, then he is to be politely requested to recode
+ *  his program in adherence to the above standard."
+ *                      -- Michael Spier, Digital Equipment Corporation
+ *
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */



More information about the Commits mailing list