/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.xnet.provider.jsse;

import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import java.util.Vector;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;

/**
 * Base class for ClientHandshakeImpl and ServerHandshakeImpl classes.
 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.
 * Handshake protocol</a>
 *
 */
public abstract class HandshakeProtocol {

    /**
     * Handshake status NEED_UNWRAP - HandshakeProtocol needs to receive data
     */
    public final static int NEED_UNWRAP = 1;

    /**
     * Handshake status NOT_HANDSHAKING - is not currently handshaking
     */
    public final static int NOT_HANDSHAKING = 2;

    /**
     * Handshake status FINISHED - HandshakeProtocol has just finished
     */
    public final static int FINISHED = 3;

    /**
     * Handshake status NEED_TASK - HandshakeProtocol needs the results of delegated task
     */
    public final static int NEED_TASK = 4;

    /**
     * Current handshake status
     */
    protected int status = NOT_HANDSHAKING;

    /**
     * IO stream for income/outcome handshake data
     */
    protected HandshakeIODataStream io_stream = new HandshakeIODataStream();

    /**
     * SSL Record Protocol implementation.
     */
    protected SSLRecordProtocol recordProtocol;

    /**
     * SSLParametersImpl suplied by SSLSocket or SSLEngine
     */
    protected SSLParametersImpl parameters;

    /**
     * Delegated tasks for this handshake implementation
     */
    protected Vector<DelegatedTask> delegatedTasks = new Vector<DelegatedTask>();

    /**
     * Indicates non-blocking handshake
     */
    protected boolean nonBlocking;

    /**
     * Pending session
     */
    protected SSLSessionImpl session;

    /**
     * Sended and received handshake messages
     */
    protected ClientHello clientHello;
    protected ServerHello serverHello;
    protected CertificateMessage serverCert;
    protected ServerKeyExchange serverKeyExchange;
    protected CertificateRequest certificateRequest;
    protected ServerHelloDone serverHelloDone;
    protected CertificateMessage clientCert;
    protected ClientKeyExchange clientKeyExchange;
    protected CertificateVerify certificateVerify;
    protected Finished clientFinished;
    protected Finished serverFinished;

    /**
     * Indicates that change cipher spec message has been received
     */
    protected boolean changeCipherSpecReceived = false;

    /**
     * Indicates previous session resuming
     */
    protected boolean isResuming = false;

    /**
     *  Premaster secret
     */
    protected byte[] preMasterSecret;

    /**
     * Exception occured in delegated task
     */
    protected Exception delegatedTaskErr;

    // reference verify_data used to verify finished message
    private byte[] verify_data = new byte[12];

    // Encoding of "master secret" string: "master secret".getBytes()
    private byte[] master_secret_bytes =
            {109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };

    // indicates whether protocol needs to send change cipher spec message
    private boolean needSendCCSpec = false;

    // indicates whether protocol needs to send change cipher spec message
    protected boolean needSendHelloRequest = false;

    /**
     * SSLEngine owning this HandshakeProtocol
     */
    public SSLEngineImpl engineOwner;

    /**
     * SSLSocket owning this HandshakeProtocol
     */
    public SSLSocketImpl socketOwner;

    /**
     * Creates HandshakeProtocol instance
     * @param owner
     */
    protected HandshakeProtocol(Object owner) {
        if (owner instanceof SSLEngineImpl) {
            engineOwner = (SSLEngineImpl) owner;
            nonBlocking = true;
            this.parameters = engineOwner.sslParameters;
        }
        else if (owner instanceof SSLSocketImpl) {
            socketOwner = (SSLSocketImpl) owner;
            nonBlocking = false;
            this.parameters = socketOwner.sslParameters;
        }
    }

    /**
     * Sets SSL Record Protocol
     * @param recordProtocol
     */
    public void setRecordProtocol(SSLRecordProtocol recordProtocol) {
        this.recordProtocol = recordProtocol;
    }

    /**
     * Start session negotiation
     * @param session
     */
    public abstract void start();

    /**
     * Stops the current session renegotiation process.
     * Such functionality is needed when it is session renegotiation
     * process and no_renegotiation alert message is received
     * from another peer.
     * @param session
     */
    protected void stop() {
        clearMessages();
        status = NOT_HANDSHAKING;
    }

