From fa13a8485ce07aecfbfa481baccfc33565f0be0d Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 20 May 2015 16:57:33 -0400 Subject: 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(-) create mode 100644 csprng.c create mode 100644 hash.c 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 +#include +#include +#include + +#if 0 +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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: + */ -- cgit v1.2.3