From 0db55f1b5e2dbed6bc774432be7172abe3daa1e4 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 2 Mar 2022 16:36:48 +0700 Subject: RFC 8879 preliminaries --- crypto/BouncyCastle.Android.csproj | 1 + crypto/BouncyCastle.csproj | 1 + crypto/BouncyCastle.iOS.csproj | 1 + crypto/crypto.csproj | 5 +++ crypto/src/tls/CertificateCompressionAlgorithm.cs | 47 +++++++++++++++++++++++ crypto/src/tls/ExtensionType.cs | 8 ++++ crypto/src/tls/HandshakeType.cs | 8 ++++ crypto/src/tls/TlsClientProtocol.cs | 2 + crypto/src/tls/TlsExtensionsUtilities.cs | 32 +++++++++++++++ crypto/src/tls/TlsServerProtocol.cs | 2 + crypto/src/tls/TlsUtilities.cs | 36 +++++++++++++++++ 11 files changed, 143 insertions(+) create mode 100644 crypto/src/tls/CertificateCompressionAlgorithm.cs diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 875c99cfe..3d84af346 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -1602,6 +1602,7 @@ + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index f7083b062..84d7bf6fc 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -1596,6 +1596,7 @@ + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 4490f0f07..d76444e71 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -1597,6 +1597,7 @@ + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index d3666bfcf..092331032 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -7868,6 +7868,11 @@ SubType = "Code" BuildAction = "Compile" /> + + public static void AddCompressCertificateExtension(IDictionary extensions, int[] algorithms) + { + extensions[ExtensionType.compress_certificate] = CreateCompressCertificateExtension(algorithms); + } + /// public static void AddCookieExtension(IDictionary extensions, byte[] cookie) { @@ -279,6 +285,13 @@ namespace Org.BouncyCastle.Tls return extensionData == null ? (short)-1 : ReadCertificateTypeExtensionServer(extensionData); } + /// + public static int[] GetCompressCertificateExtension(IDictionary extensions) + { + byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.compress_certificate); + return extensionData == null ? null : ReadCompressCertificateExtension(extensionData); + } + /// public static byte[] GetCookieExtension(IDictionary extensions) { @@ -579,6 +592,15 @@ namespace Org.BouncyCastle.Tls return CreateEmptyExtensionData(); } + /// + public static byte[] CreateCompressCertificateExtension(int[] algorithms) + { + if (TlsUtilities.IsNullOrEmpty(algorithms) || algorithms.Length > 127) + throw new TlsFatalAlert(AlertDescription.internal_error); + + return TlsUtilities.EncodeUint16ArrayWithUint8Length(algorithms); + } + /// public static byte[] CreateCookieExtension(byte[] cookie) { @@ -994,6 +1016,16 @@ namespace Org.BouncyCastle.Tls return ReadEmptyExtensionData(extensionData); } + /// + public static int[] ReadCompressCertificateExtension(byte[] extensionData) + { + int[] algorithms = TlsUtilities.DecodeUint16ArrayWithUint8Length(extensionData); + if (algorithms.Length < 1) + throw new TlsFatalAlert(AlertDescription.decode_error); + + return algorithms; + } + /// public static byte[] ReadCookieExtension(byte[] extensionData) { diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs index 40218a2fb..22700a277 100644 --- a/crypto/src/tls/TlsServerProtocol.cs +++ b/crypto/src/tls/TlsServerProtocol.cs @@ -834,6 +834,7 @@ namespace Org.BouncyCastle.Tls case HandshakeType.certificate_status: case HandshakeType.certificate_url: case HandshakeType.client_key_exchange: + case HandshakeType.compressed_certificate: case HandshakeType.encrypted_extensions: case HandshakeType.end_of_early_data: case HandshakeType.hello_request: @@ -1201,6 +1202,7 @@ namespace Org.BouncyCastle.Tls case HandshakeType.certificate_request: case HandshakeType.certificate_status: case HandshakeType.certificate_url: + case HandshakeType.compressed_certificate: case HandshakeType.encrypted_extensions: case HandshakeType.end_of_early_data: case HandshakeType.hello_request: diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs index 8733fd68f..f48c7e731 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs @@ -486,6 +486,14 @@ namespace Org.BouncyCastle.Tls } } + public static void WriteUint16ArrayWithUint8Length(int[] u16s, byte[] buf, int offset) + { + int length = 2 * u16s.Length; + CheckUint8(length); + WriteUint8(length, buf, offset); + WriteUint16Array(u16s, buf, offset + 1); + } + public static void WriteUint16ArrayWithUint16Length(int[] u16s, Stream output) { int length = 2 * u16s.Length; @@ -577,6 +585,25 @@ namespace Org.BouncyCastle.Tls return ReadUint16(buf, 0); } + public static int[] DecodeUint16ArrayWithUint8Length(byte[] buf) + { + if (buf == null) + throw new ArgumentNullException("buf"); + + int length = ReadUint8(buf, 0); + if (buf.Length != (length + 1) || (length & 1) != 0) + throw new TlsFatalAlert(AlertDescription.decode_error); + + int count = length / 2, pos = 1; + int[] u16s = new int[count]; + for (int i = 0; i < count; ++i) + { + u16s[i] = ReadUint16(buf, pos); + pos += 2; + } + return u16s; + } + public static long DecodeUint32(byte[] buf) { if (buf == null) @@ -636,6 +663,14 @@ namespace Org.BouncyCastle.Tls return encoding; } + public static byte[] EncodeUint16ArrayWithUint8Length(int[] u16s) + { + int length = 2 * u16s.Length; + byte[] result = new byte[1 + length]; + WriteUint16ArrayWithUint8Length(u16s, result, 0); + return result; + } + public static byte[] EncodeUint16ArrayWithUint16Length(int[] u16s) { int length = 2 * u16s.Length; @@ -5348,6 +5383,7 @@ namespace Org.BouncyCastle.Tls } } case ExtensionType.signature_algorithms: + case ExtensionType.compress_certificate: case ExtensionType.certificate_authorities: case ExtensionType.signature_algorithms_cert: { -- cgit 1.4.1