    /**
     * Returns handshake status
     * @return
     */
    public SSLEngineResult.HandshakeStatus getStatus() {
        if (io_stream.hasData() || needSendCCSpec ||
                needSendHelloRequest || delegatedTaskErr != null) {
            return SSLEngineResult.HandshakeStatus.NEED_WRAP;
        }
        if (!delegatedTasks.isEmpty()) {
            return SSLEngineResult.HandshakeStatus.NEED_TASK;
        }

        switch (status) {
        case HandshakeProtocol.NEED_UNWRAP:
            return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
        case HandshakeProtocol.FINISHED:
            status = NOT_HANDSHAKING;
            clearMessages();
            return SSLEngineResult.HandshakeStatus.FINISHED;
        default: // HandshakeProtocol.NOT_HANDSHAKING:
            return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
        }
    }

    /**
     * Returns pending session
     * @return session
     */
    public SSLSessionImpl getSession() {
        return session;
    }

    protected void sendChangeCipherSpec() {
        needSendCCSpec = true;
    }

    protected void sendHelloRequest() {
        needSendHelloRequest = true;
    }

    /**
     * Proceses inbound ChangeCipherSpec message
     */
    abstract void receiveChangeCipherSpec();

    /**
     * Creates and sends finished message
     */
    abstract void makeFinished();

    /**
     * Proceses inbound handshake messages
     * @param bytes
     */
    public abstract void unwrap(byte[] bytes);

    /**
     * Processes SSLv2 Hello message
     * @param bytes
     */
    public abstract void unwrapSSLv2(byte[] bytes);

