summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--hash.h2
-rw-r--r--sha1dc/sha1.c20
-rw-r--r--sha1dc/sha1.h15
4 files changed, 47 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 25c21f08b1..05a96d7177 100644
--- a/Makefile
+++ b/Makefile
@@ -142,6 +142,10 @@ all::
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
+# Define DC_SHA1 to unconditionally enable the collision-detecting sha1
+# algorithm. This is slower, but may detect attempted collision attacks.
+# Takes priority over other *_SHA1 knobs.
+#
# Define SHA1_MAX_BLOCK_SIZE to limit the amount of data that will be hashed
# in one call to the platform's SHA1_Update(). e.g. APPLE_COMMON_CRYPTO
# wants 'SHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' defined.
@@ -1386,6 +1390,11 @@ ifdef APPLE_COMMON_CRYPTO
SHA1_MAX_BLOCK_SIZE = 1024L*1024L*1024L
endif
+ifdef DC_SHA1
+ LIB_OBJS += sha1dc/sha1.o
+ LIB_OBJS += sha1dc/ubc_check.o
+ BASIC_CFLAGS += -DSHA1_DC
+else
ifdef BLK_SHA1
LIB_OBJS += block-sha1/sha1.o
BASIC_CFLAGS += -DSHA1_BLK
@@ -1403,6 +1412,7 @@ else
endif
endif
endif
+endif
ifdef SHA1_MAX_BLOCK_SIZE
LIB_OBJS += compat/sha1-chunked.o
diff --git a/hash.h b/hash.h
index f0d9ddd0c2..a11fc9233f 100644
--- a/hash.h
+++ b/hash.h
@@ -7,6 +7,8 @@
#include <CommonCrypto/CommonDigest.h>
#elif defined(SHA1_OPENSSL)
#include <openssl/sha.h>
+#elif defined(SHA1_DC)
+#include "sha1dc/sha1.h"
#else /* SHA1_BLK */
#include "block-sha1/sha1.h"
#endif
diff --git a/sha1dc/sha1.c b/sha1dc/sha1.c
index 8ff2321dfb..6dd0da3608 100644
--- a/sha1dc/sha1.c
+++ b/sha1dc/sha1.c
@@ -1786,3 +1786,23 @@ int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
output[19] = (unsigned char)(ctx->ihv[4]);
return ctx->found_collision;
}
+
+void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx)
+{
+ if (!SHA1DCFinal(hash, ctx))
+ return;
+ die("SHA-1 appears to be part of a collision attack: %s",
+ sha1_to_hex(hash));
+}
+
+void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, unsigned long len)
+{
+ const char *data = vdata;
+ /* We expect an unsigned long, but sha1dc only takes an int */
+ while (len > INT_MAX) {
+ SHA1DCUpdate(ctx, data, INT_MAX);
+ data += INT_MAX;
+ len -= INT_MAX;
+ }
+ SHA1DCUpdate(ctx, data, len);
+}
diff --git a/sha1dc/sha1.h b/sha1dc/sha1.h
index 7d4d423b9d..bd8bd928fb 100644
--- a/sha1dc/sha1.h
+++ b/sha1dc/sha1.h
@@ -100,6 +100,21 @@ void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */
int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
+/*
+ * Same as SHA1DCFinal, but convert collision attack case into a verbose die().
+ */
+void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *);
+
+/*
+ * Same as SHA1DCUpdate, but adjust types to match git's usual interface.
+ */
+void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len);
+
+#define platform_SHA_CTX SHA1_CTX
+#define platform_SHA1_Init SHA1DCInit
+#define platform_SHA1_Update git_SHA1DCUpdate
+#define platform_SHA1_Final git_SHA1DCFinal
+
#if defined(__cplusplus)
}
#endif