aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2014-11-18 15:21:20 -0500
committerPaul Selkirk <paul@psgd.org>2014-11-18 15:21:20 -0500
commitc0153c65d55f7b47dc6e94a3ce7b33daec95592d (patch)
tree4710627e2204e8087c9947c08e06fe5738c3705a
parent9a6299ea9c3bda1d908e5435d2ea332849b4a4f5 (diff)
do proper SHA* padding
-rw-r--r--src/sw/hash.c148
-rw-r--r--src/sw/nist_1024_double.binbin256 -> 112 bytes
-rw-r--r--src/sw/nist_1024_single.binbin128 -> 3 bytes
-rw-r--r--src/sw/nist_512_double.binbin128 -> 56 bytes
-rw-r--r--src/sw/nist_512_single.binbin64 -> 3 bytes
5 files changed, 91 insertions, 57 deletions
diff --git a/src/sw/hash.c b/src/sw/hash.c
index f67a863..29110eb 100644
--- a/src/sw/hash.c
+++ b/src/sw/hash.c
@@ -47,6 +47,7 @@
#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"
@@ -84,30 +85,33 @@ char *usage =
#define STATUS_VALID_BIT 1
/* addresses and codes for the specific hash cores */
-/* block and digest lengths are number of 32-bit words */
+/* block and digest lengths are number of bytes */
#define SHA1_ADDR_PREFIX 0x10
#define SHA1_ADDR_BLOCK 0x10
-#define SHA1_BLOCK_LEN 16
+#define SHA1_BLOCK_LEN 512/8
#define SHA1_ADDR_DIGEST 0x20
-#define SHA1_DIGEST_LEN 5
+#define SHA1_DIGEST_LEN 160/8
#define SHA256_ADDR_PREFIX 0x20
#define SHA256_ADDR_BLOCK 0x10
-#define SHA256_BLOCK_LEN 16
+#define SHA256_BLOCK_LEN 512/8
#define SHA256_ADDR_DIGEST 0x20
-#define SHA256_DIGEST_LEN 8
+#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 32
+#define SHA512_BLOCK_LEN 1024/8
#define SHA512_ADDR_DIGEST 0x40
-#define SHA512_DIGEST_LEN 16
-#define MODE_SHA_512_224 0
-#define MODE_SHA_512_256 1
-#define MODE_SHA_384 2
-#define MODE_SHA_512 3
+#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;
@@ -129,13 +133,13 @@ struct ctrl {
{ "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, 7, MODE_SHA_512_224 },
+ 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, 8, MODE_SHA_512_256 },
+ SHA512_ADDR_DIGEST, SHA512_256_DIGEST_LEN, MODE_SHA512_256 },
{ "sha-384", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, 12, MODE_SHA_384 },
+ SHA512_ADDR_DIGEST, SHA384_DIGEST_LEN, MODE_SHA384 },
{ "sha-512", SHA512_ADDR_PREFIX, SHA512_ADDR_BLOCK, SHA512_BLOCK_LEN,
- SHA512_ADDR_DIGEST, 16, MODE_SHA_512 },
+ SHA512_ADDR_DIGEST, SHA512_DIGEST_LEN, MODE_SHA512 },
{ NULL, 0, 0, 0 }
};
@@ -157,8 +161,6 @@ struct ctrl *find_algo(char *algo)
int i2c_open(char *dev, int addr)
{
- if (debug) printf("i2c_open(%s, %d)\n", dev, addr);
-
i2cfd = open(dev, O_RDWR);
if (i2cfd < 0) {
fprintf(stderr, "Unable to open %s: ", dev);
@@ -376,7 +378,7 @@ int tc_write_block(uint8_t addr0, uint8_t addr1, uint8_t *buf, int len)
{
int i;
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < len/4; ++i) {
if (tc_write(addr0, addr1 + i, &buf[i*4]) != 0)
return 1;
}
@@ -388,7 +390,7 @@ int tc_read_digest(uint8_t addr0, uint8_t addr1, uint8_t *buf, int len)
{
int i;
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < len/4; ++i) {
if (tc_read(addr0, addr1 + i, &buf[i*4]) != 0)
return 1;
}
@@ -398,19 +400,71 @@ int tc_read_digest(uint8_t addr0, uint8_t addr1, uint8_t *buf, int len)
/* ---------------- 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 * 4];
+ 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 i, ret = -1;
+ int ret = -1;
struct timeval start, stop, difftime;
- if (debug) printf("hash(algo=%s, file=%s, digest=%p)\n", algo, file, digest);
-
ctrl = find_algo(algo);
if (ctrl == NULL)
return -1;
@@ -436,49 +490,29 @@ int hash(char *algo, char *file, uint8_t *digest)
}
}
- for (nblk = 0, first = 1; ; ++nblk) {
- nread = read(in_fd, block, blen * 4);
- if (nread != blen * 4) {
- if (nread < 0) {
- /* read error */
- perror("read");
- goto out;
- }
- else if (nread == 0) {
- /* EOF */
- break;
- }
- else {
- /* partial read - pad the block with 0 */
- while (nread < blen * 4) {
- block[nread++] = 0;
- }
- }
- }
- if (debug) {
- printf("write [");
- for (i = 0; i < blen * 4; ++i)
- printf(" %02x", block[i]);
- printf(" ]\n");
- }
- if (tc_write_block(addr0, baddr, block, blen) != 0) {
+ for (nblk = 0, first = 1; ; ++nblk, first = 0) {
+ nread = read(in_fd, block, blen);
+ if (nread < 0) {
+ /* read error */
+ perror("read");
goto out;
}
- if (first) {
- first = 0;
- if (tc_init(addr0, mode) != 0)
+ 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 {
- if (tc_next(addr0, mode) != 0)
+ /* full block read */
+ if (transmit(block, blen, addr0, baddr, mode, first) != 0)
goto out;
}
- if (tc_wait_ready(addr0) != 0)
- goto out;
}
if (tc_wait_valid(addr0) != 0)
- goto out;
+ goto out;
if (tc_read_digest(addr0, daddr, digest, dlen) != 0) {
perror("i2c read failed");
goto out;
@@ -495,7 +529,7 @@ int hash(char *algo, char *file, uint8_t *digest)
(float)nblk / ((float)difftime.tv_sec + ((float)difftime.tv_usec)/1000000));
}
- ret = dlen * 4;
+ ret = dlen;
out:
if (in_fd != 0)
close(in_fd);
diff --git a/src/sw/nist_1024_double.bin b/src/sw/nist_1024_double.bin
index 543b415..4674ea4 100644
--- a/src/sw/nist_1024_double.bin
+++ b/src/sw/nist_1024_double.bin
Binary files differ
diff --git a/src/sw/nist_1024_single.bin b/src/sw/nist_1024_single.bin
index 100111a..f2ba8f8 100644
--- a/src/sw/nist_1024_single.bin
+++ b/src/sw/nist_1024_single.bin
Binary files differ
diff --git a/src/sw/nist_512_double.bin b/src/sw/nist_512_double.bin
index ac8d755..199f24e 100644
--- a/src/sw/nist_512_double.bin
+++ b/src/sw/nist_512_double.bin
Binary files differ
diff --git a/src/sw/nist_512_single.bin b/src/sw/nist_512_single.bin
index 1f3a5ce..f2ba8f8 100644
--- a/src/sw/nist_512_single.bin
+++ b/src/sw/nist_512_single.bin
Binary files differ