[Cryptech-Commits] [core/novena_i2c_simple] 01/03: do proper SHA* padding

git at cryptech.is git at cryptech.is
Thu Nov 20 00:12:01 UTC 2014


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch master
in repository core/novena_i2c_simple.

commit 283dea2f82bdfac2aeb0d026bc86c9d57b131915
Author: Paul Selkirk <paul at psgd.org>
Date:   Tue Nov 18 15:28:23 2014 -0500

    do proper SHA* padding
---
 src/sw/hash.c | 117 ++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 72 insertions(+), 45 deletions(-)

diff --git a/src/sw/hash.c b/src/sw/hash.c
index 2314fe4..f9bb3b8 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"
@@ -58,24 +59,24 @@ char *usage =
 int debug = 0;
 int verbose = 0;
 
-/* block and digest lengths are number of 32-bit words */
-#define SHA1_BLOCK_LEN          16
-#define SHA1_DIGEST_LEN         5
-#define SHA256_BLOCK_LEN        16
-#define SHA256_DIGEST_LEN       8
-#define SHA512_BLOCK_LEN        32
-#define SHA512_224_DIGEST_LEN   7
-#define SHA512_256_DIGEST_LEN   8
-#define SHA384_DIGEST_LEN       12
-#define SHA512_DIGEST_LEN       16
+/* block and digest lengths are number of bytes */
+#define SHA1_BLOCK_LEN          512/8
+#define SHA1_DIGEST_LEN         160/8
+#define SHA256_BLOCK_LEN        512/8
+#define SHA256_DIGEST_LEN       256/8
+#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
 
 /* ---------------- algorithm lookup code ---------------- */
 
 struct ctrl {
     char *name;
-    int i2c_addr;
-    int block_len;
-    int digest_len;
+    uint8_t i2c_addr;
+    uint8_t block_len;
+    uint8_t digest_len;
 } ctrl[] = {
     { "sha-1",       0x1e, SHA1_BLOCK_LEN,   SHA1_DIGEST_LEN },
     { "sha-256",     0x1f, SHA256_BLOCK_LEN, SHA256_DIGEST_LEN },
@@ -95,7 +96,7 @@ struct ctrl *find_algo(char *algo)
         if (strcmp(ctrl[i].name, algo) == 0)
             return &ctrl[i];
 
-    fprintf(stderr, "algorithm \"%s\" not found\n", algo);
+    fprintf(stderr, "algorithm \"%s\" not found\n\n", algo);
     fprintf(stderr, usage, "hash");
     return NULL;
 }
@@ -131,10 +132,50 @@ void i2c_close(int ifd)
 
 /* ---------------- hash ---------------- */
 
+int transmit(uint8_t *block, uint8_t blen, int fd)
+{
+    int i;
+
+    if (debug) {
+        printf("write [");
+        for (i = 0; i < blen; ++i)
+            printf(" %02x", block[i]);
+        printf(" ]\n");
+    }
+
+    if (write(fd, block, blen) != blen) {
+        return 1;
+    }
+
+    return 0;
+}
+
+int pad_transmit(uint8_t *block, uint8_t flen, uint8_t blen, int fd, long long tlen)
+{
+    assert(flen < blen);
+
+    block[flen++] = 0x80;
+    memset(block + flen, 0, blen - flen);
+
+    if (blen - flen < ((blen == 64) ? 8 : 16)) {
+        if (transmit(block, blen, fd) != 0)
+            return 1;
+        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, fd);
+}
+
 /* return number of digest bytes read */
 int hash(char *dev, char *algo, char *file, uint8_t *digest)
 {
-    uint8_t block[SHA512_BLOCK_LEN * 4];
+    uint8_t block[SHA512_BLOCK_LEN];
     struct ctrl *ctrl;
     int i2c_fd, in_fd = 0;
     int addr, blen, dlen;
@@ -142,16 +183,12 @@ int hash(char *dev, char *algo, char *file, uint8_t *digest)
     int i, ret = -1;
     struct timeval start, stop, difftime;
 
-    if (debug) printf("hash(dev=%s, algo=%s, file=%s, digest=%p)\n", dev, algo, file, digest);
-
     ctrl = find_algo(algo);
     if (ctrl == NULL)
         return -1;
     addr = ctrl->i2c_addr;
-    blen = ctrl->block_len * 4;
-    dlen = ctrl->digest_len * 4;
-
-    if (debug) printf("algorithm %s, device addr %02x\n", ctrl->name, ctrl->i2c_addr);
+    blen = ctrl->block_len;
+    dlen = ctrl->digest_len;
 
     i2c_fd = i2c_open(dev, addr);
     if (i2c_fd < 0)
@@ -174,32 +211,22 @@ int hash(char *dev, char *algo, char *file, uint8_t *digest)
 
     for (nblk = 0; ; ++nblk) {
         nread = read(in_fd, block, blen);
-        if (nread != blen) {
-            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) {
-                    block[nread++] = 0;
-                }
-            }
+        if (nread < 0) {
+            /* read error */
+            perror("read");
+            goto out;
         }
-        if (debug) {
-            printf("write [");
-            for (i = 0; i < blen; ++i)
-                printf(" %02x", block[i]);
-            printf(" ]\n");
+        else if (nread < blen) {
+            /* partial read = last block */
+            if (pad_transmit(block, nread, blen, i2c_fd,
+                             (nblk * blen + nread) * 8) != 0)
+                goto out;
+            break;
         }
-        if (write(i2c_fd, block, blen) != blen) {
-            perror("i2c write failed");
-            goto out;
+        else {
+            /* full block read */
+            if (transmit(block, blen, i2c_fd) != 0)
+                goto out;
         }
     }
 



More information about the Commits mailing list