void processServerHelloDone()

in modules/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java [365:533]


    void processServerHelloDone() {
        PrivateKey clientKey = null;

        if (serverCert != null) {
            if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon
                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
                unexpectedMessage();
                return;
            }
            verifyServerCert();
        } else {
            if (session.cipherSuite.keyExchange != CipherSuite.KeyExchange_DH_anon
                    && session.cipherSuite.keyExchange != CipherSuite.KeyExchange_DH_anon_EXPORT) {
                unexpectedMessage();
                return;
            }
        }

        // Client certificate
        if (certificateRequest != null) {
            X509Certificate[] certs = null;
            String clientAlias = ((X509ExtendedKeyManager) parameters
                    .getKeyManager()).chooseClientAlias(certificateRequest
                    .getTypesAsString(),
                    certificateRequest.certificate_authorities, null);
            if (clientAlias != null) {
                X509ExtendedKeyManager km = (X509ExtendedKeyManager) parameters
                        .getKeyManager();
                certs = km.getCertificateChain((clientAlias));
                clientKey = km.getPrivateKey(clientAlias);
            }
            session.localCertificates = certs;
            clientCert = new CertificateMessage(certs);
            send(clientCert);
        }
        // Client key exchange
        if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
                || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
            // RSA encrypted premaster secret message
            Cipher c;
            try {
                c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                if (serverKeyExchange != null) {
                    c.init(Cipher.ENCRYPT_MODE, serverKeyExchange
                            .getRSAPublicKey());
                } else {
                    c.init(Cipher.ENCRYPT_MODE, serverCert.certs[0]);
                }
            } catch (Exception e) {
                fatalAlert(AlertProtocol.INTERNAL_ERROR,
                        "Unexpected exception", e);
                return;
            }
            preMasterSecret = new byte[48];
            parameters.getSecureRandom().nextBytes(preMasterSecret);
            System.arraycopy(clientHello.client_version, 0, preMasterSecret, 0,
                    2);
            try {
                clientKeyExchange = new ClientKeyExchange(c
                        .doFinal(preMasterSecret),
                        serverHello.server_version[1] == 1);
            } catch (Exception e) {
                fatalAlert(AlertProtocol.INTERNAL_ERROR,
                        "Unexpected exception", e);
                return;
            }
        } else {
            PublicKey serverPublic;
            KeyAgreement agreement = null;
            DHParameterSpec spec;
            try {
                KeyFactory kf = null;
                try {
                    kf = KeyFactory.getInstance("DH");
                } catch (NoSuchAlgorithmException e) {
                    kf = KeyFactory.getInstance("DiffieHellman");
                }
                
                try {
                    agreement = KeyAgreement.getInstance("DH");
                } catch (NoSuchAlgorithmException ee) {
                    agreement = KeyAgreement.getInstance("DiffieHellman");
                }

                KeyPairGenerator kpg = null;
                try {
                    kpg = KeyPairGenerator.getInstance("DH");
                } catch (NoSuchAlgorithmException e) {
                    kpg = KeyPairGenerator.getInstance("DiffieHellman");
                }
                if (serverKeyExchange != null) {
                    serverPublic = kf.generatePublic(new DHPublicKeySpec(
                            serverKeyExchange.par3, serverKeyExchange.par1,
                            serverKeyExchange.par2));
                    spec = new DHParameterSpec(serverKeyExchange.par1,
                            serverKeyExchange.par2);
                } else {
                    serverPublic = serverCert.certs[0].getPublicKey();
                    spec = ((DHPublicKey) serverPublic).getParams();
                }
                kpg.initialize(spec);

                KeyPair kp = kpg.generateKeyPair();
                Key key = kp.getPublic();
                if (clientCert != null
                        && serverCert != null
                        && (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
                                || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS)) {
                    PublicKey client_pk = clientCert.certs[0].getPublicKey();
                    PublicKey server_pk = serverCert.certs[0].getPublicKey();
                    if (client_pk instanceof DHKey
                            && server_pk instanceof DHKey) {
                        if (((DHKey) client_pk).getParams().getG().equals(
                                ((DHKey) server_pk).getParams().getG())
                                && ((DHKey) client_pk).getParams().getP()
                                    .equals(((DHKey) server_pk).getParams().getG())) {
                            // client cert message DH public key parameters
                            // matched those specified by the
                            //   server in its certificate,
                            clientKeyExchange = new ClientKeyExchange(); // empty
                        }
                    }
                } else {
                    clientKeyExchange = new ClientKeyExchange(
                            ((DHPublicKey) key).getY());
                }
                key = kp.getPrivate();
                agreement.init(key);
                agreement.doPhase(serverPublic, true);
                preMasterSecret = agreement.generateSecret();
            } catch (Exception e) {
                fatalAlert(AlertProtocol.INTERNAL_ERROR,
                        "Unexpected exception", e);
                return;
            }
        }
        if (clientKeyExchange != null) {
            send(clientKeyExchange);
        }

        computerMasterSecret();

        // send certificate verify for all certificates except those containing
        // fixed DH parameters
        if (clientCert != null && !clientKeyExchange.isEmpty()) {
            // Certificate verify
            DigitalSignature ds = new DigitalSignature(
                    session.cipherSuite.keyExchange);
            ds.init(clientKey);

            if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT
                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) { 
                ds.setMD5(io_stream.getDigestMD5());
                ds.setSHA(io_stream.getDigestSHA());
            } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
                    || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
                ds.setSHA(io_stream.getDigestSHA());
            // The Signature should be empty in case of anonimous signature algorithm:
            // } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon ||
            //         session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
            }
            certificateVerify = new CertificateVerify(ds.sign());
            send(certificateVerify);
        }

        sendChangeCipherSpec();
    }