public void unwrap()

in modules/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java [102:313]


    public void unwrap(byte[] bytes) {

        io_stream.append(bytes);
        while (io_stream.available() > 0) {
            int handshakeType;
            int length;
            io_stream.mark();
            try {
                handshakeType = io_stream.read();
                length = io_stream.readUint24();
                if (io_stream.available() < length) {
                    io_stream.reset();
                    return;
                }

                switch (handshakeType) {
                case 1: // CLIENT_HELLO
                    if (clientHello != null && this.status != FINISHED) {
                            // Client hello has been received during handshake
                            unexpectedMessage();
                            return;
                    }
                    // if protocol planed to send Hello Request message
                    // - cancel this demand.
                    needSendHelloRequest = false;
                    clientHello = new ClientHello(io_stream, length);
                    if (nonBlocking) {
                        delegatedTasks.add(new DelegatedTask(new PrivilegedExceptionAction<Void>() {
                            public Void run() throws Exception {
                                processClientHello();
                                return null;
                            }
                        }, this, AccessController.getContext()));
                        return;
                    }
                    processClientHello();
                    break;

                case 11: //    CLIENT CERTIFICATE
                    if (isResuming || certificateRequest == null
                            || serverHelloDone == null || clientCert != null) {
                        unexpectedMessage();
                        return;
                    }
                    clientCert = new CertificateMessage(io_stream, length);
                    if (clientCert.certs.length == 0) {
                        if (parameters.getNeedClientAuth()) {
                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
                                    "HANDSHAKE FAILURE: no client certificate received");
                        }
                    } else {
                        String authType = clientCert.certs[0].getPublicKey()
                                .getAlgorithm();
                        try {
                            parameters.getTrustManager().checkClientTrusted(
                                    clientCert.certs, authType);
                        } catch (CertificateException e) {
                            fatalAlert(AlertProtocol.BAD_CERTIFICATE,
                                    "Untrusted Client Certificate ", e);
                        }
                        session.peerCertificates = clientCert.certs;
                    }
                    break;

                case 15: // CERTIFICATE_VERIFY
                    if (isResuming
                            || clientKeyExchange == null
                            || clientCert == null
                            || clientKeyExchange.isEmpty() //client certificate
                                                           // contains fixed DH
                                                           // parameters
                            || certificateVerify != null
                            || changeCipherSpecReceived) {
                        unexpectedMessage();
                        return;
                    }
                    certificateVerify = new CertificateVerify(io_stream, length);

                    DigitalSignature ds = new DigitalSignature(session.cipherSuite.keyExchange);
                    ds.init(serverCert.certs[0]);                 
                    byte[] md5_hash = null;
                    byte[] sha_hash = null;

                    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) {
                        md5_hash = io_stream.getDigestMD5withoutLast();
                        sha_hash = io_stream.getDigestSHAwithoutLast();
                    } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
                            || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
                        sha_hash = io_stream.getDigestSHAwithoutLast();
                    } else if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon
                            || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
                    }
                    ds.setMD5(md5_hash);
                    ds.setSHA(sha_hash);
                    if (!ds.verifySignature(certificateVerify.signedHash)) {
                        fatalAlert(AlertProtocol.DECRYPT_ERROR,
                                "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature");
                    }
                    break;
                case 16: // CLIENT_KEY_EXCHANGE
                    if (isResuming
                            || serverHelloDone == null
                            || clientKeyExchange != null
                            || (clientCert == null && parameters
                                    .getNeedClientAuth())) {
                        unexpectedMessage();
                        return;
                    }
                    if (session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA
                            || session.cipherSuite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
                        clientKeyExchange = new ClientKeyExchange(io_stream,
                                length, serverHello.server_version[1] == 1,
                                true);
                        Cipher c = null;
                        try {
                            c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                            c.init(Cipher.DECRYPT_MODE, privKey);
                            preMasterSecret = c
                                    .doFinal(clientKeyExchange.exchange_keys);
                            // check preMasterSecret:
                            if (preMasterSecret.length != 48
                                    || preMasterSecret[0] != clientHello.client_version[0]
                                    || preMasterSecret[1] != clientHello.client_version[1]) {
                                // incorrect preMasterSecret
                                // prevent an attack (see TLS 1.0 spec., 7.4.7.1.)
                                preMasterSecret = new byte[48];
                                parameters.getSecureRandom().nextBytes(
                                        preMasterSecret);
                            }
                        } catch (Exception e) {
                            fatalAlert(AlertProtocol.INTERNAL_ERROR,
                                    "INTERNAL ERROR", e);
                        }
                    } else { // diffie hellman key exchange
                        clientKeyExchange = new ClientKeyExchange(io_stream,
                                length, serverHello.server_version[1] == 1,
                                false);
                        if (clientKeyExchange.isEmpty()) {
                            // TODO check that client cert. DH params
                            // matched server cert. DH params

                            // client cert. contains fixed DH parameters 
                            preMasterSecret = ((DHPublicKey) clientCert.certs[0]
                                    .getPublicKey()).getY().toByteArray();
                        } else {
                            PublicKey clientPublic;
                            KeyAgreement agreement;
                            try {
                                KeyFactory kf = null;
                                try {
                                    kf = KeyFactory.getInstance("DH");
                                } catch (NoSuchAlgorithmException ee) {
                                    kf = KeyFactory
                                            .getInstance("DiffieHellman");
                                }
                                try {
                                    agreement = KeyAgreement.getInstance("DH");
                                } catch (NoSuchAlgorithmException ee) {
                                    agreement = KeyAgreement
                                            .getInstance("DiffieHellman");
                                }
                                clientPublic = kf
                                        .generatePublic(new DHPublicKeySpec(
                                                new BigInteger(
                                                        1,
                                                        clientKeyExchange.exchange_keys),
                                                serverKeyExchange.par1,
                                                serverKeyExchange.par2));
                                agreement.init(privKey);
                                agreement.doPhase(clientPublic, true);
                                preMasterSecret = agreement.generateSecret();
                            } catch (Exception e) {
                                fatalAlert(AlertProtocol.INTERNAL_ERROR,
                                        "INTERNAL ERROR", e);
                                return;
                            }
                        }
                    }

                    computerMasterSecret();
                    break;

                case 20: // FINISHED
                    if (!isResuming && !changeCipherSpecReceived) {
                        unexpectedMessage();
                        return;
                    }

                    clientFinished = new Finished(io_stream, length);
                    verifyFinished(clientFinished.getData());
                    parameters.getServerSessionContext().putSession(session);
                    if (!isResuming) {
                        sendChangeCipherSpec();
                    } else {
                        session.lastAccessedTime = System.currentTimeMillis();
                        status = FINISHED;
                    }
                    break;
                default:
                    unexpectedMessage();
                    return;
                }
            } catch (IOException e) {
                // io stream dosn't contain complete handshake message
                io_stream.reset();
                return;
            }
        }
    }