aboutsummaryrefslogtreecommitdiff
path: root/src/sw/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sw/hash.c')
-rw-r--r--src/sw/hash.c620
1 files changed, 0 insertions, 620 deletions
diff --git a/src/sw/hash.c b/src/sw/hash.c
deleted file mode 100644
index 29110eb..0000000
--- a/src/sw/hash.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * 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, 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 <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>
-
-char *usage =
-"Usage: %s [-d] [-v] [-q] [-i I2C_device] [-a I2C_addr] [algorithm [file]]\n"
-"algorithms: sha-1, sha-256, sha-512/224, sha-512/256, sha-384, sha-512\n";
-
-/* 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 hash 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 0
-#define STATUS_VALID_BIT 1
-
-/* addresses and codes for the specific hash cores */
-/* block and digest lengths are number of bytes */
-#define SHA1_ADDR_PREFIX 0x10
-#define SHA1_ADDR_BLOCK 0x10
-#define SHA1_BLOCK_LEN 512/8
-#define SHA1_ADDR_DIGEST 0x20
-#define SHA1_DIGEST_LEN 160/8
-
-#define SHA256_ADDR_PREFIX 0x20
-#define SHA256_ADDR_BLOCK 0x10
-#define SHA256_BLOCK_LEN 512/8
-#define SHA256_ADDR_DIGEST 0x20
-#define SHA256_DIGEST_LEN 256/8
-
-#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 1024/8
-#define SHA512_ADDR_DIGEST 0x40
-#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_SHA512_224 0
-#define MODE_SHA512_256 1
-#define MODE_SHA384 2
-#define MODE_SHA512 3
-
-int i2cfd;
-int debug = 0;
-int verbose = 0;
-
-/* ---------------- algorithm lookup code ---------------- */
-
-struct ctrl {
- char *name;
- uint8_t addr_prefix;
- uint8_t addr_block;
- uint8_t block_len;
- uint8_t addr_digest;
- uint8_t digest_len;
- uint8_t mode;
-} ctrl[] = {
- { "sha-1", SHA1_ADDR_PREFIX, SHA1_ADDR_BLOCK, SHA1_BLOCK_LEN,
- SHA1_ADDR_DIGEST, SHA1_DIGEST_LEN, 0 },
- { "sha-256", SHA256_ADDR_PREFIX, SHA256_ADDR_BLOCK, SHA256_BLOCK_LEN,
- SHA256_ADDR_DIGEST, SHA256_DIGEST_LEN, 0 },
- { "sha-512/224", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, SHA512_224_DIGEST_LEN, MODE_SHA512_224 },
- { "sha-512/256", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, SHA512_256_DIGEST_LEN, MODE_SHA512_256 },
- { "sha-384", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, SHA384_DIGEST_LEN, MODE_SHA384 },
- { "sha-512", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, SHA512_DIGEST_LEN, MODE_SHA512 },
- { 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;
-}
-
-/* ---------------- I2C low-level code ---------------- */
-
-int i2c_open(char *dev, int addr)
-{
- i2cfd = open(dev, O_RDWR);
- if (i2cfd < 0) {
- fprintf(stderr, "Unable to open %s: ", dev);
- perror("");
- i2cfd = 0;
- return 1;
- }
-
- if (ioctl(i2cfd, I2C_SLAVE, addr) < 0) {
- fprintf(stderr, "Unable to set I2C slave device 0x%02x: ", addr);
- perror("");
- return 1;
- }
-
- return 0;
-}
-
-void i2c_close(void)
-{
- close(i2cfd);
-}
-
-int i2c_write(uint8_t *buf, int len)
-{
- if (debug) {
- int i;
- printf("write [");
- for (i = 0; i < len; ++i)
- printf(" %02x", buf[i]);
- printf(" ]\n");
- }
-
- if (write(i2cfd, buf, len) != len) {
- perror("i2c write failed");
- return 1;
- }
-
- return 0;
-}
-
-int i2c_read(uint8_t *b)
-{
- /* read() on the i2c device only returns one byte at a time,
- * and tc_get_resp() needs to parse the response one byte at a time
- */
- if (read(i2cfd, b, 1) != 1) {
- perror("i2c read failed");
- return 1;
- }
-
- return 0;
-}
-
-/* ---------------- test-case low-level code ---------------- */
-
-int tc_send_write_cmd(uint8_t addr0, uint8_t addr1, uint8_t *data)
-{
- uint8_t buf[9] = { SOC, WRITE_CMD, addr0, addr1,
- data[0], data[1], data[2], data[3], EOC };
-
- return i2c_write(buf, sizeof(buf));
-}
-
-int tc_send_read_cmd(uint8_t addr0, uint8_t addr1)
-{
- uint8_t buf[5] = { SOC, READ_CMD, addr0, addr1, EOC };
-
- return i2c_write(buf, sizeof(buf));
-}
-
-int tc_get_resp(uint8_t *buf, int len)
-{
- int i;
-
- for (i = 0; i < len; ++i) {
- if (i2c_read(&buf[i]) != 0)
- return 1;
- 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;
- }
- else if (i == 1) { /* response code */
- switch (buf[i]) {
- case READ_OK:
- len = 9;
- break;
- case WRITE_OK:
- len = 5;
- break;
- case RESET_OK:
- len = 3;
- break;
- case ERROR:
- case UNKNOWN:
- len = 4;
- 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) {
- printf("read [");
- for (i = 0; i < len; ++i)
- printf(" %02x", buf[i]);
- printf(" ]\n");
- }
-
- return 0;
-}
-
-int tc_compare(uint8_t *buf, uint8_t *expected, int len)
-{
- int i;
-
- /* start at byte 1 because SOR has already been tested */
- for (i = 1; 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]);
- return 1;
- }
- }
-
- return 0;
-}
-
-int tc_get_write_resp(uint8_t addr0, uint8_t addr1)
-{
- uint8_t buf[5];
- uint8_t expected[5] = { SOR, WRITE_OK, addr0, addr1, EOR };
-
- return
- tc_get_resp(buf, sizeof(buf)) ||
- tc_compare(buf, expected, sizeof(expected));
-}
-
-int tc_get_read_resp(uint8_t addr0, uint8_t addr1, uint8_t *data)
-{
- uint8_t buf[9];
- uint8_t expected[4] = { SOR, READ_OK, addr0, addr1 };
-
- if ((tc_get_resp(buf, sizeof(buf)) != 0) ||
- (tc_compare(buf, expected, 4) != 0) || buf[8] != EOR)
- return 1;
-
- data[0] = buf[4];
- data[1] = buf[5];
- data[2] = buf[6];
- data[3] = buf[7];
-
- return 0;
-}
-
-int tc_write(uint8_t addr0, uint8_t addr1, uint8_t *data)
-{
- return (tc_send_write_cmd(addr0, addr1, data) ||
- tc_get_write_resp(addr0, addr1));
-}
-
-int tc_read(uint8_t addr0, uint8_t addr1, uint8_t *data)
-{
- return (tc_send_read_cmd(addr0, addr1) ||
- tc_get_read_resp(addr0, addr1, data));
-}
-
-int tc_init(uint8_t addr0, uint8_t mode)
-{
- uint8_t buf[4] = { 0, 0, 0, CTRL_INIT_CMD };
-
- if (addr0 == SHA512_ADDR_PREFIX)
- buf[3] += (mode << SHA512_CTRL_MODE_LOW);
-
- return tc_write(addr0, ADDR_CTRL, buf);
-}
-
-int tc_next(uint8_t addr0, uint8_t mode)
-{
- uint8_t buf[4] = { 0, 0, 0, CTRL_NEXT_CMD };
-
- if (addr0 == SHA512_ADDR_PREFIX)
- buf[3] += (mode << SHA512_CTRL_MODE_LOW);
-
- return tc_write(addr0, ADDR_CTRL, buf);
-}
-
-int tc_wait(uint8_t addr0, uint8_t status)
-{
- uint8_t buf[4];
-
- do {
- if (tc_read(addr0, ADDR_STATUS, &buf[0]) != 0)
- return 1;
- } while ((buf[3] & status) != status);
-
- return 0;
-}
-
-int tc_wait_ready(uint8_t addr0)
-{
- return tc_wait(addr0, STATUS_READY_BIT);
-}
-
-int tc_wait_valid(uint8_t addr0)
-{
- return tc_wait(addr0, STATUS_VALID_BIT);
-}
-
-int tc_write_block(uint8_t addr0, uint8_t addr1, uint8_t *buf, int len)
-{
- int i;
-
- for (i = 0; i < len/4; ++i) {
- if (tc_write(addr0, addr1 + i, &buf[i*4]) != 0)
- return 1;
- }
-
- return 0;
-}
-
-int tc_read_digest(uint8_t addr0, uint8_t addr1, uint8_t *buf, int len)
-{
- int i;
-
- for (i = 0; i < len/4; ++i) {
- if (tc_read(addr0, addr1 + i, &buf[i*4]) != 0)
- return 1;
- }
-
- return 0;
-}
-
-/* ---------------- hash ---------------- */
-
-int transmit(uint8_t *block, uint8_t blen, uint8_t addr0, uint8_t baddr,
- uint8_t mode, int first)
-{
- int i;
-
- if (debug) {
- printf("write [");
- for (i = 0; i < blen; ++i)
- printf(" %02x", block[i]);
- printf(" ]\n");
- }
-
- if (tc_write_block(addr0, baddr, block, blen) != 0) {
- return 1;
- }
- if (first) {
- if (tc_init(addr0, mode) != 0)
- return 1;
- }
- else {
- if (tc_next(addr0, mode) != 0)
- return 1;
- }
- if (tc_wait_ready(addr0) != 0)
- return 1;
-
- return 0;
-}
-
-int pad_transmit(uint8_t *block, uint8_t flen, uint8_t blen,
- uint8_t addr0, uint8_t baddr, 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(block, blen, addr0, baddr, 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(block, blen, addr0, baddr, 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 */
- uint8_t addr0, baddr, blen, daddr, dlen, mode;
- int nblk, nread, first;
- int ret = -1;
- struct timeval start, stop, difftime;
-
- ctrl = find_algo(algo);
- if (ctrl == NULL)
- return -1;
- addr0 = ctrl->addr_prefix;
- baddr = ctrl->addr_block;
- blen = ctrl->block_len;
- daddr = ctrl->addr_digest;
- 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(block, nread, blen, addr0, baddr, mode,
- (nblk * blen + nread) * 8, first) != 0)
- goto out;
- break;
- }
- else {
- /* full block read */
- if (transmit(block, blen, addr0, baddr, mode, first) != 0)
- goto out;
- }
- }
-
- if (tc_wait_valid(addr0) != 0)
- goto out;
- if (tc_read_digest(addr0, 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[])
-{
- char *dev = I2C_dev;
- int addr = I2C_addr;
- int i, opt, quiet = 0;
- char *algo = "sha-1";
- char *file = "-";
- uint8_t digest[512/8];
- int dlen;
-
- while ((opt = getopt(argc, argv, "h?dvqi:a:")) != -1) {
- switch (opt) {
- case 'h':
- case '?':
- printf(usage, argv[0]);
- return 0;
- case 'd':
- debug = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'i':
- dev = optarg;
- break;
- case 'a':
- addr = (int)strtol(optarg, NULL, 0);
- if ((addr < 0x03) || (addr > 0x77)) {
- fprintf(stderr, "addr must be between 0x03 and 0x77\n");
- return 1;
- }
- break;
- default:
- fprintf(stderr, usage, argv[0]);
- return 1;
- }
- }
-
- 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 (i2c_open(dev, addr) != 0)
- return -1;
-
- dlen = hash(algo, file, digest);
- if (dlen < 0)
- return 1;
-
- 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");
-
- i2c_close();
-
- return 0;
-}