Add sha256 and sha512 checksums
authorJens Axboe <jens.axboe@oracle.com>
Mon, 30 Jul 2007 08:59:33 +0000 (10:59 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 30 Jul 2007 08:59:33 +0000 (10:59 +0200)
That should suffice...

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
Makefile
fio.h
options.c
sha256.c [new file with mode: 0644]
sha256.h [new file with mode: 0644]
sha512.c [new file with mode: 0644]
sha512.h [new file with mode: 0644]
verify.c

diff --git a/HOWTO b/HOWTO
index 58e12819e7f5868f5adb12eac6e5949784266227..21ba96033c283d0742f9191cc76ef97cf969277d 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -588,6 +588,10 @@ verify=str If writing to a file, fio can verify the file contents
                        crc7    Use a crc7 sum of the data area and store
                                it in the header of each block.
 
+                       sha512  Use sha512 as the checksum function.
+
+                       sha256  Use sha256 as the checksum function.
+
                        null    Only pretend to verify. Useful for testing
                                internals with ioengine=null, not for much
                                else.
index 7cbc7bc7bf7d17f40284b253a0b38f70b65c259a..410cf7c68d873b475fa41a83be6c7af22ddf172e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,9 @@ CFLAGS  = -Wwrite-strings -Wall -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_
 PROGS  = fio
 SCRIPTS = fio_generate_plots
 OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o \
-       crc16.o crc7.o crc64.o filesetup.o eta.o verify.o memory.o io_u.o \
-       parse.o mutex.o options.o rbtree.o diskutil.o fifo.o blktrace.o
+       crc16.o crc7.o crc64.o sha256.o sha512.o filesetup.o eta.o verify.o \
+       memory.o io_u.o parse.o mutex.o options.o rbtree.o diskutil.o fifo.o \
+       blktrace.o
 
 OBJS += engines/cpu.o
 OBJS += engines/libaio.o
diff --git a/fio.h b/fio.h
index 2ca800bf1a618e7144b84b474f8564437e5f6ceb..8f437f74f02a22bf8dad51a8f8a10c87200943f1 100644 (file)
--- a/fio.h
+++ b/fio.h
 #include <unistd.h>
 #include <string.h>
 #include <getopt.h>
+#include <inttypes.h>
 
 #include "compiler/compiler.h"
 #include "list.h"
 #include "fifo.h"
 #include "rbtree.h"
-#include "md5.h"
-#include "crc64.h"
-#include "crc32.h"
-#include "crc16.h"
-#include "crc7.h"
 #include "arch/arch.h"
 #include "os/os.h"
 #include "mutex.h"
@@ -199,6 +195,8 @@ enum {
        VERIFY_CRC32,                   /* crc32 sum data blocks */
        VERIFY_CRC16,                   /* crc16 sum data blocks */
        VERIFY_CRC7,                    /* crc7 sum data blocks */
+       VERIFY_SHA256,                  /* sha256 sum data blocks */
+       VERIFY_SHA512,                  /* sha512 sum data blocks */
        VERIFY_NULL,                    /* pretend to verify */
 };
 
@@ -210,7 +208,9 @@ struct verify_header {
        unsigned int len;
        unsigned int verify_type;
        union {
-               char md5_digest[MD5_HASH_WORDS * 4];
+               uint32_t md5_digest[16];
+               uint8_t sha512[128];
+               uint8_t sha256[128];
                unsigned long long crc64;
                unsigned long crc32;
                unsigned short crc16;
index 35a08d3aa6554a238f457966922993708b3b9db7..9ba9ca566802eea7743b1ec9d177024d2938d6fc 100644 (file)
--- a/options.c
+++ b/options.c
@@ -621,6 +621,14 @@ static struct fio_option options[] = {
                            .oval = VERIFY_CRC7,
                            .help = "Use crc7 checksums for verification",
                          },
+                         { .ival = "sha256",
+                           .oval = VERIFY_SHA256,
+                           .help = "Use sha256 checksums for verification",
+                         },
+                         { .ival = "sha512",
+                           .oval = VERIFY_SHA512,
+                           .help = "Use sha512 checksums for verification",
+                         },
                          {
                            .ival = "null",
                            .oval = VERIFY_NULL,
diff --git a/sha256.c b/sha256.c
new file mode 100644 (file)
index 0000000..8ec2943
--- /dev/null
+++ b/sha256.c
@@ -0,0 +1,280 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ */
+#include <string.h>
+#include <inttypes.h>
+#include <byteswap.h>
+#include <endian.h>
+
+#include "sha256.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define        __be32_to_cpu(x)        __bswap_32(x)
+#else
+#define __be32_to_cpu(x)       (x)
+#endif
+
+#define SHA256_DIGEST_SIZE     32
+#define SHA256_HMAC_BLOCK_SIZE 64
+
+static inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
+{
+       return z ^ (x & (y ^ z));
+}
+
+static inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z)
+{
+       return (x & y) | (z & (x | y));
+}
+
+#define e0(x)       (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x)       (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x)       (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x)       (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
+
+#define H0         0x6a09e667
+#define H1         0xbb67ae85
+#define H2         0x3c6ef372
+#define H3         0xa54ff53a
+#define H4         0x510e527f
+#define H5         0x9b05688c
+#define H6         0x1f83d9ab
+#define H7         0x5be0cd19
+
+static inline uint32_t ror32(uint32_t word, unsigned int shift)
+{
+        return (word >> shift) | (word << (32 - shift));
+}
+
+static inline void LOAD_OP(int I, uint32_t *W, const uint8_t *input)
+{
+       W[I] = __be32_to_cpu(((uint32_t *)(input))[I]);
+}
+
+static inline void BLEND_OP(int I, uint32_t *W)
+{
+       W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha256_transform(uint32_t *state, const uint8_t *input)
+{
+       uint32_t a, b, c, d, e, f, g, h, t1, t2;
+       uint32_t W[64];
+       int i;
+
+       /* load the input */
+       for (i = 0; i < 16; i++)
+               LOAD_OP(i, W, input);
+
+       /* now blend */
+       for (i = 16; i < 64; i++)
+               BLEND_OP(i, W);
+
+       /* load the state into our registers */
+       a=state[0];  b=state[1];  c=state[2];  d=state[3];
+       e=state[4];  f=state[5];  g=state[6];  h=state[7];
+
+       /* now iterate */
+       t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56];
+       t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+       t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57];
+       t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+       t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58];
+       t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+       t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59];
+       t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+       t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60];
+       t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+       t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61];
+       t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+       t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62];
+       t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+       t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63];
+       t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+       state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+       state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+       /* clear any sensitive info... */
+       a = b = c = d = e = f = g = h = t1 = t2 = 0;
+       memset(W, 0, 64 * sizeof(uint32_t));
+}
+
+void sha256_init(struct sha256_ctx *sctx)
+{
+       sctx->state[0] = H0;
+       sctx->state[1] = H1;
+       sctx->state[2] = H2;
+       sctx->state[3] = H3;
+       sctx->state[4] = H4;
+       sctx->state[5] = H5;
+       sctx->state[6] = H6;
+       sctx->state[7] = H7;
+       sctx->count[0] = sctx->count[1] = 0;
+}
+
+void sha256_update(struct sha256_ctx *sctx, const uint8_t *data,
+                  unsigned int len)
+{
+       unsigned int i, index, part_len;
+
+       /* Compute number of bytes mod 128 */
+       index = (unsigned int)((sctx->count[0] >> 3) & 0x3f);
+
+       /* Update number of bits */
+       if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+               sctx->count[1]++;
+               sctx->count[1] += (len >> 29);
+       }
+
+       part_len = 64 - index;
+
+       /* Transform as many times as possible. */
+       if (len >= part_len) {
+               memcpy(&sctx->buf[index], data, part_len);
+               sha256_transform(sctx->state, sctx->buf);
+
+               for (i = part_len; i + 63 < len; i += 64)
+                       sha256_transform(sctx->state, &data[i]);
+               index = 0;
+       } else {
+               i = 0;
+       }
+       
+       /* Buffer remaining input */
+       memcpy(&sctx->buf[index], &data[i], len-i);
+}
diff --git a/sha256.h b/sha256.h
new file mode 100644 (file)
index 0000000..a3ca0e6
--- /dev/null
+++ b/sha256.h
@@ -0,0 +1,13 @@
+#ifndef FIO_SHA256_H
+#define FIO_SHA256_H
+
+struct sha256_ctx {
+       uint32_t count[2];
+       uint32_t state[8];
+       uint8_t *buf;
+};
+
+void sha256_init(struct sha256_ctx *);
+void sha256_update(struct sha256_ctx *, const uint8_t *, unsigned int);
+
+#endif
diff --git a/sha512.c b/sha512.c
new file mode 100644 (file)
index 0000000..1f9ebb4
--- /dev/null
+++ b/sha512.c
@@ -0,0 +1,205 @@
+/* SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <byteswap.h>
+#include <endian.h>
+
+#include "sha512.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define        __be64_to_cpu(x)        __bswap_64(x)
+#else
+#define __be64_to_cpu(x)       (x)
+#endif
+
+#define SHA384_DIGEST_SIZE 48
+#define SHA512_DIGEST_SIZE 64
+#define SHA384_HMAC_BLOCK_SIZE 128
+#define SHA512_HMAC_BLOCK_SIZE 128
+
+static inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z)
+{
+        return z ^ (x & (y ^ z));
+}
+
+static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z)
+{
+        return (x & y) | (z & (x | y));
+}
+
+static inline uint64_t RORuint64_t(uint64_t x, uint64_t y)
+{
+        return (x >> y) | (x << (64 - y));
+}
+
+static const uint64_t sha512_K[80] = {
+        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+        0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+        0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+        0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+        0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+        0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+        0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+        0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+        0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+        0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+        0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+        0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+        0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+        0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+        0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+        0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+        0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+        0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+        0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+        0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+};
+
+#define e0(x)       (RORuint64_t(x,28) ^ RORuint64_t(x,34) ^ RORuint64_t(x,39))
+#define e1(x)       (RORuint64_t(x,14) ^ RORuint64_t(x,18) ^ RORuint64_t(x,41))
+#define s0(x)       (RORuint64_t(x, 1) ^ RORuint64_t(x, 8) ^ (x >> 7))
+#define s1(x)       (RORuint64_t(x,19) ^ RORuint64_t(x,61) ^ (x >> 6))
+
+/* H* initial state for SHA-512 */
+#define H0         0x6a09e667f3bcc908ULL
+#define H1         0xbb67ae8584caa73bULL
+#define H2         0x3c6ef372fe94f82bULL
+#define H3         0xa54ff53a5f1d36f1ULL
+#define H4         0x510e527fade682d1ULL
+#define H5         0x9b05688c2b3e6c1fULL
+#define H6         0x1f83d9abfb41bd6bULL
+#define H7         0x5be0cd19137e2179ULL
+
+/* H'* initial state for SHA-384 */
+#define HP0 0xcbbb9d5dc1059ed8ULL
+#define HP1 0x629a292a367cd507ULL
+#define HP2 0x9159015a3070dd17ULL
+#define HP3 0x152fecd8f70e5939ULL
+#define HP4 0x67332667ffc00b31ULL
+#define HP5 0x8eb44a8768581511ULL
+#define HP6 0xdb0c2e0d64f98fa7ULL
+#define HP7 0x47b5481dbefa4fa4ULL
+
+static inline void LOAD_OP(int I, uint64_t *W, const uint8_t *input)
+{
+       W[I] = __be64_to_cpu( ((uint64_t *)(input))[I] );
+}
+
+static inline void BLEND_OP(int I, uint64_t *W)
+{
+       W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha512_transform(uint64_t *state, uint64_t *W, const uint8_t *input)
+{
+       uint64_t a, b, c, d, e, f, g, h, t1, t2;
+
+       int i;
+
+       /* load the input */
+       for (i = 0; i < 16; i++)
+               LOAD_OP(i, W, input);
+
+       for (i = 16; i < 80; i++)
+               BLEND_OP(i, W);
+
+       /* load the state into our registers */
+       a=state[0];   b=state[1];   c=state[2];   d=state[3];
+       e=state[4];   f=state[5];   g=state[6];   h=state[7];
+
+       /* now iterate */
+       for (i=0; i<80; i+=8) {
+               t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
+               t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+               t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
+               t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+               t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
+               t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+               t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
+               t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+               t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
+               t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+               t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
+               t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+               t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
+               t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+               t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
+               t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+       }
+
+       state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+       state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+       /* erase our data */
+       a = b = c = d = e = f = g = h = t1 = t2 = 0;
+}
+
+void sha512_init(struct sha512_ctx *sctx)
+{
+       sctx->state[0] = H0;
+       sctx->state[1] = H1;
+       sctx->state[2] = H2;
+       sctx->state[3] = H3;
+       sctx->state[4] = H4;
+       sctx->state[5] = H5;
+       sctx->state[6] = H6;
+       sctx->state[7] = H7;
+       sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
+}
+
+void sha512_update(struct sha512_ctx *sctx, const uint8_t *data,
+                  unsigned int len)
+{
+       unsigned int i, index, part_len;
+
+       /* Compute number of bytes mod 128 */
+       index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
+       
+       /* Update number of bits */
+       if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+               if ((sctx->count[1] += 1) < 1)
+                       if ((sctx->count[2] += 1) < 1)
+                               sctx->count[3]++;
+               sctx->count[1] += (len >> 29);
+       }
+       
+        part_len = 128 - index;
+       
+       /* Transform as many times as possible. */
+       if (len >= part_len) {
+               memcpy(&sctx->buf[index], data, part_len);
+               sha512_transform(sctx->state, sctx->W, sctx->buf);
+
+               for (i = part_len; i + 127 < len; i+=128)
+                       sha512_transform(sctx->state, sctx->W, &data[i]);
+
+               index = 0;
+       } else {
+               i = 0;
+       }
+
+       /* Buffer remaining input */
+       memcpy(&sctx->buf[index], &data[i], len - i);
+
+       /* erase our data */
+       memset(sctx->W, 0, sizeof(sctx->W));
+}
diff --git a/sha512.h b/sha512.h
new file mode 100644 (file)
index 0000000..46e10cb
--- /dev/null
+++ b/sha512.h
@@ -0,0 +1,14 @@
+#ifndef FIO_SHA512_H
+#define FIO_SHA512_H
+
+struct sha512_ctx {
+       uint64_t state[8];
+       uint32_t count[4];
+       uint8_t *buf;
+       uint64_t W[80];
+};
+
+void sha512_init(struct sha512_ctx *);
+void sha512_update(struct sha512_ctx *, const uint8_t *, unsigned int);
+
+#endif
index 566c53c1f995c42d51f41f681df880005c6cc078..4f0c14b4f97a3b1d4ed62582adaca11711353c70 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -8,6 +8,14 @@
 
 #include "fio.h"
 
