From b2f438fc57997fc40f5bd808c1579cad86553eef Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 26 May 2017 08:47:03 +0700 Subject: No variable-length padding w/ truncated MAC (unless EtM enabled) --- crypto/src/crypto/tls/TlsBlockCipher.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsBlockCipher.cs b/crypto/src/crypto/tls/TlsBlockCipher.cs index d81b881fc..76b476a18 100644 --- a/crypto/src/crypto/tls/TlsBlockCipher.cs +++ b/crypto/src/crypto/tls/TlsBlockCipher.cs @@ -160,13 +160,22 @@ namespace Org.BouncyCastle.Crypto.Tls int padding_length = blockSize - 1 - (enc_input_length % blockSize); - // TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though) - if (!version.IsDtls && !version.IsSsl) + /* + * Don't use variable-length padding with truncated MACs. + * + * See "Tag Size Does Matter: Attacks and Proofs for the TLS Record Protocol", Paterson, + * Ristenpart, Shrimpton. + */ + if (encryptThenMac || !context.SecurityParameters.truncatedHMac) { - // Add a random number of extra blocks worth of padding - int maxExtraPadBlocks = (255 - padding_length) / blockSize; - int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks); - padding_length += actualExtraPadBlocks * blockSize; + // TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though) + if (!version.IsDtls && !version.IsSsl) + { + // Add a random number of extra blocks worth of padding + int maxExtraPadBlocks = (255 - padding_length) / blockSize; + int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks); + padding_length += actualExtraPadBlocks * blockSize; + } } int totalSize = len + macSize + padding_length + 1; -- cgit 1.4.1 From 5828176f009e4c68c65518c32845ae5ef9ed60da Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 26 May 2017 08:50:01 +0700 Subject: X.509 certificates in TLS Certificate message allowed to be BER --- crypto/src/crypto/tls/Certificate.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/Certificate.cs b/crypto/src/crypto/tls/Certificate.cs index c59616c95..e0479997a 100644 --- a/crypto/src/crypto/tls/Certificate.cs +++ b/crypto/src/crypto/tls/Certificate.cs @@ -115,8 +115,8 @@ namespace Org.BouncyCastle.Crypto.Tls IList certificate_list = Platform.CreateArrayList(); while (buf.Position < buf.Length) { - byte[] derEncoding = TlsUtilities.ReadOpaque24(buf); - Asn1Object asn1Cert = TlsUtilities.ReadDerObject(derEncoding); + byte[] berEncoding = TlsUtilities.ReadOpaque24(buf); + Asn1Object asn1Cert = TlsUtilities.ReadAsn1Object(berEncoding); certificate_list.Add(X509CertificateStructure.GetInstance(asn1Cert)); } -- cgit 1.4.1 From 761f05e294941ddf765a713b5fe662419266054d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 26 May 2017 09:29:10 +0700 Subject: RFC 7250 Add methods to work with required extension types --- crypto/src/crypto/tls/TlsDHUtilities.cs | 24 ++----- crypto/src/crypto/tls/TlsEccUtilities.cs | 15 +--- crypto/src/crypto/tls/TlsExtensionsUtilities.cs | 94 ++++++++++++++++++++++--- crypto/src/crypto/tls/TlsUtilities.cs | 35 +++++++++ 4 files changed, 125 insertions(+), 43 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs index 7a44670fd..6df61cbed 100644 --- a/crypto/src/crypto/tls/TlsDHUtilities.cs +++ b/crypto/src/crypto/tls/TlsDHUtilities.cs @@ -204,36 +204,20 @@ namespace Org.BouncyCastle.Crypto.Tls public static byte[] CreateNegotiatedDheGroupsServerExtension(byte dheGroup) { - return new byte[]{ dheGroup }; + return TlsUtilities.EncodeUint8(dheGroup); } public static byte[] ReadNegotiatedDheGroupsClientExtension(byte[] extensionData) { - if (extensionData == null) - throw new ArgumentNullException("extensionData"); - - MemoryStream buf = new MemoryStream(extensionData, false); - - byte length = TlsUtilities.ReadUint8(buf); - if (length < 1) + byte[] dheGroups = TlsUtilities.DecodeUint8ArrayWithUint8Length(extensionData); + if (dheGroups.Length < 1) throw new TlsFatalAlert(AlertDescription.decode_error); - - byte[] dheGroups = TlsUtilities.ReadUint8Array(length, buf); - - TlsProtocol.AssertEmpty(buf); - return dheGroups; } public static byte ReadNegotiatedDheGroupsServerExtension(byte[] extensionData) { - if (extensionData == null) - throw new ArgumentNullException("extensionData"); - - if (extensionData.Length != 1) - throw new TlsFatalAlert(AlertDescription.decode_error); - - return extensionData[0]; + return TlsUtilities.DecodeUint8(extensionData); } public static DHParameters GetParametersForDHEGroup(short dheGroup) diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs index a5c8fa910..fb31e1b07 100644 --- a/crypto/src/crypto/tls/TlsEccUtilities.cs +++ b/crypto/src/crypto/tls/TlsEccUtilities.cs @@ -90,19 +90,7 @@ namespace Org.BouncyCastle.Crypto.Tls public static byte[] ReadSupportedPointFormatsExtension(byte[] extensionData) { - if (extensionData == null) - throw new ArgumentNullException("extensionData"); - - MemoryStream buf = new MemoryStream(extensionData, false); - - byte length = TlsUtilities.ReadUint8(buf); - if (length < 1) - throw new TlsFatalAlert(AlertDescription.decode_error); - - byte[] ecPointFormats = TlsUtilities.ReadUint8Array(length, buf); - - TlsProtocol.AssertEmpty(buf); - + byte[] ecPointFormats = TlsUtilities.DecodeUint8ArrayWithUint8Length(extensionData); if (!Arrays.Contains(ecPointFormats, ECPointFormat.uncompressed)) { /* @@ -111,7 +99,6 @@ namespace Org.BouncyCastle.Crypto.Tls */ throw new TlsFatalAlert(AlertDescription.illegal_parameter); } - return ecPointFormats; } diff --git a/crypto/src/crypto/tls/TlsExtensionsUtilities.cs b/crypto/src/crypto/tls/TlsExtensionsUtilities.cs index 7f6a26ef2..4b3d9e0c5 100644 --- a/crypto/src/crypto/tls/TlsExtensionsUtilities.cs +++ b/crypto/src/crypto/tls/TlsExtensionsUtilities.cs @@ -13,6 +13,18 @@ namespace Org.BouncyCastle.Crypto.Tls return extensions == null ? Platform.CreateHashtable() : extensions; } + /// + public static void AddClientCertificateTypeExtensionClient(IDictionary extensions, byte[] certificateTypes) + { + extensions[ExtensionType.client_certificate_type] = CreateCertificateTypeExtensionClient(certificateTypes); + } + + /// + public static void AddClientCertificateTypeExtensionServer(IDictionary extensions, byte certificateType) + { + extensions[ExtensionType.client_certificate_type] = CreateCertificateTypeExtensionServer(certificateType); + } + public static void AddEncryptThenMacExtension(IDictionary extensions) { extensions[ExtensionType.encrypt_then_mac] = CreateEncryptThenMacExtension(); @@ -41,6 +53,18 @@ namespace Org.BouncyCastle.Crypto.Tls extensions[ExtensionType.padding] = CreatePaddingExtension(dataLength); } + /// + public static void AddServerCertificateTypeExtensionClient(IDictionary extensions, byte[] certificateTypes) + { + extensions[ExtensionType.server_certificate_type] = CreateCertificateTypeExtensionClient(certificateTypes); + } + + /// + public static void AddServerCertificateTypeExtensionServer(IDictionary extensions, byte certificateType) + { + extensions[ExtensionType.server_certificate_type] = CreateCertificateTypeExtensionServer(certificateType); + } + /// public static void AddServerNameExtension(IDictionary extensions, ServerNameList serverNameList) { @@ -58,6 +82,20 @@ namespace Org.BouncyCastle.Crypto.Tls extensions[ExtensionType.truncated_hmac] = CreateTruncatedHMacExtension(); } + /// + public static byte[] GetClientCertificateTypeExtensionClient(IDictionary extensions) + { + byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.client_certificate_type); + return extensionData == null ? null : ReadCertificateTypeExtensionClient(extensionData); + } + + /// + public static short GetClientCertificateTypeExtensionServer(IDictionary extensions) + { + byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.client_certificate_type); + return extensionData == null ? (short)-1 : (short)ReadCertificateTypeExtensionServer(extensionData); + } + /// public static HeartbeatExtension GetHeartbeatExtension(IDictionary extensions) { @@ -79,6 +117,20 @@ namespace Org.BouncyCastle.Crypto.Tls return extensionData == null ? -1 : ReadPaddingExtension(extensionData); } + /// + public static byte[] GetServerCertificateTypeExtensionClient(IDictionary extensions) + { + byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.server_certificate_type); + return extensionData == null ? null : ReadCertificateTypeExtensionClient(extensionData); + } + + /// + public static short GetServerCertificateTypeExtensionServer(IDictionary extensions) + { + byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.server_certificate_type); + return extensionData == null ? (short)-1 : (short)ReadCertificateTypeExtensionServer(extensionData); + } + /// public static ServerNameList GetServerNameExtension(IDictionary extensions) { @@ -114,6 +166,21 @@ namespace Org.BouncyCastle.Crypto.Tls return extensionData == null ? false : ReadTruncatedHMacExtension(extensionData); } + /// + public static byte[] CreateCertificateTypeExtensionClient(byte[] certificateTypes) + { + if (certificateTypes == null || certificateTypes.Length < 1 || certificateTypes.Length > 255) + throw new TlsFatalAlert(AlertDescription.internal_error); + + return TlsUtilities.EncodeUint8ArrayWithUint8Length(certificateTypes); + } + + /// + public static byte[] CreateCertificateTypeExtensionServer(byte certificateType) + { + return TlsUtilities.EncodeUint8(certificateType); + } + public static byte[] CreateEmptyExtensionData() { return TlsUtilities.EmptyBytes; @@ -145,7 +212,7 @@ namespace Org.BouncyCastle.Crypto.Tls /// public static byte[] CreateMaxFragmentLengthExtension(byte maxFragmentLength) { - return new byte[]{ maxFragmentLength }; + return TlsUtilities.EncodeUint8(maxFragmentLength); } /// @@ -200,6 +267,21 @@ namespace Org.BouncyCastle.Crypto.Tls return true; } + /// + public static byte[] ReadCertificateTypeExtensionClient(byte[] extensionData) + { + byte[] certificateTypes = TlsUtilities.DecodeUint8ArrayWithUint8Length(extensionData); + if (certificateTypes.Length < 1) + throw new TlsFatalAlert(AlertDescription.decode_error); + return certificateTypes; + } + + /// + public static byte ReadCertificateTypeExtensionServer(byte[] extensionData) + { + return TlsUtilities.DecodeUint8(extensionData); + } + /// public static bool ReadEncryptThenMacExtension(byte[] extensionData) { @@ -228,15 +310,9 @@ namespace Org.BouncyCastle.Crypto.Tls } /// - public static short ReadMaxFragmentLengthExtension(byte[] extensionData) + public static byte ReadMaxFragmentLengthExtension(byte[] extensionData) { - if (extensionData == null) - throw new ArgumentNullException("extensionData"); - - if (extensionData.Length != 1) - throw new TlsFatalAlert(AlertDescription.decode_error); - - return extensionData[0]; + return TlsUtilities.DecodeUint8(extensionData); } /// diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index 48e51a7b6..48eb9d375 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -324,12 +324,47 @@ namespace Org.BouncyCastle.Crypto.Tls WriteUint16Array(uints, buf, offset + 2); } + public static byte DecodeUint8(byte[] buf) + { + if (buf == null) + throw new ArgumentNullException("buf"); + if (buf.Length != 1) + throw new TlsFatalAlert(AlertDescription.decode_error); + return ReadUint8(buf, 0); + } + + public static byte[] DecodeUint8ArrayWithUint8Length(byte[] buf) + { + if (buf == null) + throw new ArgumentNullException("buf"); + + int count = ReadUint8(buf, 0); + if (buf.Length != (count + 1)) + throw new TlsFatalAlert(AlertDescription.decode_error); + + byte[] uints = new byte[count]; + for (int i = 0; i < count; ++i) + { + uints[i] = ReadUint8(buf, i + 1); + } + return uints; + } + public static byte[] EncodeOpaque8(byte[] buf) { CheckUint8(buf.Length); return Arrays.Prepend(buf, (byte)buf.Length); } + public static byte[] EncodeUint8(byte val) + { + CheckUint8(val); + + byte[] extensionData = new byte[1]; + WriteUint8(val, extensionData, 0); + return extensionData; + } + public static byte[] EncodeUint8ArrayWithUint8Length(byte[] uints) { byte[] result = new byte[1 + uints.Length]; -- cgit 1.4.1