summaryrefslogtreecommitdiff
path: root/builtin/receive-pack.c
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2020-04-28 15:49:57 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2020-04-28 15:49:57 -0700
commit2abd648b17899679f9a76bfdeba8f620fa6fff21 (patch)
tree4ea2933f777ae25c343377eeb77132eed66a9614 /builtin/receive-pack.c
parentMerge branch 'lr/freshen-file-fix' (diff)
parentreceive-pack: compilation fix (diff)
downloadtgif-2abd648b17899679f9a76bfdeba8f620fa6fff21.tar.xz
Merge branch 'bc/constant-memequal'
Validation of push certificate has been made more robust against timing attacks. * bc/constant-memequal: receive-pack: compilation fix builtin/receive-pack: use constant-time comparison for HMAC value
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r--builtin/receive-pack.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d46147f709..239094d2dc 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -499,12 +499,27 @@ static char *find_header(const char *msg, size_t len, const char *key,
return NULL;
}
+/*
+ * Return zero if a and b are equal up to n bytes and nonzero if they are not.
+ * This operation is guaranteed to run in constant time to avoid leaking data.
+ */
+static int constant_memequal(const char *a, const char *b, size_t n)
+{
+ int res = 0;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ res |= a[i] ^ b[i];
+ return res;
+}
+
static const char *check_nonce(const char *buf, size_t len)
{
char *nonce = find_header(buf, len, "nonce", NULL);
timestamp_t stamp, ostamp;
char *bohmac, *expect = NULL;
const char *retval = NONCE_BAD;
+ size_t noncelen;
if (!nonce) {
retval = NONCE_MISSING;
@@ -546,8 +561,14 @@ static const char *check_nonce(const char *buf, size_t len)
goto leave;
}
+ noncelen = strlen(nonce);
expect = prepare_push_cert_nonce(service_dir, stamp);
- if (strcmp(expect, nonce)) {
+ if (noncelen != strlen(expect)) {
+ /* This is not even the right size. */
+ retval = NONCE_BAD;
+ goto leave;
+ }
+ if (constant_memequal(expect, nonce, noncelen)) {
/* Not what we would have signed earlier */
retval = NONCE_BAD;
goto leave;