aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-05-20 16:57:33 -0400
committerRob Austein <sra@hactrn.net>2015-05-20 16:57:33 -0400
commitfa13a8485ce07aecfbfa481baccfc33565f0be0d (patch)
tree48d7da997e617fbbcb22bf86f96a3a43ca7049ce
parent93941c6393ec3454c64528e537534284a81b04ac (diff)
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.
-rw-r--r--Makefile.in40
-rw-r--r--configure.ac20
-rw-r--r--cryptech.h740
-rw-r--r--csprng.c93
-rw-r--r--hal_io_eim.c65
-rw-r--r--hal_io_i2c.c211
-rw-r--r--hash.c376
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_@FPGA_BUS@)
-
-LIB_OBJ = $(HAL_IO_OBJ)
+IO_OBJ = ${IO_OBJ_@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:
+ */