[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r12289: HMAC-SHA-1 implementation, with unit tests based on vectors (in tor/trunk: . src/common src/or)



Author: nickm
Date: 2007-10-31 00:56:59 -0400 (Wed, 31 Oct 2007)
New Revision: 12289

Modified:
   tor/trunk/
   tor/trunk/src/common/crypto.c
   tor/trunk/src/common/crypto.h
   tor/trunk/src/or/test.c
Log:
 r16287@catbus:  nickm | 2007-10-31 00:53:53 -0400
 HMAC-SHA-1 implementation, with unit tests based on vectors from RVFC2202.  Steven's stuff will need this.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r16287] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/common/crypto.c
===================================================================
--- tor/trunk/src/common/crypto.c	2007-10-31 03:41:58 UTC (rev 12288)
+++ tor/trunk/src/common/crypto.c	2007-10-31 04:56:59 UTC (rev 12289)
@@ -1261,7 +1261,7 @@
 crypto_digest_get_digest(crypto_digest_env_t *digest,
                          char *out, size_t out_len)
 {
-  static unsigned char r[DIGEST_LEN];
+  static unsigned char r[DIGEST_LEN]; /*XXXXX020 why static? */
   SHA_CTX tmpctx;
   tor_assert(digest);
   tor_assert(out);
@@ -1297,6 +1297,54 @@
   memcpy(into,from,sizeof(crypto_digest_env_t));
 }
 
+/**DOCDOC */
+#define DIGEST_BLOCKSIZE 64
+
+/** Compute the HMAC-SHA-1 of the <b>msg_len</b> bytes in <b>msg</b>, using
+ * the <b>key</b> of length <b>key_len</b>.  Store the DIGEST_LEN-byte result
+ * in <b>hmac_out</b>.
+ */
+void
+crypto_hmac_sha1(char *hmac_out,
+                 const char *key, size_t key_len,
+                 const char *msg, size_t msg_len)
+{
+  SHA_CTX sha;
+  uint8_t K[DIGEST_BLOCKSIZE], D[DIGEST_LEN], K_SHORT[DIGEST_LEN];
+  const uint8_t *real_key;
+  unsigned int i;
+
+  if (key_len > DIGEST_BLOCKSIZE) {
+    SHA1((const unsigned char*)key, key_len, K_SHORT);
+    key_len = DIGEST_LEN;
+    real_key = K_SHORT;
+  } else {
+    real_key = (const uint8_t*)key;
+  }
+
+  memset(K, 0, sizeof(K));
+  memcpy(K, real_key, key_len);
+  for (i=0; i < sizeof(K); ++i)
+    K[i] ^= 0x36;
+  SHA1_Init(&sha);
+  SHA1_Update(&sha, K, sizeof(K));
+  SHA1_Update(&sha, msg, msg_len);
+  SHA1_Final(D, &sha);
+
+  /*
+  memset(K, 0, sizeof(K));
+  memcpy(K, real_key, key_len);
+  for (i=0; i < sizeof(K); ++i)
+    K[i] ^= 0x5c;
+  */
+  for (i=0; i < sizeof(K); ++i)
+    K[i] ^= (0x36 ^ 0x5c);
+  SHA1_Init(&sha);
+  SHA1_Update(&sha, K, sizeof(K));
+  SHA1_Update(&sha, D, sizeof(D));
+  SHA1_Final((unsigned char*)hmac_out, &sha);
+}
+
 /* DH */
 
 /** Shared P parameter for our DH key exchanged. */

Modified: tor/trunk/src/common/crypto.h
===================================================================
--- tor/trunk/src/common/crypto.h	2007-10-31 03:41:58 UTC (rev 12288)
+++ tor/trunk/src/common/crypto.h	2007-10-31 04:56:59 UTC (rev 12289)
@@ -146,6 +146,9 @@
 crypto_digest_env_t *crypto_digest_dup(const crypto_digest_env_t *digest);
 void crypto_digest_assign(crypto_digest_env_t *into,
                           const crypto_digest_env_t *from);
+void crypto_hmac_sha1(char *hmac_out,
+                      const char *key, size_t key_len,
+                      const char *msg, size_t msg_len);
 
 /* Key negotiation */
 crypto_dh_env_t *crypto_dh_new(void);

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2007-10-31 03:41:58 UTC (rev 12288)
+++ tor/trunk/src/or/test.c	2007-10-31 04:56:59 UTC (rev 12289)
@@ -445,6 +445,42 @@
              "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78"
              "\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20);
 
+  /* Test HMAC-SHA-1 with test cases from RFC2202. */
+  {
+    char key[80];
+    char digest[20];
+    char data[50];
+
+    /* Case 1. */
+    memset(key, 0x0b, 20);
+    crypto_hmac_sha1(digest, key, 20, "Hi There", 8);
+    test_streq(hex_str(digest, 20),
+               "B617318655057264E28BC0B6FB378C8EF146BE00");
+
+    /* Case 2. */
+    crypto_hmac_sha1(digest, "Jefe", 4, "what do ya want for nothing?", 28);
+    test_streq(hex_str(digest, 20),
+               "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79");
+
+    /* Case 4. */
+    base16_decode(key, 25,
+                  "0102030405060708090a0b0c0d0e0f10111213141516171819", 50);
+    memset(data, 0xcd, 50);
+    crypto_hmac_sha1(digest, key, 25, data, 50);
+    test_streq(hex_str(digest, 20),
+               "4C9007F4026250C6BC8414F9BF50C86C2D7235DA");
+
+    /* Case . */
+    memset(key, 0xaa, 80);
+    crypto_hmac_sha1(digest, key, 80,
+                     "Test Using Larger Than Block-Size Key - Hash Key First",
+                     54);
+    test_streq(hex_str(digest, 20),
+               "AA4AE5E15272D00E95705637CE8A3B55ED402112");
+
+  }
+
+
   /* Public-key ciphers */
   pk1 = pk_generate(0);
   pk2 = crypto_new_pk_env();
@@ -2175,6 +2211,7 @@
           "platform Tor "VERSION" on ", sizeof(buf2));
   strlcat(buf2, get_uname(), sizeof(buf2));
   strlcat(buf2, "\n"
+          "opt protocols Link 1 Circuit 1\n"
           "published 1970-01-01 00:00:00\n"
           "opt fingerprint ", sizeof(buf2));
   test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1));