package org.bouncycastle.tls; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; import org.bouncycastle.tls.crypto.TlsCertificate; import org.bouncycastle.tls.crypto.TlsCryptoParameters; import org.bouncycastle.tls.crypto.TlsSecret; import org.bouncycastle.util.io.Streams; /** * (D)TLS and SSLv3 RSA key exchange. */ public class TlsRSAKeyExchange extends AbstractTlsKeyExchange { protected TlsCredentialedDecryptor serverCredentials = null; protected TlsCertificate serverCertificate; protected TlsSecret preMasterSecret; public TlsRSAKeyExchange(Vector supportedSignatureAlgorithms) { super(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms); } public void skipServerCredentials() throws IOException { throw new TlsFatalAlert(AlertDescription.internal_error); } public void processServerCredentials(TlsCredentials serverCredentials) throws IOException { if (!(serverCredentials instanceof TlsCredentialedDecryptor)) { throw new TlsFatalAlert(AlertDescription.internal_error); } this.serverCredentials = (TlsCredentialedDecryptor)serverCredentials; } public void processServerCertificate(Certificate serverCertificate) throws IOException { if (serverCertificate.isEmpty()) { throw new TlsFatalAlert(AlertDescription.bad_certificate); } checkServerCertSigAlg(serverCertificate); this.serverCertificate = serverCertificate.getCertificateAt(0).useInRole(ConnectionEnd.server, keyExchange); } public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException { short[] types = certificateRequest.getCertificateTypes(); for (int i = 0; i < types.length; ++i) { switch (types[i]) { case ClientCertificateType.rsa_sign: case ClientCertificateType.dss_sign: case ClientCertificateType.ecdsa_sign: break; default: throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } public void processClientCredentials(TlsCredentials clientCredentials) throws IOException { if (!(clientCredentials instanceof TlsCredentialedSigner)) { throw new TlsFatalAlert(AlertDescription.internal_error); } } public void generateClientKeyExchange(OutputStream output) throws IOException { this.preMasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context, serverCertificate, output); } public void processClientKeyExchange(InputStream input) throws IOException { byte[] encryptedPreMasterSecret; if (TlsUtils.isSSL(context)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.readAll(input); } else { encryptedPreMasterSecret = TlsUtils.readOpaque16(input); } this.preMasterSecret = serverCredentials.decrypt(new TlsCryptoParameters(context), encryptedPreMasterSecret); } public TlsSecret generatePreMasterSecret() throws IOException { TlsSecret tmp = this.preMasterSecret; this.preMasterSecret = null; return tmp; } }