| package org.bouncycastle.crypto.tls; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Vector; |
| |
| public abstract class AbstractTlsKeyExchange |
| implements TlsKeyExchange |
| { |
| protected int keyExchange; |
| protected Vector supportedSignatureAlgorithms; |
| |
| protected TlsContext context; |
| |
| protected AbstractTlsKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms) |
| { |
| this.keyExchange = keyExchange; |
| this.supportedSignatureAlgorithms = supportedSignatureAlgorithms; |
| } |
| |
| protected DigitallySigned parseSignature(InputStream input) throws IOException |
| { |
| DigitallySigned signature = DigitallySigned.parse(context, input); |
| SignatureAndHashAlgorithm signatureAlgorithm = signature.getAlgorithm(); |
| if (signatureAlgorithm != null) |
| { |
| TlsUtils.verifySupportedSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm); |
| } |
| return signature; |
| } |
| |
| public void init(TlsContext context) |
| { |
| this.context = context; |
| |
| ProtocolVersion clientVersion = context.getClientVersion(); |
| |
| if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion)) |
| { |
| /* |
| * RFC 5264 7.4.1.4.1. If the client does not send the signature_algorithms extension, |
| * the server MUST do the following: |
| * |
| * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK, |
| * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}. |
| * |
| * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if |
| * the client had sent the value {sha1,dsa}. |
| * |
| * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA), |
| * behave as if the client had sent value {sha1,ecdsa}. |
| */ |
| if (this.supportedSignatureAlgorithms == null) |
| { |
| switch (keyExchange) |
| { |
| case KeyExchangeAlgorithm.DH_DSS: |
| case KeyExchangeAlgorithm.DHE_DSS: |
| case KeyExchangeAlgorithm.SRP_DSS: |
| { |
| this.supportedSignatureAlgorithms = TlsUtils.getDefaultDSSSignatureAlgorithms(); |
| break; |
| } |
| |
| case KeyExchangeAlgorithm.ECDH_ECDSA: |
| case KeyExchangeAlgorithm.ECDHE_ECDSA: |
| { |
| this.supportedSignatureAlgorithms = TlsUtils.getDefaultECDSASignatureAlgorithms(); |
| break; |
| } |
| |
| case KeyExchangeAlgorithm.DH_RSA: |
| case KeyExchangeAlgorithm.DHE_RSA: |
| case KeyExchangeAlgorithm.ECDH_RSA: |
| case KeyExchangeAlgorithm.ECDHE_RSA: |
| case KeyExchangeAlgorithm.RSA: |
| case KeyExchangeAlgorithm.RSA_PSK: |
| case KeyExchangeAlgorithm.SRP_RSA: |
| { |
| this.supportedSignatureAlgorithms = TlsUtils.getDefaultRSASignatureAlgorithms(); |
| break; |
| } |
| |
| case KeyExchangeAlgorithm.DHE_PSK: |
| case KeyExchangeAlgorithm.ECDHE_PSK: |
| case KeyExchangeAlgorithm.PSK: |
| case KeyExchangeAlgorithm.SRP: |
| break; |
| |
| default: |
| throw new IllegalStateException("unsupported key exchange algorithm"); |
| } |
| } |
| } |
| else if (this.supportedSignatureAlgorithms != null) |
| { |
| throw new IllegalStateException("supported_signature_algorithms not allowed for " + clientVersion); |
| } |
| } |
| |
| public void processServerCertificate(Certificate serverCertificate) |
| throws IOException |
| { |
| if (supportedSignatureAlgorithms == null) |
| { |
| /* |
| * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the |
| * certificate must be the same as the algorithm for the certificate key. |
| */ |
| } |
| else |
| { |
| /* |
| * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then |
| * all certificates provided by the server MUST be signed by a hash/signature algorithm |
| * pair that appears in that extension. |
| */ |
| } |
| } |
| |
| public void processServerCredentials(TlsCredentials serverCredentials) |
| throws IOException |
| { |
| processServerCertificate(serverCredentials.getCertificate()); |
| } |
| |
| public boolean requiresServerKeyExchange() |
| { |
| return false; |
| } |
| |
| public byte[] generateServerKeyExchange() |
| throws IOException |
| { |
| if (requiresServerKeyExchange()) |
| { |
| throw new TlsFatalAlert(AlertDescription.internal_error); |
| } |
| return null; |
| } |
| |
| public void skipServerKeyExchange() |
| throws IOException |
| { |
| if (requiresServerKeyExchange()) |
| { |
| throw new TlsFatalAlert(AlertDescription.unexpected_message); |
| } |
| } |
| |
| public void processServerKeyExchange(InputStream input) |
| throws IOException |
| { |
| if (!requiresServerKeyExchange()) |
| { |
| throw new TlsFatalAlert(AlertDescription.unexpected_message); |
| } |
| } |
| |
| public void skipClientCredentials() |
| throws IOException |
| { |
| } |
| |
| public void processClientCertificate(Certificate clientCertificate) |
| throws IOException |
| { |
| } |
| |
| public void processClientKeyExchange(InputStream input) |
| throws IOException |
| { |
| // Key exchange implementation MUST support client key exchange |
| throw new TlsFatalAlert(AlertDescription.internal_error); |
| } |
| } |