aboutsummaryrefslogtreecommitdiff
path: root/crypto.c
diff options
context:
space:
mode:
authorFranklin Wei <me@fwei.tk>2018-06-04 21:37:57 -0400
committerFranklin Wei <me@fwei.tk>2018-06-04 21:37:57 -0400
commit040a9bab4cafb4dd6ec44485a5c421d99a00cffe (patch)
treedd0f95ae3d2f6215c0b5380046c8a1d675e3c52e /crypto.c
parent35d085feee188ef5b6910fe67222fb297c5c6ea6 (diff)
downloadcsaa-040a9bab4cafb4dd6ec44485a5c421d99a00cffe.zip
csaa-040a9bab4cafb4dd6ec44485a5c421d99a00cffe.tar.gz
csaa-040a9bab4cafb4dd6ec44485a5c421d99a00cffe.tar.bz2
csaa-040a9bab4cafb4dd6ec44485a5c421d99a00cffe.tar.xz
Restructure; test file creation
sp_test() now shows a bare minimum example of creating a file. Further improvements are definitely needed.
Diffstat (limited to 'crypto.c')
-rw-r--r--crypto.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/crypto.c b/crypto.c
new file mode 100644
index 0000000..6039b7f
--- /dev/null
+++ b/crypto.c
@@ -0,0 +1,117 @@
+#include "crypto.h"
+
+#include <string.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+/* return true iff [b, bprime] encloses a */
+bool encloses(int b, int bprime, int a)
+{
+ return (b < a && a < bprime) || (bprime <= b && b < a) || (a < bprime && bprime <= b);
+}
+
+hash_t hash_node(const struct iomt_node *node)
+{
+ return sha256(node, sizeof(*node));
+}
+
+hash_t hmac_sha256(const void *data, size_t datalen, const void *key, size_t keylen)
+{
+ hash_t h;
+ HMAC(EVP_sha256(), key, keylen, data, datalen, h.hash, NULL);
+ return h;
+}
+
+hash_t sha256(const void *data, size_t datalen)
+{
+ hash_t h;
+ SHA256(data, datalen, h.hash);
+ return h;
+}
+
+bool is_zero(hash_t u)
+{
+ /* constant-time comparison */
+ volatile char c = 0;
+ for(int i = 0; i < 32; ++i)
+ c |= u.hash[i];
+
+ return c == 0;
+}
+
+void dump_hash(hash_t u)
+{
+ for(int i = 0; i < 32; ++i)
+ printf("%02x", u.hash[i]);
+ printf("\n");
+}
+
+bool hash_equals(hash_t a, hash_t b)
+{
+ return !memcmp(a.hash, b.hash, 32);
+}
+
+hash_t hash_xor(hash_t a, hash_t b)
+{
+ for(int i = 0; i < 32; ++i)
+ a.hash[i] ^= b.hash[i];
+ return a;
+}
+
+/* NOTE: we fail to distinguish between intermediate and leaf
+ * nodes, making a second-preimage attack possible */
+/* order: 0: u is left, v is right, 1: u is right, v is left */
+hash_t merkle_parent(hash_t u, hash_t v, int order)
+{
+ if(is_zero(u))
+ return v;
+ if(is_zero(v))
+ return u;
+
+ /* append and hash */
+ SHA256_CTX ctx;
+ hash_t h;
+
+ SHA256_Init(&ctx);
+
+ if(order != 0)
+ SHA256_Update(&ctx, v.hash, 32);
+
+ SHA256_Update(&ctx, u.hash, 32);
+
+ if(order == 0)
+ SHA256_Update(&ctx, v.hash, 32);
+
+ SHA256_Final(h.hash, &ctx);
+
+ return h;
+}
+
+/* Calculate the root of a Merkle tree given the leaf node v, and n
+ * complementary nodes, ordered from the closest node (the sibling
+ * leaf node at the bottom of the tree) to most distant (the opposite
+ * half of the tree). orders[i] represents whether each complementarty
+ * node is a left or right child, which is necessary to compute the
+ * proper hash value at each stage. This is the f_bt() algorithm
+ * described in Mohanty et al. */
+
+/* orders: 0 indiciates that the complementary node is LEFT child, 1:
+ * node is RIGHT child */
+hash_t merkle_compute(hash_t node, const hash_t *comp, const int *orders, size_t n)
+{
+ hash_t parent = node;
+ for(size_t i = 0; i < n; ++i)
+ parent = merkle_parent(comp[i], parent, orders[i]);
+
+ return parent;
+}
+
+/* convert the first 8 bytes (little endian) to a 64-bit int */
+uint64_t hash_to_u64(hash_t h)
+{
+ uint64_t ret = 0;
+ for(int i = 0; i < 8; ++i)
+ ret |= h.hash[i] << (i * 8);
+ return ret;
+}