aboutsummaryrefslogtreecommitdiff
path: root/eim
diff options
context:
space:
mode:
Diffstat (limited to 'eim')
-rwxr-xr-xeim/sw/Makefile19
-rw-r--r--eim/sw/hash_eim.c402
-rw-r--r--eim/sw/hash_tester_eim.c155
-rw-r--r--eim/sw/tc_eim.c137
-rw-r--r--eim/sw/tc_eim.h42
-rw-r--r--eim/sw/trng_tester_eim.c159
6 files changed, 645 insertions, 269 deletions
diff --git a/eim/sw/Makefile b/eim/sw/Makefile
index 87cd78f..8e584fa 100755
--- a/eim/sw/Makefile
+++ b/eim/sw/Makefile
@@ -1,19 +1,26 @@
-all: hash_tester_eim trng_tester_eim
+all: hash_tester_eim trng_tester_eim hash_eim
.c.o:
gcc -c -Wall -o $@ $<
-hash_tester_eim: hash_tester_eim.o novena-eim.o
+hash_tester_eim: hash_tester_eim.o novena-eim.o tc_eim.o
gcc -o $@ $^
-hash_tester_eim.o: hash_tester_eim.c novena-eim.h
+hash_tester_eim.o: hash_tester_eim.c tc_eim.h
-trng_tester_eim: trng_tester_eim.o novena-eim.o
+trng_tester_eim: trng_tester_eim.o novena-eim.o tc_eim.o
gcc -o $@ $^
-trng_tester_eim.o: trng_tester_eim.c novena-eim.h
+trng_tester_eim.o: trng_tester_eim.c tc_eim.h
+
+hash_eim: hash_eim.o novena-eim.o tc_eim.o
+ gcc -o $@ $^
+
+hash_eim.o: hash_eim.c tc_eim.h
novena-eim.o: novena-eim.c novena-eim.h
+tc_eim.o: tc_eim.c tc_eim.h novena-eim.h
+
clean:
- rm -f *.o hash_tester_eim trng_tester_eim
+ rm -f *.o hash_tester_eim trng_tester_eim hash_eim
diff --git a/eim/sw/hash_eim.c b/eim/sw/hash_eim.c
new file mode 100644
index 0000000..281914c
--- /dev/null
+++ b/eim/sw/hash_eim.c
@@ -0,0 +1,402 @@
+/*
+ * hash.c
+ * ------
+ * This program uses the coretest_hashes subsystem to produce a
+ * cryptographic hash of a file or input stream. It is a generalization
+ * of the hash_tester.c test program.
+ *
+ * Authors: Joachim Strömbergson, Paul Selkirk
+ * Copyright (c) 2014-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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "tc_eim.h"
+
+char *usage =
+"Usage: %s [-d] [-v] [-q] [algorithm [file]]\n"
+"algorithms: sha-1, sha-256, sha-512/224, sha-512/256, sha-384, sha-512\n";
+
+int debug = 0;
+int quiet = 0;
+int verbose = 0;
+
+/* memory segments for core families */
+#define SEGMENT_OFFSET_GLOBALS EIM_BASE_ADDR + 0x000000
+#define SEGMENT_OFFSET_HASHES EIM_BASE_ADDR + 0x010000
+#define SEGMENT_OFFSET_RNGS EIM_BASE_ADDR + 0x020000
+#define SEGMENT_OFFSET_CIPHERS EIM_BASE_ADDR + 0x030000
+
+#define CORE_SIZE (0x100 << 2)
+
+/* addresses and codes common to all cores */
+#define ADDR_NAME0 (0x0 << 2)
+#define ADDR_NAME1 (0x1 << 2)
+#define ADDR_VERSION (0x2 << 2)
+
+/* At segment 0, we have board-level register and communication channel registers */
+#define BOARD_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x00 * 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 << 2)
+
+#define COMM_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x01 * 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
+
+/* addresses and codes common to all hash cores */
+#define ADDR_CTRL (0x8 << 2)
+#define CTRL_INIT_CMD 1
+#define CTRL_NEXT_CMD 2
+#define ADDR_STATUS (9 << 2)
+#define STATUS_READY_BIT 1
+#define STATUS_VALID_BIT 2
+#define ADDR_BLOCK (0x10 << 2)
+#define ADDR_DIGEST (0x20 << 2)
+
+/* 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 512 / 8
+#define SHA1_DIGEST_LEN 160 / 8
+
+#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 512 / 8
+#define SHA256_DIGEST_LEN 256 / 8
+
+#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 << 2)
+#define SHA512_BLOCK_LEN 1024 / 8
+#define SHA512_224_DIGEST_LEN 224 / 8
+#define SHA512_256_DIGEST_LEN 256 / 8
+#define SHA384_DIGEST_LEN 384 / 8
+#define SHA512_DIGEST_LEN 512 / 8
+#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
+
+/* ---------------- algorithm lookup code ---------------- */
+
+struct ctrl {
+ char *name;
+ off_t block_addr;
+ int block_len;
+ off_t digest_addr;
+ int digest_len;
+ int mode;
+} ctrl[] = {
+ { "sha-1", SHA1_ADDR_BLOCK, SHA1_BLOCK_LEN,
+ SHA1_ADDR_DIGEST, SHA1_DIGEST_LEN, 0 },
+ { "sha-256", SHA256_ADDR_BLOCK, SHA256_BLOCK_LEN,
+ SHA256_ADDR_DIGEST, SHA256_DIGEST_LEN, 0 },
+ { "sha-512/224", SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
+ SHA512_ADDR_DIGEST, SHA512_224_DIGEST_LEN, MODE_SHA_512_224 },
+ { "sha-512/256", SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
+ SHA512_ADDR_DIGEST, SHA512_256_DIGEST_LEN, MODE_SHA_512_256 },
+ { "sha-384", SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
+ SHA512_ADDR_DIGEST, SHA384_DIGEST_LEN, MODE_SHA_384 },
+ { "sha-512", SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
+ SHA512_ADDR_DIGEST, SHA512_DIGEST_LEN, MODE_SHA_512 },
+ { NULL, 0, 0, 0 }
+};
+
+/* return the control structure for the given algorithm */
+struct ctrl *find_algo(char *algo)
+{
+ int i;
+
+ for (i = 0; ctrl[i].name != NULL; ++i)
+ if (strcmp(ctrl[i].name, algo) == 0)
+ return &ctrl[i];
+
+ fprintf(stderr, "algorithm \"%s\" not found\n\n", algo);
+ fprintf(stderr, usage, "hash");
+ return NULL;
+}
+
+/* ---------------- test-case low-level code ---------------- */
+
+int tc_init(off_t offset, int mode)
+{
+ uint8_t buf[4] = { 0, 0, 0, CTRL_INIT_CMD + mode };
+
+ return tc_write(offset, buf, 4);
+}
+
+int tc_next(off_t offset, int mode)
+{
+ uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT_CMD + mode };
+
+ return tc_write(offset, buf, 4);
+}
+
+int tc_wait_ready(off_t offset)
+{
+ return tc_wait(offset, STATUS_READY_BIT, NULL);
+}
+
+int tc_wait_valid(off_t offset)
+{
+ return tc_wait(offset, STATUS_VALID_BIT, NULL);
+}
+
+/* ---------------- hash ---------------- */
+
+int transmit(off_t offset, uint8_t *block, int blen, int mode, int first)
+{
+ off_t base = offset & ~(0xff);
+
+ if (tc_write(offset, block, blen) != 0)
+ return 1;
+
+ if (first) {
+ if (tc_init(base + ADDR_CTRL, mode) != 0)
+ return 1;
+ }
+ else {
+ if (tc_next(base + ADDR_CTRL, mode) != 0)
+ return 1;
+ }
+
+ return tc_wait_ready(base + ADDR_STATUS);
+}
+
+int pad_transmit(off_t offset, uint8_t *block, uint8_t flen, uint8_t blen,
+ uint8_t mode, long long tlen, int first)
+{
+ assert(flen < blen);
+
+ block[flen++] = 0x80;
+ memset(block + flen, 0, blen - flen);
+
+ if (blen - flen < ((blen == 64) ? 8 : 16)) {
+ if (transmit(offset, block, blen, mode, first) != 0)
+ return 1;
+ first = 0;
+ memset(block, 0, blen);
+ }
+
+ /* properly the length is 128 bits for sha-512, but we can't
+ * actually count above 64 bits
+ */
+ ((uint32_t *)block)[blen/4 - 2] = htonl((tlen >> 32) & 0xffff);
+ ((uint32_t *)block)[blen/4 - 1] = htonl(tlen & 0xffff);
+
+ return transmit(offset, block, blen, mode, first);
+}
+
+/* return number of digest bytes read */
+int hash(char *algo, char *file, uint8_t *digest)
+{
+ uint8_t block[SHA512_BLOCK_LEN];
+ struct ctrl *ctrl;
+ int in_fd = 0; /* stdin */
+ off_t baddr, daddr;
+ int blen, dlen, mode;
+ int nblk, nread, first;
+ int ret = -1;
+ struct timeval start, stop, difftime;
+
+ ctrl = find_algo(algo);
+ if (ctrl == NULL)
+ return -1;
+ baddr = ctrl->block_addr;
+ blen = ctrl->block_len;
+ daddr = ctrl->digest_addr;
+ dlen = ctrl->digest_len;
+ mode = ctrl->mode;
+
+ if (strcmp(file, "-") != 0) {
+ in_fd = open(file, O_RDONLY);
+ if (in_fd < 0) {
+ perror("open");
+ return -1;
+ }
+ }
+
+ if (verbose) {
+ if (gettimeofday(&start, NULL) < 0) {
+ perror("gettimeofday");
+ goto out;
+ }
+ }
+
+ for (nblk = 0, first = 1; ; ++nblk, first = 0) {
+ nread = read(in_fd, block, blen);
+ if (nread < 0) {
+ /* read error */
+ perror("read");
+ goto out;
+ }
+ else if (nread < blen) {
+ /* partial read = last block */
+ if (pad_transmit(baddr, block, nread, blen, mode,
+ (nblk * blen + nread) * 8, first) != 0)
+ goto out;
+ break;
+ }
+ else {
+ /* full block read */
+ if (transmit(baddr, block, blen, mode, first) != 0)
+ goto out;
+ }
+ }
+
+ /* Strictly speaking we should query "valid" status before reading digest,
+ * but transmit() waits for "ready" status before returning, and the SHA
+ * cores always assert valid before ready.
+ */
+ if (tc_read(daddr, digest, dlen) != 0) {
+ perror("i2c read failed");
+ goto out;
+ }
+
+ if (verbose) {
+ if (gettimeofday(&stop, NULL) < 0) {
+ perror("gettimeofday");
+ goto out;
+ }
+ timersub(&stop, &start, &difftime);
+ printf("%d blocks written in %d.%03d sec (%.3f blocks/sec)\n",
+ nblk, (int)difftime.tv_sec, (int)difftime.tv_usec/1000,
+ (float)nblk / ((float)difftime.tv_sec + ((float)difftime.tv_usec)/1000000));
+ }
+
+ ret = dlen;
+out:
+ if (in_fd != 0)
+ close(in_fd);
+ return ret;
+}
+
+/* ---------------- main ---------------- */
+
+int main(int argc, char *argv[])
+{
+ int i, opt;
+ char *algo = "sha-1";
+ char *file = "-";
+ uint8_t digest[512/8];
+ int dlen;
+
+ while ((opt = getopt(argc, argv, "h?dvq")) != -1) {
+ switch (opt) {
+ case 'h':
+ case '?':
+ printf(usage, argv[0]);
+ return EXIT_SUCCESS;
+ case 'd':
+ debug = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ default:
+ fprintf(stderr, usage, argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (optind < argc) {
+ algo = argv[optind];
+ ++optind;
+ }
+ else {
+ if (!quiet)
+ printf("defaulting to algorithm \"%s\"\n", algo);
+ }
+
+ if (optind < argc) {
+ file = argv[optind];
+ ++optind;
+ }
+ else {
+ if (!quiet)
+ printf("reading from stdin\n");
+ }
+
+ if (eim_setup() != 0) {
+ fprintf(stderr, "EIM setup failed\n");
+ return EXIT_FAILURE;
+ }
+
+ dlen = hash(algo, file, digest);
+ if (dlen < 0)
+ return EXIT_FAILURE;
+
+ for (i = 0; i < dlen; ++i) {
+ printf("%02x", digest[i]);
+ if (i % 16 == 15)
+ printf("\n");
+ else if (i % 4 == 3)
+ printf(" ");
+ }
+ if (dlen % 16 != 0)
+ printf("\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/eim/sw/hash_tester_eim.c b/eim/sw/hash_tester_eim.c
index 74685ee..e0bcc03 100644
--- a/eim/sw/hash_tester_eim.c
+++ b/eim/sw/hash_tester_eim.c
@@ -45,41 +45,40 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
+#include <stdint.h>
#include <ctype.h>
#include <signal.h>
-#include "novena-eim.h"
+#include "tc_eim.h"
int debug = 0;
int quiet = 0;
int repeat = 0;
+/* memory segments for core families */
#define SEGMENT_OFFSET_GLOBALS EIM_BASE_ADDR + 0x000000
#define SEGMENT_OFFSET_HASHES EIM_BASE_ADDR + 0x010000
#define SEGMENT_OFFSET_RNGS EIM_BASE_ADDR + 0x020000
#define SEGMENT_OFFSET_CIPHERS EIM_BASE_ADDR + 0x030000
+#define CORE_SIZE (0x100 << 2)
+
/* addresses and codes common to all cores */
#define ADDR_NAME0 (0x0 << 2)
#define ADDR_NAME1 (0x1 << 2)
#define ADDR_VERSION (0x2 << 2)
/* At segment 0, we have board-level register and communication channel registers */
-#define BOARD_ADDR_BASE SEGMENT_OFFSET_GLOBALS + 0x0000
+#define BOARD_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x00 * 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 << 2)
-#define COMM_ADDR_BASE SEGMENT_OFFSET_GLOBALS + 0x0400
+#define COMM_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x01 * 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
@@ -94,10 +93,8 @@ int repeat = 0;
#define ADDR_BLOCK (0x10 << 2)
#define ADDR_DIGEST (0x20 << 2)
-#define HASH_CORE_SIZE (0x100 << 2)
-
/* addresses and codes for the specific hash cores */
-#define SHA1_ADDR_BASE SEGMENT_OFFSET_HASHES + (0*HASH_CORE_SIZE)
+#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
@@ -108,7 +105,7 @@ int repeat = 0;
#define SHA1_BLOCK_LEN 512 / 8
#define SHA1_DIGEST_LEN 160 / 8
-#define SHA256_ADDR_BASE SEGMENT_OFFSET_HASHES + (1*HASH_CORE_SIZE)
+#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
@@ -119,14 +116,14 @@ int repeat = 0;
#define SHA256_BLOCK_LEN 512 / 8
#define SHA256_DIGEST_LEN 256 / 8
-#define SHA512_ADDR_BASE SEGMENT_OFFSET_HASHES + (2*HASH_CORE_SIZE)
+#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 + 0x100
+#define SHA512_ADDR_DIGEST SHA512_ADDR_BASE + (0x40 << 2)
#define SHA512_BLOCK_LEN 1024 / 8
#define SHA512_224_DIGEST_LEN 224 / 8
#define SHA512_256_DIGEST_LEN 256 / 8
@@ -306,75 +303,6 @@ const uint8_t SHA512_DOUBLE_DIGEST[] =
/* ---------------- test-case low-level code ---------------- */
-void dump(char *label, const uint8_t *buf, int len)
-{
- if (debug) {
- int i;
- printf("%s [", label);
- for (i = 0; i < len; ++i)
- printf(" %02x", buf[i]);
- printf(" ]\n");
- }
-}
-
-int tc_write(off_t offset, const uint8_t *buf, int len)
-{
- dump("write ", buf, len);
-
- for (; len > 0; offset += 4, buf += 4, len -= 4) {
- uint32_t val;
- val = htonl(*(uint32_t *)buf);
- eim_write_32(offset, &val);
- }
-
- return 0;
-}
-
-int tc_read(off_t offset, uint8_t *buf, int len)
-{
- uint8_t *rbuf = buf;
- int rlen = len;
-
- for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
- uint32_t val;
- eim_read_32(offset, &val);
- *(uint32_t *)rbuf = ntohl(val);
- }
-
- dump("read ", buf, len);
-
- return 0;
-}
-
-int tc_expected(off_t offset, const uint8_t *expected, int len)
-{
- uint8_t *buf;
- int i;
-
- buf = malloc(len);
- if (buf == NULL) {
- perror("malloc");
- return 1;
- }
- dump("expect", expected, len);
-
- if (tc_read(offset, buf, len) != 0)
- goto errout;
-
- 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]);
- goto errout;
- }
-
- free(buf);
- return 0;
-errout:
- free(buf);
- return 1;
-}
-
int tc_init(off_t offset)
{
uint8_t buf[4] = { 0, 0, 0, CTRL_INIT_CMD };
@@ -389,51 +317,27 @@ int tc_next(off_t offset)
return tc_write(offset, buf, 4);
}
-int tc_wait(off_t offset, uint8_t status)
-{
- uint8_t buf[4];
-
-#if 0
- do {
- if (tc_read(offset, buf, 4) != 0)
- return 1;
- } while (!(buf[3] & status));
-
- return 0;
-#else
- int i;
- for (i = 0; i < 10; ++i) {
- if (tc_read(offset, buf, 4) != 0)
- return 1;
- if (buf[3] & status)
- return 0;
- }
- fprintf(stderr, "tc_wait timed out\n");
- return 1;
-#endif
-}
-
int tc_wait_ready(off_t offset)
{
- return tc_wait(offset, STATUS_READY_BIT);
+ return tc_wait(offset, STATUS_READY_BIT, NULL);
}
int tc_wait_valid(off_t offset)
{
- return tc_wait(offset, STATUS_VALID_BIT);
+ return tc_wait(offset, STATUS_VALID_BIT, NULL);
}
/* ---------------- sanity test case ---------------- */
int TC0()
{
- uint8_t board_name0[4] = { 'P', 'V', 'T', '1'};
- uint8_t board_name1[4] = { ' ', ' ', ' ', ' '};
- uint8_t board_version[4] = { '0', '.', '1', '0'};
+ uint8_t board_name0[4] = "PVT1";
+ uint8_t board_name1[4] = " ";
+ uint8_t board_version[4] = "0.10";
- uint8_t comm_name0[4] = { 'e', 'i', 'm', ' '};
- uint8_t comm_name1[4] = { ' ', ' ', ' ', ' '};
- uint8_t comm_version[4] = { '0', '.', '1', '0'};
+ uint8_t comm_name0[4] = "eim ";
+ uint8_t comm_name1[4] = " ";
+ uint8_t comm_version[4] = "0.10";
uint8_t t[4];
@@ -444,7 +348,8 @@ int TC0()
* to make sure that we can actually write something into EIM
*/
(void)time((time_t *)t);
- tc_write(BOARD_ADDR_DUMMY, (void *)&t, 4);
+ if (tc_write(BOARD_ADDR_DUMMY, (void *)&t, 4) != 0)
+ return 1;
if (tc_expected(BOARD_ADDR_NAME0, board_name0, 4) ||
tc_expected(BOARD_ADDR_NAME1, board_name1, 4) ||
@@ -466,9 +371,9 @@ int TC0()
/* TC1: Read name and version from SHA-1 core. */
int TC1(void)
{
- uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x31 }; /* "sha1" */
- uint8_t name1[4] = { 0x20, 0x20, 0x20, 0x20 }; /* " " */
- uint8_t version[4] = { 0x30, 0x2e, 0x35, 0x30 }; /* "0.50" */
+ uint8_t name0[4] = "sha1";
+ uint8_t name1[4] = " ";
+ uint8_t version[4] = "0.50";
if (!quiet)
printf("TC1: Reading name and version words from SHA-1 core.\n");
@@ -535,9 +440,9 @@ int TC3(void)
/* TC4: Read name and version from SHA-256 core. */
int TC4(void)
{
- uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x32 }; /* "sha2" */
- uint8_t name1[4] = { 0x2d, 0x32, 0x35, 0x36 }; /* "-256" */
- uint8_t version[4] = { 0x30, 0x2e, 0x38, 0x30 }; /* "0.80" */
+ uint8_t name0[4] = "sha2";
+ uint8_t name1[4] = "-256";
+ uint8_t version[4] = "0.80";
if (!quiet)
printf("TC4: Reading name, type and version words from SHA-256 core.\n");
@@ -652,9 +557,9 @@ int TC7()
/* TC8: Read name and version from SHA-512 core. */
int TC8()
{
- uint8_t name0[4] = { 0x73, 0x68, 0x61, 0x32 }; /* "sha2" */
- uint8_t name1[4] = { 0x2d, 0x35, 0x31, 0x32 }; /* "-512" */
- uint8_t version[4] = { 0x30, 0x2e, 0x38, 0x30 }; /* "0.80" */
+ uint8_t name0[4] = "sha2";
+ uint8_t name1[4] = "-512";
+ uint8_t version[4] = "0.80";
if (!quiet)
printf("TC8: Reading name, type and version words from SHA-512 core.\n");
diff --git a/eim/sw/tc_eim.c b/eim/sw/tc_eim.c
new file mode 100644
index 0000000..0d8c83c
--- /dev/null
+++ b/eim/sw/tc_eim.c
@@ -0,0 +1,137 @@
+/*
+ * tc_eim.c
+ * --------
+ * This module contains common code to talk to the FPGA over the EIM bus.
+ *
+ * Author: Paul Selkirk
+ * Copyright (c) 2014-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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "tc_eim.h"
+
+extern int debug;
+
+/* ---------------- test-case low-level code ---------------- */
+
+static void dump(char *label, const uint8_t *buf, int len)
+{
+ if (debug) {
+ int i;
+ printf("%s [", label);
+ for (i = 0; i < len; ++i)
+ printf(" %02x", buf[i]);
+ printf(" ]\n");
+ }
+}
+
+int tc_write(off_t offset, const uint8_t *buf, int len)
+{
+ dump("write ", buf, len);
+
+ for (; len > 0; offset += 4, buf += 4, len -= 4) {
+ uint32_t val;
+ val = htonl(*(uint32_t *)buf);
+ eim_write_32(offset, &val);
+ }
+
+ return 0;
+}
+
+int tc_read(off_t offset, uint8_t *buf, int len)
+{
+ uint8_t *rbuf = buf;
+ int rlen = len;
+
+ for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
+ uint32_t val;
+ eim_read_32(offset, &val);
+ *(uint32_t *)rbuf = ntohl(val);
+ }
+
+ dump("read ", buf, len);
+
+ return 0;
+}
+
+int tc_expected(off_t offset, const uint8_t *expected, int len)
+{
+ uint8_t *buf;
+ int i;
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ perror("malloc");
+ return 1;
+ }
+ dump("expect", expected, len);
+
+ if (tc_read(offset, buf, len) != 0)
+ goto errout;
+
+ 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]);
+ goto errout;
+ }
+
+ free(buf);
+ return 0;
+errout:
+ free(buf);
+ return 1;
+}
+
+int tc_wait(off_t offset, uint8_t status, int *count)
+{
+ uint8_t buf[4];
+ int i;
+
+ for (i = 1; ; ++i) {
+ if (count && (*count > 0) && (i >= *count)) {
+ fprintf(stderr, "tc_wait timed out\n");
+ return 1;
+ }
+ if (tc_read(offset, buf, 4) != 0)
+ return -1;
+ if (buf[3] & status) {
+ if (count)
+ *count = i;
+ return 0;
+ }
+ }
+}
diff --git a/eim/sw/tc_eim.h b/eim/sw/tc_eim.h
new file mode 100644
index 0000000..257822d
--- /dev/null
+++ b/eim/sw/tc_eim.h
@@ -0,0 +1,42 @@
+/*
+ * tc_eim.h
+ * --------
+ * This module contains common code to talk to the FPGA over the EIM bus.
+ *
+ * Author: Paul Selkirk
+ * Copyright (c) 2014-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.
+ */
+
+#include "novena-eim.h"
+
+/* test case public functions */
+int tc_write(off_t offset, const uint8_t *buf, int len);
+int tc_read(off_t offset, uint8_t *buf, int len);
+int tc_expected(off_t offset, const uint8_t *expected, int len);
+int tc_wait(off_t offset, uint8_t status, int *count);
diff --git a/eim/sw/trng_tester_eim.c b/eim/sw/trng_tester_eim.c
index 7c452b0..eb30045 100644
--- a/eim/sw/trng_tester_eim.c
+++ b/eim/sw/trng_tester_eim.c
@@ -40,18 +40,14 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
+#include <stdint.h>
#include <ctype.h>
#include <signal.h>
-#include "novena-eim.h"
+#include "tc_eim.h"
#define WAIT_STATS /* report number of status reads before core says "ready" */
@@ -60,32 +56,33 @@ int quiet = 0;
int repeat = 0;
int num_words = 10;
+/* memory segments for core families */
#define SEGMENT_OFFSET_GLOBALS EIM_BASE_ADDR + 0x000000
#define SEGMENT_OFFSET_HASHES EIM_BASE_ADDR + 0x010000
#define SEGMENT_OFFSET_RNGS EIM_BASE_ADDR + 0x020000
#define SEGMENT_OFFSET_CIPHERS EIM_BASE_ADDR + 0x030000
+#define CORE_SIZE (0x100 << 2)
+
/* addresses and codes common to all cores */
#define ADDR_NAME0 (0x0 << 2)
#define ADDR_NAME1 (0x1 << 2)
#define ADDR_VERSION (0x2 << 2)
/* At segment 0, we have board-level register and communication channel registers */
-#define BOARD_ADDR_BASE SEGMENT_OFFSET_GLOBALS + 0x0000
+#define BOARD_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x00 * 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 << 2)
-#define COMM_ADDR_BASE SEGMENT_OFFSET_GLOBALS + 0x0400
+#define COMM_ADDR_BASE SEGMENT_OFFSET_GLOBALS + (0x01 * 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
-#define CORE_SIZE (0x100 << 2)
-
/* addresses and codes for the TRNG cores */
-#define TRNG_ADDR_BASE SEGMENT_OFFSET_RNGS + (0 * CORE_SIZE)
+#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
@@ -96,7 +93,7 @@ int num_words = 10;
/* no status bits defined */
#define TRNG_ADDR_DELAY TRNG_ADDR_BASE + (0x13 << 2)
-#define ENTROPY1_ADDR_BASE SEGMENT_OFFSET_RNGS + (5 * CORE_SIZE)
+#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
@@ -107,7 +104,7 @@ int num_words = 10;
#define ENTROPY1_ADDR_ENTROPY ENTROPY1_ADDR_BASE + (0x20 << 2)
#define ENTROPY1_ADDR_DELTA ENTROPY1_ADDR_BASE + (0x30 << 2)
-#define ENTROPY2_ADDR_BASE SEGMENT_OFFSET_RNGS + (6 * CORE_SIZE)
+#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
@@ -146,103 +143,6 @@ int num_words = 10;
#define CSPRNG_ADDR_NBLOCKS_LO CSPRNG_ADDR_BASE + (0x41 << 2)
#define CSPRNG_ADDR_NBLOCKS_HI CSPRNG_ADDR_BASE + (0x42 << 2)
-/* ---------------- test-case low-level code ---------------- */
-
-void dump(char *label, const uint8_t *buf, int len)
-{
- if (debug) {
- int i;
- printf("%s [", label);
- for (i = 0; i < len; ++i)
- printf(" %02x", buf[i]);
- printf(" ]\n");
- }
-}
-
-int tc_write(off_t offset, const uint8_t *buf, int len)
-{
- dump("write ", buf, len);
-
- for (; len > 0; offset += 4, buf += 4, len -= 4) {
- uint32_t val;
- val = htonl(*(uint32_t *)buf);
- eim_write_32(offset, &val);
- }
-
- return 0;
-}
-
-int tc_read(off_t offset, uint8_t *buf, int len)
-{
- uint8_t *rbuf = buf;
- int rlen = len;
-
- for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
- uint32_t val;
- eim_read_32(offset, &val);
- *(uint32_t *)rbuf = ntohl(val);
- }
-
- dump("read ", buf, len);
-
- return 0;
-}
-
-int tc_expected(off_t offset, const uint8_t *expected, int len)
-{
- uint8_t *buf;
- int i;
-
- buf = malloc(len);
- if (buf == NULL) {
- perror("malloc");
- return 1;
- }
- dump("expect", expected, len);
-
- if (tc_read(offset, buf, len) != 0)
- goto errout;
-
- 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]);
- goto errout;
- }
-
- free(buf);
- return 0;
-errout:
- free(buf);
- return 1;
-}
-
-#ifdef WAIT_STATS
-int tc_wait(off_t offset, uint8_t status)
-{
- uint8_t buf[4];
- int i;
-
- for (i = 1; ; ++i) {
- if (tc_read(offset, buf, 4) != 0)
- return -1;
- if (buf[3] & status)
- return i;
- }
-}
-#else
-int tc_wait(off_t offset, uint8_t status)
-{
- uint8_t buf[4];
- do {
- if (tc_read(offset, buf, 4) != 0)
- return 1;
- } while (!(buf[3] & status));
-
- return 0;
-}
-#endif
-
/* ---------------- sanity test case ---------------- */
int TC0()
@@ -264,7 +164,8 @@ int TC0()
* to make sure that we can actually write something into EIM
*/
(void)time((time_t *)t);
- tc_write(BOARD_ADDR_DUMMY, (void *)&t, 4);
+ if (tc_write(BOARD_ADDR_DUMMY, (void *)&t, 4) != 0)
+ return 1;
if (tc_expected(BOARD_ADDR_NAME0, board_name0, 4) ||
tc_expected(BOARD_ADDR_NAME1, board_name1, 4) ||
@@ -325,10 +226,7 @@ int TC2(void)
/* TC3: Read random data from avalanche_entropy. */
int TC3(void)
{
- int i;
-#ifdef WAIT_STATS
- int n;
-#endif
+ int i, n;
unsigned long entropy;
if (!quiet)
@@ -336,11 +234,8 @@ int TC3(void)
for (i = 0; i < num_words; ++i) {
/* check status */
-#ifdef WAIT_STATS
- if ((n = tc_wait(ENTROPY1_ADDR_STATUS, ENTROPY1_STATUS_VALID)) < 0)
-#else
- if (tc_wait(ENTROPY1_ADDR_STATUS, ENTROPY1_STATUS_VALID) != 0)
-#endif
+ n = 0;
+ if (tc_wait(ENTROPY1_ADDR_STATUS, ENTROPY1_STATUS_VALID, &n) != 0)
return 1;
/* read entropy data */
if (tc_read(ENTROPY1_ADDR_ENTROPY, (uint8_t *)&entropy, 4) != 0)
@@ -380,10 +275,7 @@ int TC4(void)
/* TC5: Read random data from rosc_entropy. */
int TC5(void)
{
- int i;
-#ifdef WAIT_STATS
- int n;
-#endif
+ int i, n;
unsigned long entropy;
if (!quiet)
@@ -391,11 +283,8 @@ int TC5(void)
for (i = 0; i < num_words; ++i) {
/* check status */
-#ifdef WAIT_STATS
- if ((n = tc_wait(ENTROPY2_ADDR_STATUS, ENTROPY2_STATUS_VALID)) < 0)
-#else
- if (tc_wait(ENTROPY2_ADDR_STATUS, ENTROPY2_STATUS_VALID) != 0)
-#endif
+ n = 0;
+ if (tc_wait(ENTROPY2_ADDR_STATUS, ENTROPY2_STATUS_VALID, &n) != 0)
return 1;
/* read entropy data */
if (tc_read(ENTROPY2_ADDR_ENTROPY, (uint8_t *)&entropy, 4) != 0)
@@ -427,10 +316,7 @@ int TC6(void)
/* TC7: Read random data from trng_csprng. */
int TC7(void)
{
- int i;
-#ifdef WAIT_STATS
- int n;
-#endif
+ int i, n;
unsigned long random;
if (!quiet)
@@ -438,11 +324,8 @@ int TC7(void)
for (i = 0; i < num_words; ++i) {
/* check status */
-#ifdef WAIT_STATS
- if ((n = tc_wait(CSPRNG_ADDR_STATUS, CSPRNG_STATUS_VALID)) < 0)
-#else
- if (tc_wait(CSPRNG_ADDR_STATUS, CSPRNG_STATUS_VALID) != 0)
-#endif
+ n = 0;
+ if (tc_wait(CSPRNG_ADDR_STATUS, CSPRNG_STATUS_VALID, &n) != 0)
return 1;
/* read random data */
if (tc_read(CSPRNG_ADDR_RANDOM, (uint8_t *)&random, 4) != 0)