From 32918b3230589b5bd10c44e07b4b415e3b96f767 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 14:01:39 -0500 Subject: [PATCH 01/14] Added support for session resumption using RFC5077 session ticket in TLSClient --- .../crypto/tls/AbstractTlsClient.java | 452 +++++++++--------- .../crypto/tls/DTLSClientProtocol.java | 11 +- .../crypto/tls/SecurityParameters.java | 18 + .../bouncycastle/crypto/tls/TlsClient.java | 160 ++++--- .../crypto/tls/TlsClientProtocol.java | 8 +- .../crypto/tls/test/MockTlsClient.java | 22 + 6 files changed, 356 insertions(+), 315 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 980a9678ac..1f0024768f 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -4,242 +4,218 @@ import java.util.Hashtable; import java.util.Vector; -public abstract class AbstractTlsClient - extends AbstractTlsPeer - implements TlsClient -{ - protected TlsCipherFactory cipherFactory; - - protected TlsClientContext context; - - protected Vector supportedSignatureAlgorithms; - protected int[] namedCurves; - protected short[] clientECPointFormats, serverECPointFormats; - - protected int selectedCipherSuite; - protected short selectedCompressionMethod; - - public AbstractTlsClient() - { - this(new DefaultTlsCipherFactory()); - } - - public AbstractTlsClient(TlsCipherFactory cipherFactory) - { - this.cipherFactory = cipherFactory; - } - - public void init(TlsClientContext context) - { - this.context = context; - } - - public TlsSession getSessionToResume() - { - return null; - } - - /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value - * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest - * version number supported by the client, and the value of ClientHello.client_version. No - * single value will guarantee interoperability with all old servers, but this is a complex - * topic beyond the scope of this document." - */ - public ProtocolVersion getClientHelloRecordLayerVersion() - { - // "{03,00}" - // return ProtocolVersion.SSLv3; - - // "the lowest version number supported by the client" - // return getMinimumVersion(); - - // "the value of ClientHello.client_version" - return getClientVersion(); - } - - public ProtocolVersion getClientVersion() - { - return ProtocolVersion.TLSv12; - } - - public boolean isFallback() - { - /* - * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients that repeat a - * connection attempt with a downgraded protocol in order to avoid interoperability problems - * with legacy servers. - */ - return false; - } - - public Hashtable getClientExtensions() - throws IOException - { - Hashtable clientExtensions = null; - - ProtocolVersion clientVersion = context.getClientVersion(); - - /* - * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2. - * Clients MUST NOT offer it if they are offering prior versions. - */ - if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) - { - // TODO Provide a way for the user to specify the acceptable hash/signature algorithms. - - short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; - - // TODO Sort out ECDSA signatures and add them as the preferred option here - short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa }; - - this.supportedSignatureAlgorithms = new Vector(); - for (int i = 0; i < hashAlgorithms.length; ++i) - { - for (int j = 0; j < signatureAlgorithms.length; ++j) - { - this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], - signatureAlgorithms[j])); - } - } - - /* - * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. - */ - this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, - SignatureAlgorithm.dsa)); - - clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); - - TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms); - } - - if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) - { - /* - * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message - * appends these extensions (along with any others), enumerating the curves it supports - * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic - * Curves Extension and the Supported Point Formats Extension. - */ - /* - * TODO Could just add all the curves since we support them all, but users may not want - * to use unnecessarily large fields. Need configuration options. - */ - this.namedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 }; - this.clientECPointFormats = new short[]{ ECPointFormat.uncompressed, - ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; - - clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); - - TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves); - TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats); - } - - return clientExtensions; - } - - public ProtocolVersion getMinimumVersion() - { - return ProtocolVersion.TLSv10; - } - - public void notifyServerVersion(ProtocolVersion serverVersion) - throws IOException - { - if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion)) - { - throw new TlsFatalAlert(AlertDescription.protocol_version); - } - } - - public short[] getCompressionMethods() - { - return new short[]{CompressionMethod._null}; - } - - public void notifySessionID(byte[] sessionID) - { - // Currently ignored - } - - public void notifySelectedCipherSuite(int selectedCipherSuite) - { - this.selectedCipherSuite = selectedCipherSuite; - } - - public void notifySelectedCompressionMethod(short selectedCompressionMethod) - { - this.selectedCompressionMethod = selectedCompressionMethod; - } - - public void processServerExtensions(Hashtable serverExtensions) - throws IOException - { - /* - * TlsProtocol implementation validates that any server extensions received correspond to - * client extensions sent. By default, we don't send any, and this method is not called. - */ - if (serverExtensions != null) - { - /* - * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension. - */ - if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms)) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions); - if (namedCurves != null) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions); - if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite)) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - } - } - - public void processServerSupplementalData(Vector serverSupplementalData) - throws IOException - { - if (serverSupplementalData != null) - { - throw new TlsFatalAlert(AlertDescription.unexpected_message); - } - } - - public Vector getClientSupplementalData() - throws IOException - { - return null; - } - - public TlsCompression getCompression() - throws IOException - { - switch (selectedCompressionMethod) - { - case CompressionMethod._null: - return new TlsNullCompression(); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected compression method was in the list of client-offered compression - * methods, so if we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public void notifyNewSessionTicket(NewSessionTicket newSessionTicket) - throws IOException - { - } +public abstract class AbstractTlsClient extends AbstractTlsPeer implements TlsClient { + protected TlsCipherFactory cipherFactory; + + protected TlsClientContext context; + + protected Vector supportedSignatureAlgorithms; + protected int[] namedCurves; + protected short[] clientECPointFormats, serverECPointFormats; + + protected int selectedCipherSuite; + protected short selectedCompressionMethod; + + public AbstractTlsClient() { + this(new DefaultTlsCipherFactory()); + } + + public AbstractTlsClient(TlsCipherFactory cipherFactory) { + this.cipherFactory = cipherFactory; + } + + public void init(TlsClientContext context) { + this.context = context; + } + + public TlsSession getSessionToResume() { + return null; + } + + /** + * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY + * send any value {03,XX} as the record layer version number. Typical values + * would be {03,00}, the lowest version number supported by the client, and + * the value of ClientHello.client_version. No single value will guarantee + * interoperability with all old servers, but this is a complex topic beyond + * the scope of this document." + */ + public ProtocolVersion getClientHelloRecordLayerVersion() { + // "{03,00}" + // return ProtocolVersion.SSLv3; + + // "the lowest version number supported by the client" + // return getMinimumVersion(); + + // "the value of ClientHello.client_version" + return getClientVersion(); + } + + public ProtocolVersion getClientVersion() { + return ProtocolVersion.TLSv12; + } + + public boolean isFallback() { + /* + * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients + * that repeat a connection attempt with a downgraded protocol in order + * to avoid interoperability problems with legacy servers. + */ + return false; + } + + public Hashtable getClientExtensions() throws IOException { + Hashtable clientExtensions = null; + + ProtocolVersion clientVersion = context.getClientVersion(); + + /* + * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS + * versions prior to 1.2. Clients MUST NOT offer it if they are offering + * prior versions. + */ + if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) { + // TODO Provide a way for the user to specify the acceptable + // hash/signature algorithms. + + short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, + HashAlgorithm.sha224, HashAlgorithm.sha1 }; + + // TODO Sort out ECDSA signatures and add them as the preferred + // option here + short[] signatureAlgorithms = new short[] { SignatureAlgorithm.rsa }; + + this.supportedSignatureAlgorithms = new Vector(); + for (int i = 0; i < hashAlgorithms.length; ++i) { + for (int j = 0; j < signatureAlgorithms.length; ++j) { + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); + } + } + + /* + * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. + */ + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); + + clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); + + TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms); + } + + if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) { + /* + * RFC 4492 5.1. A client that proposes ECC cipher suites in its + * ClientHello message appends these extensions (along with any + * others), enumerating the curves it supports and the point formats + * it can parse. Clients SHOULD send both the Supported Elliptic + * Curves Extension and the Supported Point Formats Extension. + */ + /* + * TODO Could just add all the curves since we support them all, but + * users may not want to use unnecessarily large fields. Need + * configuration options. + */ + this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; + this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, + ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; + + clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); + + TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves); + TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats); + } + + return clientExtensions; + } + + public ProtocolVersion getMinimumVersion() { + return ProtocolVersion.TLSv10; + } + + public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException { + if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion)) { + throw new TlsFatalAlert(AlertDescription.protocol_version); + } + } + + public short[] getCompressionMethods() { + return new short[] { CompressionMethod._null }; + } + + public void notifySessionID(byte[] sessionID) { + // Currently ignored + } + + public void notifySelectedCipherSuite(int selectedCipherSuite) { + this.selectedCipherSuite = selectedCipherSuite; + } + + public void notifySelectedCompressionMethod(short selectedCompressionMethod) { + this.selectedCompressionMethod = selectedCompressionMethod; + } + + public void processServerExtensions(Hashtable serverExtensions) throws IOException { + /* + * TlsProtocol implementation validates that any server extensions + * received correspond to client extensions sent. By default, we don't + * send any, and this method is not called. + */ + if (serverExtensions != null) { + /* + * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension. + */ + if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms)) { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions); + if (namedCurves != null) { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions); + if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite)) { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + } + } + + public void processServerSupplementalData(Vector serverSupplementalData) throws IOException { + if (serverSupplementalData != null) { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public Vector getClientSupplementalData() throws IOException { + return null; + } + + public TlsCompression getCompression() throws IOException { + switch (selectedCompressionMethod) { + case CompressionMethod._null: + return new TlsNullCompression(); + + default: + /* + * Note: internal error here; the TlsProtocol implementation + * verifies that the server-selected compression method was in the + * list of client-offered compression methods, so if we now can't + * produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException { + } + + public NewSessionTicket getNewSessionTicket() throws IOException { + return null; + } + + public SecurityParameters getSecurityParameters() throws IOException { + return null; + } } diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java index fd26555670..21260655d3 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/DTLSClientProtocol.java @@ -602,8 +602,15 @@ protected void processNewSessionTicket(ClientHandshakeState state, byte[] body) NewSessionTicket newSessionTicket = NewSessionTicket.parse(buf); TlsProtocol.assertEmpty(buf); - - state.client.notifyNewSessionTicket(newSessionTicket); + + /* + * RFC 5077 - notify client so it can save the ticket and security + * parameters for session resumption. + */ + SecurityParameters securityParameters = new SecurityParameters(); + securityParameters.copySecurityParametersFrom(state.clientContext.getSecurityParameters()); + + state.client.notifyNewSessionTicket(newSessionTicket, securityParameters); } protected Certificate processServerCertificate(ClientHandshakeState state, byte[] body) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java b/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java index 5241144ee6..fb8062b726 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/SecurityParameters.java @@ -19,6 +19,24 @@ public class SecurityParameters boolean truncatedHMac = false; boolean encryptThenMAC = false; boolean extendedMasterSecret = false; + + /** + * Copies the security parameters from another instance if it is not null, + * otherwise this is a no-op. + * + * @param other + */ + void copySecurityParametersFrom(SecurityParameters other) + { + if (other != null) { + this.entity = other.entity; + this.cipherSuite = other.cipherSuite; + this.compressionAlgorithm = other.compressionAlgorithm; + this.prfAlgorithm = other.prfAlgorithm; + this.verifyDataLength = other.verifyDataLength; + this.masterSecret = Arrays.clone(other.masterSecret); + } + } void clear() { diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java index da688b047a..21ee990446 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java @@ -4,78 +4,90 @@ import java.util.Hashtable; import java.util.Vector; -public interface TlsClient - extends TlsPeer -{ - void init(TlsClientContext context); - - /** - * Return the session this client wants to resume, if any. Note that the peer's certificate - * chain for the session (if any) may need to be periodically revalidated. - * - * @return A {@link TlsSession} representing the resumable session to be used for this - * connection, or null to use a new session. - * @see SessionParameters#getPeerCertificate() - */ - TlsSession getSessionToResume(); - - ProtocolVersion getClientHelloRecordLayerVersion(); - - ProtocolVersion getClientVersion(); - - boolean isFallback(); - - int[] getCipherSuites(); - - short[] getCompressionMethods(); - - // Hashtable is (Integer -> byte[]) - Hashtable getClientExtensions() - throws IOException; - - void notifyServerVersion(ProtocolVersion selectedVersion) - throws IOException; - - /** - * Notifies the client of the session_id sent in the ServerHello. - * - * @param sessionID - * @see TlsContext#getResumableSession() - */ - void notifySessionID(byte[] sessionID); - - void notifySelectedCipherSuite(int selectedCipherSuite); - - void notifySelectedCompressionMethod(short selectedCompressionMethod); - - // Hashtable is (Integer -> byte[]) - void processServerExtensions(Hashtable serverExtensions) - throws IOException; - - // Vector is (SupplementalDataEntry) - void processServerSupplementalData(Vector serverSupplementalData) - throws IOException; - - TlsKeyExchange getKeyExchange() - throws IOException; - - TlsAuthentication getAuthentication() - throws IOException; - - // Vector is (SupplementalDataEntry) - Vector getClientSupplementalData() - throws IOException; - - /** - * RFC 5077 3.3. NewSessionTicket Handshake Message - *

- * This method will be called (only) when a NewSessionTicket handshake message is received. The - * ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption - * that it complies with e.g. RFC 5077 4. Recommended Ticket Construction. - * - * @param newSessionTicket The ticket. - * @throws IOException - */ - void notifyNewSessionTicket(NewSessionTicket newSessionTicket) - throws IOException; +public interface TlsClient extends TlsPeer { + void init(TlsClientContext context); + + /** + * Return the session this client wants to resume, if any. Note that the + * peer's certificate chain for the session (if any) may need to be + * periodically revalidated. + * + * @return A {@link TlsSession} representing the resumable session to be + * used for this connection, or null to use a new session. + * @see SessionParameters#getPeerCertificate() + */ + TlsSession getSessionToResume(); + + ProtocolVersion getClientHelloRecordLayerVersion(); + + ProtocolVersion getClientVersion(); + + boolean isFallback(); + + int[] getCipherSuites(); + + short[] getCompressionMethods(); + + // Hashtable is (Integer -> byte[]) + Hashtable getClientExtensions() throws IOException; + + void notifyServerVersion(ProtocolVersion selectedVersion) throws IOException; + + /** + * Notifies the client of the session_id sent in the ServerHello. + * + * @param sessionID + * @see TlsContext#getResumableSession() + */ + void notifySessionID(byte[] sessionID); + + void notifySelectedCipherSuite(int selectedCipherSuite); + + void notifySelectedCompressionMethod(short selectedCompressionMethod); + + // Hashtable is (Integer -> byte[]) + void processServerExtensions(Hashtable serverExtensions) throws IOException; + + // Vector is (SupplementalDataEntry) + void processServerSupplementalData(Vector serverSupplementalData) throws IOException; + + TlsKeyExchange getKeyExchange() throws IOException; + + TlsAuthentication getAuthentication() throws IOException; + + // Vector is (SupplementalDataEntry) + Vector getClientSupplementalData() throws IOException; + + /** + * RFC 5077 3.3. NewSessionTicket Handshake Message + *

+ * This method will be called (only) when a NewSessionTicket handshake + * message is received. The ticket is opaque to the client and clients MUST + * NOT examine the ticket under the assumption that it complies with e.g. + * RFC 5077 4. Recommended Ticket Construction. + * + * @param newSessionTicket + * The ticket. + * @param sessionParameters + * @throws IOException + */ + void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException; + + /** + * + * @return a {@link NewSessionTicket} + * @throws IOException + */ + NewSessionTicket getNewSessionTicket() throws IOException; + + /** + * In the case of TLS resumption using session tickets, + * {@link TlsClient#getSessionToResume()} may return a null TlsSession. Use + * this method to retrieve the security parameters needed for session + * resumption. + * + * @return A {@link SecurityParameters} object + * @throws IOException + */ + SecurityParameters getSecurityParameters() throws IOException; } diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java index 9bf6803ffc..724282622d 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java @@ -577,7 +577,13 @@ protected void receiveNewSessionTicketMessage(ByteArrayInputStream buf) assertEmpty(buf); - tlsClient.notifyNewSessionTicket(newSessionTicket); + /* + * RFC 5077 - notify client so it can save the ticket and security + * parameters for session resumption. + */ + SecurityParameters securityParameters = new SecurityParameters(); + securityParameters.copySecurityParametersFrom(this.securityParameters); + tlsClient.notifyNewSessionTicket(newSessionTicket, securityParameters); } protected void receiveServerHelloMessage(ByteArrayInputStream buf) diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java index 3530b4a72c..c08fafdd1c 100644 --- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java +++ b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java @@ -12,7 +12,9 @@ import org.bouncycastle.crypto.tls.ClientCertificateType; import org.bouncycastle.crypto.tls.DefaultTlsClient; import org.bouncycastle.crypto.tls.MaxFragmentLength; +import org.bouncycastle.crypto.tls.NewSessionTicket; import org.bouncycastle.crypto.tls.ProtocolVersion; +import org.bouncycastle.crypto.tls.SecurityParameters; import org.bouncycastle.crypto.tls.SignatureAlgorithm; import org.bouncycastle.crypto.tls.SignatureAndHashAlgorithm; import org.bouncycastle.crypto.tls.TlsAuthentication; @@ -26,6 +28,8 @@ class MockTlsClient extends DefaultTlsClient { TlsSession session; + NewSessionTicket sessionTicket; + SecurityParameters securityParameters; MockTlsClient(TlsSession session) { @@ -167,4 +171,22 @@ public void notifyHandshakeComplete() throws IOException this.session = newSession; } } + + public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) + throws IOException + { + super.notifyNewSessionTicket(newSessionTicket, securityParameters); + this.sessionTicket = newSessionTicket; + this.securityParameters = securityParameters; + } + + public NewSessionTicket getSessionTicket() + { + return sessionTicket; + } + + public SecurityParameters getSecurityParameters() + { + return this.securityParameters; + } } From fb459392a9ffc3beff5a78007327139e9f5c1039 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 14:20:11 -0500 Subject: [PATCH 02/14] Added a constructor for MockTlsClient that takes the RFC5077 session ticket and security params --- .../org/bouncycastle/crypto/tls/test/MockTlsClient.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java index c08fafdd1c..bb60e150e4 100644 --- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java +++ b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java @@ -35,6 +35,12 @@ class MockTlsClient { this.session = session; } + + MockTlsClient(NewSessionTicket sessionTicket, SecurityParameters securityParameters) + { + this.sessionTicket = sessionTicket; + this.securityParameters = securityParameters; + } public TlsSession getSessionToResume() { From 2bbad37f3a5e04d49557b2d64db8d8a8b305d5c1 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 14:57:05 -0500 Subject: [PATCH 03/14] Use RFC 5077 session ticket for session resumption --- .../crypto/tls/TlsClientProtocol.java | 106 ++++++++++++++++-- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java index 724282622d..e405b009b2 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java @@ -1,6 +1,7 @@ package org.bouncycastle.crypto.tls; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -252,7 +253,31 @@ protected void handleHandshakeMessage(short type, byte[] data) if (this.resumedSession) { - this.securityParameters.masterSecret = Arrays.clone(this.sessionParameters.getMasterSecret()); + /* + * RFC 5077 - The master secret to use depends on whether + * resumed session using session id or ticket. + * + * If this is resumed session, we expect either session + * parameters to be available or the client to provide us + * with security parameters. If neither gives us master + * secret, we raise an alert. + */ + + if (this.sessionParameters != null) + { + this.securityParameters.masterSecret = Arrays.clone(this.sessionParameters.getMasterSecret()); + } + else if (this.tlsClient.getNewSessionTicket() != null + && this.tlsClient.getSecurityParameters() != null) + { + this.securityParameters.masterSecret = Arrays.clone(this.tlsClient.getSecurityParameters() + .getMasterSecret()); + } + else + { + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + this.recordStream.setPendingConnectionState(getPeer().getCompression(), getPeer().getCipher()); sendChangeCipherSpecMessage(); @@ -623,10 +648,12 @@ protected void receiveServerHelloMessage(ByteArrayInputStream buf) } this.tlsClient.notifySessionID(this.selectedSessionID); - - this.resumedSession = this.selectedSessionID.length > 0 && this.tlsSession != null - && Arrays.areEqual(this.selectedSessionID, this.tlsSession.getSessionID()); - + + /* + * RFC 5077 - can resume either using session id or using + * NewSessionTicket + */ + this.resumedSession = canResumeUsingSessionId() || canResumeUsingNewSessionTicket(); /* * Find out which CipherSuite the server has chosen and check that it was one of the offered * ones, and is a valid selection for the negotiated version. @@ -771,14 +798,49 @@ protected void receiveServerHelloMessage(ByteArrayInputStream buf) Hashtable sessionClientExtensions = clientExtensions, sessionServerExtensions = serverExtensions; if (this.resumedSession) { - if (selectedCipherSuite != this.sessionParameters.getCipherSuite() - || selectedCompressionMethod != this.sessionParameters.getCompressionAlgorithm()) + /* + * RFC 5077 - We will have session parameters only if there is a TLS + * session (with id). In the case of session tickets, there is no + * TLS session. So the check to ensure whether the selected cipher + * suite and compression algorithm match with expected ones depends + * on whether session resumption using session id or ticket is being + * done. In the case of session id, expected cipher suite and + * compression algorithm are from the session parameters. In the + * case of session ticket, they are from the security parameters + * (expected to be stored in the client). + */ + + int expectedCipherSuite = -1; + short expectedCompressionAlgorithm = -1; + + if (this.selectedSessionID != null && this.selectedSessionID.length > 0) + { + expectedCipherSuite = this.sessionParameters.getCipherSuite(); + expectedCompressionAlgorithm = this.sessionParameters.getCompressionAlgorithm(); + } + else if (this.tlsClient.getNewSessionTicket() != null && this.tlsClient.getSecurityParameters() != null) + { + expectedCipherSuite = this.tlsClient.getSecurityParameters().getCipherSuite(); + expectedCompressionAlgorithm = this.tlsClient.getSecurityParameters().getCompressionAlgorithm(); + } + else + { + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + + if (selectedCipherSuite != expectedCipherSuite || selectedCompressionMethod != expectedCompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } sessionClientExtensions = null; - sessionServerExtensions = this.sessionParameters.readServerExtensions(); + + // RFC 5077 - this.sessionParameters can be null if resuming using + // session tickets + if (this.sessionParameters != null) + { + sessionServerExtensions = this.sessionParameters.readServerExtensions(); + } this.securityParameters.extendedMasterSecret = TlsExtensionsUtils.hasExtendedMasterSecretExtension(sessionServerExtensions); } @@ -925,6 +987,23 @@ protected void sendClientHelloMessage() } TlsUtils.writeUint8ArrayWithUint8Length(offeredCompressionMethods, message); + + /* + * RFC 5077 - If the client supports session ticket extension and it has + * a ticket, then put the ticket in the client hello. + */ + byte[] sessionTicketExtData = TlsUtils.getExtensionData(clientExtensions, EXT_SessionTicket); + NewSessionTicket sessionTicket = tlsClient.getNewSessionTicket(); + + boolean sessionTicketExtSupported = sessionTicketExtData != null; + boolean sessionTicketPresent = sessionTicket != null; + + if (sessionTicketExtSupported && sessionTicketPresent) + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + sessionTicket.encode(output); + clientExtensions.put(EXT_SessionTicket, output.toByteArray()); + } if (clientExtensions != null) { @@ -943,4 +1022,15 @@ protected void sendClientKeyExchangeMessage() message.writeToRecordStream(); } + + private boolean canResumeUsingSessionId() + { + return this.selectedSessionID.length > 0 && this.tlsSession != null + && Arrays.areEqual(this.selectedSessionID, this.tlsSession.getSessionID()); + } + + private boolean canResumeUsingNewSessionTicket() + { + return this.tlsClient.getNewSessionTicket() != null; + } } From b9a992fe4f8288963de6f9bcbce029a1391032f3 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 15:01:40 -0500 Subject: [PATCH 04/14] Sample code for tls session resumption using RFC session tickets --- .../org/bouncycastle/crypto/tls/test/TlsClientTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java index 736913e618..f3a49e6b8d 100644 --- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java @@ -37,6 +37,7 @@ public static void main(String[] args) long time2 = System.currentTimeMillis(); System.out.println("Elapsed 1: " + (time2 - time1) + "ms"); + // session resumption using session id client = new MockTlsClient(client.getSessionToResume()); protocol = openTlsConnection(address, port, client); @@ -57,6 +58,12 @@ public static void main(String[] args) } protocol.close(); + + // session resumption using session tickets + client = new MockTlsClient(client.getSessionTicket(), client.getSecurityParameters()); + protocol = openTlsConnection(address, port, client); + protocol.close(); + } static TlsClientProtocol openTlsConnection(InetAddress address, int port, TlsClient client) throws IOException From 2f8a7670dcbfb4bd90b6ab11c2f147e45b045688 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 15:03:52 -0500 Subject: [PATCH 05/14] Removed throws clause for the new methods for session resumption in TlsClient --- .../java/org/bouncycastle/crypto/tls/AbstractTlsClient.java | 4 ++-- .../src/main/java/org/bouncycastle/crypto/tls/TlsClient.java | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 1f0024768f..f281f185ac 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -211,11 +211,11 @@ public TlsCompression getCompression() throws IOException { public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException { } - public NewSessionTicket getNewSessionTicket() throws IOException { + public NewSessionTicket getNewSessionTicket() { return null; } - public SecurityParameters getSecurityParameters() throws IOException { + public SecurityParameters getSecurityParameters() { return null; } } diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java index 21ee990446..9296b2f8c9 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java @@ -76,9 +76,8 @@ public interface TlsClient extends TlsPeer { /** * * @return a {@link NewSessionTicket} - * @throws IOException */ - NewSessionTicket getNewSessionTicket() throws IOException; + NewSessionTicket getNewSessionTicket(); /** * In the case of TLS resumption using session tickets, @@ -89,5 +88,5 @@ public interface TlsClient extends TlsPeer { * @return A {@link SecurityParameters} object * @throws IOException */ - SecurityParameters getSecurityParameters() throws IOException; + SecurityParameters getSecurityParameters(); } From 31c56244d60944a25dbe0603f6fe425eac5d19ba Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Tue, 22 Dec 2015 19:14:02 -0500 Subject: [PATCH 06/14] missed few things from my previous commit --- .../java/org/bouncycastle/crypto/tls/NewSessionTicket.java | 7 +++++++ .../org/bouncycastle/crypto/tls/TlsClientProtocol.java | 2 +- .../org/bouncycastle/crypto/tls/TlsExtensionsUtils.java | 6 ++++++ .../org/bouncycastle/crypto/tls/test/MockTlsClient.java | 3 ++- .../org/bouncycastle/crypto/tls/test/TlsClientTest.java | 2 +- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java b/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java index 8f87a65ee8..e83f190b9e 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/NewSessionTicket.java @@ -37,6 +37,13 @@ public void encode(OutputStream output) TlsUtils.writeUint32(ticketLifetimeHint, output); TlsUtils.writeOpaque16(ticket, output); } + + public void encodeWithoutLifetime(OutputStream output) throws IOException + { + // just raw ticket bytes + // length will be added later + output.write(ticket); + } /** * Parse a {@link NewSessionTicket} from an {@link InputStream}. diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java index e405b009b2..9fd8ce4bb0 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClientProtocol.java @@ -1001,7 +1001,7 @@ protected void sendClientHelloMessage() if (sessionTicketExtSupported && sessionTicketPresent) { ByteArrayOutputStream output = new ByteArrayOutputStream(); - sessionTicket.encode(output); + sessionTicket.encodeWithoutLifetime(output); clientExtensions.put(EXT_SessionTicket, output.toByteArray()); } diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java index 8e50f57d5f..1d6dc7b80e 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsExtensionsUtils.java @@ -16,6 +16,7 @@ public class TlsExtensionsUtils public static final Integer EXT_server_name = Integers.valueOf(ExtensionType.server_name); public static final Integer EXT_status_request = Integers.valueOf(ExtensionType.status_request); public static final Integer EXT_truncated_hmac = Integers.valueOf(ExtensionType.truncated_hmac); + public static final Integer EXT_session_tickets = Integer.valueOf(ExtensionType.session_ticket); public static Hashtable ensureExtensionsInitialised(Hashtable extensions) { @@ -60,6 +61,11 @@ public static void addTruncatedHMacExtension(Hashtable extensions) { extensions.put(EXT_truncated_hmac, createTruncatedHMacExtension()); } + + public static void addSessionTicketExtension(Hashtable extensions) + { + extensions.put(EXT_session_tickets, createEmptyExtensionData()); + } public static HeartbeatExtension getHeartbeatExtension(Hashtable extensions) throws IOException diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java index bb60e150e4..2d1b727d07 100644 --- a/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java +++ b/core/src/test/java/org/bouncycastle/crypto/tls/test/MockTlsClient.java @@ -90,6 +90,7 @@ public Hashtable getClientExtensions() throws IOException // TlsExtensionsUtils.addExtendedMasterSecretExtension(clientExtensions); TlsExtensionsUtils.addMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); TlsExtensionsUtils.addTruncatedHMacExtension(clientExtensions); + TlsExtensionsUtils.addSessionTicketExtension(clientExtensions); return clientExtensions; } @@ -186,7 +187,7 @@ public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityPa this.securityParameters = securityParameters; } - public NewSessionTicket getSessionTicket() + public NewSessionTicket getNewSessionTicket() { return sessionTicket; } diff --git a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java index f3a49e6b8d..3a897d822d 100644 --- a/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/tls/test/TlsClientTest.java @@ -60,7 +60,7 @@ public static void main(String[] args) protocol.close(); // session resumption using session tickets - client = new MockTlsClient(client.getSessionTicket(), client.getSecurityParameters()); + client = new MockTlsClient(client.getNewSessionTicket(), client.getSecurityParameters()); protocol = openTlsConnection(address, port, client); protocol.close(); From 7311c303e75852bb69356abb509655b7e8a364ff Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 10:59:40 -0500 Subject: [PATCH 07/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 464 ++++++++++-------- 1 file changed, 250 insertions(+), 214 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index f281f185ac..7a177e686a 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -4,218 +4,254 @@ import java.util.Hashtable; import java.util.Vector; -public abstract class AbstractTlsClient extends AbstractTlsPeer implements TlsClient { - protected TlsCipherFactory cipherFactory; - - protected TlsClientContext context; - - protected Vector supportedSignatureAlgorithms; - protected int[] namedCurves; - protected short[] clientECPointFormats, serverECPointFormats; - - protected int selectedCipherSuite; - protected short selectedCompressionMethod; - - public AbstractTlsClient() { - this(new DefaultTlsCipherFactory()); - } - - public AbstractTlsClient(TlsCipherFactory cipherFactory) { - this.cipherFactory = cipherFactory; - } - - public void init(TlsClientContext context) { - this.context = context; - } - - public TlsSession getSessionToResume() { - return null; - } - - /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY - * send any value {03,XX} as the record layer version number. Typical values - * would be {03,00}, the lowest version number supported by the client, and - * the value of ClientHello.client_version. No single value will guarantee - * interoperability with all old servers, but this is a complex topic beyond - * the scope of this document." - */ - public ProtocolVersion getClientHelloRecordLayerVersion() { - // "{03,00}" - // return ProtocolVersion.SSLv3; - - // "the lowest version number supported by the client" - // return getMinimumVersion(); - - // "the value of ClientHello.client_version" - return getClientVersion(); - } - - public ProtocolVersion getClientVersion() { - return ProtocolVersion.TLSv12; - } - - public boolean isFallback() { - /* - * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients - * that repeat a connection attempt with a downgraded protocol in order - * to avoid interoperability problems with legacy servers. - */ - return false; - } - - public Hashtable getClientExtensions() throws IOException { - Hashtable clientExtensions = null; - - ProtocolVersion clientVersion = context.getClientVersion(); - - /* - * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS - * versions prior to 1.2. Clients MUST NOT offer it if they are offering - * prior versions. - */ - if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) { - // TODO Provide a way for the user to specify the acceptable - // hash/signature algorithms. - - short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; - - // TODO Sort out ECDSA signatures and add them as the preferred - // option here - short[] signatureAlgorithms = new short[] { SignatureAlgorithm.rsa }; - - this.supportedSignatureAlgorithms = new Vector(); - for (int i = 0; i < hashAlgorithms.length; ++i) { - for (int j = 0; j < signatureAlgorithms.length; ++j) { - this.supportedSignatureAlgorithms - .addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); - } - } - - /* - * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. - */ - this.supportedSignatureAlgorithms - .addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); - - clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); - - TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms); - } - - if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) { - /* - * RFC 4492 5.1. A client that proposes ECC cipher suites in its - * ClientHello message appends these extensions (along with any - * others), enumerating the curves it supports and the point formats - * it can parse. Clients SHOULD send both the Supported Elliptic - * Curves Extension and the Supported Point Formats Extension. - */ - /* - * TODO Could just add all the curves since we support them all, but - * users may not want to use unnecessarily large fields. Need - * configuration options. - */ - this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; - this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, - ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; - - clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); - - TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves); - TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats); - } - - return clientExtensions; - } - - public ProtocolVersion getMinimumVersion() { - return ProtocolVersion.TLSv10; - } - - public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException { - if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion)) { - throw new TlsFatalAlert(AlertDescription.protocol_version); - } - } - - public short[] getCompressionMethods() { - return new short[] { CompressionMethod._null }; - } - - public void notifySessionID(byte[] sessionID) { - // Currently ignored - } - - public void notifySelectedCipherSuite(int selectedCipherSuite) { - this.selectedCipherSuite = selectedCipherSuite; - } - - public void notifySelectedCompressionMethod(short selectedCompressionMethod) { - this.selectedCompressionMethod = selectedCompressionMethod; - } - - public void processServerExtensions(Hashtable serverExtensions) throws IOException { - /* - * TlsProtocol implementation validates that any server extensions - * received correspond to client extensions sent. By default, we don't - * send any, and this method is not called. - */ - if (serverExtensions != null) { - /* - * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension. - */ - if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms)) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions); - if (namedCurves != null) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions); - if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite)) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - } - } - - public void processServerSupplementalData(Vector serverSupplementalData) throws IOException { - if (serverSupplementalData != null) { - throw new TlsFatalAlert(AlertDescription.unexpected_message); - } - } - - public Vector getClientSupplementalData() throws IOException { - return null; - } - - public TlsCompression getCompression() throws IOException { - switch (selectedCompressionMethod) { - case CompressionMethod._null: - return new TlsNullCompression(); - - default: - /* - * Note: internal error here; the TlsProtocol implementation - * verifies that the server-selected compression method was in the - * list of client-offered compression methods, so if we now can't - * produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException { - } - - public NewSessionTicket getNewSessionTicket() { - return null; - } - - public SecurityParameters getSecurityParameters() { - return null; - } +public abstract class AbstractTlsClient + extends AbstractTlsPeer + implements TlsClient +{ + protected TlsCipherFactory cipherFactory; + + protected TlsClientContext context; + + protected Vector supportedSignatureAlgorithms; + protected int[] namedCurves; + protected short[] clientECPointFormats, serverECPointFormats; + + protected int selectedCipherSuite; + protected short selectedCompressionMethod; + + public AbstractTlsClient() + { + this(new DefaultTlsCipherFactory()); + } + + public AbstractTlsClient(TlsCipherFactory cipherFactory) + { + this.cipherFactory = cipherFactory; + } + + public void init(TlsClientContext context) + { + this.context = context; + } + + public TlsSession getSessionToResume() + { + return null; + } + + /** + * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY + * send any value {03,XX} as the record layer version number. Typical values + * would be {03,00}, the lowest version number supported by the client, and + * the value of ClientHello.client_version. No single value will guarantee + * interoperability with all old servers, but this is a complex topic beyond + * the scope of this document." + */ + public ProtocolVersion getClientHelloRecordLayerVersion() + { + // "{03,00}" + // return ProtocolVersion.SSLv3; + + // "the lowest version number supported by the client" + // return getMinimumVersion(); + + // "the value of ClientHello.client_version" + return getClientVersion(); + } + + public ProtocolVersion getClientVersion() + { + return ProtocolVersion.TLSv12; + } + + public boolean isFallback() + { + /* + * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients + * that repeat a connection attempt with a downgraded protocol in order + * to avoid interoperability problems with legacy servers. + */ + return false; + } + + public Hashtable getClientExtensions() throws IOException + { + Hashtable clientExtensions = null; + + ProtocolVersion clientVersion = context.getClientVersion(); + + /* + * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS + * versions prior to 1.2. Clients MUST NOT offer it if they are offering + * prior versions. + */ + if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) + { + // TODO Provide a way for the user to specify the acceptable + // hash/signature algorithms. + + short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, + HashAlgorithm.sha224, HashAlgorithm.sha1 }; + + // TODO Sort out ECDSA signatures and add them as the preferred + // option here + short[] signatureAlgorithms = new short[] { SignatureAlgorithm.rsa }; + + this.supportedSignatureAlgorithms = new Vector(); + for (int i = 0; i < hashAlgorithms.length; ++i) + { + for (int j = 0; j < signatureAlgorithms.length; ++j) + { + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); + } + } + + /* + * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. + */ + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); + + clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); + + TlsUtils.addSignatureAlgorithmsExtension(clientExtensions, supportedSignatureAlgorithms); + } + + if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) + { + /* + * RFC 4492 5.1. A client that proposes ECC cipher suites in its + * ClientHello message appends these extensions (along with any + * others), enumerating the curves it supports and the point formats + * it can parse. Clients SHOULD send both the Supported Elliptic + * Curves Extension and the Supported Point Formats Extension. + */ + /* + * TODO Could just add all the curves since we support them all, but + * users may not want to use unnecessarily large fields. Need + * configuration options. + */ + this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; + this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, + ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; + + clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); + + TlsECCUtils.addSupportedEllipticCurvesExtension(clientExtensions, namedCurves); + TlsECCUtils.addSupportedPointFormatsExtension(clientExtensions, clientECPointFormats); + } + + return clientExtensions; + } + + public ProtocolVersion getMinimumVersion() + { + return ProtocolVersion.TLSv10; + } + + public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException + { + if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion)) + { + throw new TlsFatalAlert(AlertDescription.protocol_version); + } + } + + public short[] getCompressionMethods() + { + return new short[] { CompressionMethod._null }; + } + + public void notifySessionID(byte[] sessionID) + { + // Currently ignored + } + + public void notifySelectedCipherSuite(int selectedCipherSuite) + { + this.selectedCipherSuite = selectedCipherSuite; + } + + public void notifySelectedCompressionMethod(short selectedCompressionMethod) + { + this.selectedCompressionMethod = selectedCompressionMethod; + } + + public void processServerExtensions(Hashtable serverExtensions) throws IOException + { + /* + * TlsProtocol implementation validates that any server extensions + * received correspond to client extensions sent. By default, we don't + * send any, and this method is not called. + */ + if (serverExtensions != null) + { + /* + * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension. + */ + if (serverExtensions.containsKey(TlsUtils.EXT_signature_algorithms)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + int[] namedCurves = TlsECCUtils.getSupportedEllipticCurvesExtension(serverExtensions); + if (namedCurves != null) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + this.serverECPointFormats = TlsECCUtils.getSupportedPointFormatsExtension(serverExtensions); + if (this.serverECPointFormats != null && !TlsECCUtils.isECCCipherSuite(this.selectedCipherSuite)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + } + } + + public void processServerSupplementalData(Vector serverSupplementalData) throws IOException + { + if (serverSupplementalData != null) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + } + + public Vector getClientSupplementalData() throws IOException + { + return null; + } + + public TlsCompression getCompression() throws IOException + { + switch (selectedCompressionMethod) + { + case CompressionMethod._null: + return new TlsNullCompression(); + + default: + /* + * Note: internal error here; the TlsProtocol implementation + * verifies that the server-selected compression method was in the + * list of client-offered compression methods, so if we now can't + * produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) + throws IOException + { + } + + public NewSessionTicket getNewSessionTicket() + { + return null; + } + + public SecurityParameters getSecurityParameters() + { + return null; + } } From 33eb298142c2493c0ff1ca1bd443add78861ecc4 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:04:42 -0500 Subject: [PATCH 08/14] formatted code to conform to master repo --- .../java/org/bouncycastle/crypto/tls/AbstractTlsClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 7a177e686a..39a7762c8d 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -241,7 +241,7 @@ public TlsCompression getCompression() throws IOException } public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) - throws IOException + throws IOException { } From e31b7f6f3ea6fd5a222247682a4887a6ecbec3cf Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:06:39 -0500 Subject: [PATCH 09/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 39a7762c8d..27a0cc12d5 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -90,8 +90,8 @@ public Hashtable getClientExtensions() throws IOException // TODO Provide a way for the user to specify the acceptable // hash/signature algorithms. - short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; + short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, HashAlgorithm.sha224, + HashAlgorithm.sha1 }; // TODO Sort out ECDSA signatures and add them as the preferred // option here @@ -102,16 +102,14 @@ public Hashtable getClientExtensions() throws IOException { for (int j = 0; j < signatureAlgorithms.length; ++j) { - this.supportedSignatureAlgorithms - .addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); + this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); } } /* * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. */ - this.supportedSignatureAlgorithms - .addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); + this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -133,8 +131,8 @@ public Hashtable getClientExtensions() throws IOException * configuration options. */ this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; - this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, - ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; + this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_prime, + ECPointFormat.ansiX962_compressed_char2, }; clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -240,8 +238,7 @@ public TlsCompression getCompression() throws IOException } } - public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) - throws IOException + public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException { } From fb7bb470976c6b8ba4707a249c9a01e8a8093863 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:08:03 -0500 Subject: [PATCH 10/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 27a0cc12d5..f6c1bf2932 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -40,12 +40,10 @@ public TlsSession getSessionToResume() } /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY - * send any value {03,XX} as the record layer version number. Typical values - * would be {03,00}, the lowest version number supported by the client, and - * the value of ClientHello.client_version. No single value will guarantee - * interoperability with all old servers, but this is a complex topic beyond - * the scope of this document." + * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value {03,XX} as the record + * layer version number. Typical values would be {03,00}, the lowest version number supported by the client, and the + * value of ClientHello.client_version. No single value will guarantee interoperability with all old servers, but + * this is a complex topic beyond the scope of this document." */ public ProtocolVersion getClientHelloRecordLayerVersion() { @@ -67,9 +65,8 @@ public ProtocolVersion getClientVersion() public boolean isFallback() { /* - * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients - * that repeat a connection attempt with a downgraded protocol in order - * to avoid interoperability problems with legacy servers. + * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients that repeat a connection attempt with a + * downgraded protocol in order to avoid interoperability problems with legacy servers. */ return false; } @@ -81,17 +78,16 @@ public Hashtable getClientExtensions() throws IOException ProtocolVersion clientVersion = context.getClientVersion(); /* - * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS - * versions prior to 1.2. Clients MUST NOT offer it if they are offering - * prior versions. + * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2. Clients MUST NOT + * offer it if they are offering prior versions. */ if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) { // TODO Provide a way for the user to specify the acceptable // hash/signature algorithms. - short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, HashAlgorithm.sha224, - HashAlgorithm.sha1 }; + short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, + HashAlgorithm.sha224, HashAlgorithm.sha1 }; // TODO Sort out ECDSA signatures and add them as the preferred // option here @@ -102,14 +98,16 @@ public Hashtable getClientExtensions() throws IOException { for (int j = 0; j < signatureAlgorithms.length; ++j) { - this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(hashAlgorithms[i], signatureAlgorithms[j])); } } /* * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. */ - this.supportedSignatureAlgorithms.addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); + this.supportedSignatureAlgorithms + .addElement(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -119,20 +117,18 @@ public Hashtable getClientExtensions() throws IOException if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) { /* - * RFC 4492 5.1. A client that proposes ECC cipher suites in its - * ClientHello message appends these extensions (along with any - * others), enumerating the curves it supports and the point formats - * it can parse. Clients SHOULD send both the Supported Elliptic - * Curves Extension and the Supported Point Formats Extension. + * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message appends these + * extensions (along with any others), enumerating the curves it supports and the point formats it can + * parse. Clients SHOULD send both the Supported Elliptic Curves Extension and the Supported Point Formats + * Extension. */ /* - * TODO Could just add all the curves since we support them all, but - * users may not want to use unnecessarily large fields. Need - * configuration options. + * TODO Could just add all the curves since we support them all, but users may not want to use unnecessarily + * large fields. Need configuration options. */ this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; - this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_prime, - ECPointFormat.ansiX962_compressed_char2, }; + this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, + ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -179,9 +175,8 @@ public void notifySelectedCompressionMethod(short selectedCompressionMethod) public void processServerExtensions(Hashtable serverExtensions) throws IOException { /* - * TlsProtocol implementation validates that any server extensions - * received correspond to client extensions sent. By default, we don't - * send any, and this method is not called. + * TlsProtocol implementation validates that any server extensions received correspond to client extensions + * sent. By default, we don't send any, and this method is not called. */ if (serverExtensions != null) { @@ -229,16 +224,16 @@ public TlsCompression getCompression() throws IOException default: /* - * Note: internal error here; the TlsProtocol implementation - * verifies that the server-selected compression method was in the - * list of client-offered compression methods, so if we now can't - * produce an implementation, we shouldn't have offered it! + * Note: internal error here; the TlsProtocol implementation verifies that the server-selected compression + * method was in the list of client-offered compression methods, so if we now can't produce an + * implementation, we shouldn't have offered it! */ throw new TlsFatalAlert(AlertDescription.internal_error); } } - public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException + public void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) + throws IOException { } From 150c4c5329a837c96e7fefdb16a5123162101eef Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:14:20 -0500 Subject: [PATCH 11/14] formatted code to conform to master repo --- .../bouncycastle/crypto/tls/AbstractTlsClient.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index f6c1bf2932..b49020e4d3 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -86,12 +86,12 @@ public Hashtable getClientExtensions() throws IOException // TODO Provide a way for the user to specify the acceptable // hash/signature algorithms. - short[] hashAlgorithms = new short[] { HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; + short[] hashAlgorithms = new short[]{HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, + HashAlgorithm.sha224, HashAlgorithm.sha1}; // TODO Sort out ECDSA signatures and add them as the preferred // option here - short[] signatureAlgorithms = new short[] { SignatureAlgorithm.rsa }; + short[] signatureAlgorithms = new short[]{SignatureAlgorithm.rsa}; this.supportedSignatureAlgorithms = new Vector(); for (int i = 0; i < hashAlgorithms.length; ++i) @@ -126,9 +126,9 @@ public Hashtable getClientExtensions() throws IOException * TODO Could just add all the curves since we support them all, but users may not want to use unnecessarily * large fields. Need configuration options. */ - this.namedCurves = new int[] { NamedCurve.secp256r1, NamedCurve.secp384r1 }; - this.clientECPointFormats = new short[] { ECPointFormat.uncompressed, - ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; + this.namedCurves = new int[]{NamedCurve.secp256r1, NamedCurve.secp384r1}; + this.clientECPointFormats = new short[]{ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_prime, + ECPointFormat.ansiX962_compressed_char2,}; clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -154,7 +154,7 @@ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOExceptio public short[] getCompressionMethods() { - return new short[] { CompressionMethod._null }; + return new short[]{CompressionMethod._null}; } public void notifySessionID(byte[] sessionID) From 700c3a28422a209ae868010f16965efc5863f2d5 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:17:57 -0500 Subject: [PATCH 12/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index b49020e4d3..762c9e4684 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -40,10 +40,11 @@ public TlsSession getSessionToResume() } /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value {03,XX} as the record - * layer version number. Typical values would be {03,00}, the lowest version number supported by the client, and the - * value of ClientHello.client_version. No single value will guarantee interoperability with all old servers, but - * this is a complex topic beyond the scope of this document." + * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value + * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest + * version number supported by the client, and the value of ClientHello.client_version. No + * single value will guarantee interoperability with all old servers, but this is a complex + * topic beyond the scope of this document." */ public ProtocolVersion getClientHelloRecordLayerVersion() { @@ -65,8 +66,9 @@ public ProtocolVersion getClientVersion() public boolean isFallback() { /* - * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients that repeat a connection attempt with a - * downgraded protocol in order to avoid interoperability problems with legacy servers. + * draft-ietf-tls-downgrade-scsv-00 4. [..] is meant for use by clients that repeat a + * connection attempt with a downgraded protocol in order to avoid interoperability problems + * with legacy servers. */ return false; } @@ -78,8 +80,8 @@ public Hashtable getClientExtensions() throws IOException ProtocolVersion clientVersion = context.getClientVersion(); /* - * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2. Clients MUST NOT - * offer it if they are offering prior versions. + * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2. + * Clients MUST NOT offer it if they are offering prior versions. */ if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) { @@ -117,14 +119,14 @@ public Hashtable getClientExtensions() throws IOException if (TlsECCUtils.containsECCCipherSuites(getCipherSuites())) { /* - * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message appends these - * extensions (along with any others), enumerating the curves it supports and the point formats it can - * parse. Clients SHOULD send both the Supported Elliptic Curves Extension and the Supported Point Formats - * Extension. + * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message + * appends these extensions (along with any others), enumerating the curves it supports + * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic + * Curves Extension and the Supported Point Formats Extension. */ /* - * TODO Could just add all the curves since we support them all, but users may not want to use unnecessarily - * large fields. Need configuration options. + * TODO Could just add all the curves since we support them all, but users may not want + * to use unnecessarily large fields. Need configuration options. */ this.namedCurves = new int[]{NamedCurve.secp256r1, NamedCurve.secp384r1}; this.clientECPointFormats = new short[]{ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_prime, @@ -175,8 +177,8 @@ public void notifySelectedCompressionMethod(short selectedCompressionMethod) public void processServerExtensions(Hashtable serverExtensions) throws IOException { /* - * TlsProtocol implementation validates that any server extensions received correspond to client extensions - * sent. By default, we don't send any, and this method is not called. + * TlsProtocol implementation validates that any server extensions received correspond to + * client extensions sent. By default, we don't send any, and this method is not called. */ if (serverExtensions != null) { @@ -224,9 +226,9 @@ public TlsCompression getCompression() throws IOException default: /* - * Note: internal error here; the TlsProtocol implementation verifies that the server-selected compression - * method was in the list of client-offered compression methods, so if we now can't produce an - * implementation, we shouldn't have offered it! + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected compression method was in the list of client-offered compression + * methods, so if we now can't produce an implementation, we shouldn't have offered it! */ throw new TlsFatalAlert(AlertDescription.internal_error); } From 571da522210ce4a81f7706172250deff15235013 Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 11:26:52 -0500 Subject: [PATCH 13/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 18 +- .../bouncycastle/crypto/tls/TlsClient.java | 170 +++++++++--------- 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 762c9e4684..14bc16f9e4 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -5,8 +5,8 @@ import java.util.Vector; public abstract class AbstractTlsClient - extends AbstractTlsPeer - implements TlsClient + extends AbstractTlsPeer + implements TlsClient { protected TlsCipherFactory cipherFactory; @@ -88,12 +88,12 @@ public Hashtable getClientExtensions() throws IOException // TODO Provide a way for the user to specify the acceptable // hash/signature algorithms. - short[] hashAlgorithms = new short[]{HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1}; + short[] hashAlgorithms = new short[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, + HashAlgorithm.sha224, HashAlgorithm.sha1 }; // TODO Sort out ECDSA signatures and add them as the preferred // option here - short[] signatureAlgorithms = new short[]{SignatureAlgorithm.rsa}; + short[] signatureAlgorithms = new short[]{ SignatureAlgorithm.rsa }; this.supportedSignatureAlgorithms = new Vector(); for (int i = 0; i < hashAlgorithms.length; ++i) @@ -128,9 +128,9 @@ public Hashtable getClientExtensions() throws IOException * TODO Could just add all the curves since we support them all, but users may not want * to use unnecessarily large fields. Need configuration options. */ - this.namedCurves = new int[]{NamedCurve.secp256r1, NamedCurve.secp384r1}; - this.clientECPointFormats = new short[]{ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_prime, - ECPointFormat.ansiX962_compressed_char2,}; + this.namedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 }; + this.clientECPointFormats = new short[]{ ECPointFormat.uncompressed, + ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; clientExtensions = TlsExtensionsUtils.ensureExtensionsInitialised(clientExtensions); @@ -156,7 +156,7 @@ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOExceptio public short[] getCompressionMethods() { - return new short[]{CompressionMethod._null}; + return new short[]{ CompressionMethod._null }; } public void notifySessionID(byte[] sessionID) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java index 9296b2f8c9..68d78b0f2f 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java @@ -4,89 +4,89 @@ import java.util.Hashtable; import java.util.Vector; -public interface TlsClient extends TlsPeer { - void init(TlsClientContext context); - - /** - * Return the session this client wants to resume, if any. Note that the - * peer's certificate chain for the session (if any) may need to be - * periodically revalidated. - * - * @return A {@link TlsSession} representing the resumable session to be - * used for this connection, or null to use a new session. - * @see SessionParameters#getPeerCertificate() - */ - TlsSession getSessionToResume(); - - ProtocolVersion getClientHelloRecordLayerVersion(); - - ProtocolVersion getClientVersion(); - - boolean isFallback(); - - int[] getCipherSuites(); - - short[] getCompressionMethods(); - - // Hashtable is (Integer -> byte[]) - Hashtable getClientExtensions() throws IOException; - - void notifyServerVersion(ProtocolVersion selectedVersion) throws IOException; - - /** - * Notifies the client of the session_id sent in the ServerHello. - * - * @param sessionID - * @see TlsContext#getResumableSession() - */ - void notifySessionID(byte[] sessionID); - - void notifySelectedCipherSuite(int selectedCipherSuite); - - void notifySelectedCompressionMethod(short selectedCompressionMethod); - - // Hashtable is (Integer -> byte[]) - void processServerExtensions(Hashtable serverExtensions) throws IOException; - - // Vector is (SupplementalDataEntry) - void processServerSupplementalData(Vector serverSupplementalData) throws IOException; - - TlsKeyExchange getKeyExchange() throws IOException; - - TlsAuthentication getAuthentication() throws IOException; - - // Vector is (SupplementalDataEntry) - Vector getClientSupplementalData() throws IOException; - - /** - * RFC 5077 3.3. NewSessionTicket Handshake Message - *

- * This method will be called (only) when a NewSessionTicket handshake - * message is received. The ticket is opaque to the client and clients MUST - * NOT examine the ticket under the assumption that it complies with e.g. - * RFC 5077 4. Recommended Ticket Construction. - * - * @param newSessionTicket - * The ticket. - * @param sessionParameters - * @throws IOException - */ - void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) throws IOException; - - /** - * - * @return a {@link NewSessionTicket} - */ - NewSessionTicket getNewSessionTicket(); - - /** - * In the case of TLS resumption using session tickets, - * {@link TlsClient#getSessionToResume()} may return a null TlsSession. Use - * this method to retrieve the security parameters needed for session - * resumption. - * - * @return A {@link SecurityParameters} object - * @throws IOException - */ - SecurityParameters getSecurityParameters(); +public interface TlsClient + extends TlsPeer +{ + void init(TlsClientContext context); + + /** + * Return the session this client wants to resume, if any. Note that the peer's certificate + * chain for the session (if any) may need to be periodically revalidated. + * + * @return A {@link TlsSession} representing the resumable session to be used for this + * connection, or null to use a new session. + * @see SessionParameters#getPeerCertificate() + */ + TlsSession getSessionToResume(); + + ProtocolVersion getClientHelloRecordLayerVersion(); + + ProtocolVersion getClientVersion(); + + boolean isFallback(); + + int[] getCipherSuites(); + + short[] getCompressionMethods(); + + // Hashtable is (Integer -> byte[]) + Hashtable getClientExtensions() throws IOException; + + void notifyServerVersion(ProtocolVersion selectedVersion) throws IOException; + + /** + * Notifies the client of the session_id sent in the ServerHello. + * + * @param sessionID + * @see TlsContext#getResumableSession() + */ + void notifySessionID(byte[] sessionID); + + void notifySelectedCipherSuite(int selectedCipherSuite); + + void notifySelectedCompressionMethod(short selectedCompressionMethod); + + // Hashtable is (Integer -> byte[]) + void processServerExtensions(Hashtable serverExtensions) throws IOException; + + // Vector is (SupplementalDataEntry) + void processServerSupplementalData(Vector serverSupplementalData) throws IOException; + + TlsKeyExchange getKeyExchange() throws IOException; + + TlsAuthentication getAuthentication() throws IOException; + + // Vector is (SupplementalDataEntry) + Vector getClientSupplementalData() throws IOException; + + /** + * RFC 5077 3.3. NewSessionTicket Handshake Message + *

+ * This method will be called (only) when a NewSessionTicket handshake message is received. The + * ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption + * that it complies with e.g. RFC 5077 4. Recommended Ticket Construction. + * + * @param newSessionTicket + * The ticket. + * @param sessionParameters + * @throws IOException + */ + void notifyNewSessionTicket(NewSessionTicket newSessionTicket, SecurityParameters securityParameters) + throws IOException; + + /** + * + * @return a {@link NewSessionTicket} + */ + NewSessionTicket getNewSessionTicket(); + + /** + * In the case of TLS resumption using session tickets, {@link TlsClient#getSessionToResume()} + * may return a null TlsSession. Use this method to retrieve the security parameters needed for + * session resumption. + * + * @return A {@link SecurityParameters} object + * @throws IOException + */ + SecurityParameters getSecurityParameters(); } From 06ee318c862fbf4147980255be102c5defea4eee Mon Sep 17 00:00:00 2001 From: "Parthy Chandrasekaran (RD-CA)" Date: Wed, 23 Dec 2015 12:14:43 -0500 Subject: [PATCH 14/14] formatted code to conform to master repo --- .../crypto/tls/AbstractTlsClient.java | 18 ++++++++++------ .../bouncycastle/crypto/tls/TlsClient.java | 21 ++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java index 14bc16f9e4..f8766118dd 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsClient.java @@ -73,7 +73,8 @@ public boolean isFallback() return false; } - public Hashtable getClientExtensions() throws IOException + public Hashtable getClientExtensions() + throws IOException { Hashtable clientExtensions = null; @@ -146,7 +147,8 @@ public ProtocolVersion getMinimumVersion() return ProtocolVersion.TLSv10; } - public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException + public void notifyServerVersion(ProtocolVersion serverVersion) + throws IOException { if (!getMinimumVersion().isEqualOrEarlierVersionOf(serverVersion)) { @@ -174,7 +176,8 @@ public void notifySelectedCompressionMethod(short selectedCompressionMethod) this.selectedCompressionMethod = selectedCompressionMethod; } - public void processServerExtensions(Hashtable serverExtensions) throws IOException + public void processServerExtensions(Hashtable serverExtensions) + throws IOException { /* * TlsProtocol implementation validates that any server extensions received correspond to @@ -204,7 +207,8 @@ public void processServerExtensions(Hashtable serverExtensions) throws IOExcepti } } - public void processServerSupplementalData(Vector serverSupplementalData) throws IOException + public void processServerSupplementalData(Vector serverSupplementalData) + throws IOException { if (serverSupplementalData != null) { @@ -212,12 +216,14 @@ public void processServerSupplementalData(Vector serverSupplementalData) throws } } - public Vector getClientSupplementalData() throws IOException + public Vector getClientSupplementalData() + throws IOException { return null; } - public TlsCompression getCompression() throws IOException + public TlsCompression getCompression() + throws IOException { switch (selectedCompressionMethod) { diff --git a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java index 68d78b0f2f..9b57473bf2 100644 --- a/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java +++ b/core/src/main/java/org/bouncycastle/crypto/tls/TlsClient.java @@ -30,9 +30,11 @@ public interface TlsClient short[] getCompressionMethods(); // Hashtable is (Integer -> byte[]) - Hashtable getClientExtensions() throws IOException; + Hashtable getClientExtensions() + throws IOException; - void notifyServerVersion(ProtocolVersion selectedVersion) throws IOException; + void notifyServerVersion(ProtocolVersion selectedVersion) + throws IOException; /** * Notifies the client of the session_id sent in the ServerHello. @@ -47,17 +49,22 @@ public interface TlsClient void notifySelectedCompressionMethod(short selectedCompressionMethod); // Hashtable is (Integer -> byte[]) - void processServerExtensions(Hashtable serverExtensions) throws IOException; + void processServerExtensions(Hashtable serverExtensions) + throws IOException; // Vector is (SupplementalDataEntry) - void processServerSupplementalData(Vector serverSupplementalData) throws IOException; + void processServerSupplementalData(Vector serverSupplementalData) + throws IOException; - TlsKeyExchange getKeyExchange() throws IOException; + TlsKeyExchange getKeyExchange() + throws IOException; - TlsAuthentication getAuthentication() throws IOException; + TlsAuthentication getAuthentication() + throws IOException; // Vector is (SupplementalDataEntry) - Vector getClientSupplementalData() throws IOException; + Vector getClientSupplementalData() + throws IOException; /** * RFC 5077 3.3. NewSessionTicket Handshake Message