FileDocCategorySizeDatePackage
HandshakeProtocol.javaAPI DocAndroid 1.5 API16317Wed May 06 22:41:06 BST 2009org.apache.harmony.xnet.provider.jsse

HandshakeProtocol

public abstract class HandshakeProtocol extends Object
Base class for ClientHandshakeImpl and ServerHandshakeImpl classes.
see
TLS 1.0 spec., 7.4. Handshake protocol

Fields Summary
public static final int
NEED_UNWRAP
Handshake status NEED_UNWRAP - HandshakeProtocol needs to receive data
public static final int
NOT_HANDSHAKING
Handshake status NOT_HANDSHAKING - is not currently handshaking
public static final int
FINISHED
Handshake status FINISHED - HandshakeProtocol has just finished
public static final int
NEED_TASK
Handshake status NEED_TASK - HandshakeProtocol needs the results of delegated task
protected int
status
Current handshake status
protected HandshakeIODataStream
io_stream
IO stream for income/outcome handshake data
protected SSLRecordProtocol
recordProtocol
SSL Record Protocol implementation.
protected SSLParameters
parameters
SSLParameters suplied by SSLSocket or SSLEngine
protected Vector
delegatedTasks
Delegated tasks for this handshake implementation
protected boolean
nonBlocking
Indicates non-blocking handshake
protected SSLSessionImpl
session
Pending session
protected ClientHello
clientHello
Sended and received handshake messages
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
protected boolean
changeCipherSpecReceived
Indicates that change cipher spec message has been received
protected boolean
isResuming
Indicates previous session resuming
protected byte[]
preMasterSecret
Premaster secret
protected Exception
delegatedTaskErr
Exception occured in delegated task
private byte[]
verify_data
private byte[]
master_secret_bytes
private boolean
needSendCCSpec
protected boolean
needSendHelloRequest
public SSLEngineImpl
engineOwner
SSLEngine owning this HandshakeProtocol
Constructors Summary
protected HandshakeProtocol(Object owner)
Creates HandshakeProtocol instance

param
owner

    
             
    // BEGIN android-removed
    // public SSLSocketImpl socketOwner;
    // END android-removed
    
              
       
        if (owner instanceof SSLEngineImpl) {
            engineOwner = (SSLEngineImpl) owner;
            nonBlocking = true;
            this.parameters = (SSLParameters) engineOwner.sslParameters;
        }
        // BEGIN android-removed
        // else if (owner instanceof SSLSocketImpl) {
        //     socketOwner = (SSLSocketImpl) owner;
        //     nonBlocking = false;
        //     this.parameters = (SSLParameters) socketOwner.sslParameters;
        // }
        // END android-removed
    
Methods Summary
protected voidclearMessages()
Clears previously sended and received handshake messages

        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;
    
public voidcomputerMasterSecret()
Computers master secret

        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;        
    
protected voidcomputerReferenceVerifyDataSSLv3(byte[] sender)
Computer reference SSLv3 verify_data that is used to verify finished message

see
"SSLv3 spec. 7.6.9. Finished"
param
label

        verify_data = new byte[36];
        computerVerifyDataSSLv3(sender, verify_data);
    
protected voidcomputerReferenceVerifyDataTLS(java.lang.String label)
Computers reference TLS verify_data that is used to verify finished message

see
TLS spec. 7.4.9. Finished
param
label

        computerVerifyDataTLS(label, verify_data);
    
protected voidcomputerVerifyDataSSLv3(byte[] sender, byte[] buf)
Computer SSLv3 verify_data

see
"SSLv3 spec. 7.6.9. Finished"
param
label
param
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[] hanshake_messages = io_stream.getMessages();
            md5.update(hanshake_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(hanshake_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);

        }
    
protected voidcomputerVerifyDataTLS(java.lang.String label, byte[] buf)
Computer TLS verify_data

see
TLS spec. 7.4.9. Finished
param
label
param
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);
        }
    
protected voidfatalAlert(byte description, java.lang.String reason)
Sends fatal alert, breaks execution

param
description
param
reason

        throw new AlertException(description, new SSLHandshakeException(reason));
    
protected voidfatalAlert(byte description, java.lang.String reason, java.lang.Exception cause)
Sends fatal alert, breaks execution

param
description
param
reason
param
cause

        throw new AlertException(description, new SSLException(reason, cause));
    
protected voidfatalAlert(byte description, javax.net.ssl.SSLException cause)
Sends fatal alert, breaks execution

param
description
param
cause

        throw new AlertException(description, cause);
    
protected static intgetRSAKeyLength(java.security.PublicKey pk)
Returns RSA key length

param
pk
return
throws
NoSuchAlgorithmException
throws
InvalidKeySpecException


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

return
session

        return session;
    
public javax.net.ssl.SSLEngineResult$HandshakeStatusgetStatus()
Returns handshake status

return

        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;
        }
    
public java.lang.RunnablegetTask()
Returns a delegated task.

return
Delegated task or null

        if (delegatedTasks.isEmpty()) {
            return null;
        } else {
            Runnable task = (Runnable)delegatedTasks.firstElement();
            delegatedTasks.remove(0);
            return task;
        }
    
abstract voidmakeFinished()
Creates and sends finished message

abstract voidreceiveChangeCipherSpec()
Proceses inbound ChangeCipherSpec message

public voidsend(Message message)
Writes message to HandshakeIODataStream

param
message

        io_stream.writeUint8(message.getType());
        io_stream.writeUint24(message.length());
        message.send(io_stream);
    
protected voidsendChangeCipherSpec()

        needSendCCSpec = true;
    
protected voidsendHelloRequest()

        needSendHelloRequest = true;
    
protected voidsendWarningAlert(byte description)
Sends fatal alert, breaks execution

param
description

        recordProtocol.alert(AlertProtocol.WARNING, description);
    
public voidsetRecordProtocol(SSLRecordProtocol recordProtocol)
Sets SSL Record Protocol

param
recordProtocol

        this.recordProtocol = recordProtocol;
    
protected voidshutdown()
Shutdownes the protocol. It will be impossiblke to use the instance after the calling of this method.

        clearMessages();
        session = null;
        preMasterSecret = null;
        delegatedTasks.clear();
    
public abstract voidstart()
Start session negotiation

param
session

protected voidstop()
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

        clearMessages();
        status = NOT_HANDSHAKING;
    
protected voidunexpectedMessage()
Sends fatal alert "UNEXPECTED MESSAGE"

        fatalAlert(AlertProtocol.UNEXPECTED_MESSAGE, "UNEXPECTED MESSAGE");
    
public abstract voidunwrap(byte[] bytes)
Proceses inbound handshake messages

param
bytes

public abstract voidunwrapSSLv2(byte[] bytes)
Processes SSLv2 Hello message

param
bytes

protected voidverifyFinished(byte[] data)
Verifies finished data

param
data
param
isServer

        if (!Arrays.equals(verify_data, data)) {
            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Incorrect FINISED");
        }
    
public byte[]wrap()
Proceses outbound handshake messages

return

        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;
        }