+#include "md5.h"
+#include "crc64.h"
+#include "crc32.h"
+#include "crc16.h"
+#include "crc7.h"
+#include "sha256.h"
+#include "sha512.h"
+
 static void fill_random_bytes(struct thread_data *td, void *p, unsigned int len)
 {
        unsigned int todo;
@@ -102,6 +110,54 @@ static inline void *io_u_verify_off(struct verify_header *hdr,
        return io_u->buf + sizeof(*hdr) + header_num * hdr->len;
 }
 
+static int verify_io_u_sha512(struct verify_header *hdr, struct io_u *io_u,
+                             unsigned int header_num)
+{
+       void *p = io_u_verify_off(hdr, io_u, header_num);
+       uint8_t sha512[128];
+       struct sha512_ctx sha512_ctx = {
+               .buf = sha512,
+       };
+
+       sha512_init(&sha512_ctx);
+       sha512_update(&sha512_ctx, p, hdr->len - sizeof(*hdr));
+
+       if (memcmp(hdr->sha512, sha512_ctx.buf, sizeof(sha512))) {
+               log_err("sha512: verify failed at %llu/%u\n",
+                             io_u->offset + header_num * hdr->len,
+                             hdr->len);
+               hexdump(hdr->sha512, sizeof(hdr->sha512));
+               hexdump(sha512_ctx.buf, sizeof(sha512));
+               return 1;
+       }
+
+       return 0;
+}
+
+static int verify_io_u_sha256(struct verify_header *hdr, struct io_u *io_u,
+                             unsigned int header_num)
+{
+       void *p = io_u_verify_off(hdr, io_u, header_num);
+       uint8_t sha256[128];
+       struct sha256_ctx sha256_ctx = {
+               .buf = sha256,
+       };
+
+       sha256_init(&sha256_ctx);
+       sha256_update(&sha256_ctx, p, hdr->len - sizeof(*hdr));
+
+       if (memcmp(hdr->sha256, sha256_ctx.buf, sizeof(sha256))) {
+               log_err("sha256: verify failed at %llu/%u\n",
+                             io_u->offset + header_num * hdr->len,
+                             hdr->len);
+               hexdump(hdr->sha256, sizeof(hdr->sha256));
+               hexdump(sha256_ctx.buf, sizeof(sha256));
+               return 1;
+       }
+
+       return 0;
+}
+
 static int verify_io_u_crc7(struct verify_header *hdr, struct io_u *io_u,
                             unsigned char header_num)
 {
@@ -243,6 +299,12 @@ int verify_io_u(struct thread_data *td, struct io_u *io_u)
                case VERIFY_CRC7:
                        ret = verify_io_u_crc7(hdr, io_u, hdr_num);
                        break;
+               case VERIFY_SHA256:
+                       ret = verify_io_u_sha256(hdr, io_u, hdr_num);
+                       break;
+               case VERIFY_SHA512:
+                       ret = verify_io_u_sha512(hdr, io_u, hdr_num);
+                       break;
                default:
                        log_err("Bad verify type %u\n", hdr->verify_type);
                        ret = 1;
@@ -253,6 +315,26 @@ int verify_io_u(struct thread_data *td, struct io_u *io_u)
        return 0;
 }
 
+static void fill_sha512(struct verify_header *hdr, void *p, unsigned int len)
+{
+       struct sha512_ctx sha512_ctx = {
+               .buf = hdr->sha512,
+       };
+
+       sha512_init(&sha512_ctx);
+       sha512_update(&sha512_ctx, p, len);
+}
+
+static void fill_sha256(struct verify_header *hdr, void *p, unsigned int len)
+{
+       struct sha256_ctx sha256_ctx = {
+               .buf = hdr->sha256,
+       };
+
+       sha256_init(&sha256_ctx);
+       sha256_update(&sha256_ctx, p, len);
+}
+
 static void fill_crc7(struct verify_header *hdr, void *p, unsigned int len)
 {
        hdr->crc7 = crc7(p, len);
@@ -327,6 +409,12 @@ void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
                case VERIFY_CRC7:
                        fill_crc7(hdr, data, data_len);
                        break;
+               case VERIFY_SHA256:
+                       fill_sha256(hdr, data, data_len);
+                       break;
+               case VERIFY_SHA512:
+                       fill_sha512(hdr, data, data_len);
+                       break;
                default:
                        log_err("fio: bad verify type: %d\n", td->o.verify);
                        assert(0);