Browse Source

Use SHA256 in the replaycache, rather than SHA1

This migrates away from SHA1, and provides further hash flooding
protection on top of the randomised siphash implementation.

Add unit tests to make sure that different inputs don't have the
same hash.
teor (Tim Wilson-Brown) 8 years ago
parent
commit
2e9779e5d8
4 changed files with 51 additions and 15 deletions
  1. 4 0
      changes/feature8961-replaycache-sha256
  2. 13 13
      src/or/replaycache.c
  3. 1 1
      src/or/replaycache.h
  4. 33 1
      src/test/test_replay.c

+ 4 - 0
changes/feature8961-replaycache-sha256

@@ -0,0 +1,4 @@
+  o Minor enhancement (replaycache):
+    - The replay cache now uses SHA256 instead of SHA1.
+      Implements feature #8961.
+      Patch by "teor", issue reported by "rransom".

+ 13 - 13
src/or/replaycache.c

@@ -23,7 +23,7 @@ replaycache_free(replaycache_t *r)
     return;
   }
 
-  if (r->digests_seen) digestmap_free(r->digests_seen, tor_free_);
+  if (r->digests_seen) digest256map_free(r->digests_seen, tor_free_);
 
   tor_free(r);
 }
@@ -54,7 +54,7 @@ replaycache_new(time_t horizon, time_t interval)
   r->scrub_interval = interval;
   r->scrubbed = 0;
   r->horizon = horizon;
-  r->digests_seen = digestmap_new();
+  r->digests_seen = digest256map_new();
 
  err:
   return r;
@@ -69,7 +69,7 @@ replaycache_add_and_test_internal(
     time_t *elapsed)
 {
   int rv = 0;
-  char digest[DIGEST_LEN];
+  uint8_t digest[DIGEST256_LEN];
   time_t *access_time;
 
   /* sanity check */
@@ -80,10 +80,10 @@ replaycache_add_and_test_internal(
   }
 
   /* compute digest */
-  crypto_digest(digest, (const char *)data, len);
+  crypto_digest256((char *)digest, (const char *)data, len, DIGEST_SHA256);
 
   /* check map */
-  access_time = digestmap_get(r->digests_seen, digest);
+  access_time = digest256map_get(r->digests_seen, digest);
 
   /* seen before? */
   if (access_time != NULL) {
@@ -114,7 +114,7 @@ replaycache_add_and_test_internal(
     /* No, so no hit and update the digest map with the current time */
     access_time = tor_malloc(sizeof(*access_time));
     *access_time = present;
-    digestmap_set(r->digests_seen, digest, access_time);
+    digest256map_set(r->digests_seen, digest, access_time);
   }
 
   /* now scrub the cache if it's time */
@@ -130,8 +130,8 @@ replaycache_add_and_test_internal(
 STATIC void
 replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r)
 {
-  digestmap_iter_t *itr = NULL;
-  const char *digest;
+  digest256map_iter_t *itr = NULL;
+  const uint8_t *digest;
   void *valp;
   time_t *access_time;
 
@@ -149,19 +149,19 @@ replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r)
   if (r->horizon == 0) return;
 
   /* okay, scrub time */
-  itr = digestmap_iter_init(r->digests_seen);
-  while (!digestmap_iter_done(itr)) {
-    digestmap_iter_get(itr, &digest, &valp);
+  itr = digest256map_iter_init(r->digests_seen);
+  while (!digest256map_iter_done(itr)) {
+    digest256map_iter_get(itr, &digest, &valp);
     access_time = (time_t *)valp;
     /* aged out yet? */
     if (*access_time < present - r->horizon) {
       /* Advance the iterator and remove this one */
-      itr = digestmap_iter_next_rmv(r->digests_seen, itr);
+      itr = digest256map_iter_next_rmv(r->digests_seen, itr);
       /* Free the value removed */
       tor_free(access_time);
     } else {
       /* Just advance the iterator */
-      itr = digestmap_iter_next(r->digests_seen, itr);
+      itr = digest256map_iter_next(r->digests_seen, itr);
     }
   }
 

+ 1 - 1
src/or/replaycache.h

@@ -26,7 +26,7 @@ struct replaycache_s {
   /*
    * Digest map: keys are digests, values are times the digest was last seen
    */
-  digestmap_t *digests_seen;
+  digest256map_t *digests_seen;
 };
 
 #endif /* REPLAYCACHE_PRIVATE */

+ 33 - 1
src/test/test_replay.c

@@ -17,6 +17,20 @@ static const char *test_buffer =
   " occaecat cupidatat non proident, sunt in culpa qui officia deserunt"
   " mollit anim id est laborum.";
 
+static const char *test_buffer_2 =
+  "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis"
+  " praesentium voluptatum deleniti atque corrupti quos dolores et quas"
+  " molestias excepturi sint occaecati cupiditate non provident, similique"
+  " sunt in culpa qui officia deserunt mollitia animi, id est laborum et"
+  " dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio."
+  " Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil"
+  " impedit quo minus id quod maxime placeat facere possimus, omnis voluptas"
+  " assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut"
+  " officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates"
+  " repudiandae sint et molestiae non recusandae. Itaque earum rerum hic"
+  " tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias"
+  " consequatur aut perferendis doloribus asperiores repellat.";
+
 static void
 test_replaycache_alloc(void *arg)
 {
@@ -83,6 +97,12 @@ test_replaycache_miss(void *arg)
         strlen(test_buffer), NULL);
   tt_int_op(result,OP_EQ, 0);
 
+  /* make sure a different buffer misses as well */
+  result =
+  replaycache_add_and_test_internal(1200, NULL, test_buffer_2,
+                                    strlen(test_buffer_2), NULL);
+  tt_int_op(result,OP_EQ, 0);
+
   /* poke the bad-parameter error case too */
   result =
     replaycache_add_and_test_internal(1200, NULL, test_buffer,
@@ -115,6 +135,18 @@ test_replaycache_hit(void *arg)
         strlen(test_buffer), NULL);
   tt_int_op(result,OP_EQ, 1);
 
+  /* make sure a different buffer misses then hits as well */
+
+  result =
+  replaycache_add_and_test_internal(1200, r, test_buffer_2,
+                                    strlen(test_buffer_2), NULL);
+  tt_int_op(result,OP_EQ, 0);
+
+  result =
+  replaycache_add_and_test_internal(1300, r, test_buffer_2,
+                                    strlen(test_buffer_2), NULL);
+  tt_int_op(result,OP_EQ, 1);
+
  done:
   if (r) replaycache_free(r);
 
@@ -245,7 +277,7 @@ test_replaycache_scrub(void *arg)
   /* Make sure we hit the aging-out case too */
   replaycache_scrub_if_needed_internal(1500, r);
   /* Assert that we aged it */
-  tt_int_op(digestmap_size(r->digests_seen),OP_EQ, 0);
+  tt_int_op(digest256map_size(r->digests_seen),OP_EQ, 0);
 
  done:
   if (r) replaycache_free(r);