Browse Source

prop224 prepwork: Introduce HMAC-SHA3 function.

George Kadianakis 7 years ago
parent
commit
b9010c8bf5
3 changed files with 68 additions and 0 deletions
  1. 22 0
      src/common/crypto.c
  2. 3 0
      src/common/crypto.h
  3. 43 0
      src/test/test_crypto.c

+ 22 - 0
src/common/crypto.c

@@ -2109,6 +2109,28 @@ crypto_hmac_sha256(char *hmac_out,
   tor_assert(rv);
 }
 
+/** Compute an SHA3 MAC of <b>msg</b> using <b>key</b> as the key. The format
+ * used for our MAC is SHA3(k | m). Write the DIGEST256_LEN-byte result into
+ * <b>mac_out</b> of size <b>mac_out_len</b>. */
+void
+crypto_mac_sha3_256(char *mac_out, size_t mac_out_len,
+                    const char *key, size_t key_len,
+                    const char *msg, size_t msg_len)
+{
+  crypto_digest_t *digest;
+
+  tor_assert(mac_out);
+  tor_assert(key);
+  tor_assert(msg);
+
+  digest = crypto_digest256_new(DIGEST_SHA3_256);
+
+  crypto_digest_add_bytes(digest, key, key_len);
+  crypto_digest_add_bytes(digest, msg, msg_len);
+  crypto_digest_get_digest(digest, mac_out, mac_out_len);
+  crypto_digest_free(digest);
+}
+
 /** Internal state for a eXtendable-Output Function (XOF). */
 struct crypto_xof_t {
   keccak_state s;

+ 3 - 0
src/common/crypto.h

@@ -255,6 +255,9 @@ void crypto_digest_assign(crypto_digest_t *into,
 void crypto_hmac_sha256(char *hmac_out,
                         const char *key, size_t key_len,
                         const char *msg, size_t msg_len);
+void crypto_mac_sha3_256(char *mac_out, size_t mac_out_len,
+                         const char *key, size_t key_len,
+                         const char *msg, size_t msg_len);
 crypto_xof_t *crypto_xof_new(void);
 void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
 void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);

+ 43 - 0
src/test/test_crypto.c

@@ -1135,6 +1135,48 @@ test_crypto_sha3_xof(void *arg)
   tor_free(mem_op_hex_tmp);
 }
 
+/* Test our MAC-SHA3 function. There are not actually any MAC-SHA3 test
+ * vectors out there for our H(len(k) || k || m) construction. Hence what we
+ * are gonna do is test our crypto_mac_sha3_256() function against manually
+ * doing H(len(k) || k||m).  If in the future the Keccak group decides to
+ * standarize an MAC construction and make test vectors, we should
+ * incorporate them here. */
+static void
+test_crypto_mac_sha3(void *arg)
+{
+  const char msg[] = "i am in a library somewhere using my computer";
+  const char key[] = "i'm from the past talking to the future.";
+
+  char hmac_test[DIGEST256_LEN];
+  char hmac_manual[DIGEST256_LEN];
+
+  (void) arg;
+
+  /* First let's use our nice HMAC-SHA3 function */
+  crypto_mac_sha3_256(hmac_test, sizeof(hmac_test),
+                      key, strlen(key),
+                      msg, strlen(msg));
+
+  /* Now let's try a manual H(k || m) construction */
+  {
+    char *key_msg_concat = NULL;
+    int result;
+
+    tor_asprintf(&key_msg_concat, "%s%s", key, msg);
+
+    result = crypto_digest256(hmac_manual,
+                              key_msg_concat, strlen(key_msg_concat),
+                              DIGEST_SHA3_256);
+    tt_int_op(result, ==, 0);
+    tor_free(key_msg_concat);
+  }
+
+  /* Now compare the two results */
+  tt_mem_op(hmac_test, OP_EQ, hmac_manual, DIGEST256_LEN);
+
+ done: ;
+}
+
 /** Run unit tests for our public key crypto functions */
 static void
 test_crypto_pk(void *arg)
@@ -2918,6 +2960,7 @@ struct testcase_t crypto_tests[] = {
   { "digest_names", test_crypto_digest_names, 0, NULL, NULL },
   { "sha3", test_crypto_sha3, TT_FORK, NULL, NULL},
   { "sha3_xof", test_crypto_sha3_xof, TT_FORK, NULL, NULL},
+  { "mac_sha3", test_crypto_mac_sha3, TT_FORK, NULL, NULL},
   CRYPTO_LEGACY(dh),
   { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup,
     (void*)"aes" },