Add patches for alternative ciphersuite
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
56d25e7bd6
commit
d787d2479a
11 changed files with 3514 additions and 0 deletions
879
debian/patches/alt-ciphersuite/0001-Add-AES-256-GCM-support-to-SPTPS.patch
vendored
Normal file
879
debian/patches/alt-ciphersuite/0001-Add-AES-256-GCM-support-to-SPTPS.patch
vendored
Normal file
|
@ -0,0 +1,879 @@
|
||||||
|
From cc521f3d5f3a0c758163c871e75f5e533e86771b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Mon, 2 Aug 2021 23:53:13 +0200
|
||||||
|
Subject: [PATCH 01/10] Add AES-256-GCM support to SPTPS.
|
||||||
|
|
||||||
|
This also adds a simple cipher suite negotiation, where peers announce the
|
||||||
|
ciphers they support, and their preferred cipher. Since we need to bump the
|
||||||
|
SPTPS version anyway, also prefer little endian over network byte order.
|
||||||
|
---
|
||||||
|
doc/SPTPS | 45 +++++--
|
||||||
|
src/invitation.c | 11 +-
|
||||||
|
src/protocol_auth.c | 25 +++-
|
||||||
|
src/protocol_key.c | 30 ++++-
|
||||||
|
src/sptps.c | 310 +++++++++++++++++++++++++++++++++-----------
|
||||||
|
src/sptps.h | 44 ++++++-
|
||||||
|
src/sptps_test.c | 13 +-
|
||||||
|
7 files changed, 382 insertions(+), 96 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/SPTPS b/doc/SPTPS
|
||||||
|
index 2d8fee5b..2da27604 100644
|
||||||
|
--- a/doc/SPTPS
|
||||||
|
+++ b/doc/SPTPS
|
||||||
|
@@ -18,8 +18,8 @@ Stream record layer
|
||||||
|
|
||||||
|
A record consists of these fields:
|
||||||
|
|
||||||
|
-- uint32_t seqno (network byte order)
|
||||||
|
-- uint16_t length (network byte order)
|
||||||
|
+- uint32_t seqno (little endian)
|
||||||
|
+- uint16_t length (little endian)
|
||||||
|
- uint8_t type
|
||||||
|
- opaque data[length]
|
||||||
|
- opaque hmac[HMAC_SIZE] (HMAC over all preceding fields)
|
||||||
|
@@ -45,8 +45,8 @@ Datagram record layer
|
||||||
|
|
||||||
|
A record consists of these fields:
|
||||||
|
|
||||||
|
-- uint16_t length (network byte order)
|
||||||
|
-- uint32_t seqno (network byte order)
|
||||||
|
+- uint16_t length (little endian)
|
||||||
|
+- uint32_t seqno (little endian)
|
||||||
|
- uint8_t type
|
||||||
|
- opaque data[length]
|
||||||
|
- opaque hmac[HMAC_SIZE] (HMAC over all preceding fields)
|
||||||
|
@@ -75,7 +75,7 @@ SIG ->
|
||||||
|
...encrypt and HMAC using session keys from now on...
|
||||||
|
|
||||||
|
App ->
|
||||||
|
- <- App
|
||||||
|
+ <- App
|
||||||
|
...
|
||||||
|
...
|
||||||
|
|
||||||
|
@@ -91,7 +91,7 @@ ACK ->
|
||||||
|
...encrypt and HMAC using new session keys from now on...
|
||||||
|
|
||||||
|
App ->
|
||||||
|
- <- App
|
||||||
|
+ <- App
|
||||||
|
...
|
||||||
|
...
|
||||||
|
---------------------
|
||||||
|
@@ -102,7 +102,11 @@ connection.
|
||||||
|
|
||||||
|
Key EXchange message:
|
||||||
|
|
||||||
|
-- uint8_t kex_version (always 0 in this version of SPTPS)
|
||||||
|
+- uint8_t kex_version (always 1 in this version of SPTPS)
|
||||||
|
+- uint8_t
|
||||||
|
+ - high 4 bits: public key algorithm
|
||||||
|
+ - low 4 bits: preferred cipher suite
|
||||||
|
+- uint16_t bitmask of cipher suites supported
|
||||||
|
- opaque nonce[32] (random number)
|
||||||
|
- opaque ecdh_key[ECDH_SIZE]
|
||||||
|
|
||||||
|
@@ -162,9 +166,34 @@ The expanded key is used as follows:
|
||||||
|
Where initiator_cipher_key is the key used by session initiator to encrypt
|
||||||
|
messages sent to the responder.
|
||||||
|
|
||||||
|
+Public key suites
|
||||||
|
+-----------------
|
||||||
|
+
|
||||||
|
+0: Ed25519 + SHA512
|
||||||
|
+1: Ed448 + SHAKE256?
|
||||||
|
+
|
||||||
|
+Symmetric cipher suites
|
||||||
|
+-----------------------
|
||||||
|
+
|
||||||
|
+Value in parentheses is the static priority used to break ties in cipher suite
|
||||||
|
+negotiation. We favor those algorithms that run faster without hardware
|
||||||
|
+acceleration.
|
||||||
|
+
|
||||||
|
+0: Chacha20-Poly1305 (1)
|
||||||
|
+1: AES256-GCM (0)
|
||||||
|
+
|
||||||
|
+Cipher suite selection
|
||||||
|
+----------------------
|
||||||
|
+
|
||||||
|
+Public key suites are required to match on both sides. The symmetric suite is chosen as follows:
|
||||||
|
+
|
||||||
|
+1. AND the supported cipher suite bitmasks
|
||||||
|
+2. If both preferred cipher suites are possible, choose the one with the highest static priority.
|
||||||
|
+3. If only one is possible, choose that one.
|
||||||
|
+4. If none is possible, choose the suite from the resulting bitmask that has the highest static priority.
|
||||||
|
+
|
||||||
|
TODO:
|
||||||
|
-----
|
||||||
|
|
||||||
|
- Document format of ECDH public key, ECDSA signature
|
||||||
|
-- Document how CTR mode is used
|
||||||
|
- Refer to TLS RFCs where appropriate
|
||||||
|
diff --git a/src/invitation.c b/src/invitation.c
|
||||||
|
index cff9e727..6c49af48 100644
|
||||||
|
--- a/src/invitation.c
|
||||||
|
+++ b/src/invitation.c
|
||||||
|
@@ -1399,7 +1399,16 @@ next:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start an SPTPS session
|
||||||
|
- if(!sptps_start(&sptps, NULL, true, false, key, hiskey, "tinc invitation", 15, invitation_send, invitation_receive)) {
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .initiator = true,
|
||||||
|
+ .mykey = key,
|
||||||
|
+ .hiskey = hiskey,
|
||||||
|
+ .label = "tinc invitation",
|
||||||
|
+ .send_data = invitation_send,
|
||||||
|
+ .receive_record = invitation_receive,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if(!sptps_start(&sptps, ¶ms)) {
|
||||||
|
ecdsa_free(hiskey);
|
||||||
|
ecdsa_free(key);
|
||||||
|
return 1;
|
||||||
|
diff --git a/src/protocol_auth.c b/src/protocol_auth.c
|
||||||
|
index 22254575..050b266c 100644
|
||||||
|
--- a/src/protocol_auth.c
|
||||||
|
+++ b/src/protocol_auth.c
|
||||||
|
@@ -412,7 +412,17 @@ bool id_h(connection_t *c, const char *request) {
|
||||||
|
|
||||||
|
c->protocol_minor = 2;
|
||||||
|
|
||||||
|
- return sptps_start(&c->sptps, c, false, false, invitation_key, c->ecdsa, "tinc invitation", 15, send_meta_sptps, receive_invitation_sptps);
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .handle = c,
|
||||||
|
+ .initiator = false,
|
||||||
|
+ .mykey = invitation_key,
|
||||||
|
+ .hiskey = c->ecdsa,
|
||||||
|
+ .label = "tinc invitation",
|
||||||
|
+ .send_data = send_meta_sptps,
|
||||||
|
+ .receive_record = receive_invitation_sptps,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ return sptps_start(&c->sptps, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if identity is a valid name */
|
||||||
|
@@ -507,7 +517,18 @@ bool id_h(connection_t *c, const char *request) {
|
||||||
|
snprintf(label, labellen, "tinc TCP key expansion %s %s", c->name, myself->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
- return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, labellen, send_meta_sptps, receive_meta_sptps);
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .handle = c,
|
||||||
|
+ .initiator = c->outgoing,
|
||||||
|
+ .mykey = myself->connection->ecdsa,
|
||||||
|
+ .hiskey = c->ecdsa,
|
||||||
|
+ .label = label,
|
||||||
|
+ .labellen = sizeof(label),
|
||||||
|
+ .send_data = send_meta_sptps,
|
||||||
|
+ .receive_record = receive_meta_sptps,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ return sptps_start(&c->sptps, ¶ms);
|
||||||
|
} else {
|
||||||
|
return send_metakey(c);
|
||||||
|
}
|
||||||
|
diff --git a/src/protocol_key.c b/src/protocol_key.c
|
||||||
|
index 740d2fb4..da53c16c 100644
|
||||||
|
--- a/src/protocol_key.c
|
||||||
|
+++ b/src/protocol_key.c
|
||||||
|
@@ -128,7 +128,20 @@ bool send_req_key(node_t *to) {
|
||||||
|
to->status.waitingforkey = true;
|
||||||
|
to->last_req_key = now.tv_sec;
|
||||||
|
to->incompression = myself->incompression;
|
||||||
|
- return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
|
||||||
|
+
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .handle = to,
|
||||||
|
+ .initiator = true,
|
||||||
|
+ .datagram = true,
|
||||||
|
+ .mykey = myself->connection->ecdsa,
|
||||||
|
+ .hiskey = to->ecdsa,
|
||||||
|
+ .label = label,
|
||||||
|
+ .labellen = sizeof(label),
|
||||||
|
+ .send_data = send_initial_sptps_data,
|
||||||
|
+ .receive_record = receive_sptps_record,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ return sptps_start(&to->sptps, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
|
||||||
|
@@ -249,7 +262,20 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, no
|
||||||
|
from->status.validkey = false;
|
||||||
|
from->status.waitingforkey = true;
|
||||||
|
from->last_req_key = now.tv_sec;
|
||||||
|
- sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
|
||||||
|
+
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .handle = from,
|
||||||
|
+ .initiator = false,
|
||||||
|
+ .datagram = true,
|
||||||
|
+ .mykey = myself->connection->ecdsa,
|
||||||
|
+ .hiskey = from->ecdsa,
|
||||||
|
+ .label = label,
|
||||||
|
+ .labellen = sizeof(label),
|
||||||
|
+ .send_data = send_sptps_data_myself,
|
||||||
|
+ .receive_record = receive_sptps_record,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ sptps_start(&from->sptps, ¶ms);
|
||||||
|
sptps_receive_data(&from->sptps, buf, len);
|
||||||
|
send_mtu_info(myself, from, MTU);
|
||||||
|
return true;
|
||||||
|
diff --git a/src/sptps.c b/src/sptps.c
|
||||||
|
index a0483c34..33c41424 100644
|
||||||
|
--- a/src/sptps.c
|
||||||
|
+++ b/src/sptps.c
|
||||||
|
@@ -28,6 +28,10 @@
|
||||||
|
#include "sptps.h"
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
+#ifdef HAVE_OPENSSL
|
||||||
|
+#include <openssl/evp.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
unsigned int sptps_replaywin = 16;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -90,25 +94,159 @@ static void warning(sptps_t *s, const char *format, ...) {
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_half) {
|
||||||
|
+ switch(suite) {
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ *ctx = chacha_poly1305_init();
|
||||||
|
+ return ctx && chacha_poly1305_set_key(*ctx, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0));
|
||||||
|
+
|
||||||
|
+ case SPTPS_AES256_GCM:
|
||||||
|
+#ifdef HAVE_OPENSSL
|
||||||
|
+ *ctx = EVP_CIPHER_CTX_new();
|
||||||
|
+
|
||||||
|
+ if(!ctx) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
|
||||||
|
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 4, NULL)
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 32 : 0), key);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void cipher_exit(uint8_t suite, void *ctx) {
|
||||||
|
+ switch(suite) {
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ chacha_poly1305_exit(ctx);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case SPTPS_AES256_GCM:
|
||||||
|
+#ifdef HAVE_OPENSSL
|
||||||
|
+ EVP_CIPHER_CTX_free(ctx);
|
||||||
|
+ break;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
|
||||||
|
+ switch(suite) {
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ chacha_poly1305_encrypt(ctx, seqno, in, inlen, out, outlen);
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ case SPTPS_AES256_GCM:
|
||||||
|
+#ifdef HAVE_OPENSSL
|
||||||
|
+ {
|
||||||
|
+ if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int outlen1 = 0, outlen2 = 0;
|
||||||
|
+
|
||||||
|
+ if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ outlen1 += outlen2;
|
||||||
|
+
|
||||||
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ outlen1 += 16;
|
||||||
|
+
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
|
||||||
|
+ switch(suite) {
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ return chacha_poly1305_decrypt(ctx, seqno, in, inlen, out, outlen);
|
||||||
|
+
|
||||||
|
+ case SPTPS_AES256_GCM:
|
||||||
|
+#ifdef HAVE_OPENSSL
|
||||||
|
+ {
|
||||||
|
+ if(inlen < 16) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ inlen -= 16;
|
||||||
|
+
|
||||||
|
+ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int outlen1 = 0, outlen2 = 0;
|
||||||
|
+
|
||||||
|
+ if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1 + outlen2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
// Send a record (datagram version, accepts all record types, handles encryption and authentication).
|
||||||
|
static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
|
||||||
|
- uint8_t *buffer = alloca(len + 21UL);
|
||||||
|
-
|
||||||
|
+ uint8_t *buffer = alloca(len + SPTPS_DATAGRAM_OVERHEAD);
|
||||||
|
// Create header with sequence number, length and record type
|
||||||
|
uint32_t seqno = s->outseqno++;
|
||||||
|
- uint32_t netseqno = ntohl(seqno);
|
||||||
|
|
||||||
|
- memcpy(buffer, &netseqno, 4);
|
||||||
|
+ memcpy(buffer, &seqno, 4);
|
||||||
|
buffer[4] = type;
|
||||||
|
memcpy(buffer + 5, data, len);
|
||||||
|
|
||||||
|
if(s->outstate) {
|
||||||
|
// If first handshake has finished, encrypt and HMAC
|
||||||
|
- chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL);
|
||||||
|
- return s->send_data(s->handle, type, buffer, len + 21UL);
|
||||||
|
+ if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL)) {
|
||||||
|
+ return error(s, EINVAL, "Failed to encrypt message");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_OVERHEAD);
|
||||||
|
} else {
|
||||||
|
// Otherwise send as plaintext
|
||||||
|
- return s->send_data(s->handle, type, buffer, len + 5UL);
|
||||||
|
+ return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_HEADER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Send a record (private version, accepts all record types, handles encryption and authentication).
|
||||||
|
@@ -117,11 +255,11 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
|
||||||
|
return send_record_priv_datagram(s, type, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
- uint8_t *buffer = alloca(len + 19UL);
|
||||||
|
+ uint8_t *buffer = alloca(len + SPTPS_OVERHEAD);
|
||||||
|
|
||||||
|
// Create header with sequence number, length and record type
|
||||||
|
uint32_t seqno = s->outseqno++;
|
||||||
|
- uint16_t netlen = htons(len);
|
||||||
|
+ uint16_t netlen = len;
|
||||||
|
|
||||||
|
memcpy(buffer, &netlen, 2);
|
||||||
|
buffer[2] = type;
|
||||||
|
@@ -129,11 +267,14 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
|
||||||
|
|
||||||
|
if(s->outstate) {
|
||||||
|
// If first handshake has finished, encrypt and HMAC
|
||||||
|
- chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL);
|
||||||
|
- return s->send_data(s->handle, type, buffer, len + 19UL);
|
||||||
|
+ if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL)) {
|
||||||
|
+ return error(s, EINVAL, "Failed to encrypt message");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return s->send_data(s->handle, type, buffer, len + SPTPS_OVERHEAD);
|
||||||
|
} else {
|
||||||
|
// Otherwise send as plaintext
|
||||||
|
- return s->send_data(s->handle, type, buffer, len + 3UL);
|
||||||
|
+ return s->send_data(s->handle, type, buffer, len + SPTPS_HEADER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -161,7 +302,7 @@ static bool send_kex(sptps_t *s) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- s->mykex = realloc(s->mykex, 1 + 32 + keylen);
|
||||||
|
+ s->mykex = realloc(s->mykex, 4 + 32 + keylen);
|
||||||
|
|
||||||
|
if(!s->mykex) {
|
||||||
|
return error(s, errno, strerror(errno));
|
||||||
|
@@ -169,16 +310,18 @@ static bool send_kex(sptps_t *s) {
|
||||||
|
|
||||||
|
// Set version byte to zero.
|
||||||
|
s->mykex[0] = SPTPS_VERSION;
|
||||||
|
+ s->mykex[1] = s->preferred_suite;
|
||||||
|
+ memcpy(s->mykex + 2, &s->cipher_suites, 2);
|
||||||
|
|
||||||
|
// Create a random nonce.
|
||||||
|
- randomize(s->mykex + 1, 32);
|
||||||
|
+ randomize(s->mykex + 4, 32);
|
||||||
|
|
||||||
|
// Create a new ECDH public key.
|
||||||
|
- if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) {
|
||||||
|
+ if(!(s->ecdh = ecdh_generate_public(s->mykex + 4 + 32))) {
|
||||||
|
return error(s, EINVAL, "Failed to generate ECDH public key");
|
||||||
|
}
|
||||||
|
|
||||||
|
- return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen);
|
||||||
|
+ return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 4 + 32 + keylen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a SIGnature record, containing an Ed25519 signature over both KEX records.
|
||||||
|
@@ -192,9 +335,9 @@ static bool send_sig(sptps_t *s) {
|
||||||
|
uint8_t *sig = alloca(siglen);
|
||||||
|
|
||||||
|
msg[0] = s->initiator;
|
||||||
|
- memcpy(msg + 1, s->mykex, 1 + 32 + keylen);
|
||||||
|
- memcpy(msg + 1 + 33 + keylen, s->hiskex, 1 + 32 + keylen);
|
||||||
|
- memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
|
||||||
|
+ memcpy(msg + 1, s->mykex, 4 + 32 + keylen);
|
||||||
|
+ memcpy(msg + 1 + (4 + 32 + keylen), s->hiskex, 4 + 32 + keylen);
|
||||||
|
+ memcpy(msg + 1 + 2 * (4 + 32 + keylen), s->label, s->labellen);
|
||||||
|
|
||||||
|
// Sign the result.
|
||||||
|
if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
|
||||||
|
@@ -207,16 +350,6 @@ static bool send_sig(sptps_t *s) {
|
||||||
|
|
||||||
|
// Generate key material from the shared secret created from the ECDHE key exchange.
|
||||||
|
static bool generate_key_material(sptps_t *s, const uint8_t *shared, size_t len) {
|
||||||
|
- // Initialise cipher and digest structures if necessary
|
||||||
|
- if(!s->outstate) {
|
||||||
|
- s->incipher = chacha_poly1305_init();
|
||||||
|
- s->outcipher = chacha_poly1305_init();
|
||||||
|
-
|
||||||
|
- if(!s->incipher || !s->outcipher) {
|
||||||
|
- return error(s, EINVAL, "Failed to open cipher");
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
// Allocate memory for key material
|
||||||
|
size_t keylen = 2 * CHACHA_POLY1305_KEYLEN;
|
||||||
|
|
||||||
|
@@ -261,14 +394,8 @@ static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
return error(s, EIO, "Invalid ACK record length");
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(s->initiator) {
|
||||||
|
- if(!chacha_poly1305_set_key(s->incipher, s->key)) {
|
||||||
|
- return error(s, EINVAL, "Failed to set counter");
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) {
|
||||||
|
- return error(s, EINVAL, "Failed to set counter");
|
||||||
|
- }
|
||||||
|
+ if(!cipher_init(s->cipher_suite, &s->incipher, s->key, s->initiator)) {
|
||||||
|
+ return error(s, EINVAL, "Failed to initialize cipher");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(s->key);
|
||||||
|
@@ -278,14 +405,51 @@ static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static uint8_t select_cipher_suite(uint16_t mask, uint8_t pref1, uint8_t pref2) {
|
||||||
|
+ // Check if there is a viable preference, if so select the lowest one
|
||||||
|
+ uint8_t selection = 255;
|
||||||
|
+
|
||||||
|
+ if(mask & (1U << pref1)) {
|
||||||
|
+ selection = pref1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(pref2 < selection && (mask & (1U << pref2))) {
|
||||||
|
+ selection = pref2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Otherwise, select the lowest cipher suite both sides support
|
||||||
|
+ if(selection == 255) {
|
||||||
|
+ selection = 0;
|
||||||
|
+
|
||||||
|
+ while(!(mask & 1U)) {
|
||||||
|
+ selection++;
|
||||||
|
+ mask >>= 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return selection;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// Receive a Key EXchange record, respond by sending a SIG record.
|
||||||
|
static bool receive_kex(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
// Verify length of the HELLO record
|
||||||
|
- if(len != 1 + 32 + ECDH_SIZE) {
|
||||||
|
+ if(len != 4 + 32 + ECDH_SIZE) {
|
||||||
|
return error(s, EIO, "Invalid KEX record length");
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Ignore version number for now.
|
||||||
|
+ if(data[0] != SPTPS_VERSION) {
|
||||||
|
+ return error(s, EIO, "Incompatible SPTPS version");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uint16_t suites;
|
||||||
|
+ memcpy(&suites, data + 2, 2);
|
||||||
|
+ suites &= s->cipher_suites;
|
||||||
|
+
|
||||||
|
+ if(!suites) {
|
||||||
|
+ return error(s, EIO, "No matching cipher suites");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ s->cipher_suite = select_cipher_suite(suites, s->preferred_suite, data[1] & 0xf);
|
||||||
|
|
||||||
|
// Make a copy of the KEX message, send_sig() and receive_sig() need it
|
||||||
|
if(s->hiskex) {
|
||||||
|
@@ -322,9 +486,9 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
uint8_t *msg = alloca(msglen);
|
||||||
|
|
||||||
|
msg[0] = !s->initiator;
|
||||||
|
- memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
|
||||||
|
- memcpy(msg + 1 + 33 + keylen, s->mykex, 1 + 32 + keylen);
|
||||||
|
- memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
|
||||||
|
+ memcpy(msg + 1, s->hiskex, 4 + 32 + keylen);
|
||||||
|
+ memcpy(msg + 1 + (4 + 32 + keylen), s->mykex, 4 + 32 + keylen);
|
||||||
|
+ memcpy(msg + 1 + 2 * (4 + 32 + keylen), s->label, s->labellen);
|
||||||
|
|
||||||
|
// Verify signature.
|
||||||
|
if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
|
||||||
|
@@ -334,7 +498,7 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
// Compute shared secret.
|
||||||
|
uint8_t shared[ECDH_SHARED_SIZE];
|
||||||
|
|
||||||
|
- if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) {
|
||||||
|
+ if(!ecdh_compute_shared(s->ecdh, s->hiskex + 4 + 32, shared)) {
|
||||||
|
return error(s, EINVAL, "Failed to compute ECDH shared secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -360,15 +524,8 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // TODO: only set new keys after ACK has been set/received
|
||||||
|
- if(s->initiator) {
|
||||||
|
- if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) {
|
||||||
|
- return error(s, EINVAL, "Failed to set key");
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- if(!chacha_poly1305_set_key(s->outcipher, s->key)) {
|
||||||
|
- return error(s, EINVAL, "Failed to set key");
|
||||||
|
- }
|
||||||
|
+ if(!cipher_init(s->cipher_suite, &s->outcipher, s->key, !s->initiator)) {
|
||||||
|
+ return error(s, EINVAL, "Failed to initialize cipher");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
@@ -518,15 +675,13 @@ bool sptps_verify_datagram(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
const uint8_t *data = vdata;
|
||||||
|
uint32_t seqno;
|
||||||
|
memcpy(&seqno, data, 4);
|
||||||
|
- seqno = ntohl(seqno);
|
||||||
|
|
||||||
|
if(!sptps_check_seqno(s, seqno, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *buffer = alloca(len);
|
||||||
|
- size_t outlen;
|
||||||
|
- return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
|
||||||
|
+ return cipher_decrypt(s->cipher_suite, s->incipher, seqno, data + 4, len - 4, buffer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive incoming data, datagram version.
|
||||||
|
@@ -537,7 +692,6 @@ static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t
|
||||||
|
|
||||||
|
uint32_t seqno;
|
||||||
|
memcpy(&seqno, data, 4);
|
||||||
|
- seqno = ntohl(seqno);
|
||||||
|
data += 4;
|
||||||
|
len -= 4;
|
||||||
|
|
||||||
|
@@ -563,7 +717,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t
|
||||||
|
uint8_t *buffer = alloca(len);
|
||||||
|
size_t outlen;
|
||||||
|
|
||||||
|
- if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen)) {
|
||||||
|
+ if(!cipher_decrypt(s->cipher_suite, s->incipher, seqno, data, len, buffer, &outlen)) {
|
||||||
|
return error(s, EIO, "Failed to decrypt and verify packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -635,10 +789,9 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
// Get the length bytes
|
||||||
|
|
||||||
|
memcpy(&s->reclen, s->inbuf, 2);
|
||||||
|
- s->reclen = ntohs(s->reclen);
|
||||||
|
|
||||||
|
// If we have the length bytes, ensure our buffer can hold the whole request.
|
||||||
|
- s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
|
||||||
|
+ s->inbuf = realloc(s->inbuf, s->reclen + SPTPS_OVERHEAD);
|
||||||
|
|
||||||
|
if(!s->inbuf) {
|
||||||
|
return error(s, errno, strerror(errno));
|
||||||
|
@@ -651,7 +804,7 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read up to the end of the record.
|
||||||
|
- size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
|
||||||
|
+ size_t toread = s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER) - s->buflen;
|
||||||
|
|
||||||
|
if(toread > len) {
|
||||||
|
toread = len;
|
||||||
|
@@ -662,7 +815,7 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
s->buflen += toread;
|
||||||
|
|
||||||
|
// If we don't have a whole record, exit.
|
||||||
|
- if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {
|
||||||
|
+ if(s->buflen < s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER)) {
|
||||||
|
return total_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -672,13 +825,13 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
|
||||||
|
// Check HMAC and decrypt.
|
||||||
|
if(s->instate) {
|
||||||
|
- if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
|
||||||
|
+ if(!cipher_decrypt(s->cipher_suite, s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
|
||||||
|
return error(s, EINVAL, "Failed to decrypt and verify record");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append a NULL byte for safety.
|
||||||
|
- s->inbuf[s->reclen + 3UL] = 0;
|
||||||
|
+ s->inbuf[s->reclen + SPTPS_HEADER] = 0;
|
||||||
|
|
||||||
|
uint8_t type = s->inbuf[2];
|
||||||
|
|
||||||
|
@@ -704,16 +857,18 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a SPTPS session.
|
||||||
|
-bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
|
||||||
|
+bool sptps_start(sptps_t *s, const sptps_params_t *params) {
|
||||||
|
// Initialise struct sptps
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
|
||||||
|
- s->handle = handle;
|
||||||
|
- s->initiator = initiator;
|
||||||
|
- s->datagram = datagram;
|
||||||
|
- s->mykey = mykey;
|
||||||
|
- s->hiskey = hiskey;
|
||||||
|
+ s->handle = params->handle;
|
||||||
|
+ s->initiator = params->initiator;
|
||||||
|
+ s->datagram = params->datagram;
|
||||||
|
+ s->mykey = params->mykey;
|
||||||
|
+ s->hiskey = params->hiskey;
|
||||||
|
s->replaywin = sptps_replaywin;
|
||||||
|
+ s->cipher_suites = params->cipher_suites ? params->cipher_suites & SPTPS_ALL_CIPHER_SUITES : SPTPS_ALL_CIPHER_SUITES;
|
||||||
|
+ s->preferred_suite = params->preferred_suite;
|
||||||
|
|
||||||
|
if(s->replaywin) {
|
||||||
|
s->late = malloc(s->replaywin);
|
||||||
|
@@ -725,13 +880,16 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
|
||||||
|
memset(s->late, 0, s->replaywin);
|
||||||
|
}
|
||||||
|
|
||||||
|
- s->label = malloc(labellen);
|
||||||
|
+ s->labellen = params->labellen ? params->labellen : strlen(params->label);
|
||||||
|
+ s->label = malloc(s->labellen);
|
||||||
|
|
||||||
|
if(!s->label) {
|
||||||
|
return error(s, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(!datagram) {
|
||||||
|
+ memcpy(s->label, params->label, s->labellen);
|
||||||
|
+
|
||||||
|
+ if(!s->datagram) {
|
||||||
|
s->inbuf = malloc(7);
|
||||||
|
|
||||||
|
if(!s->inbuf) {
|
||||||
|
@@ -741,11 +899,9 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
|
||||||
|
s->buflen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- memcpy(s->label, label, labellen);
|
||||||
|
- s->labellen = labellen;
|
||||||
|
|
||||||
|
- s->send_data = send_data;
|
||||||
|
- s->receive_record = receive_record;
|
||||||
|
+ s->send_data = params->send_data;
|
||||||
|
+ s->receive_record = params->receive_record;
|
||||||
|
|
||||||
|
// Do first KEX immediately
|
||||||
|
s->state = SPTPS_KEX;
|
||||||
|
@@ -755,8 +911,8 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
|
||||||
|
// Stop a SPTPS session.
|
||||||
|
bool sptps_stop(sptps_t *s) {
|
||||||
|
// Clean up any resources.
|
||||||
|
- chacha_poly1305_exit(s->incipher);
|
||||||
|
- chacha_poly1305_exit(s->outcipher);
|
||||||
|
+ cipher_exit(s->cipher_suite, s->incipher);
|
||||||
|
+ cipher_exit(s->cipher_suite, s->outcipher);
|
||||||
|
ecdh_free(s->ecdh);
|
||||||
|
free(s->inbuf);
|
||||||
|
free(s->mykex);
|
||||||
|
diff --git a/src/sptps.h b/src/sptps.h
|
||||||
|
index 96edc366..b9ec11fd 100644
|
||||||
|
--- a/src/sptps.h
|
||||||
|
+++ b/src/sptps.h
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
#include "ecdh.h"
|
||||||
|
#include "ecdsa.h"
|
||||||
|
|
||||||
|
-#define SPTPS_VERSION 0
|
||||||
|
+#define SPTPS_VERSION 1
|
||||||
|
|
||||||
|
// Record types
|
||||||
|
#define SPTPS_HANDSHAKE 128 // Key exchange and authentication
|
||||||
|
@@ -34,7 +34,10 @@
|
||||||
|
#define SPTPS_CLOSE 130 // Application closed the connection
|
||||||
|
|
||||||
|
// Overhead for datagrams
|
||||||
|
-#define SPTPS_DATAGRAM_OVERHEAD 21
|
||||||
|
+static const size_t SPTPS_OVERHEAD = 19;
|
||||||
|
+static const size_t SPTPS_HEADER = 3;
|
||||||
|
+static const size_t SPTPS_DATAGRAM_OVERHEAD = 21;
|
||||||
|
+static const size_t SPTPS_DATAGRAM_HEADER = 5;
|
||||||
|
|
||||||
|
typedef bool (*send_data_t)(void *handle, uint8_t type, const void *data, size_t len);
|
||||||
|
typedef bool (*receive_record_t)(void *handle, uint8_t type, const void *data, uint16_t len);
|
||||||
|
@@ -47,9 +50,40 @@ typedef enum sptps_state_t {
|
||||||
|
SPTPS_ACK = 4, // Waiting for an ACKnowledgement record
|
||||||
|
} sptps_state_t;
|
||||||
|
|
||||||
|
+// Public key suites
|
||||||
|
+enum {
|
||||||
|
+ SPTPS_ED25519 = 0,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+// Cipher suites
|
||||||
|
+enum {
|
||||||
|
+ SPTPS_CHACHA_POLY1305 = 0,
|
||||||
|
+ SPTPS_AES256_GCM = 1,
|
||||||
|
+ SPTPS_ALL_CIPHER_SUITES = 0x3,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+typedef struct sptps_params {
|
||||||
|
+ void *handle;
|
||||||
|
+ bool initiator;
|
||||||
|
+ bool datagram;
|
||||||
|
+ uint8_t preferred_suite;
|
||||||
|
+ uint16_t cipher_suites;
|
||||||
|
+ ecdsa_t *mykey;
|
||||||
|
+ ecdsa_t *hiskey;
|
||||||
|
+ const void *label;
|
||||||
|
+ size_t labellen;
|
||||||
|
+ send_data_t send_data;
|
||||||
|
+ receive_record_t receive_record;
|
||||||
|
+} sptps_params_t;
|
||||||
|
+
|
||||||
|
typedef struct sptps {
|
||||||
|
bool initiator;
|
||||||
|
bool datagram;
|
||||||
|
+ uint8_t preferred_suite;
|
||||||
|
+ uint16_t cipher_suites;
|
||||||
|
+
|
||||||
|
+ uint8_t pk_suite;
|
||||||
|
+ uint8_t cipher_suite;
|
||||||
|
sptps_state_t state;
|
||||||
|
|
||||||
|
uint8_t *inbuf;
|
||||||
|
@@ -57,7 +91,7 @@ typedef struct sptps {
|
||||||
|
uint16_t reclen;
|
||||||
|
|
||||||
|
bool instate;
|
||||||
|
- chacha_poly1305_ctx_t *incipher;
|
||||||
|
+ void *incipher;
|
||||||
|
uint32_t inseqno;
|
||||||
|
uint32_t received;
|
||||||
|
unsigned int replaywin;
|
||||||
|
@@ -65,7 +99,7 @@ typedef struct sptps {
|
||||||
|
uint8_t *late;
|
||||||
|
|
||||||
|
bool outstate;
|
||||||
|
- chacha_poly1305_ctx_t *outcipher;
|
||||||
|
+ void *outcipher;
|
||||||
|
uint32_t outseqno;
|
||||||
|
|
||||||
|
ecdsa_t *mykey;
|
||||||
|
@@ -87,7 +121,7 @@ extern unsigned int sptps_replaywin;
|
||||||
|
extern void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap);
|
||||||
|
extern void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap);
|
||||||
|
extern void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap);
|
||||||
|
-extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record);
|
||||||
|
+extern bool sptps_start(sptps_t *s, const struct sptps_params *params);
|
||||||
|
extern bool sptps_stop(sptps_t *s);
|
||||||
|
extern bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len);
|
||||||
|
extern size_t sptps_receive_data(sptps_t *s, const void *data, size_t len);
|
||||||
|
diff --git a/src/sptps_test.c b/src/sptps_test.c
|
||||||
|
index 249f2e4f..e77ab9c7 100644
|
||||||
|
--- a/src/sptps_test.c
|
||||||
|
+++ b/src/sptps_test.c
|
||||||
|
@@ -562,7 +562,18 @@ static int run_test(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
sptps_t s;
|
||||||
|
|
||||||
|
- if(!sptps_start(&s, &sock, initiator, datagram, mykey, hiskey, "sptps_test", 10, send_data, receive_record)) {
|
||||||
|
+ sptps_params_t params = {
|
||||||
|
+ .handle = &sock,
|
||||||
|
+ .initiator = initiator,
|
||||||
|
+ .datagram = datagram,
|
||||||
|
+ .mykey = mykey,
|
||||||
|
+ .hiskey = hiskey,
|
||||||
|
+ .label = "sptps_test",
|
||||||
|
+ .send_data = send_data,
|
||||||
|
+ .receive_record = receive_record,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if(!sptps_start(&s, ¶ms)) {
|
||||||
|
free(mykey);
|
||||||
|
free(hiskey);
|
||||||
|
return 1;
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
91
debian/patches/alt-ciphersuite/0002-Add-cipher-suite-selection-options-to-sptps_test.patch
vendored
Normal file
91
debian/patches/alt-ciphersuite/0002-Add-cipher-suite-selection-options-to-sptps_test.patch
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
From 1d0eea4899f9642a3945c07b9266e660b9f9ce71 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Tue, 3 Aug 2021 00:38:37 +0200
|
||||||
|
Subject: [PATCH 02/10] Add cipher suite selection options to sptps_test.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sptps_test.c | 38 +++++++++++++++++++++++++++-----------
|
||||||
|
1 file changed, 27 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sptps_test.c b/src/sptps_test.c
|
||||||
|
index e77ab9c7..32ed62d3 100644
|
||||||
|
--- a/src/sptps_test.c
|
||||||
|
+++ b/src/sptps_test.c
|
||||||
|
@@ -127,6 +127,8 @@ static struct option const long_options[] = {
|
||||||
|
{"replay-window", required_argument, NULL, 'W'},
|
||||||
|
{"special", no_argument, NULL, 's'},
|
||||||
|
{"verbose", required_argument, NULL, 'v'},
|
||||||
|
+ {"cipher-suites", required_argument, NULL, 'M'},
|
||||||
|
+ {"preferred-cipher", required_argument, NULL, 'P'},
|
||||||
|
{"help", no_argument, NULL, 1},
|
||||||
|
{NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
@@ -136,19 +138,21 @@ static void usage(void) {
|
||||||
|
"Usage: %s [options] my_ed25519_key_file his_ed25519_key_file [host] port\n"
|
||||||
|
"\n"
|
||||||
|
"Valid options are:\n"
|
||||||
|
- " -d, --datagram Enable datagram mode.\n"
|
||||||
|
- " -q, --quit Quit when EOF occurs on stdin.\n"
|
||||||
|
- " -r, --readonly Only send data from the socket to stdout.\n"
|
||||||
|
+ " -d, --datagram Enable datagram mode.\n"
|
||||||
|
+ " -q, --quit Quit when EOF occurs on stdin.\n"
|
||||||
|
+ " -r, --readonly Only send data from the socket to stdout.\n"
|
||||||
|
#ifdef HAVE_LINUX
|
||||||
|
- " -t, --tun Use a tun device instead of stdio.\n"
|
||||||
|
+ " -t, --tun Use a tun device instead of stdio.\n"
|
||||||
|
#endif
|
||||||
|
- " -w, --writeonly Only send data from stdin to the socket.\n"
|
||||||
|
- " -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
|
||||||
|
- " -R, --replay-window N Set replay window to N bytes.\n"
|
||||||
|
- " -s, --special Enable special handling of lines starting with #, ^ and $.\n"
|
||||||
|
- " -v, --verbose Display debug messages.\n"
|
||||||
|
- " -4 Use IPv4.\n"
|
||||||
|
- " -6 Use IPv6.\n"
|
||||||
|
+ " -w, --writeonly Only send data from stdin to the socket.\n"
|
||||||
|
+ " -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
|
||||||
|
+ " -R, --replay-window N Set replay window to N bytes.\n"
|
||||||
|
+ " -M, --cipher-suites MASK Set the mask of allowed cipher suites.\n"
|
||||||
|
+ " -P, --preferred-suite N Set the preferred cipher suite.\n"
|
||||||
|
+ " -s, --special Enable special handling of lines starting with #, ^ and $.\n"
|
||||||
|
+ " -v, --verbose Display debug messages.\n"
|
||||||
|
+ " -4 Use IPv4.\n"
|
||||||
|
+ " -6 Use IPv6.\n"
|
||||||
|
"\n"
|
||||||
|
"Report bugs to tinc@tinc-vpn.org.\n";
|
||||||
|
|
||||||
|
@@ -326,6 +330,8 @@ static int run_test(int argc, char *argv[]) {
|
||||||
|
int r;
|
||||||
|
int option_index = 0;
|
||||||
|
bool quit = false;
|
||||||
|
+ unsigned long cipher_suites = SPTPS_ALL_CIPHER_SUITES;
|
||||||
|
+ unsigned long preferred_suite = 0;
|
||||||
|
|
||||||
|
while((r = getopt_long(argc, argv, "dqrstwL:W:v46", long_options, &option_index)) != EOF) {
|
||||||
|
switch(r) {
|
||||||
|
@@ -366,6 +372,14 @@ static int run_test(int argc, char *argv[]) {
|
||||||
|
sptps_replaywin = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case 'M': /* cipher suites */
|
||||||
|
+ cipher_suites = strtoul(optarg, NULL, 0);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'P': /* preferred cipher */
|
||||||
|
+ preferred_suite = strtoul(optarg, NULL, 0);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case 'v': /* be verbose */
|
||||||
|
verbose = true;
|
||||||
|
break;
|
||||||
|
@@ -571,6 +585,8 @@ static int run_test(int argc, char *argv[]) {
|
||||||
|
.label = "sptps_test",
|
||||||
|
.send_data = send_data,
|
||||||
|
.receive_record = receive_record,
|
||||||
|
+ .cipher_suites = cipher_suites,
|
||||||
|
+ .preferred_suite = preferred_suite,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!sptps_start(&s, ¶ms)) {
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
285
debian/patches/alt-ciphersuite/0003-Let-sptps_speed-benchmark-all-cipher-suites.patch
vendored
Normal file
285
debian/patches/alt-ciphersuite/0003-Let-sptps_speed-benchmark-all-cipher-suites.patch
vendored
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
From c0f0610037847ea2abae1e7a826d36a55f9dfa36 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Tue, 3 Aug 2021 00:39:05 +0200
|
||||||
|
Subject: [PATCH 03/10] Let sptps_speed benchmark all cipher suites.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sptps_speed.c | 212 +++++++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 125 insertions(+), 87 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sptps_speed.c b/src/sptps_speed.c
|
||||||
|
index c7c6e546..45bbeb5c 100644
|
||||||
|
--- a/src/sptps_speed.c
|
||||||
|
+++ b/src/sptps_speed.c
|
||||||
|
@@ -168,22 +168,76 @@ static int run_benchmark(int argc, char *argv[]) {
|
||||||
|
fprintf(stderr, "%28.2lf op/s\n", rate);
|
||||||
|
ecdh_free(ecdh1);
|
||||||
|
|
||||||
|
- // SPTPS authentication phase
|
||||||
|
-
|
||||||
|
int fd[2];
|
||||||
|
+ struct pollfd pfd[2] = {{fd[0], POLLIN}, {fd[1], POLLIN}};
|
||||||
|
+
|
||||||
|
+ sptps_params_t params1 = {
|
||||||
|
+ .handle = fd + 0,
|
||||||
|
+ .initiator = true,
|
||||||
|
+ .datagram = false,
|
||||||
|
+ .mykey = key1,
|
||||||
|
+ .hiskey = key2,
|
||||||
|
+ .label = "sptps_speed",
|
||||||
|
+ .send_data = send_data,
|
||||||
|
+ .receive_record = receive_record,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ sptps_params_t params2 = {
|
||||||
|
+ .handle = fd + 1,
|
||||||
|
+ .initiator = false,
|
||||||
|
+ .datagram = false,
|
||||||
|
+ .mykey = key2,
|
||||||
|
+ .hiskey = key1,
|
||||||
|
+ .label = "sptps_speed",
|
||||||
|
+ .send_data = send_data,
|
||||||
|
+ .receive_record = receive_record,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ static const char *suite_names[] = {
|
||||||
|
+ "Chacha20-Poly1305",
|
||||||
|
+ "AES-256-GCM",
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ for(uint8_t suite = 0; suite < 2; suite++) {
|
||||||
|
+ fprintf(stderr, "\nCipher suite %u (%s):\n", suite, suite_names[suite]);
|
||||||
|
+ params1.preferred_suite = params2.preferred_suite = suite;
|
||||||
|
+
|
||||||
|
+ // SPTPS authentication phase
|
||||||
|
+
|
||||||
|
+ fprintf(stderr, "SPTPS/TCP authenticate for %lg seconds: ", duration);
|
||||||
|
+
|
||||||
|
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
|
||||||
|
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
|
||||||
|
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
+ pfd[0].fd = fd[0], pfd[1].fd = fd[1];
|
||||||
|
+ params1.datagram = params2.datagram = false;
|
||||||
|
|
||||||
|
- struct pollfd pfd[2] = {{fd[0], POLLIN, 0}, {fd[1], POLLIN, 0}};
|
||||||
|
+ for(clock_start(); clock_countto(duration);) {
|
||||||
|
+ sptps_start(&sptps1, ¶ms1);
|
||||||
|
+ sptps_start(&sptps2, ¶ms2);
|
||||||
|
|
||||||
|
- fprintf(stderr, "SPTPS/TCP authenticate for %lg seconds: ", duration);
|
||||||
|
+ while(poll(pfd, 2, 0)) {
|
||||||
|
+ if(pfd[0].revents) {
|
||||||
|
+ receive_data(&sptps1);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- for(clock_start(); clock_countto(duration);) {
|
||||||
|
- sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
- sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
+ if(pfd[1].revents) {
|
||||||
|
+ receive_data(&sptps2);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sptps_stop(&sptps1);
|
||||||
|
+ sptps_stop(&sptps2);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fprintf(stderr, "%10.2lf op/s\n", rate * 2);
|
||||||
|
+
|
||||||
|
+ // SPTPS data
|
||||||
|
+
|
||||||
|
+ sptps_start(&sptps1, ¶ms1);
|
||||||
|
+ sptps_start(&sptps2, ¶ms2);
|
||||||
|
|
||||||
|
while(poll(pfd, 2, 0)) {
|
||||||
|
if(pfd[0].revents) {
|
||||||
|
@@ -195,65 +249,68 @@ static int run_benchmark(int argc, char *argv[]) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- sptps_stop(&sptps1);
|
||||||
|
- sptps_stop(&sptps2);
|
||||||
|
- }
|
||||||
|
+ fprintf(stderr, "SPTPS/TCP transmit for %lg seconds: ", duration);
|
||||||
|
|
||||||
|
- fprintf(stderr, "%10.2lf op/s\n", rate * 2);
|
||||||
|
+ for(clock_start(); clock_countto(duration);) {
|
||||||
|
+ if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- // SPTPS data
|
||||||
|
+ receive_data(&sptps2);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
- sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
+ rate *= 2 * 1451 * 8;
|
||||||
|
|
||||||
|
- while(poll(pfd, 2, 0)) {
|
||||||
|
- if(pfd[0].revents) {
|
||||||
|
- receive_data(&sptps1);
|
||||||
|
+ if(rate > 1e9) {
|
||||||
|
+ fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
|
||||||
|
+ } else if(rate > 1e6) {
|
||||||
|
+ fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
|
||||||
|
+ } else if(rate > 1e3) {
|
||||||
|
+ fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(pfd[1].revents) {
|
||||||
|
- receive_data(&sptps2);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ sptps_stop(&sptps1);
|
||||||
|
+ sptps_stop(&sptps2);
|
||||||
|
|
||||||
|
- fprintf(stderr, "SPTPS/TCP transmit for %lg seconds: ", duration);
|
||||||
|
+ close(fd[0]);
|
||||||
|
+ close(fd[1]);
|
||||||
|
|
||||||
|
- for(clock_start(); clock_countto(duration);) {
|
||||||
|
- if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
|
||||||
|
- abort();
|
||||||
|
+ // SPTPS datagram authentication phase
|
||||||
|
+
|
||||||
|
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
|
||||||
|
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- receive_data(&sptps2);
|
||||||
|
- }
|
||||||
|
+ pfd[0].fd = fd[0], pfd[1].fd = fd[1];
|
||||||
|
+ params1.datagram = params2.datagram = true;
|
||||||
|
|
||||||
|
- rate *= 2 * 1451 * 8;
|
||||||
|
+ fprintf(stderr, "SPTPS/UDP authenticate for %lg seconds: ", duration);
|
||||||
|
|
||||||
|
- if(rate > 1e9) {
|
||||||
|
- fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
|
||||||
|
- } else if(rate > 1e6) {
|
||||||
|
- fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
|
||||||
|
- } else if(rate > 1e3) {
|
||||||
|
- fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
|
||||||
|
- }
|
||||||
|
+ for(clock_start(); clock_countto(duration);) {
|
||||||
|
+ sptps_start(&sptps1, ¶ms1);
|
||||||
|
+ sptps_start(&sptps2, ¶ms2);
|
||||||
|
|
||||||
|
- sptps_stop(&sptps1);
|
||||||
|
- sptps_stop(&sptps2);
|
||||||
|
+ while(poll(pfd, 2, 0)) {
|
||||||
|
+ if(pfd[0].revents) {
|
||||||
|
+ receive_data(&sptps1);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- // SPTPS datagram authentication phase
|
||||||
|
+ if(pfd[1].revents) {
|
||||||
|
+ receive_data(&sptps2);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- close(fd[0]);
|
||||||
|
- close(fd[1]);
|
||||||
|
+ sptps_stop(&sptps1);
|
||||||
|
+ sptps_stop(&sptps2);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
|
||||||
|
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
+ fprintf(stderr, "%10.2lf op/s\n", rate * 2);
|
||||||
|
|
||||||
|
- fprintf(stderr, "SPTPS/UDP authenticate for %lg seconds: ", duration);
|
||||||
|
+ // SPTPS datagram data
|
||||||
|
|
||||||
|
- for(clock_start(); clock_countto(duration);) {
|
||||||
|
- sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
- sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
+ sptps_start(&sptps1, ¶ms1);
|
||||||
|
+ sptps_start(&sptps2, ¶ms2);
|
||||||
|
|
||||||
|
while(poll(pfd, 2, 0)) {
|
||||||
|
if(pfd[0].revents) {
|
||||||
|
@@ -265,54 +322,35 @@ static int run_benchmark(int argc, char *argv[]) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- sptps_stop(&sptps1);
|
||||||
|
- sptps_stop(&sptps2);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- fprintf(stderr, "%10.2lf op/s\n", rate * 2);
|
||||||
|
+ fprintf(stderr, "SPTPS/UDP transmit for %lg seconds: ", duration);
|
||||||
|
|
||||||
|
- // SPTPS datagram data
|
||||||
|
-
|
||||||
|
- sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
- sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record);
|
||||||
|
-
|
||||||
|
- while(poll(pfd, 2, 0)) {
|
||||||
|
- if(pfd[0].revents) {
|
||||||
|
- receive_data(&sptps1);
|
||||||
|
- }
|
||||||
|
+ for(clock_start(); clock_countto(duration);) {
|
||||||
|
+ if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(pfd[1].revents) {
|
||||||
|
receive_data(&sptps2);
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
|
||||||
|
- fprintf(stderr, "SPTPS/UDP transmit for %lg seconds: ", duration);
|
||||||
|
+ rate *= 2 * 1451 * 8;
|
||||||
|
|
||||||
|
- for(clock_start(); clock_countto(duration);) {
|
||||||
|
- if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
|
||||||
|
- abort();
|
||||||
|
+ if(rate > 1e9) {
|
||||||
|
+ fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
|
||||||
|
+ } else if(rate > 1e6) {
|
||||||
|
+ fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
|
||||||
|
+ } else if(rate > 1e3) {
|
||||||
|
+ fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
|
||||||
|
}
|
||||||
|
|
||||||
|
- receive_data(&sptps2);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- rate *= 2 * 1451 * 8;
|
||||||
|
+ sptps_stop(&sptps1);
|
||||||
|
+ sptps_stop(&sptps2);
|
||||||
|
|
||||||
|
- if(rate > 1e9) {
|
||||||
|
- fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
|
||||||
|
- } else if(rate > 1e6) {
|
||||||
|
- fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
|
||||||
|
- } else if(rate > 1e3) {
|
||||||
|
- fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
|
||||||
|
+ close(fd[0]);
|
||||||
|
+ close(fd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sptps_stop(&sptps1);
|
||||||
|
- sptps_stop(&sptps2);
|
||||||
|
-
|
||||||
|
// Clean up
|
||||||
|
|
||||||
|
- close(fd[0]);
|
||||||
|
- close(fd[1]);
|
||||||
|
ecdsa_free(key1);
|
||||||
|
ecdsa_free(key2);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
219
debian/patches/alt-ciphersuite/0004-If-we-link-with-OpenSSL-use-it-for-Chacha20-Poly1305.patch
vendored
Normal file
219
debian/patches/alt-ciphersuite/0004-If-we-link-with-OpenSSL-use-it-for-Chacha20-Poly1305.patch
vendored
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
From 9d423c31024e37655aac014662cb5bee82c26464 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Mon, 9 Aug 2021 21:55:09 +0200
|
||||||
|
Subject: [PATCH 04/10] If we link with OpenSSL, use it for Chacha20-Poly1305
|
||||||
|
as well.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sptps.c | 128 ++++++++++++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 78 insertions(+), 50 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sptps.c b/src/sptps.c
|
||||||
|
index 33c41424..55b9e5ca 100644
|
||||||
|
--- a/src/sptps.c
|
||||||
|
+++ b/src/sptps.c
|
||||||
|
@@ -96,12 +96,26 @@ static void warning(sptps_t *s, const char *format, ...) {
|
||||||
|
|
||||||
|
static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_half) {
|
||||||
|
switch(suite) {
|
||||||
|
+#ifndef HAVE_OPENSSL
|
||||||
|
+
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
*ctx = chacha_poly1305_init();
|
||||||
|
return ctx && chacha_poly1305_set_key(*ctx, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0));
|
||||||
|
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ *ctx = EVP_CIPHER_CTX_new();
|
||||||
|
+
|
||||||
|
+ if(!ctx) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
|
||||||
|
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0), key);
|
||||||
|
+
|
||||||
|
case SPTPS_AES256_GCM:
|
||||||
|
-#ifdef HAVE_OPENSSL
|
||||||
|
*ctx = EVP_CIPHER_CTX_new();
|
||||||
|
|
||||||
|
if(!ctx) {
|
||||||
|
@@ -109,8 +123,8 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
|
||||||
|
}
|
||||||
|
|
||||||
|
return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
|
||||||
|
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 4, NULL)
|
||||||
|
- && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 32 : 0), key);
|
||||||
|
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 64 : 0), key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
@@ -120,12 +134,16 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
|
||||||
|
|
||||||
|
static void cipher_exit(uint8_t suite, void *ctx) {
|
||||||
|
switch(suite) {
|
||||||
|
+#ifndef HAVE_OPENSSL
|
||||||
|
+
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
chacha_poly1305_exit(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
case SPTPS_AES256_GCM:
|
||||||
|
-#ifdef HAVE_OPENSSL
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
@@ -136,43 +154,48 @@ static void cipher_exit(uint8_t suite, void *ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
|
||||||
|
+ uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
|
||||||
|
+
|
||||||
|
switch(suite) {
|
||||||
|
+#ifndef HAVE_OPENSSL
|
||||||
|
+
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
chacha_poly1305_encrypt(ctx, seqno, in, inlen, out, outlen);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
- case SPTPS_AES256_GCM:
|
||||||
|
-#ifdef HAVE_OPENSSL
|
||||||
|
- {
|
||||||
|
- if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+#else
|
||||||
|
|
||||||
|
- int outlen1 = 0, outlen2 = 0;
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ case SPTPS_AES256_GCM: {
|
||||||
|
+ if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ int outlen1 = 0, outlen2 = 0;
|
||||||
|
|
||||||
|
- if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- outlen1 += outlen2;
|
||||||
|
+ if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ outlen1 += outlen2;
|
||||||
|
|
||||||
|
- outlen1 += 16;
|
||||||
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(outlen) {
|
||||||
|
- *outlen = outlen1;
|
||||||
|
- }
|
||||||
|
+ outlen1 += 16;
|
||||||
|
|
||||||
|
- return true;
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
@@ -181,44 +204,49 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
|
||||||
|
+ uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
|
||||||
|
+
|
||||||
|
switch(suite) {
|
||||||
|
+#ifndef HAVE_OPENSSL
|
||||||
|
+
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
return chacha_poly1305_decrypt(ctx, seqno, in, inlen, out, outlen);
|
||||||
|
|
||||||
|
- case SPTPS_AES256_GCM:
|
||||||
|
-#ifdef HAVE_OPENSSL
|
||||||
|
- {
|
||||||
|
- if(inlen < 16) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+#else
|
||||||
|
|
||||||
|
- inlen -= 16;
|
||||||
|
+ case SPTPS_CHACHA_POLY1305:
|
||||||
|
+ case SPTPS_AES256_GCM: {
|
||||||
|
+ if(inlen < 16) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ inlen -= 16;
|
||||||
|
|
||||||
|
- int outlen1 = 0, outlen2 = 0;
|
||||||
|
+ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ int outlen1 = 0, outlen2 = 0;
|
||||||
|
|
||||||
|
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if(outlen) {
|
||||||
|
- *outlen = outlen1 + outlen2;
|
||||||
|
- }
|
||||||
|
+ if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- return true;
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1 + outlen2;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
1295
debian/patches/alt-ciphersuite/0005-Update-the-built-in-Chacha20-Poly1305-code-to-an-RFC.patch
vendored
Normal file
1295
debian/patches/alt-ciphersuite/0005-Update-the-built-in-Chacha20-Poly1305-code-to-an-RFC.patch
vendored
Normal file
File diff suppressed because it is too large
Load diff
117
debian/patches/alt-ciphersuite/0006-Ensure-we-are-compatible-with-LibreSSL.patch
vendored
Normal file
117
debian/patches/alt-ciphersuite/0006-Ensure-we-are-compatible-with-LibreSSL.patch
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
From d64b9c4a2f48ce7533e9f7a8f5f6e890764515ab Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Tue, 10 Aug 2021 23:08:04 +0200
|
||||||
|
Subject: [PATCH 06/10] Ensure we are compatible with LibreSSL.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sptps.c | 66 ++++++++++++++++++++++++++++++++++++++++++-----------
|
||||||
|
1 file changed, 53 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/sptps.c b/src/sptps.c
|
||||||
|
index 33e88ed9..7c8d20b7 100644
|
||||||
|
--- a/src/sptps.c
|
||||||
|
+++ b/src/sptps.c
|
||||||
|
@@ -107,26 +107,26 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
|
||||||
|
#else
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
- *ctx = EVP_CIPHER_CTX_new();
|
||||||
|
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
|
||||||
|
+ *ctx = malloc(sizeof(EVP_AEAD_CTX));
|
||||||
|
|
||||||
|
- if(!ctx) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
+ return *ctx && EVP_AEAD_CTX_init(*ctx, EVP_aead_chacha20_poly1305(), key + (key_half ? CIPHER_KEYLEN : 0), 32, 16, NULL);
|
||||||
|
+#else
|
||||||
|
+ *ctx = EVP_CIPHER_CTX_new();
|
||||||
|
|
||||||
|
- return EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
|
||||||
|
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
|
||||||
|
+ return *ctx
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
|
||||||
|
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL)
|
||||||
|
&& EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CIPHER_KEYLEN : 0), key);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
case SPTPS_AES256_GCM:
|
||||||
|
*ctx = EVP_CIPHER_CTX_new();
|
||||||
|
|
||||||
|
- if(!ctx) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
|
||||||
|
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
|
||||||
|
- && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 64 : 0), key);
|
||||||
|
+ return *ctx
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
|
||||||
|
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL)
|
||||||
|
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CIPHER_KEYLEN : 0), key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
@@ -145,6 +145,12 @@ static void cipher_exit(uint8_t suite, void *ctx) {
|
||||||
|
#else
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
|
||||||
|
+ EVP_AEAD_CTX_cleanup(ctx);
|
||||||
|
+ free(ctx);
|
||||||
|
+ break;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
case SPTPS_AES256_GCM:
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
break;
|
||||||
|
@@ -176,6 +182,23 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
|
||||||
|
#else
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
|
||||||
|
+ {
|
||||||
|
+ size_t outlen1;
|
||||||
|
+
|
||||||
|
+ if(!EVP_AEAD_CTX_seal(ctx, out, &outlen1, inlen + 16, nonce, sizeof(nonce), in, inlen, NULL, 0)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
case SPTPS_AES256_GCM: {
|
||||||
|
if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
|
||||||
|
return false;
|
||||||
|
@@ -239,6 +262,23 @@ static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
|
||||||
|
#else
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
|
||||||
|
+ {
|
||||||
|
+ size_t outlen1;
|
||||||
|
+
|
||||||
|
+ if(!EVP_AEAD_CTX_open(ctx, out, &outlen1, inlen, nonce, sizeof(nonce), in, inlen + 16, NULL, 0)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(outlen) {
|
||||||
|
+ *outlen = outlen1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
case SPTPS_AES256_GCM: {
|
||||||
|
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
|
||||||
|
return false;
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
26
debian/patches/alt-ciphersuite/0007-Fix-infinite-loop-on-SPTPS-errors-when-running-sptps.patch
vendored
Normal file
26
debian/patches/alt-ciphersuite/0007-Fix-infinite-loop-on-SPTPS-errors-when-running-sptps.patch
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
From 948be5b4a813e814e36be23a63817df283e8db91 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Tue, 10 Aug 2021 23:08:52 +0200
|
||||||
|
Subject: [PATCH 07/10] Fix infinite loop on SPTPS errors when running
|
||||||
|
sptps_test in datagram mode.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/sptps_test.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/sptps_test.c b/src/sptps_test.c
|
||||||
|
index 32ed62d3..7e5977ed 100644
|
||||||
|
--- a/src/sptps_test.c
|
||||||
|
+++ b/src/sptps_test.c
|
||||||
|
@@ -721,6 +721,8 @@ static int run_test(int argc, char *argv[]) {
|
||||||
|
free(mykey);
|
||||||
|
free(hiskey);
|
||||||
|
return 1;
|
||||||
|
+ } else {
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
40
debian/patches/alt-ciphersuite/0008-Fix-documentation-of-default-cipher-algorithm-used-f.patch
vendored
Normal file
40
debian/patches/alt-ciphersuite/0008-Fix-documentation-of-default-cipher-algorithm-used-f.patch
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
From 440bf1e9e484ac9800308dafbb5089e400df3522 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Sun, 22 Aug 2021 22:16:42 +0200
|
||||||
|
Subject: [PATCH 08/10] Fix documentation of default cipher algorithm used for
|
||||||
|
the legacy protocol.
|
||||||
|
|
||||||
|
---
|
||||||
|
doc/tinc.conf.5.in | 2 +-
|
||||||
|
doc/tinc.texi | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in
|
||||||
|
index d7aa7d99..0cfdd089 100644
|
||||||
|
--- a/doc/tinc.conf.5.in
|
||||||
|
+++ b/doc/tinc.conf.5.in
|
||||||
|
@@ -562,7 +562,7 @@ Multiple
|
||||||
|
.Va Address
|
||||||
|
variables can be specified, in which case each address will be tried until a working
|
||||||
|
connection has been established.
|
||||||
|
-.It Va Cipher Li = Ar cipher Pq blowfish
|
||||||
|
+.It Va Cipher Li = Ar cipher Pq aes-256-cbc
|
||||||
|
The symmetric cipher algorithm used to encrypt UDP packets.
|
||||||
|
Any cipher supported by LibreSSL or OpenSSL is recognised.
|
||||||
|
Furthermore, specifying
|
||||||
|
diff --git a/doc/tinc.texi b/doc/tinc.texi
|
||||||
|
index 2e519d1c..ab3dca23 100644
|
||||||
|
--- a/doc/tinc.texi
|
||||||
|
+++ b/doc/tinc.texi
|
||||||
|
@@ -1328,7 +1328,7 @@ Multiple Address variables can be specified, in which case each address will be
|
||||||
|
tried until a working connection has been established.
|
||||||
|
|
||||||
|
@cindex Cipher
|
||||||
|
-@item Cipher = <@var{cipher}> (blowfish)
|
||||||
|
+@item Cipher = <@var{cipher}> (aes-256-cbc)
|
||||||
|
The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol.
|
||||||
|
Any cipher supported by LibreSSL or OpenSSL is recognized.
|
||||||
|
Furthermore, specifying @samp{none} will turn off packet encryption.
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
230
debian/patches/alt-ciphersuite/0009-Make-the-ExperimentalProtocol-option-obsolete.patch
vendored
Normal file
230
debian/patches/alt-ciphersuite/0009-Make-the-ExperimentalProtocol-option-obsolete.patch
vendored
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
From 4e64f72feb99b7933e907fb0fab93368749db779 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Sun, 22 Aug 2021 22:44:04 +0200
|
||||||
|
Subject: [PATCH 09/10] Make the ExperimentalProtocol option obsolete.
|
||||||
|
|
||||||
|
Remove mentions of it from the documentation, but keep supporting the
|
||||||
|
option for now, as this makes it easier to test compatibility with the
|
||||||
|
legacy protocol.
|
||||||
|
---
|
||||||
|
README.md | 8 ++++----
|
||||||
|
doc/tinc.conf.5.in | 18 +++---------------
|
||||||
|
doc/tinc.texi | 21 ++++++---------------
|
||||||
|
src/tincctl.c | 2 +-
|
||||||
|
test/integration/algorithms.py | 4 ++--
|
||||||
|
test/integration/legacy_protocol.py | 4 ++--
|
||||||
|
test/integration/splice.py | 4 ++--
|
||||||
|
7 files changed, 20 insertions(+), 41 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/README.md b/README.md
|
||||||
|
index 11129f79..9e3a64a4 100644
|
||||||
|
--- a/README.md
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -55,12 +55,12 @@ versions, the security might only be as good as that of the oldest version.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
-Version 1.1pre18 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||||
|
+Version 1.1pre18 is compatible with 1.0 and later, but not with older
|
||||||
|
versions of tinc.
|
||||||
|
|
||||||
|
-When the ExperimentalProtocol option is used, tinc is still compatible with
|
||||||
|
-1.0.X, 1.1pre11 and later, but not with any version between 1.1pre1 and
|
||||||
|
-1.1pre10.
|
||||||
|
+Note that this pre-release version of tinc 1.1 might be incompatible with older
|
||||||
|
+pre-release versions as the new cryptographic protocol might still undergo
|
||||||
|
+changes.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in
|
||||||
|
index 0cfdd089..a5a56ed5 100644
|
||||||
|
--- a/doc/tinc.conf.5.in
|
||||||
|
+++ b/doc/tinc.conf.5.in
|
||||||
|
@@ -287,15 +287,6 @@ When combined with the IndirectData option,
|
||||||
|
packets for nodes for which we do not have a meta connection with are also dropped.
|
||||||
|
.It Va Ed25519PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ed25519_key.priv Pc
|
||||||
|
The file in which the private Ed25519 key of this tinc daemon resides.
|
||||||
|
-This is only used if
|
||||||
|
-.Va ExperimentalProtocol
|
||||||
|
-is enabled.
|
||||||
|
-.It Va ExperimentalProtocol Li = yes | no Pq yes
|
||||||
|
-When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
|
||||||
|
-Ephemeral ECDH will be used for key exchanges,
|
||||||
|
-and Ed25519 will be used instead of RSA for authentication.
|
||||||
|
-When enabled, an Ed25519 key must have been generated before with
|
||||||
|
-.Nm tinc generate-ed25519-keys .
|
||||||
|
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
|
||||||
|
This option selects the way indirect packets are forwarded.
|
||||||
|
.Bl -tag -width indent
|
||||||
|
@@ -569,8 +560,7 @@ Furthermore, specifying
|
||||||
|
.Qq none
|
||||||
|
will turn off packet encryption.
|
||||||
|
It is best to use only those ciphers which support CBC mode.
|
||||||
|
-This option has no effect for connections between nodes using
|
||||||
|
-.Va ExperimentalProtocol .
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
.It Va ClampMSS Li = yes | no Pq yes
|
||||||
|
This option specifies whether tinc should clamp the maximum segment size (MSS)
|
||||||
|
of TCP packets to the path MTU. This helps in situations where ICMP
|
||||||
|
@@ -585,8 +575,7 @@ Any digest supported by LibreSSL or OpenSSL is recognised.
|
||||||
|
Furthermore, specifying
|
||||||
|
.Qq none
|
||||||
|
will turn off packet authentication.
|
||||||
|
-This option has no effect for connections between nodes using
|
||||||
|
-.Va ExperimentalProtocol .
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
.It Va IndirectData Li = yes | no Pq no
|
||||||
|
When set to yes, only nodes which already have a meta connection to you
|
||||||
|
will try to establish direct communication with you.
|
||||||
|
@@ -596,8 +585,7 @@ The length of the message authentication code used to authenticate UDP packets.
|
||||||
|
Can be anything from
|
||||||
|
.Qq 0
|
||||||
|
up to the length of the digest produced by the digest algorithm.
|
||||||
|
-This option has no effect for connections between nodes using
|
||||||
|
-.Va ExperimentalProtocol .
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
.It Va PMTU Li = Ar mtu Po 1514 Pc
|
||||||
|
This option controls the initial path MTU to this node.
|
||||||
|
.It Va PMTUDiscovery Li = yes | no Po yes Pc
|
||||||
|
diff --git a/doc/tinc.texi b/doc/tinc.texi
|
||||||
|
index ab3dca23..c1e62a52 100644
|
||||||
|
--- a/doc/tinc.texi
|
||||||
|
+++ b/doc/tinc.texi
|
||||||
|
@@ -1025,15 +1025,6 @@ packets for nodes for which we do not have a meta connection with are also dropp
|
||||||
|
@cindex Ed25519PrivateKeyFile
|
||||||
|
@item Ed25519PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ed25519_key.priv})
|
||||||
|
The file in which the private Ed25519 key of this tinc daemon resides.
|
||||||
|
-This is only used if ExperimentalProtocol is enabled.
|
||||||
|
-
|
||||||
|
-@cindex ExperimentalProtocol
|
||||||
|
-@item ExperimentalProtocol = <yes|no> (yes)
|
||||||
|
-When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
|
||||||
|
-Ephemeral ECDH will be used for key exchanges,
|
||||||
|
-and Ed25519 will be used instead of RSA for authentication.
|
||||||
|
-When enabled, an Ed25519 key must have been generated before with
|
||||||
|
-@command{tinc generate-ed25519-keys}.
|
||||||
|
|
||||||
|
@cindex Forwarding
|
||||||
|
@item Forwarding = <off|internal|kernel> (internal) [experimental]
|
||||||
|
@@ -1333,7 +1324,7 @@ The symmetric cipher algorithm used to encrypt UDP packets using the legacy prot
|
||||||
|
Any cipher supported by LibreSSL or OpenSSL is recognized.
|
||||||
|
Furthermore, specifying @samp{none} will turn off packet encryption.
|
||||||
|
It is best to use only those ciphers which support CBC mode.
|
||||||
|
-This option has no effect for connections using the SPTPS protocol, which always use AES-256-CTR.
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
|
||||||
|
@cindex ClampMSS
|
||||||
|
@item ClampMSS = <yes|no> (yes)
|
||||||
|
@@ -1352,7 +1343,7 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
|
||||||
|
The digest algorithm used to authenticate UDP packets using the legacy protocol.
|
||||||
|
Any digest supported by LibreSSL or OpenSSL is recognized.
|
||||||
|
Furthermore, specifying @samp{none} will turn off packet authentication.
|
||||||
|
-This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256.
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
|
||||||
|
@cindex IndirectData
|
||||||
|
@item IndirectData = <yes|no> (no)
|
||||||
|
@@ -1365,7 +1356,7 @@ It is best to leave this option out or set it to no.
|
||||||
|
The length of the message authentication code used to authenticate UDP packets using the legacy protocol.
|
||||||
|
Can be anything from 0
|
||||||
|
up to the length of the digest produced by the digest algorithm.
|
||||||
|
-This option has no effect for connections using the SPTPS protocol, which never truncate MACs.
|
||||||
|
+This option only affects communication using the legacy protocol.
|
||||||
|
|
||||||
|
@cindex PMTU
|
||||||
|
@item PMTU = <@var{mtu}> (1514)
|
||||||
|
@@ -3030,9 +3021,9 @@ Therefore, tinc also authenticates the data.
|
||||||
|
Finally, tinc uses sequence numbers (which themselves are also authenticated) to prevent an attacker from replaying valid packets.
|
||||||
|
|
||||||
|
Since version 1.1pre3, tinc has two protocols used to protect your data; the legacy protocol, and the new Simple Peer-to-Peer Security (SPTPS) protocol.
|
||||||
|
-The SPTPS protocol is designed to address some weaknesses in the legacy protocol.
|
||||||
|
-The new authentication protocol is used when two nodes connect to each other that both have the ExperimentalProtocol option set to yes,
|
||||||
|
-otherwise the legacy protocol will be used.
|
||||||
|
+The SPTPS protocol is designed to address some weaknesses in the legacy protocol,
|
||||||
|
+and is used automatically if both sides support it.
|
||||||
|
+Once two nodes have connected with the new protocol, rollback to the legacy protocol is not allowed.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Legacy authentication protocol::
|
||||||
|
diff --git a/src/tincctl.c b/src/tincctl.c
|
||||||
|
index 9b39f2ce..2032b33a 100644
|
||||||
|
--- a/src/tincctl.c
|
||||||
|
+++ b/src/tincctl.c
|
||||||
|
@@ -1651,7 +1651,7 @@ const var_t variables[] = {
|
||||||
|
{"DeviceType", VAR_SERVER},
|
||||||
|
{"DirectOnly", VAR_SERVER | VAR_SAFE},
|
||||||
|
{"Ed25519PrivateKeyFile", VAR_SERVER},
|
||||||
|
- {"ExperimentalProtocol", VAR_SERVER},
|
||||||
|
+ {"ExperimentalProtocol", VAR_SERVER | VAR_OBSOLETE},
|
||||||
|
{"Forwarding", VAR_SERVER},
|
||||||
|
{"FWMark", VAR_SERVER},
|
||||||
|
{"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
|
||||||
|
diff --git a/test/integration/algorithms.py b/test/integration/algorithms.py
|
||||||
|
index b056c7d5..52e0f820 100755
|
||||||
|
--- a/test/integration/algorithms.py
|
||||||
|
+++ b/test/integration/algorithms.py
|
||||||
|
@@ -23,7 +23,7 @@ def init(ctx: Test, digest: str, cipher: str) -> T.Tuple[Tinc, Tinc]:
|
||||||
|
set Digest {digest}
|
||||||
|
set Cipher {cipher}
|
||||||
|
"""
|
||||||
|
- foo.cmd(stdin=stdin)
|
||||||
|
+ foo.cmd("--force", stdin=stdin)
|
||||||
|
foo.start()
|
||||||
|
|
||||||
|
stdin = f"""
|
||||||
|
@@ -35,7 +35,7 @@ def init(ctx: Test, digest: str, cipher: str) -> T.Tuple[Tinc, Tinc]:
|
||||||
|
set Digest {digest}
|
||||||
|
set Cipher {cipher}
|
||||||
|
"""
|
||||||
|
- bar.cmd(stdin=stdin)
|
||||||
|
+ bar.cmd("--force", stdin=stdin)
|
||||||
|
|
||||||
|
foo.add_script(bar.script_up)
|
||||||
|
bar.add_script(foo.script_up)
|
||||||
|
diff --git a/test/integration/legacy_protocol.py b/test/integration/legacy_protocol.py
|
||||||
|
index 845ac345..f7ab1bd2 100755
|
||||||
|
--- a/test/integration/legacy_protocol.py
|
||||||
|
+++ b/test/integration/legacy_protocol.py
|
||||||
|
@@ -73,14 +73,14 @@ with Test("foo 1.1, bar 1.1") as context:
|
||||||
|
|
||||||
|
with Test("foo 1.1, bar 1.0") as context:
|
||||||
|
foo_node, bar_node = init(context)
|
||||||
|
- bar_node.cmd("set", "ExperimentalProtocol", "no")
|
||||||
|
+ bar_node.cmd("--force", "set", "ExperimentalProtocol", "no")
|
||||||
|
foo_node.cmd("del", f"{bar_node}.Ed25519PublicKey")
|
||||||
|
bar_node.cmd("del", f"{foo_node}.Ed25519PublicKey")
|
||||||
|
run_keys_test(foo_node, bar_node, empty=True)
|
||||||
|
|
||||||
|
with Test("bar 1.0 must not be allowed to connect") as context:
|
||||||
|
foo_node, bar_node = init(context)
|
||||||
|
- bar_node.cmd("set", "ExperimentalProtocol", "no")
|
||||||
|
+ bar_node.cmd("--force", "set", "ExperimentalProtocol", "no")
|
||||||
|
|
||||||
|
bar_up = bar_node.add_script(Script.SUBNET_UP)
|
||||||
|
bar_node.cmd("start")
|
||||||
|
diff --git a/test/integration/splice.py b/test/integration/splice.py
|
||||||
|
index 578845fb..868ffbc3 100755
|
||||||
|
--- a/test/integration/splice.py
|
||||||
|
+++ b/test/integration/splice.py
|
||||||
|
@@ -28,7 +28,7 @@ def init(ctx: Test, *options: str) -> T.Tuple[Tinc, Tinc]:
|
||||||
|
set Subnet 10.96.96.1
|
||||||
|
{custom}
|
||||||
|
"""
|
||||||
|
- foo.cmd(stdin=stdin)
|
||||||
|
+ foo.cmd("--force", stdin=stdin)
|
||||||
|
|
||||||
|
stdin = f"""
|
||||||
|
init {bar}
|
||||||
|
@@ -39,7 +39,7 @@ def init(ctx: Test, *options: str) -> T.Tuple[Tinc, Tinc]:
|
||||||
|
set Subnet 10.96.96.2
|
||||||
|
{custom}
|
||||||
|
"""
|
||||||
|
- bar.cmd(stdin=stdin)
|
||||||
|
+ bar.cmd("--force", stdin=stdin)
|
||||||
|
|
||||||
|
foo.add_script(Script.SUBNET_UP)
|
||||||
|
bar.add_script(Script.SUBNET_UP)
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
322
debian/patches/alt-ciphersuite/0010-Move-poly1305_get_tag-into-poly1305.c-hide-poly1305_.patch
vendored
Normal file
322
debian/patches/alt-ciphersuite/0010-Move-poly1305_get_tag-into-poly1305.c-hide-poly1305_.patch
vendored
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
From f4db140a8ffc63b575181299c3964e4634606280 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
Date: Tue, 31 Aug 2021 16:27:47 +0200
|
||||||
|
Subject: [PATCH 10/10] Move poly1305_get_tag() into poly1305.c, hide
|
||||||
|
poly1305_init().
|
||||||
|
|
||||||
|
The crypto library on Windows exposes a symbol named poly1305_init(),
|
||||||
|
which clashes with ours. We can avoid this by moving poly1305_get_tag()
|
||||||
|
to poly1305.[ch], where it belongs better, and this allows us to make
|
||||||
|
all the lower-level Poly1305 functions static.
|
||||||
|
|
||||||
|
Also remove the support for associated data while we are at it, since we
|
||||||
|
are never using it.
|
||||||
|
---
|
||||||
|
src/chacha-poly1305/chacha.h | 1 -
|
||||||
|
src/chacha-poly1305/chachapoly.c | 58 ++++----------------------------
|
||||||
|
src/chacha-poly1305/chachapoly.h | 6 ++--
|
||||||
|
src/chacha-poly1305/poly1305.c | 54 +++++++++++++++++++++++++----
|
||||||
|
src/chacha-poly1305/poly1305.h | 20 +----------
|
||||||
|
src/sptps.c | 4 +--
|
||||||
|
6 files changed, 58 insertions(+), 85 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/chacha-poly1305/chacha.h b/src/chacha-poly1305/chacha.h
|
||||||
|
index a137ab6b..d4784f49 100644
|
||||||
|
--- a/src/chacha-poly1305/chacha.h
|
||||||
|
+++ b/src/chacha-poly1305/chacha.h
|
||||||
|
@@ -31,4 +31,3 @@ void chacha_encrypt_bytes(struct chacha_ctx *x, const unsigned char *m,
|
||||||
|
unsigned char *c, uint32_t bytes);
|
||||||
|
|
||||||
|
#endif /* CHACHA_H */
|
||||||
|
-
|
||||||
|
diff --git a/src/chacha-poly1305/chachapoly.c b/src/chacha-poly1305/chachapoly.c
|
||||||
|
index 9a6620ce..68f04edd 100644
|
||||||
|
--- a/src/chacha-poly1305/chachapoly.c
|
||||||
|
+++ b/src/chacha-poly1305/chachapoly.c
|
||||||
|
@@ -53,52 +53,6 @@ static int memcmp_eq(const void *av, const void *bv, int n) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/**
|
||||||
|
- * Poly1305 tag generation. This concatenates a string according to the rules
|
||||||
|
- * outlined in RFC 7539 and calculates the tag.
|
||||||
|
- *
|
||||||
|
- * \param poly_key 32 byte secret one-time key for poly1305
|
||||||
|
- * \param ad associated data
|
||||||
|
- * \param ad_len associated data length in bytes
|
||||||
|
- * \param ct ciphertext
|
||||||
|
- * \param ct_len ciphertext length in bytes
|
||||||
|
- * \param tag pointer to 16 bytes for tag storage
|
||||||
|
- */
|
||||||
|
-static void poly1305_get_tag(unsigned char *poly_key, const void *ad,
|
||||||
|
- int ad_len, const void *ct, int ct_len, unsigned char *tag) {
|
||||||
|
- struct poly1305_context poly;
|
||||||
|
- unsigned left_over;
|
||||||
|
- uint64_t len;
|
||||||
|
- unsigned char pad[16];
|
||||||
|
-
|
||||||
|
- poly1305_init(&poly, poly_key);
|
||||||
|
- memset(&pad, 0, sizeof(pad));
|
||||||
|
-
|
||||||
|
- /* associated data and padding */
|
||||||
|
- poly1305_update(&poly, ad, ad_len);
|
||||||
|
- left_over = ad_len % 16;
|
||||||
|
-
|
||||||
|
- if(left_over) {
|
||||||
|
- poly1305_update(&poly, pad, 16 - left_over);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* payload and padding */
|
||||||
|
- poly1305_update(&poly, ct, ct_len);
|
||||||
|
- left_over = ct_len % 16;
|
||||||
|
-
|
||||||
|
- if(left_over) {
|
||||||
|
- poly1305_update(&poly, pad, 16 - left_over);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* lengths */
|
||||||
|
- len = ad_len;
|
||||||
|
- poly1305_update(&poly, (unsigned char *)&len, 8);
|
||||||
|
- len = ct_len;
|
||||||
|
- poly1305_update(&poly, (unsigned char *)&len, 8);
|
||||||
|
-
|
||||||
|
- poly1305_finish(&poly, tag);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len) {
|
||||||
|
assert(key_len == 128 || key_len == 256);
|
||||||
|
|
||||||
|
@@ -108,7 +62,7 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
- const void *ad, int ad_len, void *input, int input_len,
|
||||||
|
+ void *input, int input_len,
|
||||||
|
void *output, void *tag, int tag_len, int encrypt) {
|
||||||
|
unsigned char poly_key[CHACHA_BLOCKLEN];
|
||||||
|
unsigned char calc_tag[POLY1305_TAGLEN];
|
||||||
|
@@ -121,7 +75,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
|
||||||
|
/* check tag if decrypting */
|
||||||
|
if(encrypt == 0 && tag_len) {
|
||||||
|
- poly1305_get_tag(poly_key, ad, ad_len, input, input_len, calc_tag);
|
||||||
|
+ poly1305_get_tag(poly_key, input, input_len, calc_tag);
|
||||||
|
|
||||||
|
if(memcmp_eq(calc_tag, tag, tag_len) != 0) {
|
||||||
|
return CHACHAPOLY_INVALID_MAC;
|
||||||
|
@@ -135,7 +89,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
|
||||||
|
/* add tag if encrypting */
|
||||||
|
if(encrypt && tag_len) {
|
||||||
|
- poly1305_get_tag(poly_key, ad, ad_len, output, input_len, calc_tag);
|
||||||
|
+ poly1305_get_tag(poly_key, output, input_len, calc_tag);
|
||||||
|
memcpy(tag, calc_tag, tag_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -143,7 +97,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
}
|
||||||
|
|
||||||
|
int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
- const void *ad, int ad_len, void *input, int input_len,
|
||||||
|
+ void *input, int input_len,
|
||||||
|
void *output, void *tag, int tag_len, int encrypt) {
|
||||||
|
unsigned char keystream[CHACHA_BLOCKLEN];
|
||||||
|
unsigned char calc_tag[POLY1305_TAGLEN];
|
||||||
|
@@ -159,7 +113,7 @@ int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
|
||||||
|
/* check tag if decrypting */
|
||||||
|
if(encrypt == 0 && tag_len) {
|
||||||
|
- poly1305_get_tag(keystream, ad, ad_len, input, input_len, calc_tag);
|
||||||
|
+ poly1305_get_tag(keystream, input, input_len, calc_tag);
|
||||||
|
|
||||||
|
if(memcmp_eq(calc_tag, tag, tag_len) != 0) {
|
||||||
|
return CHACHAPOLY_INVALID_MAC;
|
||||||
|
@@ -174,7 +128,7 @@ int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
|
||||||
|
/* add tag if encrypting */
|
||||||
|
if(encrypt && tag_len) {
|
||||||
|
- poly1305_get_tag(keystream, ad, ad_len, output, input_len, calc_tag);
|
||||||
|
+ poly1305_get_tag(keystream, output, input_len, calc_tag);
|
||||||
|
memcpy(tag, calc_tag, tag_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/chacha-poly1305/chachapoly.h b/src/chacha-poly1305/chachapoly.h
|
||||||
|
index ffc9576d..5d01f525 100644
|
||||||
|
--- a/src/chacha-poly1305/chachapoly.h
|
||||||
|
+++ b/src/chacha-poly1305/chachapoly.h
|
||||||
|
@@ -52,8 +52,6 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len);
|
||||||
|
*
|
||||||
|
* \param ctx context data
|
||||||
|
* \param nonce nonce (12 bytes)
|
||||||
|
- * \param ad associated data
|
||||||
|
- * \param ad_len associated data length in bytes
|
||||||
|
* \param input plaintext/ciphertext input
|
||||||
|
* \param input_len input length in bytes;
|
||||||
|
* \param output plaintext/ciphertext output
|
||||||
|
@@ -65,7 +63,7 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len);
|
||||||
|
* failed when decrypting
|
||||||
|
*/
|
||||||
|
int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
- const void *ad, int ad_len, void *input, int input_len,
|
||||||
|
+ void *input, int input_len,
|
||||||
|
void *output, void *tag, int tag_len, int encrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -76,7 +74,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
* chachapoly_crypt.
|
||||||
|
*/
|
||||||
|
int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
|
||||||
|
- const void *ad, int ad_len, void *input, int input_len,
|
||||||
|
+ void *input, int input_len,
|
||||||
|
void *output, void *tag, int tag_len, int encrypt);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/src/chacha-poly1305/poly1305.c b/src/chacha-poly1305/poly1305.c
|
||||||
|
index 0c90564c..b25435a7 100644
|
||||||
|
--- a/src/chacha-poly1305/poly1305.c
|
||||||
|
+++ b/src/chacha-poly1305/poly1305.c
|
||||||
|
@@ -5,6 +5,20 @@ public domain
|
||||||
|
|
||||||
|
#include "poly1305.h"
|
||||||
|
|
||||||
|
+/* use memcpy() to copy blocks of memory (typically faster) */
|
||||||
|
+#define USE_MEMCPY 1
|
||||||
|
+/* use unaligned little-endian load/store (can be faster) */
|
||||||
|
+#define USE_UNALIGNED 0
|
||||||
|
+
|
||||||
|
+struct poly1305_context {
|
||||||
|
+ uint32_t r[5];
|
||||||
|
+ uint32_t h[5];
|
||||||
|
+ uint32_t pad[4];
|
||||||
|
+ size_t leftover;
|
||||||
|
+ unsigned char buffer[POLY1305_BLOCK_SIZE];
|
||||||
|
+ unsigned char final;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#if (USE_UNALIGNED == 1)
|
||||||
|
#define U8TO32(p) \
|
||||||
|
(*((uint32_t *)(p)))
|
||||||
|
@@ -33,7 +47,7 @@ U32TO8(unsigned char *p, uint32_t v) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-void
|
||||||
|
+static void
|
||||||
|
poly1305_init(struct poly1305_context *st, const unsigned char key[32]) {
|
||||||
|
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||||
|
st->r[0] = (U8TO32(&key[ 0])) & 0x3ffffff;
|
||||||
|
@@ -131,7 +145,7 @@ poly1305_blocks(struct poly1305_context *st, const unsigned char *m, size_t byte
|
||||||
|
st->h[4] = h4;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void
|
||||||
|
+static void
|
||||||
|
poly1305_finish(struct poly1305_context *st, unsigned char mac[16]) {
|
||||||
|
uint32_t h0, h1, h2, h3, h4, c;
|
||||||
|
uint32_t g0, g1, g2, g3, g4;
|
||||||
|
@@ -241,8 +255,7 @@ poly1305_finish(struct poly1305_context *st, unsigned char mac[16]) {
|
||||||
|
st->pad[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
-void
|
||||||
|
+static void
|
||||||
|
poly1305_update(struct poly1305_context *st, const unsigned char *m, size_t bytes) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
@@ -293,10 +306,37 @@ poly1305_update(struct poly1305_context *st, const unsigned char *m, size_t byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * Poly1305 tag generation. This concatenates a string according to the rules
|
||||||
|
+ * outlined in RFC 7539 and calculates the tag.
|
||||||
|
+ *
|
||||||
|
+ * \param key 32 byte secret one-time key for poly1305
|
||||||
|
+ * \param ct ciphertext
|
||||||
|
+ * \param ct_len ciphertext length in bytes
|
||||||
|
+ * \param tag pointer to 16 bytes for tag storage
|
||||||
|
+ */
|
||||||
|
void
|
||||||
|
-poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]) {
|
||||||
|
+poly1305_get_tag(const unsigned char key[32], const void *ct, int ct_len, unsigned char tag[16]) {
|
||||||
|
struct poly1305_context ctx;
|
||||||
|
+ unsigned left_over;
|
||||||
|
+ uint64_t len;
|
||||||
|
+ unsigned char pad[16];
|
||||||
|
+
|
||||||
|
poly1305_init(&ctx, key);
|
||||||
|
- poly1305_update(&ctx, m, bytes);
|
||||||
|
- poly1305_finish(&ctx, mac);
|
||||||
|
+ memset(&pad, 0, sizeof(pad));
|
||||||
|
+
|
||||||
|
+ /* payload and padding */
|
||||||
|
+ poly1305_update(&ctx, ct, ct_len);
|
||||||
|
+ left_over = ct_len % 16;
|
||||||
|
+
|
||||||
|
+ if(left_over) {
|
||||||
|
+ poly1305_update(&ctx, pad, 16 - left_over);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* lengths */
|
||||||
|
+ len = 0;
|
||||||
|
+ poly1305_update(&ctx, (unsigned char *)&len, 8);
|
||||||
|
+ len = ct_len;
|
||||||
|
+ poly1305_update(&ctx, (unsigned char *)&len, 8);
|
||||||
|
+ poly1305_finish(&ctx, tag);
|
||||||
|
}
|
||||||
|
diff --git a/src/chacha-poly1305/poly1305.h b/src/chacha-poly1305/poly1305.h
|
||||||
|
index 624a19a9..5fc3b903 100644
|
||||||
|
--- a/src/chacha-poly1305/poly1305.h
|
||||||
|
+++ b/src/chacha-poly1305/poly1305.h
|
||||||
|
@@ -9,24 +9,6 @@
|
||||||
|
#define POLY1305_TAGLEN 16
|
||||||
|
#define POLY1305_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
-/* use memcpy() to copy blocks of memory (typically faster) */
|
||||||
|
-#define USE_MEMCPY 1
|
||||||
|
-/* use unaligned little-endian load/store (can be faster) */
|
||||||
|
-#define USE_UNALIGNED 0
|
||||||
|
-
|
||||||
|
-struct poly1305_context {
|
||||||
|
- uint32_t r[5];
|
||||||
|
- uint32_t h[5];
|
||||||
|
- uint32_t pad[4];
|
||||||
|
- size_t leftover;
|
||||||
|
- unsigned char buffer[POLY1305_BLOCK_SIZE];
|
||||||
|
- unsigned char final;
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-void poly1305_init(struct poly1305_context *ctx, const unsigned char key[32]);
|
||||||
|
-void poly1305_update(struct poly1305_context *ctx, const unsigned char *m, size_t bytes);
|
||||||
|
-void poly1305_finish(struct poly1305_context *ctx, unsigned char mac[16]);
|
||||||
|
-void poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]);
|
||||||
|
+void poly1305_get_tag(const unsigned char key[32], const void *ct, int ct_len, unsigned char tag[16]);
|
||||||
|
|
||||||
|
#endif /* POLY1305_H */
|
||||||
|
-
|
||||||
|
diff --git a/src/sptps.c b/src/sptps.c
|
||||||
|
index 7c8d20b7..8f713fe6 100644
|
||||||
|
--- a/src/sptps.c
|
||||||
|
+++ b/src/sptps.c
|
||||||
|
@@ -168,7 +168,7 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
|
||||||
|
#ifndef HAVE_OPENSSL
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305: {
|
||||||
|
- if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) {
|
||||||
|
+ if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -249,7 +249,7 @@ static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
|
||||||
|
#ifndef HAVE_OPENSSL
|
||||||
|
|
||||||
|
case SPTPS_CHACHA_POLY1305:
|
||||||
|
- if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) {
|
||||||
|
+ if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.36.0
|
||||||
|
|
10
debian/patches/series
vendored
10
debian/patches/series
vendored
|
@ -1 +1,11 @@
|
||||||
|
alt-ciphersuite/0001-Add-AES-256-GCM-support-to-SPTPS.patch
|
||||||
|
alt-ciphersuite/0002-Add-cipher-suite-selection-options-to-sptps_test.patch
|
||||||
|
alt-ciphersuite/0003-Let-sptps_speed-benchmark-all-cipher-suites.patch
|
||||||
|
alt-ciphersuite/0004-If-we-link-with-OpenSSL-use-it-for-Chacha20-Poly1305.patch
|
||||||
|
alt-ciphersuite/0005-Update-the-built-in-Chacha20-Poly1305-code-to-an-RFC.patch
|
||||||
|
alt-ciphersuite/0006-Ensure-we-are-compatible-with-LibreSSL.patch
|
||||||
|
alt-ciphersuite/0007-Fix-infinite-loop-on-SPTPS-errors-when-running-sptps.patch
|
||||||
|
alt-ciphersuite/0008-Fix-documentation-of-default-cipher-algorithm-used-f.patch
|
||||||
|
alt-ciphersuite/0009-Make-the-ExperimentalProtocol-option-obsolete.patch
|
||||||
|
alt-ciphersuite/0010-Move-poly1305_get_tag-into-poly1305.c-hide-poly1305_.patch
|
||||||
fix-version-number
|
fix-version-number
|
||||||
|
|
Loading…
Reference in a new issue