[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Forward secrecy in spiped
On Thu, Apr 24, 2014 at 4:04 PM, Colin Percival <cperciva@tarsnap.com> wrote:
>
> Want to send me a patch?
Okay, here is my first attempt. I found it to be simplest to mandate
that both sides use -f to turn off forward secrecy, but I don't know
if that rules out valid use cases. Thoughts?
(Also, let me know if the diff below doesn't work. Gmail's handling of
plain text content is...special.)
-- Fred
diff --git a/proto/proto_crypt.c b/proto/proto_crypt.c
index d674bfc..092f57b 100644
--- a/proto/proto_crypt.c
+++ b/proto/proto_crypt.c
@@ -145,14 +145,29 @@ void proto_crypt_dhmac(const struct proto_secret * K,
}
/**
- * proto_crypt_dh_validate(yh_r, dhmac_r):
+ * is_zero_or_one(x, len):
+ * Returns non-zero if the big-endian value stored at (${x}, ${len}) is equal
+ * to either 0 or 1.
+ */
+static int is_zero_or_one(const uint8_t *x, size_t len) {
+ for (size_t i = 0; i < len - 1; i++) {
+ if (x[i] != 0)
+ return (0);
+ }
+
+ return ((x[len - 1] == 0) || (x[len - 1] == 1));
+}
+
+/**
+ * proto_crypt_dh_validate(yh_r, dhmac_r, nofps):
* Return non-zero if the value ${yh_r} received from the remote party is not
* correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or
- * if the included y value is >= the diffie-hellman group modulus.
+ * if the included y value is >= the diffie-hellman group modulus, or if
+ * "${nofps} is zero" does not equal "the included value is > 1".
*/
int
proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN],
- const uint8_t dhmac_r[PCRYPT_DHMAC_LEN])
+ const uint8_t dhmac_r[PCRYPT_DHMAC_LEN], int nofps)
{
uint8_t hbuf[32];
@@ -165,7 +180,15 @@ proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN],
return (1);
/* Sanity-check the diffie-hellman value. */
- return (crypto_dh_sanitycheck(&yh_r[0]));
+ if (crypto_dh_sanitycheck(&yh_r[0]))
+ return (1);
+
+ /* Check that forward perfect secrecy is used if and only if the
+ * diffie-hellman value is > 1. */
+ if ((nofps != 0) != (is_zero_or_one(&yh_r[0], CRYPTO_DH_PUBLEN) != 0))
+ return (1);
+
+ return (0);
}
/**
diff --git a/proto/proto_crypt.h b/proto/proto_crypt.h
index 8801aa7..cd8fbcb 100644
--- a/proto/proto_crypt.h
+++ b/proto/proto_crypt.h
@@ -39,13 +39,14 @@ void proto_crypt_dhmac(const struct proto_secret *,
uint8_t[PCRYPT_DHMAC_LEN], uint8_t[PCRYPT_DHMAC_LEN], int);
/**
- * proto_crypt_dh_validate(yh_r, dhmac_r):
+ * proto_crypt_dh_validate(yh_r, dhmac_r, nofps):
* Return non-zero if the value ${yh_r} received from the remote party is not
* correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or
- * if the included y value is >= the diffie-hellman group modulus.
+ * if the included y value is >= the diffie-hellman group modulus, or if
+ * "${nofps} is zero" does not equal "the included value is > 1".
*/
int proto_crypt_dh_validate(const uint8_t[PCRYPT_YH_LEN],
- const uint8_t[PCRYPT_DHMAC_LEN]);
+ const uint8_t[PCRYPT_DHMAC_LEN], int);
/**
* proto_crypt_dh_generate(yh_l, x, dhmac_l, nofps):
diff --git a/proto/proto_handshake.c b/proto/proto_handshake.c
index 0c87caa..c677e07 100644
--- a/proto/proto_handshake.c
+++ b/proto/proto_handshake.c
@@ -209,7 +209,7 @@ callback_dh_read(void * cookie, ssize_t len)
return (handshakefail(H));
/* Is the value we read valid? */
- if (proto_crypt_dh_validate(H->yh_remote, H->dhmac_remote))
+ if (proto_crypt_dh_validate(H->yh_remote, H->dhmac_remote, H->nofps))
return (handshakefail(H));
/*
diff --git a/spipe/spipe.1 b/spipe/spipe.1
index 5086d6b..c39f2bf 100644
--- a/spipe/spipe.1
+++ b/spipe/spipe.1
@@ -41,7 +41,7 @@ Use the provided key file to authenticate and encrypt.
.B \-f
Use fast/weak handshaking: This reduces the CPU time spent in the
initial connection setup, at the expense of losing perfect forward
-secrecy.
+secrecy. The other party must also use this flag.
.TP
.B \-j
Disable transport layer keep-alives.
diff --git a/spiped/spiped.1 b/spiped/spiped.1
index 09d5abe..82ca7b3 100644
--- a/spiped/spiped.1
+++ b/spiped/spiped.1
@@ -73,7 +73,7 @@ finished launching it will be ready to create pipes.
.B \-f
Use fast/weak handshaking: This reduces the CPU time spent in the
initial connection setup, at the expense of losing perfect forward
-secrecy.
+secrecy. The other party must also use this flag.
.TP
.B \-F
Run in foreground. This can be useful with systems like daemontools.