    /**
     * Proceses outbound handshake messages
     * @return
     */
    public byte[] wrap() {
        if (delegatedTaskErr != null) {
            // process error occured in delegated task
            Exception e = delegatedTaskErr;
            delegatedTaskErr = null;
            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
                    "Error occured in delegated task:" + e.getMessage(), e);
        }
        if (io_stream.hasData()) {
            return recordProtocol.wrap(ContentType.HANDSHAKE, io_stream);
        } else if (needSendCCSpec) {
            makeFinished();
            needSendCCSpec = false;
            return recordProtocol.getChangeCipherSpecMesage(getSession());
        } else if (needSendHelloRequest) {
            needSendHelloRequest = false;
            return recordProtocol.wrap(ContentType.HANDSHAKE,
                    // hello request message
                    // (see TLS v 1 specification:
                    // http://www.ietf.org/rfc/rfc2246.txt)
                    new byte[] {0, 0, 0, 0}, 0, 4);
        } else {
            return null; // nothing to send;
        }
    }

    /**
     * Sends fatal alert, breaks execution
     *
     * @param description
     */
    protected void sendWarningAlert(byte description) {
        recordProtocol.alert(AlertProtocol.WARNING, description);
    }

    /**
     * Sends fatal alert, breaks execution
     *
     * @param description
     * @param reason
     */
    protected void fatalAlert(byte description, String reason) {
        throw new AlertException(description, new SSLHandshakeException(reason));
    }

    /**
     * Sends fatal alert, breaks execution
     *
     * @param description
     * @param reason
     * @param cause
     */
    protected void fatalAlert(byte description, String reason, Exception cause) {
        throw new AlertException(description, new SSLException(reason, cause));
    }

    /**
     * Sends fatal alert, breaks execution
     *
     * @param description
     * @param cause
     */
    protected void fatalAlert(byte description, SSLException cause) {
        throw new AlertException(description, cause);
    }

    /**
     * Computers reference TLS verify_data that is used to verify finished message
     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a>
     * @param label
     */
    protected void computerReferenceVerifyDataTLS(String label) {
        computerVerifyDataTLS(label, verify_data);
    }

    /**
     * Computer TLS verify_data
     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS spec. 7.4.9. Finished</a>
     * @param label
     * @param buf
     */
    protected void computerVerifyDataTLS(String label, byte[] buf) {
        byte[] md5_digest = io_stream.getDigestMD5();
        byte[] sha_digest = io_stream.getDigestSHA();

        byte[] digest = new byte[md5_digest.length + sha_digest.length];
        System.arraycopy(md5_digest, 0, digest, 0, md5_digest.length);
        System.arraycopy(sha_digest, 0, digest, md5_digest.length,
                sha_digest.length);
        try {
            PRF.computePRF(buf, session.master_secret,
                    label.getBytes(), digest);
        } catch (GeneralSecurityException e) {
            fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
        }
    }

    /**
     * Computer reference SSLv3 verify_data that is used to verify finished message
     * @see "SSLv3 spec. 7.6.9. Finished"
     * @param label
     */
    protected void computerReferenceVerifyDataSSLv3(byte[] sender) {
        verify_data = new byte[36];
        computerVerifyDataSSLv3(sender, verify_data);
    }

    /**
     * Computer SSLv3 verify_data
     * @see "SSLv3 spec. 7.6.9. Finished"
     * @param label
     * @param buf
     */
    protected void computerVerifyDataSSLv3(byte[] sender, byte[] buf) {
        MessageDigest md5;
        MessageDigest sha;
        try {
            md5 = MessageDigest.getInstance("MD5");
            sha = MessageDigest.getInstance("SHA-1");
        } catch (Exception e) {
            fatalAlert(AlertProtocol.INTERNAL_ERROR,
                       "Could not initialize the Digest Algorithms.",
                       e);
            return;
        }
        try {
            byte[] handshake_messages = io_stream.getMessages();
            md5.update(handshake_messages);
            md5.update(sender);
            md5.update(session.master_secret);
            byte[] b = md5.digest(SSLv3Constants.MD5pad1);
            md5.update(session.master_secret);
            md5.update(SSLv3Constants.MD5pad2);
            System.arraycopy(md5.digest(b), 0, buf, 0, 16);

            sha.update(handshake_messages);
            sha.update(sender);
            sha.update(session.master_secret);
            b = sha.digest(SSLv3Constants.SHApad1);
            sha.update(session.master_secret);
            sha.update(SSLv3Constants.SHApad2);
            System.arraycopy(sha.digest(b), 0, buf, 16, 20);
        } catch (Exception e) {
            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);

        }
    }

    /**
     * Verifies finished data
     *
     * @param data
     * @param isServer
     */
    protected void verifyFinished(byte[] data) {
        if (!Arrays.equals(verify_data, data)) {
            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Incorrect FINISED");
        }
    }

    /**
     * Sends fatal alert "UNEXPECTED MESSAGE"
     *
     */
    protected void unexpectedMessage() {
        fatalAlert(AlertProtocol.UNEXPECTED_MESSAGE, "UNEXPECTED MESSAGE");
    }

    /**
     * Writes message to HandshakeIODataStream
     *
     * @param message
     */
    public void send(Message message) {
        io_stream.writeUint8(message.getType());
        io_stream.writeUint24(message.length());
        message.send(io_stream);
    }

    /**
     * Computers master secret
     *
     */
    public void computerMasterSecret() {
        byte[] seed = new byte[64];
        System.arraycopy(clientHello.getRandom(), 0, seed, 0, 32);
        System.arraycopy(serverHello.getRandom(), 0, seed, 32, 32);
        session.master_secret = new byte[48];
        if (serverHello.server_version[1] == 1) { // TLSv1
            try {
                PRF.computePRF(session.master_secret, preMasterSecret,
                        master_secret_bytes, seed);
            } catch (GeneralSecurityException e) {
                fatalAlert(AlertProtocol.INTERNAL_ERROR, "PRF error", e);
            }
        } else { // SSL3.0
            PRF.computePRF_SSLv3(session.master_secret, preMasterSecret, seed);
        }

        //delete preMasterSecret from memory
        Arrays.fill(preMasterSecret, (byte)0);
        preMasterSecret = null;
    }

    /**
     * Returns a delegated task.
     * @return Delegated task or null
     */
    public Runnable getTask() {
        if (delegatedTasks.isEmpty()) {
            return null;
        }
        return delegatedTasks.remove(0);
    }

    /**
     *
     * Clears previously sended and received handshake messages
     */
    protected void clearMessages() {
        io_stream.clearBuffer();
        clientHello = null;
        serverHello = null;
        serverCert = null;
        serverKeyExchange = null;
        certificateRequest = null;
        serverHelloDone = null;
        clientCert = null;
        clientKeyExchange = null;
        certificateVerify = null;
        clientFinished = null;
        serverFinished = null;
    }

    /**
     * Returns RSA key length
     * @param pk
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    protected static int getRSAKeyLength(PublicKey pk)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        BigInteger mod;
        if (pk instanceof RSAKey) {
            mod = ((RSAKey) pk).getModulus();
        } else {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            mod = kf.getKeySpec(pk, RSAPublicKeySpec.class)
                    .getModulus();
        }
        return mod.bitLength();
    }

    /**
     * Shutdownes the protocol. It will be impossiblke to use the instance
     * after the calling of this method.
     */
    protected void shutdown() {
        clearMessages();
        session = null;
        preMasterSecret = null;
        delegatedTasks.clear();
    }
}
