aboutsummaryrefslogtreecommitdiff
path: root/src/cryptech_novena_i2c_trng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptech_novena_i2c_trng.c')
-rw-r--r--src/cryptech_novena_i2c_trng.c430
1 files changed, 51 insertions, 379 deletions
diff --git a/src/cryptech_novena_i2c_trng.c b/src/cryptech_novena_i2c_trng.c
index 5877acc..92f851a 100644
--- a/src/cryptech_novena_i2c_trng.c
+++ b/src/cryptech_novena_i2c_trng.c
@@ -1,6 +1,6 @@
/*
* cryptech_novena_i2c_trng.c
- * ------------------------------
+ * --------------------------
*
* This is an early prototype Hardware Adaption Layer (HAL) for using
* Cryptlib with the Cryptech project's FGPA cores over an I2C bus on
@@ -14,7 +14,7 @@
* use, this is just a prototype.
*
* Authors: Joachim Strömbergson, Paul Selkirk, Rob Austein
- * Copyright (c) 2014, SUNET
+ * Copyright (c) 2014-2015, SUNET
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
@@ -53,6 +53,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <stdint.h>
#if defined( INC_ALL )
#include "crypt.h"
@@ -64,87 +65,13 @@
#include "device/hardware.h"
#endif /* Compiler-specific includes */
-/*
- * I2C_SLAVE comes from /usr/include/linux/i2c-dev.h, but if we
- * include that we won't be able to compile this except on Linux. It
- * won't *run* anywhere but on Linux, but it's useful to be able to do
- * compilation tests on other platforms, eg, with Clang, so for now we
- * take the small risk that this one magic constant might change.
- */
-
-#define I2C_SLAVE 0x0703
+#include "tc_i2c.h"
+/* XXX This is gross, but it saves us from having to build a library. */
+#include "tc_i2c.c"
#ifdef USE_HARDWARE
-/*
- * I2C-related parameters, copied from hash_tester.c
- */
-
-/* I2C configuration */
-#define I2C_DEV "/dev/i2c-2"
-#define I2C_ADDR 0x0f
-
-/* Command codes */
-#define SOC 0x55
-#define EOC 0xaa
-#define READ_CMD 0x10
-#define WRITE_CMD 0x11
-#define RESET_CMD 0x01
-
-/* Response codes */
-#define SOR 0xaa
-#define EOR 0x55
-#define READ_OK 0x7f
-#define WRITE_OK 0x7e
-#define RESET_OK 0x7d
-#define UNKNOWN 0xfe
-#define ERROR 0xfd
-
-/* 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_CMD 1
-#define CTRL_NEXT_CMD 2
-#define ADDR_STATUS 0x09
-#define STATUS_READY_BIT 1
-#define STATUS_VALID_BIT 2
-
-/*
- * Addresses and codes for the specific hash cores.
- * Lengths here are in bytes (not bits, not 32-bit words).
- */
-
-#define SHA1_ADDR_PREFIX 0x10
-#define SHA1_ADDR_BLOCK 0x10
-#define SHA1_BLOCK_LEN bitsToBytes(512)
-#define SHA1_LENGTH_LEN bitsToBytes(64)
-#define SHA1_ADDR_DIGEST 0x20
-#define SHA1_DIGEST_LEN bitsToBytes(160)
-
-#define SHA256_ADDR_PREFIX 0x20
-#define SHA256_ADDR_BLOCK 0x10
-#define SHA256_BLOCK_LEN bitsToBytes(512)
-#define SHA256_LENGTH_LEN bitsToBytes(64)
-#define SHA256_ADDR_DIGEST 0x20
-#define SHA256_DIGEST_LEN bitsToBytes(256)
-
-#define SHA512_ADDR_PREFIX 0x30
-#define SHA512_CTRL_MODE_LOW 2
-#define SHA512_CTRL_MODE_HIGH 3
-#define SHA512_ADDR_BLOCK 0x10
-#define SHA512_BLOCK_LEN bitsToBytes(1024)
-#define SHA512_LENGTH_LEN bitsToBytes(128)
-#define SHA512_ADDR_DIGEST 0x40
-#define SHA384_DIGEST_LEN bitsToBytes(384)
-#define SHA512_DIGEST_LEN bitsToBytes(512)
-#define MODE_SHA_512_224 (0 << SHA512_CTRL_MODE_LOW)
-#define MODE_SHA_512_256 (1 << SHA512_CTRL_MODE_LOW)
-#define MODE_SHA_384 (2 << SHA512_CTRL_MODE_LOW)
-#define MODE_SHA_512 (3 << SHA512_CTRL_MODE_LOW)
-
/* Longest digest block we support at the moment */
#define MAX_BLOCK_LEN SHA512_BLOCK_LEN
@@ -158,251 +85,7 @@ typedef struct {
unsigned block_count; /* Blocks sent */
} hash_state_t;
-/*
- * Address for reading 32 bits of entropy from the noise board.
- * TRNG_VALID is nonzero if valid random bits are available.
- */
-
-#define TRNG_PREFIX 0x0b
-#define TRNG_DATA 0x20
-#define TRNG_VALID 0x11
-
-static int i2cfd = -1;
-static int debug = 0;
-
-/*
- * I2C low-level code
- */
-
-static int i2c_open(void)
-{
- if (i2cfd >= 0)
- return 1;
-
- i2cfd = open(I2C_DEV, O_RDWR);
-
- if (i2cfd < 0) {
- perror("Unable to open " I2C_DEV);
- i2cfd = -1;
- return 0;
- }
-
- if (ioctl(i2cfd, I2C_SLAVE, I2C_ADDR) < 0) {
- perror("Unable to set i2c slave device");
- return 0;
- }
-
- if (debug)
- fprintf(stderr, "[ Opened %s, fd %d ]\n", I2C_DEV, i2cfd);
-
- return 1;
-}
-
-static int i2c_write_bytes(const unsigned char *buf, const size_t len)
-{
- if (debug) {
- int i;
- fprintf(stderr, "write [");
- for (i = 0; i < len; ++i)
- fprintf(stderr, " %02x", buf[i]);
- fprintf(stderr, " ]\n");
- }
-
- if (!i2c_open())
- return 0;
-
- if (write(i2cfd, buf, len) != len) {
- perror("i2c write failed");
- return 0;
- }
-
- return 1;
-}
-
-
-static int i2c_read_byte(unsigned char *b)
-{
- /*
- * read() on the i2c device only returns one byte at a time,
- * and we need to parse the response one byte at a time anyway.
- */
-
- if (!i2c_open())
- return 0;
-
- if (read(i2cfd, b, 1) != 1) {
- perror("i2c read failed");
- return 0;
- }
-
- return 1;
-}
-
-static int i2c_send_write_cmd(const unsigned char addr0, const unsigned char addr1, const unsigned char data[])
-{
- unsigned char buf[9];
-
- buf[0] = SOC;
- buf[1] = WRITE_CMD;
- buf[2] = addr0;
- buf[3] = addr1;
- buf[4] = data[0];
- buf[5] = data[1];
- buf[6] = data[2];
- buf[7] = data[3];
- buf[8] = EOC;
-
- return i2c_write_bytes(buf, sizeof(buf));
-}
-
-static int i2c_send_read_cmd(const unsigned char addr0, const unsigned char addr1)
-{
- unsigned char buf[5];
-
- buf[0] = SOC;
- buf[1] = READ_CMD;
- buf[2] = addr0;
- buf[3] = addr1;
- buf[4] = EOC;
-
- return i2c_write_bytes(buf, sizeof(buf));
-}
-
-static int i2c_get_resp(unsigned char *buf, const size_t length)
-{
- int i, len = length;
-
- for (i = 0; i < len; ++i) {
- assert(len <= length); /* Paranoia */
-
- if (!i2c_read_byte(&buf[i]))
- return 0;
-
- switch (i) { /* Special handling for certain positions in response */
-
- case 0:
- if (buf[i] == SOR) /* Start of record (we hope) */
- continue;
- fprintf(stderr, "Lost sync: expected 0x%02x (SOR), got 0x%02x\n", SOR, buf[0]);
- return 0;
-
- case 1: /* Response code */
- switch (buf[i]) {
- case READ_OK:
- len = 9;
- continue;
- case WRITE_OK:
- len = 5;
- continue;
- case RESET_OK:
- len = 3;
- continue;
- case ERROR:
- case UNKNOWN:
- len = 4;
- continue;
- default:
- fprintf(stderr, "Lost sync: unknown response code 0x%02x\n", buf[i]);
- return 0;
- }
- }
- }
-
- if (debug) {
- fprintf(stderr, "read [");
- for (i = 0; i < len; ++i)
- fprintf(stderr, " %02x", buf[i]);
- fprintf(stderr, " ]\n");
- }
-
- return 1;
-}
-
-static int i2c_check_expected(const unsigned char buf[], const int i, const unsigned char expected)
-{
- if (buf[i] == expected)
- return 1;
- fprintf(stderr, "Response byte %d: expected 0x%02x, got 0x%02x\n", i, expected, buf[i]);
- return 0;
-}
-
-
-static int i2c_write(const unsigned char addr0, const unsigned char addr1, const unsigned char data[])
-{
- unsigned char buf[5];
-
- if (!i2c_send_write_cmd(addr0, addr1, data) ||
- !i2c_get_resp(buf, sizeof(buf)) ||
- !i2c_check_expected(buf, 0, SOR) ||
- !i2c_check_expected(buf, 1, WRITE_OK) ||
- !i2c_check_expected(buf, 2, addr0) ||
- !i2c_check_expected(buf, 3, addr1) ||
- !i2c_check_expected(buf, 4, EOR))
- return 0;
-
- return 1;
-}
-
-static int i2c_read(const unsigned char addr0, const unsigned char addr1, unsigned char data[])
-{
- unsigned char buf[9];
-
- if (!i2c_send_read_cmd(addr0, addr1) ||
- !i2c_get_resp(buf, sizeof(buf)) ||
- !i2c_check_expected(buf, 0, SOR) ||
- !i2c_check_expected(buf, 1, READ_OK) ||
- !i2c_check_expected(buf, 2, addr0) ||
- !i2c_check_expected(buf, 3, addr1) ||
- !i2c_check_expected(buf, 8, EOR))
- return 0;
-
- data[0] = buf[4];
- data[1] = buf[5];
- data[2] = buf[6];
- data[3] = buf[7];
- return 1;
-}
-
-static int i2c_ctrl(const unsigned char addr0, const unsigned char ctrl_cmd)
-{
- unsigned char data[4];
- memset(data, 0, sizeof(data));
- data[3] = ctrl_cmd;
- return i2c_write(addr0, ADDR_CTRL, data);
-}
-
-static int i2c_wait(const unsigned char addr0, const unsigned char status)
-{
- unsigned char buf[9];
-
- do {
- if (!i2c_send_read_cmd(addr0, ADDR_STATUS))
- return 0;
- if (!i2c_get_resp(buf, sizeof(buf)))
- return 0;
- if (buf[1] != READ_OK)
- return 0;
- } while ((buf[7] & status) != status);
-
- if (debug)
- fprintf(stderr, "[ Done waiting ]\n");
-
- return 1;
-}
-
-static int i2c_wait_ready(const unsigned char addr0)
-{
- if (debug)
- fprintf(stderr, "[ Waiting for ready ]\n");
- return i2c_wait(addr0, STATUS_READY_BIT);
-}
-
-static int i2c_wait_valid(const unsigned char addr0)
-{
- if (debug)
- fprintf(stderr, "[ Waiting for valid ]\n");
- return i2c_wait(addr0, STATUS_VALID_BIT);
-}
+int debug = 0;
/****************************************************************************
* *
@@ -414,47 +97,44 @@ static int i2c_wait_valid(const unsigned char addr0)
* Send one block to a core.
*/
-static int hash_write_block(const unsigned char addr_prefix,
- const unsigned char addr_block,
- const unsigned char ctrl_mode,
+static int hash_write_block(const off_t offset,
+ const uint8_t ctrl_mode,
const hash_state_t *state)
{
- unsigned char ctrl_cmd;
- int i;
+ uint8_t ctrl_cmd[4] = { 0 };
+ off_t base = offset & ~(0xff);
assert(state != NULL && state->block_length % 4 == 0);
- for (i = 0; i + 3 < state->block_length; i += 4)
- if (!i2c_write(addr_prefix, addr_block + i/4, state->block + i))
- return 0;
+ if (tc_write(offset, state->block, state->block_length) != 0)
+ return CRYPT_ERROR_FAILED;
- ctrl_cmd = state->block_count == 0 ? CTRL_INIT_CMD : CTRL_NEXT_CMD;
+ ctrl_cmd[3] = (state->block_count == 0 ? CTRL_INIT_CMD : CTRL_NEXT_CMD) | ctrl_mode;
if (debug)
fprintf(stderr, "[ %s ]\n", state->block_count == 0 ? "init" : "next");
- return i2c_ctrl(addr_prefix, ctrl_cmd|ctrl_mode) && i2c_wait_ready(addr_prefix);
+ return
+ tc_write(base + ADDR_CTRL, ctrl_cmd, 4) ||
+ tc_wait_ready(base + ADDR_STATUS);
}
/*
* Read hash result from core.
*/
-static int hash_read_digest(const unsigned char addr_prefix, const unsigned char addr_digest,
- unsigned char *digest, const size_t digest_length)
+static int hash_read_digest(const off_t offset,
+ unsigned char *digest,
+ const size_t digest_length)
{
- int i;
-
assert(digest_length % 4 == 0);
- if (!i2c_wait_valid(addr_prefix))
- return 0;
-
- for (i = 0; i + 3 < digest_length; i += 4)
- if (!i2c_read(addr_prefix, addr_digest + i/4, digest + i))
- return 0;
+ /* Technically, we should poll the status register for the "valid" bit, but
+ * hash_write_block() has already polled for the "ready" bit, and we know
+ * that the sha cores always set valid one clock cycle before ready.
+ */
- return 1;
+ return tc_read(offset, digest, digest_length);
}
/****************************************************************************
@@ -475,7 +155,7 @@ static int hash_read_digest(const unsigned char addr_prefix, const unsigned char
* signals this (deliberately?) by returning all zeros.
*/
-#define WAIT_FOR_TRNG_VALID 0
+#define WAIT_FOR_TRNG_VALID 0
static int readRandom(void *buffer, const int length)
{
@@ -492,26 +172,16 @@ static int readRandom(void *buffer, const int length)
for (i = 0; i < length; i += 4) {
#if WAIT_FOR_TRNG_VALID
- if (!i2c_wait_valid(TRNG_PREFIX)) {
- fprintf(stderr, "[ i2c_wait_valid(TRNG_PREFIX) failed ]\n");
- return 0;
- }
- do {
- if (!i2c_read(TRNG_PREFIX, TRNG_VALID, temp)) {
- fprintf(stderr, "[ i2c_read(TRNG_VALID) failed ]\n");
- return 0;
- }
- } while (!temp[3]);
- if (!i2c_wait_valid(TRNG_PREFIX)) {
- fprintf(stderr, "[ i2c_wait_valid(TRNG_PREFIX) failed ]\n");
- return 0;
+ if (tc_wait_ready(CSPRNG_ADDR_STATUS) != 0) {
+ fprintf(stderr, "[ tc_wait_valid(CSPRNG_ADDR_STATUS) failed ]\n");
+ return CRYPT_ERROR_FAILED;
}
#endif /* WAIT_FOR_TRNG_VALID */
last = (length - i) < 4;
- if (!i2c_read(TRNG_PREFIX, TRNG_DATA, (last ? temp : (buf + i)))) {
- fprintf(stderr, "[ i2c_read(TRNG_DATA) failed ]\n");
- return 0;
+ if (tc_read(CSPRNG_ADDR_RANDOM, (last ? temp : (buf + i)), 4) != 0) {
+ fprintf(stderr, "[ tc_read(CSPRNG_ADDR_RANDOM) failed ]\n");
+ return CRYPT_ERROR_FAILED;
}
if (last) {
for (; i < length; i++)
@@ -521,10 +191,10 @@ static int readRandom(void *buffer, const int length)
for (i = 0, buf = buffer; i < length; i++, buf++)
if (*buf != 0)
- return 1;
+ return CRYPT_OK;
fprintf(stderr, "[ \"Random\" data all zeros, guess TRNG is not installed ]\n");
- return 0;
+ return CRYPT_ERROR_FAILED;
}
/****************************************************************************
@@ -562,9 +232,14 @@ static int hashGetInfo(const CAPABILITY_INFO_TYPE type,
* with a few parameters which we handle via closures below.
*/
-static int doHash(CONTEXT_INFO *contextInfoPtr, const unsigned char *buffer, int length,
- const size_t block_length, const unsigned char addr_prefix, const unsigned char addr_block,
- const size_t digest_length, const unsigned char addr_digest, const unsigned char ctrl_mode,
+static int doHash(CONTEXT_INFO *contextInfoPtr,
+ const unsigned char *buffer,
+ int length,
+ const size_t block_length,
+ const off_t addr_block,
+ const size_t digest_length,
+ const off_t addr_digest,
+ const unsigned char ctrl_mode,
const size_t length_length)
{
hash_state_t *state = NULL;
@@ -605,7 +280,7 @@ static int doHash(CONTEXT_INFO *contextInfoPtr, const unsigned char *buffer, int
state->block_used = 0;
length -= n;
p += n;
- if (!hash_write_block(addr_prefix, addr_block, ctrl_mode, state))
+ if (hash_write_block(addr_block, ctrl_mode, state) != 0)
return CRYPT_ERROR_FAILED;
state->block_count++;
}
@@ -642,7 +317,7 @@ static int doHash(CONTEXT_INFO *contextInfoPtr, const unsigned char *buffer, int
(unsigned long) 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 (!hash_write_block(addr_prefix, addr_block, ctrl_mode, state))
+ if (hash_write_block(addr_block, ctrl_mode, state) != 0)
return CRYPT_ERROR_FAILED;
state->block_count++;
state->block_used = 0;
@@ -667,14 +342,14 @@ static int doHash(CONTEXT_INFO *contextInfoPtr, const unsigned char *buffer, int
}
/* Push final block */
- if (!hash_write_block(addr_prefix, addr_block, ctrl_mode, state))
+ if (hash_write_block(addr_block, ctrl_mode, state) != 0)
return CRYPT_ERROR_FAILED;
state->block_count++;
/* All data pushed to core, now we just need to read back the result */
assert(digest_length <= sizeof(contextInfoPtr->ctxHash->hash));
- if (!hash_read_digest(addr_prefix, addr_digest, contextInfoPtr->ctxHash->hash, digest_length))
+ if (hash_read_digest(addr_digest, contextInfoPtr->ctxHash->hash, digest_length) != 0)
return CRYPT_ERROR_FAILED;
}
@@ -697,7 +372,7 @@ static int sha1SelfTest(void)
static int sha1Hash(CONTEXT_INFO *contextInfoPtr, unsigned char *buffer, int length)
{
return doHash(contextInfoPtr, buffer, length,
- SHA1_BLOCK_LEN, SHA1_ADDR_PREFIX, SHA1_ADDR_BLOCK,
+ SHA1_BLOCK_LEN, SHA1_ADDR_BLOCK,
SHA1_DIGEST_LEN, SHA1_ADDR_DIGEST, 0, SHA1_LENGTH_LEN);
}
@@ -722,18 +397,18 @@ static int sha2Hash(CONTEXT_INFO *contextInfoPtr, unsigned char *buffer, int len
case bitsToBytes(256):
return doHash(contextInfoPtr, buffer, length,
- SHA256_BLOCK_LEN, SHA256_ADDR_PREFIX, SHA256_ADDR_BLOCK,
+ SHA256_BLOCK_LEN, SHA256_ADDR_BLOCK,
SHA256_DIGEST_LEN, SHA256_ADDR_DIGEST, 0, SHA256_LENGTH_LEN);
case bitsToBytes(384):
return doHash(contextInfoPtr, buffer, length,
- SHA512_BLOCK_LEN, SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK,
+ SHA512_BLOCK_LEN, SHA512_ADDR_BLOCK,
SHA384_DIGEST_LEN, SHA512_ADDR_DIGEST, MODE_SHA_384,
SHA512_LENGTH_LEN);
case bitsToBytes(512):
return doHash(contextInfoPtr, buffer, length,
- SHA512_BLOCK_LEN, SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK,
+ SHA512_BLOCK_LEN, SHA512_ADDR_BLOCK,
SHA512_DIGEST_LEN, SHA512_ADDR_DIGEST, MODE_SHA_512,
SHA512_LENGTH_LEN);
@@ -837,10 +512,7 @@ int hwGetRandom(void *buffer, const int length)
REQUIRES(length >= 1 && length < MAX_INTLENGTH);
- if (readRandom(buffer, length))
- return CRYPT_OK;
- else
- return CRYPT_ERROR_RANDOM;
+ return readRandom(buffer, length);
}
/*