All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tls: Implement the RFC 7919 Supported Groups extension
@ 2019-01-08 23:25 Andrew Zaborowski
  2019-01-09 17:49 ` Denis Kenzior
  0 siblings, 1 reply; 2+ messages in thread
From: Andrew Zaborowski @ 2019-01-08 23:25 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 41830 bytes --]

For ECDHE (RFC 8422) we implemented the Supported Elliptic Curves
extension which was later renamed Supported Groups in RFC 7919 and
extended to be used for negotiating FF groups for DHE too.  This change
is acknowledged in RFC 8422 too.  This fixes some problems with the DHE
key exchange in TLS although it seems like it may have been released
too late to get TLS users to re-enable DHE when ECDHE is widely
supported and had the group negotiation specified in a way free of
the issues in DHE.  RFC 7919 is only supported by few https servers
(all wikipedia servers as far as I could tell)
---
 ell/tls-extensions.c | 515 +++++++++++++++++++++++++++++++++++++++++--
 ell/tls-private.h    |  29 ++-
 ell/tls-suites.c     | 101 +++------
 ell/tls.c            |  14 ++
 4 files changed, 568 insertions(+), 91 deletions(-)

diff --git a/ell/tls-extensions.c b/ell/tls-extensions.c
index be2fa10..6769948 100644
--- a/ell/tls-extensions.c
+++ b/ell/tls-extensions.c
@@ -31,26 +31,385 @@
 #include "cert.h"
 #include "tls-private.h"
 
-static const struct tls_named_curve tls_curve_pref[] = {
-	{ "secp256r1", 23, 19, 64 },
-	{ "secp384r1", 24, 20, 96 },
+/* RFC 7919, Section A.1 */
+static const uint8_t tls_ffdhe2048_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x28, 0x5c, 0x97, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
 };
 
-/* RFC 8422, Section 5.1 */
+/* RFC 7919, Section A.2 */
+static const uint8_t tls_ffdhe3072_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0xc6, 0x2e, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.3 */
+static const uint8_t tls_ffdhe4096_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x65, 0x5f, 0x6a,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.4 */
+static const uint8_t tls_ffdhe6144_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02,
+	0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03, 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c,
+	0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca, 0xf5, 0x3e, 0xa6,
+	0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
+	0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a,
+	0xcd, 0xad, 0x06, 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e,
+	0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81, 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77,
+	0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8, 0x55, 0x32, 0x2e,
+	0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
+	0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c,
+	0x18, 0x30, 0x23, 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4,
+	0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2, 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e,
+	0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a, 0x28, 0x1b, 0xf6,
+	0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
+	0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c,
+	0xd7, 0x2b, 0x03, 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31,
+	0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d, 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a,
+	0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c, 0xcf, 0x2d, 0xd5,
+	0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
+	0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e,
+	0x9a, 0xdb, 0x1e, 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1,
+	0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38, 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c,
+	0xd0, 0xe4, 0x0e, 0x65, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 7919, Section A.5 */
+static const uint8_t tls_ffdhe8192_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58,
+	0xa2, 0xbb, 0x4a, 0x9a, 0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1,
+	0xd8, 0xb9, 0xc5, 0x83, 0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41,
+	0x14, 0x64, 0x33, 0xfb, 0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9,
+	0x7d, 0x2f, 0xe3, 0x63, 0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02,
+	0xae, 0xc4, 0x61, 0x7a, 0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61,
+	0x24, 0x33, 0xf5, 0x1f, 0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55,
+	0x3d, 0xed, 0x1a, 0xf3, 0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35,
+	0x98, 0x4f, 0x0c, 0x70, 0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda,
+	0xf3, 0xef, 0xe8, 0x72, 0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35,
+	0x30, 0xac, 0xca, 0x4f, 0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82,
+	0xb3, 0x24, 0xfb, 0x61, 0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb,
+	0xb9, 0x6a, 0xda, 0xb7, 0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3,
+	0xde, 0x39, 0x4d, 0xf4, 0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19,
+	0x0b, 0x07, 0xa7, 0xc8, 0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1,
+	0xcd, 0xf7, 0xe2, 0xec, 0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61,
+	0x91, 0x72, 0xfe, 0x9c, 0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32,
+	0xee, 0xf2, 0x81, 0x83, 0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73,
+	0x3b, 0xb5, 0xfc, 0xbc, 0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83,
+	0x7d, 0x16, 0x83, 0xb2, 0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa,
+	0x88, 0x6b, 0x42, 0x38, 0x61, 0x1f, 0xcf, 0xdc, 0xde, 0x35, 0x5b, 0x3b,
+	0x65, 0x19, 0x03, 0x5b, 0xbc, 0x34, 0xf4, 0xde, 0xf9, 0x9c, 0x02, 0x38,
+	0x61, 0xb4, 0x6f, 0xc9, 0xd6, 0xe6, 0xc9, 0x07, 0x7a, 0xd9, 0x1d, 0x26,
+	0x91, 0xf7, 0xf7, 0xee, 0x59, 0x8c, 0xb0, 0xfa, 0xc1, 0x86, 0xd9, 0x1c,
+	0xae, 0xfe, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xb4, 0x13, 0x0c, 0x93,
+	0xbc, 0x43, 0x79, 0x44, 0xf4, 0xfd, 0x44, 0x52, 0xe2, 0xd7, 0x4d, 0xd3,
+	0x64, 0xf2, 0xe2, 0x1e, 0x71, 0xf5, 0x4b, 0xff, 0x5c, 0xae, 0x82, 0xab,
+	0x9c, 0x9d, 0xf6, 0x9e, 0xe8, 0x6d, 0x2b, 0xc5, 0x22, 0x36, 0x3a, 0x0d,
+	0xab, 0xc5, 0x21, 0x97, 0x9b, 0x0d, 0xea, 0xda, 0x1d, 0xbf, 0x9a, 0x42,
+	0xd5, 0xc4, 0x48, 0x4e, 0x0a, 0xbc, 0xd0, 0x6b, 0xfa, 0x53, 0xdd, 0xef,
+	0x3c, 0x1b, 0x20, 0xee, 0x3f, 0xd5, 0x9d, 0x7c, 0x25, 0xe4, 0x1d, 0x2b,
+	0x66, 0x9e, 0x1e, 0xf1, 0x6e, 0x6f, 0x52, 0xc3, 0x16, 0x4d, 0xf4, 0xfb,
+	0x79, 0x30, 0xe9, 0xe4, 0xe5, 0x88, 0x57, 0xb6, 0xac, 0x7d, 0x5f, 0x42,
+	0xd6, 0x9f, 0x6d, 0x18, 0x77, 0x63, 0xcf, 0x1d, 0x55, 0x03, 0x40, 0x04,
+	0x87, 0xf5, 0x5b, 0xa5, 0x7e, 0x31, 0xcc, 0x7a, 0x71, 0x35, 0xc8, 0x86,
+	0xef, 0xb4, 0x31, 0x8a, 0xed, 0x6a, 0x1e, 0x01, 0x2d, 0x9e, 0x68, 0x32,
+	0xa9, 0x07, 0x60, 0x0a, 0x91, 0x81, 0x30, 0xc4, 0x6d, 0xc7, 0x78, 0xf9,
+	0x71, 0xad, 0x00, 0x38, 0x09, 0x29, 0x99, 0xa3, 0x33, 0xcb, 0x8b, 0x7a,
+	0x1a, 0x1d, 0xb9, 0x3d, 0x71, 0x40, 0x00, 0x3c, 0x2a, 0x4e, 0xce, 0xa9,
+	0xf9, 0x8d, 0x0a, 0xcc, 0x0a, 0x82, 0x91, 0xcd, 0xce, 0xc9, 0x7d, 0xcf,
+	0x8e, 0xc9, 0xb5, 0x5a, 0x7f, 0x88, 0xa4, 0x6b, 0x4d, 0xb5, 0xa8, 0x51,
+	0xf4, 0x41, 0x82, 0xe1, 0xc6, 0x8a, 0x00, 0x7e, 0x5e, 0x0d, 0xd9, 0x02,
+	0x0b, 0xfd, 0x64, 0xb6, 0x45, 0x03, 0x6c, 0x7a, 0x4e, 0x67, 0x7d, 0x2c,
+	0x38, 0x53, 0x2a, 0x3a, 0x23, 0xba, 0x44, 0x42, 0xca, 0xf5, 0x3e, 0xa6,
+	0x3b, 0xb4, 0x54, 0x32, 0x9b, 0x76, 0x24, 0xc8, 0x91, 0x7b, 0xdd, 0x64,
+	0xb1, 0xc0, 0xfd, 0x4c, 0xb3, 0x8e, 0x8c, 0x33, 0x4c, 0x70, 0x1c, 0x3a,
+	0xcd, 0xad, 0x06, 0x57, 0xfc, 0xcf, 0xec, 0x71, 0x9b, 0x1f, 0x5c, 0x3e,
+	0x4e, 0x46, 0x04, 0x1f, 0x38, 0x81, 0x47, 0xfb, 0x4c, 0xfd, 0xb4, 0x77,
+	0xa5, 0x24, 0x71, 0xf7, 0xa9, 0xa9, 0x69, 0x10, 0xb8, 0x55, 0x32, 0x2e,
+	0xdb, 0x63, 0x40, 0xd8, 0xa0, 0x0e, 0xf0, 0x92, 0x35, 0x05, 0x11, 0xe3,
+	0x0a, 0xbe, 0xc1, 0xff, 0xf9, 0xe3, 0xa2, 0x6e, 0x7f, 0xb2, 0x9f, 0x8c,
+	0x18, 0x30, 0x23, 0xc3, 0x58, 0x7e, 0x38, 0xda, 0x00, 0x77, 0xd9, 0xb4,
+	0x76, 0x3e, 0x4e, 0x4b, 0x94, 0xb2, 0xbb, 0xc1, 0x94, 0xc6, 0x65, 0x1e,
+	0x77, 0xca, 0xf9, 0x92, 0xee, 0xaa, 0xc0, 0x23, 0x2a, 0x28, 0x1b, 0xf6,
+	0xb3, 0xa7, 0x39, 0xc1, 0x22, 0x61, 0x16, 0x82, 0x0a, 0xe8, 0xdb, 0x58,
+	0x47, 0xa6, 0x7c, 0xbe, 0xf9, 0xc9, 0x09, 0x1b, 0x46, 0x2d, 0x53, 0x8c,
+	0xd7, 0x2b, 0x03, 0x74, 0x6a, 0xe7, 0x7f, 0x5e, 0x62, 0x29, 0x2c, 0x31,
+	0x15, 0x62, 0xa8, 0x46, 0x50, 0x5d, 0xc8, 0x2d, 0xb8, 0x54, 0x33, 0x8a,
+	0xe4, 0x9f, 0x52, 0x35, 0xc9, 0x5b, 0x91, 0x17, 0x8c, 0xcf, 0x2d, 0xd5,
+	0xca, 0xce, 0xf4, 0x03, 0xec, 0x9d, 0x18, 0x10, 0xc6, 0x27, 0x2b, 0x04,
+	0x5b, 0x3b, 0x71, 0xf9, 0xdc, 0x6b, 0x80, 0xd6, 0x3f, 0xdd, 0x4a, 0x8e,
+	0x9a, 0xdb, 0x1e, 0x69, 0x62, 0xa6, 0x95, 0x26, 0xd4, 0x31, 0x61, 0xc1,
+	0xa4, 0x1d, 0x57, 0x0d, 0x79, 0x38, 0xda, 0xd4, 0xa4, 0x0e, 0x32, 0x9c,
+	0xcf, 0xf4, 0x6a, 0xaa, 0x36, 0xad, 0x00, 0x4c, 0xf6, 0x00, 0xc8, 0x38,
+	0x1e, 0x42, 0x5a, 0x31, 0xd9, 0x51, 0xae, 0x64, 0xfd, 0xb2, 0x3f, 0xce,
+	0xc9, 0x50, 0x9d, 0x43, 0x68, 0x7f, 0xeb, 0x69, 0xed, 0xd1, 0xcc, 0x5e,
+	0x0b, 0x8c, 0xc3, 0xbd, 0xf6, 0x4b, 0x10, 0xef, 0x86, 0xb6, 0x31, 0x42,
+	0xa3, 0xab, 0x88, 0x29, 0x55, 0x5b, 0x2f, 0x74, 0x7c, 0x93, 0x26, 0x65,
+	0xcb, 0x2c, 0x0f, 0x1c, 0xc0, 0x1b, 0xd7, 0x02, 0x29, 0x38, 0x88, 0x39,
+	0xd2, 0xaf, 0x05, 0xe4, 0x54, 0x50, 0x4a, 0xc7, 0x8b, 0x75, 0x82, 0x82,
+	0x28, 0x46, 0xc0, 0xba, 0x35, 0xc3, 0x5f, 0x5c, 0x59, 0x16, 0x0c, 0xc0,
+	0x46, 0xfd, 0x82, 0x51, 0x54, 0x1f, 0xc6, 0x8c, 0x9c, 0x86, 0xb0, 0x22,
+	0xbb, 0x70, 0x99, 0x87, 0x6a, 0x46, 0x0e, 0x74, 0x51, 0xa8, 0xa9, 0x31,
+	0x09, 0x70, 0x3f, 0xee, 0x1c, 0x21, 0x7e, 0x6c, 0x38, 0x26, 0xe5, 0x2c,
+	0x51, 0xaa, 0x69, 0x1e, 0x0e, 0x42, 0x3c, 0xfc, 0x99, 0xe9, 0xe3, 0x16,
+	0x50, 0xc1, 0x21, 0x7b, 0x62, 0x48, 0x16, 0xcd, 0xad, 0x9a, 0x95, 0xf9,
+	0xd5, 0xb8, 0x01, 0x94, 0x88, 0xd9, 0xc0, 0xa0, 0xa1, 0xfe, 0x30, 0x75,
+	0xa5, 0x77, 0xe2, 0x31, 0x83, 0xf8, 0x1d, 0x4a, 0x3f, 0x2f, 0xa4, 0x57,
+	0x1e, 0xfc, 0x8c, 0xe0, 0xba, 0x8a, 0x4f, 0xe8, 0xb6, 0x85, 0x5d, 0xfe,
+	0x72, 0xb0, 0xa6, 0x6e, 0xde, 0xd2, 0xfb, 0xab, 0xfb, 0xe5, 0x8a, 0x30,
+	0xfa, 0xfa, 0xbe, 0x1c, 0x5d, 0x71, 0xa8, 0x7e, 0x2f, 0x74, 0x1e, 0xf8,
+	0xc1, 0xfe, 0x86, 0xfe, 0xa6, 0xbb, 0xfd, 0xe5, 0x30, 0x67, 0x7f, 0x0d,
+	0x97, 0xd1, 0x1d, 0x49, 0xf7, 0xa8, 0x44, 0x3d, 0x08, 0x22, 0xe5, 0x06,
+	0xa9, 0xf4, 0x61, 0x4e, 0x01, 0x1e, 0x2a, 0x94, 0x83, 0x8f, 0xf8, 0x8c,
+	0xd6, 0x8c, 0x8b, 0xb7, 0xc5, 0xc6, 0x42, 0x4c, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+};
+
+/* RFC 3526, Section 3 */
+static const uint8_t tls_dh14_prime[] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
+	0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
+	0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
+	0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+	0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
+	0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
+	0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
+	0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+	0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
+	0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
+	0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
+	0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
+	0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
+	0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
+	0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
+	0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
+	0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2,
+	0xec, 0x07, 0xa2, 0x8f, 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9,
+	0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7c,
+	0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
+	0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xac, 0xaa, 0x68, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+};
+
+static const struct tls_named_group tls_group_pref[] = {
+	{
+		"secp256r1", 23, TLS_GROUP_TYPE_EC,
+		.ec = { .l_group = 19, .point_bytes = 64 },
+	},
+	{
+		"secp384r1", 24, TLS_GROUP_TYPE_EC,
+		.ec = { .l_group = 20, .point_bytes = 96 },
+	},
+	{
+		"ffdhe2048", 256, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe2048_prime,
+			.prime_len = sizeof(tls_ffdhe2048_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe3072", 257, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe3072_prime,
+			.prime_len = sizeof(tls_ffdhe3072_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe4096", 258, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe4096_prime,
+			.prime_len = sizeof(tls_ffdhe4096_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe6144", 259, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe6144_prime,
+			.prime_len = sizeof(tls_ffdhe6144_prime),
+			.generator = 2,
+		},
+	},
+	{
+		"ffdhe8192", 260, TLS_GROUP_TYPE_FF,
+		.ff = {
+			.prime = tls_ffdhe8192_prime,
+			.prime_len = sizeof(tls_ffdhe8192_prime),
+			.generator = 2,
+		},
+	},
+};
+
+/*
+ * For now hardcode a default group for non-RFC7919 clients - same group
+ * as some other TLS servers use, which is actually a downside because the
+ * more common the group parameters are the less secure they are assumed
+ * to be, but it is also a test that the group is sufficiently good.
+ *
+ * Eventually we need to make this configurable so that a unique
+ * likely-prime number generated by either 'openssl dhparam' or
+ * 'ssh-keygen -G' can be set, or parse /etc/ssh/moduli to select
+ * a random pre-generated FFDH group each time.
+ */
+static const struct tls_named_group tls_default_ffdh_group = {
+	"RFC3526/Oakley Group 14", 0, TLS_GROUP_TYPE_FF,
+	.ff = {
+		.prime = tls_dh14_prime,
+		.prime_len = sizeof(tls_dh14_prime),
+		.generator = 2,
+	},
+};
+
+/* RFC 8422, Section 5.1 + RFC 7919 */
 static ssize_t tls_elliptic_curves_client_write(struct l_tls *tls,
 						uint8_t *buf, size_t len)
 {
 	uint8_t *ptr = buf;
 	unsigned int i;
 
-	if (len < 2 + L_ARRAY_SIZE(tls_curve_pref) * 2)
+	if (len < 2 + L_ARRAY_SIZE(tls_group_pref) * 2)
 		return -ENOMEM;
 
-	l_put_be16(L_ARRAY_SIZE(tls_curve_pref) * 2, ptr);
+	l_put_be16(L_ARRAY_SIZE(tls_group_pref) * 2, ptr);
 	ptr += 2;
 
-	for (i = 0; i < L_ARRAY_SIZE(tls_curve_pref); i++) {
-		l_put_be16(tls_curve_pref[i].id, ptr);
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++) {
+		l_put_be16(tls_group_pref[i].id, ptr);
 		ptr += 2;
 	}
 
@@ -60,6 +419,8 @@ static ssize_t tls_elliptic_curves_client_write(struct l_tls *tls,
 static bool tls_elliptic_curves_client_handle(struct l_tls *tls,
 						const uint8_t *buf, size_t len)
 {
+	bool ffdh_offered = false;
+
 	if (len < 2)
 		return false;
 
@@ -69,30 +430,113 @@ static bool tls_elliptic_curves_client_handle(struct l_tls *tls,
 	buf += 2;
 	len -= 2;
 
+	/*
+	 * We select one group for DH and one group for ECDH and we'll
+	 * let the cipher suite selection logic decide which one is actually
+	 * used.  It will take into account the client's cipher suite
+	 * preference but it could just as well look at the strengths of
+	 * the groups chosen.  This is not done for simplicity but RFC 7919
+	 * suggests the Supported Groups should actually overrule the
+	 * cipher suite preference list in case of a conflict:
+	 * "A server that encounters such a contradiction when selecting
+	 * between an ECDHE or FFDHE key exchange mechanism while trying
+	 * to respect client preferences SHOULD give priority to the
+	 * Supported Groups extension (...) but MAY resolve the
+	 * contradiction any way it sees fit."
+	 *
+	 * Not implemented: "If a non-anonymous FFDHE cipher suite is
+	 * selected and the TLS client has used this extension to offer
+	 * an FFDHE group of comparable or greater strength than the server's
+	 * public key, the server SHOULD select an FFDHE group@least
+	 * as strong as the server's public key."
+	 */
+
 	while (len) {
 		unsigned int i;
 		uint16_t id;
+		const struct tls_named_group *group = NULL;
 
 		id = l_get_be16(buf);
 		buf += 2;
 		len -= 2;
 
-		for (i = 0; i < L_ARRAY_SIZE(tls_curve_pref); i++)
-			if (tls_curve_pref[i].id == id) {
-				tls->negotiated_curve = &tls_curve_pref[i];
-				TLS_DEBUG("Negotiated %s",
-						tls_curve_pref[i].name);
-				return true;
+		if (id >> 8 == 1)	/* RFC 7919 ids */
+			ffdh_offered = true;
+
+		for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+			if (tls_group_pref[i].id == id) {
+				group = &tls_group_pref[i];
+				break;
 			}
+
+		if (!group)
+			continue;
+
+		switch (group->type) {
+		case TLS_GROUP_TYPE_EC:
+			if (!tls->negotiated_curve)
+				tls->negotiated_curve = group;
+
+			break;
+		case TLS_GROUP_TYPE_FF:
+			if (!tls->negotiated_ff_group)
+				tls->negotiated_ff_group = group;
+
+			break;
+		}
 	}
 
-	TLS_DEBUG("non-fatal: No common supported elliptic curves");
+	/*
+	 * Note we need to treat DH slightly differently from ECDH groups
+	 * here because the extension is defined in RFC 8422 and if the
+	 * client offers no elliptic curves we can't use ECDH at all:
+	 * "If a server (...) is unable to complete the ECC handshake while
+	 * restricting itself to the enumerated curves (...), it MUST NOT
+	 * negotiate the use of an ECC cipher suite.  Depending on what
+	 * other cipher suites are proposed by the client and supported by
+	 * the server, this may result in a fatal handshake failure alert
+	 * due to the lack of common cipher suites."
+	 *
+	 * On the other hand if the client offers no FFDH groups we can
+	 * only assume the client is okay with us picking a group.  Note
+	 * the "includes any FFDHE group" part in RFC 7919 Section 4:
+	 * "If a compatible TLS server receives a Supported Groups
+	 * extension from a client that includes any FFDHE group (i.e.,
+	 * any codepoint between 256 and 511, inclusive, even if unknown
+	 * to the server), and if none of the client-proposed FFDHE groups
+	 * are known and acceptable to the server, then the server MUST
+	 * NOT select an FFDHE cipher suite."
+	 */
+
+	if (tls->negotiated_curve)
+		TLS_DEBUG("Negotiated %s", tls->negotiated_curve->name);
+	else
+		TLS_DEBUG("non-fatal: No common supported elliptic curves "
+				"for ECDHE");
+
+	if (tls->negotiated_ff_group)
+		TLS_DEBUG("Negotiated %s", tls->negotiated_ff_group->name);
+	else if (ffdh_offered)
+		TLS_DEBUG("non-fatal: No common supported finite-field groups "
+				"for DHE");
+	else
+		tls->negotiated_ff_group = &tls_default_ffdh_group;
+
 	return true;
 }
 
 static bool tls_elliptic_curves_client_absent(struct l_tls *tls)
 {
-	tls->negotiated_curve = &tls_curve_pref[0];
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+		if (tls_group_pref[i].type == TLS_GROUP_TYPE_EC) {
+			tls->negotiated_curve = &tls_group_pref[i];
+			break;
+		}
+
+	tls->negotiated_ff_group = &tls_default_ffdh_group;
+
 	return true;
 }
 
@@ -132,7 +576,7 @@ static ssize_t tls_ec_point_formats_server_write(struct l_tls *tls,
 
 const struct tls_hello_extension tls_extensions[] = {
 	{
-		"Supported Elliptic Curves", "elliptic_curves", 10,
+		"Supported Groups", "elliptic_curves", 10,
 		tls_elliptic_curves_client_write,
 		tls_elliptic_curves_client_handle,
 		tls_elliptic_curves_client_absent,
@@ -149,13 +593,42 @@ const struct tls_hello_extension tls_extensions[] = {
 	{}
 };
 
-const struct tls_named_curve *tls_find_curve(uint16_t id)
+const struct tls_named_group *tls_find_group(uint16_t id)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++)
+		if (tls_group_pref[i].id == id)
+			return &tls_group_pref[i];
+
+	return NULL;
+}
+
+const struct tls_named_group *tls_find_ff_group(const uint8_t *prime,
+						size_t prime_len,
+						const uint8_t *generator,
+						size_t generator_len)
 {
 	unsigned int i;
 
-	for (i = 0; i < L_ARRAY_SIZE(tls_curve_pref); i++)
-		if (tls_curve_pref[i].id == id)
-			return &tls_curve_pref[i];
+	if (generator_len != 1)
+		return NULL;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_group_pref); i++) {
+		const struct tls_named_group *g = &tls_group_pref[i];
+
+		if (g->type != TLS_GROUP_TYPE_FF)
+			continue;
+
+		if (g->ff.prime_len != prime_len ||
+				memcmp(prime, g->ff.prime, prime_len))
+			continue;
+
+		if (g->ff.generator != *generator)
+			continue;
+
+		return g;
+	}
 
 	return NULL;
 }
diff --git a/ell/tls-private.h b/ell/tls-private.h
index 12d350a..c82a4d5 100644
--- a/ell/tls-private.h
+++ b/ell/tls-private.h
@@ -67,6 +67,7 @@ struct tls_key_exchange_algorithm {
 
 	bool certificate_check;
 	bool need_ecc;
+	bool need_ffdh;
 
 	bool (*validate_cert_key_type)(struct l_cert *cert);
 
@@ -130,11 +131,24 @@ struct tls_hello_extension {
 
 extern const struct tls_hello_extension tls_extensions[];
 
-struct tls_named_curve {
+struct tls_named_group {
 	const char *name;
 	uint16_t id;
-	unsigned int l_group;
-	size_t point_bytes;
+	enum {
+		TLS_GROUP_TYPE_EC,
+		TLS_GROUP_TYPE_FF,
+	} type;
+	union {
+		struct {
+			unsigned int l_group;
+			size_t point_bytes;
+		} ec;
+		struct {
+			const uint8_t *prime;
+			size_t prime_len;
+			unsigned int generator;
+		} ff;
+	};
 };
 
 enum tls_handshake_state {
@@ -233,7 +247,8 @@ struct l_tls {
 	size_t peer_pubkey_size;
 	enum handshake_hash_type signature_hash;
 	const struct tls_hash_algorithm *prf_hmac;
-	const struct tls_named_curve *negotiated_curve;
+	const struct tls_named_group *negotiated_curve;
+	const struct tls_named_group *negotiated_ff_group;
 
 	/* SecurityParameters current and pending */
 
@@ -305,7 +320,11 @@ void tls_generate_master_secret(struct l_tls *tls,
 				const uint8_t *pre_master_secret,
 				int pre_master_secret_len);
 
-const struct tls_named_curve *tls_find_curve(uint16_t id);
+const struct tls_named_group *tls_find_group(uint16_t id);
+const struct tls_named_group *tls_find_ff_group(const uint8_t *prime,
+						size_t prime_len,
+						const uint8_t *generator,
+						size_t generator_len);
 
 int tls_parse_certificate_list(const void *data, size_t len,
 				struct l_certchain **out_certchain);
diff --git a/ell/tls-suites.c b/ell/tls-suites.c
index 2ae13ea..cb1416a 100644
--- a/ell/tls-suites.c
+++ b/ell/tls-suites.c
@@ -343,13 +343,13 @@ static void tls_free_ecdhe_params(struct l_tls *tls)
 }
 
 static size_t tls_write_ecpoint(uint8_t *buf,
-				const struct tls_named_curve *curve,
+				const struct tls_named_group *curve,
 				const struct l_ecc_point *point)
 {
 	/* RFC 8422, Section 5.4.1 */
-	buf[0] = 1 + curve->point_bytes;	/* length */
+	buf[0] = 1 + curve->ec.point_bytes;	/* length */
 	buf[1] = 4;				/* form: uncompressed */
-	return 2 + l_ecc_point_get_data(point, buf + 2, curve->point_bytes);
+	return 2 + l_ecc_point_get_data(point, buf + 2, curve->ec.point_bytes);
 }
 
 static size_t tls_write_server_ecdh_params(struct l_tls *tls, uint8_t *buf)
@@ -428,7 +428,7 @@ static bool tls_send_ecdhe_server_key_xchg(struct l_tls *tls)
 	 */
 
 	params = l_new(struct tls_ecdhe_params, 1);
-	params->curve = l_ecc_curve_get(tls->negotiated_curve->l_group);
+	params->curve = l_ecc_curve_get(tls->negotiated_curve->ec.l_group);
 	tls->pending.key_xchg_params = params;
 
 	if (!l_ecdh_generate_key_pair(params->curve,
@@ -475,9 +475,10 @@ static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
 	buf += 3;
 	len -= 3;
 
-	tls->negotiated_curve = tls_find_curve(namedcurve);
+	tls->negotiated_curve = tls_find_group(namedcurve);
 
-	if (!tls->negotiated_curve) {
+	if (!tls->negotiated_curve ||
+			tls->negotiated_curve->type != TLS_GROUP_TYPE_EC) {
 		TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
 				"Unsupported NamedCurve %u", namedcurve);
 		return;
@@ -485,7 +486,7 @@ static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
 
 	TLS_DEBUG("Negotiated %s", tls->negotiated_curve->name);
 
-	if (*buf++ != 1 + tls->negotiated_curve->point_bytes)
+	if (*buf++ != 1 + tls->negotiated_curve->ec.point_bytes)
 		goto decode_error;
 
 	if (*buf != 4) {	/* uncompressed */
@@ -498,7 +499,7 @@ static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
 	buf++;
 	len -= 2;
 
-	if (len < tls->negotiated_curve->point_bytes)
+	if (len < tls->negotiated_curve->ec.point_bytes)
 		goto decode_error;
 
 	/*
@@ -509,13 +510,13 @@ static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
 	 * format is used.
 	 */
 	params = l_new(struct tls_ecdhe_params, 1);
-	params->curve = l_ecc_curve_get(tls->negotiated_curve->l_group);
+	params->curve = l_ecc_curve_get(tls->negotiated_curve->ec.l_group);
 	params->public = l_ecc_point_from_data(params->curve,
 						L_ECC_POINT_TYPE_FULL,
 						buf, len);
 	tls->pending.key_xchg_params = params;
-	buf += tls->negotiated_curve->point_bytes;
-	len -= tls->negotiated_curve->point_bytes;
+	buf += tls->negotiated_curve->ec.point_bytes;
+	len -= tls->negotiated_curve->ec.point_bytes;
 
 	if (!params->public) {
 		TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
@@ -610,7 +611,7 @@ static void tls_handle_ecdhe_client_key_xchg(struct l_tls *tls,
 	if (len < 2)
 		goto decode_error;
 
-	if (*buf++ != 1 + tls->negotiated_curve->point_bytes)
+	if (*buf++ != 1 + tls->negotiated_curve->ec.point_bytes)
 		goto decode_error;
 
 	if (*buf != 4) {	/* uncompressed */
@@ -623,7 +624,7 @@ static void tls_handle_ecdhe_client_key_xchg(struct l_tls *tls,
 	buf++;
 	len -= 2;
 
-	if (len != tls->negotiated_curve->point_bytes)
+	if (len != tls->negotiated_curve->ec.point_bytes)
 		goto decode_error;
 
 	/*
@@ -691,34 +692,6 @@ static struct tls_key_exchange_algorithm tls_ecdhe_rsa = {
 /* Maximum FF DH prime modulus size in bytes */
 #define TLS_DHE_MAX_SIZE 1024
 
-/* RFC 3526, Section 3 */
-static const uint8_t tls_dh14_prime[] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
-	0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
-	0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
-	0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
-	0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
-	0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
-	0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
-	0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
-	0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
-	0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
-	0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
-	0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
-	0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
-	0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
-	0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
-	0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
-	0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2,
-	0xec, 0x07, 0xa2, 0x8f, 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9,
-	0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7c,
-	0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
-	0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xac, 0xaa, 0x68, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff,
-};
-
-static const unsigned int tls_dh14_generator = 2;
-
 struct tls_dhe_params {
 	size_t prime_len;
 	struct l_key *prime;
@@ -792,28 +765,15 @@ static bool tls_send_dhe_server_key_xchg(struct l_tls *tls)
 	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
 	struct tls_dhe_params *params;
 	const uint8_t *prime_buf;
-	uint8_t generator_buf = tls_dh14_generator;
+	uint8_t generator_buf = tls->negotiated_ff_group->ff.generator;
 	uint8_t public_buf[TLS_DHE_MAX_SIZE];
 	size_t public_len;
 	unsigned int zeros = 0;
 	ssize_t sign_len;
 
 	params = l_new(struct tls_dhe_params, 1);
-
-	/*
-	 * For now hardcode the Oakley Group 14 parameters like some other
-	 * TLS implementations do without RFC 7919, which is actually a
-	 * downside because the more common the group parameters are the
-	 * less secure they are assumed to be, but also is a test that the
-	 * group is sufficiently good.
-	 *
-	 * Eventually we should make this configurable so that a unique
-	 * likely-prime number generated by either 'openssl dhparam' or
-	 * 'ssh-keygen -G' can be set, or parse /etc/ssh/moduli to select
-	 * a random pre-generated FFDH group each time.
-	 */
-	prime_buf = tls_dh14_prime;
-	params->prime_len = sizeof(tls_dh14_prime);
+	prime_buf = tls->negotiated_ff_group->ff.prime;
+	params->prime_len = tls->negotiated_ff_group->ff.prime_len;
 
 	params->prime = l_key_new(L_KEY_RAW, prime_buf, params->prime_len);
 	params->generator = l_key_new(L_KEY_RAW, &generator_buf, 1);
@@ -929,13 +889,14 @@ static void tls_handle_dhe_server_key_xchg(struct l_tls *tls,
 	params->server_dh_params_len = buf - params->server_dh_params_buf;
 
 	/*
-	 * Validate the values received.  Without RFC 7919 we basically have
-	 * to blindly accept the provided prime value.  We have no way to
-	 * confirm that it's actually prime or that it's a "safe prime" or
-	 * that it forms a group without small sub-groups.  There's also no
-	 * way to whitelist all valid values.  But we do a basic sanity
-	 * check and require it to be 1024-bit or longer (see weakdh.org),
-	 * might need to move to 2048 bits actually.
+	 * Validate the values received.  Without requiring RFC 7919 from
+	 * the server, and there are many servers that don't implement it
+	 * yet, we basically have to blindly accept the provided prime value.
+	 * We have no way to confirm that it's actually prime or that it's a
+	 * "safe prime" or that it forms a group without small sub-groups.
+	 * There's also no way to whitelist all valid values.  But we do a
+	 * basic sanity check and require it to be 1024-bit or longer
+	 * (see weakdh.org), might need to move to 2048 bits actually.
 	 * The generator must also be at least within the min & max interval
 	 * for the private/public values.
 	 */
@@ -954,6 +915,15 @@ static void tls_handle_dhe_server_key_xchg(struct l_tls *tls,
 		goto free_params;
 	}
 
+	/*
+	 * Just output a warning if the server sent group parameters not
+	 * offered in our RFC 7919 Supported Groups extension.
+	 */
+	if (!tls_find_ff_group(prime_buf, params->prime_len,
+				generator_buf, generator_len))
+		TLS_DEBUG("Warning: using server's custom %i-bit FF DH group",
+				(int) (params->prime_len * 8));
+
 	/*
 	 * RFC 7919 Section 3.0:
 	 * "the client MUST verify that dh_Ys is in the range
@@ -1085,7 +1055,8 @@ static void tls_handle_dhe_client_key_xchg(struct l_tls *tls,
 	 * a fatal handshake_failure(40) alert."
 	 */
 	if (!l_key_validate_dh_payload(buf, public_len,
-					tls_dh14_prime, params->prime_len)) {
+					tls->negotiated_ff_group->ff.prime,
+					params->prime_len)) {
 		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
 				"Client DH public value invalid");
 		return;
diff --git a/ell/tls.c b/ell/tls.c
index 919c696..0809a47 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -494,6 +494,20 @@ static bool tls_cipher_suite_is_compatible(struct l_tls *tls,
 		return false;
 	}
 
+	/* Similarly for FF DH groups */
+	if (suite->key_xchg->need_ffdh && tls->server &&
+			!tls->negotiated_ff_group) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"No common supported finite-field "
+					"groups with the client, can't use %s",
+					suite->name);
+		}
+
+		return false;
+	}
+
 	return true;
 }
 
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] tls: Implement the RFC 7919 Supported Groups extension
  2019-01-08 23:25 [PATCH] tls: Implement the RFC 7919 Supported Groups extension Andrew Zaborowski
@ 2019-01-09 17:49 ` Denis Kenzior
  0 siblings, 0 replies; 2+ messages in thread
From: Denis Kenzior @ 2019-01-09 17:49 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 982 bytes --]

Hi Andrew,

On 01/08/2019 05:25 PM, Andrew Zaborowski wrote:
> For ECDHE (RFC 8422) we implemented the Supported Elliptic Curves
> extension which was later renamed Supported Groups in RFC 7919 and
> extended to be used for negotiating FF groups for DHE too.  This change
> is acknowledged in RFC 8422 too.  This fixes some problems with the DHE
> key exchange in TLS although it seems like it may have been released
> too late to get TLS users to re-enable DHE when ECDHE is widely
> supported and had the group negotiation specified in a way free of
> the issues in DHE.  RFC 7919 is only supported by few https servers
> (all wikipedia servers as far as I could tell)
> ---
>   ell/tls-extensions.c | 515 +++++++++++++++++++++++++++++++++++++++++--
>   ell/tls-private.h    |  29 ++-
>   ell/tls-suites.c     | 101 +++------
>   ell/tls.c            |  14 ++
>   4 files changed, 568 insertions(+), 91 deletions(-)
> 

Applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-01-09 17:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-08 23:25 [PATCH] tls: Implement the RFC 7919 Supported Groups extension Andrew Zaborowski
2019-01-09 17:49 ` Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.