From c0153c65d55f7b47dc6e94a3ce7b33daec95592d Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 18 Nov 2014 15:21:20 -0500 Subject: do proper SHA* padding --- src/sw/hash.c | 148 +++++++++++++++++++++++++++----------------- src/sw/nist_1024_double.bin | Bin 256 -> 112 bytes src/sw/nist_1024_single.bin | Bin 128 -> 3 bytes src/sw/nist_512_double.bin | Bin 128 -> 56 bytes src/sw/nist_512_single.bin | Bin 64 -> 3 bytes 5 files changed, 91 insertions(+), 57 deletions(-) (limited to 'src') 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 #include #include +#include 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 Binary files a/src/sw/nist_1024_double.bin and b/src/sw/nist_1024_double.bin differ diff --git a/src/sw/nist_1024_single.bin b/src/sw/nist_1024_single.bin index 100111a..f2ba8f8 100644 Binary files a/src/sw/nist_1024_single.bin and b/src/sw/nist_1024_single.bin differ diff --git a/src/sw/nist_512_double.bin b/src/sw/nist_512_double.bin index ac8d755..199f24e 100644 Binary files a/src/sw/nist_512_double.bin and b/src/sw/nist_512_double.bin differ diff --git a/src/sw/nist_512_single.bin b/src/sw/nist_512_single.bin index 1f3a5ce..f2ba8f8 100644 Binary files a/src/sw/nist_512_single.bin and b/src/sw/nist_512_single.bin differ -- cgit v1.2.3