1386 lines · 48.9 KB · Java
RawDownload
        calculateConnectionKeys(master);    }      /*     * Calculate the master secret from its various components.  This is     * used for key exchange by all cipher suites.     *     * The master secret is the catenation of three MD5 hashes, each     * consisting of the pre-master secret and a SHA1 hash.  Those three     * SHA1 hashes are of (different) constant strings, the pre-master     * secret, and the nonces provided by the client and the server.     */    private SecretKey calculateMasterSecret(SecretKey preMasterSecret,            ProtocolVersion requestedVersion) {         if (debug != null && Debug.isOn("keygen")) {            HexDumpEncoder      dump = new HexDumpEncoder();             System.out.println("SESSION KEYGEN:");             System.out.println("PreMaster Secret:");            printHex(dump, preMasterSecret.getEncoded());             // Nonces are dumped with connection keygen, no            // benefit to doing it twice        }         // What algs/params do we need to use?        String masterAlg;        PRF prf;         if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            masterAlg = "SunTls12MasterSecret";            prf = cipherSuite.prfAlg;        } else {            masterAlg = "SunTlsMasterSecret";            prf = P_NONE;        }         String prfHashAlg = prf.getPRFHashAlg();        int prfHashLength = prf.getPRFHashLength();        int prfBlockSize = prf.getPRFBlockSize();         TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(                preMasterSecret, protocolVersion.major, protocolVersion.minor,                clnt_random.random_bytes, svr_random.random_bytes,                prfHashAlg, prfHashLength, prfBlockSize);         SecretKey masterSecret;        try {            KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);            kg.init(spec);            masterSecret = kg.generateKey();        } catch (GeneralSecurityException e) {            // For RSA premaster secrets, do not signal a protocol error            // due to the Bleichenbacher attack. See comments further down.            if (!preMasterSecret.getAlgorithm().equals(                    "TlsRsaPremasterSecret")) {                throw new ProviderException(e);            }             if (debug != null && Debug.isOn("handshake")) {                System.out.println("RSA master secret generation error:");                e.printStackTrace(System.out);                System.out.println("Generating new random premaster secret");            }             if (requestedVersion != null) {                preMasterSecret =                    RSAClientKeyExchange.generateDummySecret(requestedVersion);            } else {                preMasterSecret =                    RSAClientKeyExchange.generateDummySecret(protocolVersion);            }             // recursive call with new premaster secret            return calculateMasterSecret(preMasterSecret, null);        }         // if no version check requested (client side handshake), or version        // information is not available (not an RSA premaster secret),        // return master secret immediately.        if ((requestedVersion == null) ||                !(masterSecret instanceof TlsMasterSecret)) {            return masterSecret;        }         // we have checked the ClientKeyExchange message when reading TLS        // record, the following check is necessary to ensure that        // JCE provider does not ignore the checking, or the previous        // checking process bypassed the premaster secret version checking.        TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;        int major = tlsKey.getMajorVersion();        int minor = tlsKey.getMinorVersion();        if ((major < 0) || (minor < 0)) {            return masterSecret;        }         // check if the premaster secret version is ok        // the specification says that it must be the maximum version supported        // by the client from its ClientHello message. However, many        // implementations send the negotiated version, so accept both        // for SSL v3.0 and TLS v1.0.        // NOTE that we may be comparing two unsupported version numbers, which        // is why we cannot use object reference equality in this special case.        ProtocolVersion premasterVersion =                                    ProtocolVersion.valueOf(major, minor);        boolean versionMismatch = (premasterVersion.v != requestedVersion.v);         /*         * we never checked the client_version in server side         * for TLS v1.0 and SSL v3.0. For compatibility, we         * maintain this behavior.         */        if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {            versionMismatch = (premasterVersion.v != protocolVersion.v);        }         if (versionMismatch == false) {            // check passed, return key            return masterSecret;        }         // Due to the Bleichenbacher attack, do not signal a protocol error.        // Generate a random premaster secret and continue with the handshake,        // which will fail when verifying the finished messages.        // For more information, see comments in PreMasterSecret.        if (debug != null && Debug.isOn("handshake")) {            System.out.println("RSA PreMasterSecret version error: expected"                + protocolVersion + " or " + requestedVersion + ", decrypted: "                + premasterVersion);            System.out.println("Generating new random premaster secret");        }        preMasterSecret =            RSAClientKeyExchange.generateDummySecret(requestedVersion);         // recursive call with new premaster secret        return calculateMasterSecret(preMasterSecret, null);    }     /*     * Calculate the keys needed for this connection, once the session's     * master secret has been calculated.  Uses the master key and nonces;     * the amount of keying material generated is a function of the cipher     * suite that's been negotiated.     *     * This gets called both on the "full handshake" (where we exchanged     * a premaster secret and started a new session) as well as on the     * "fast handshake" (where we just resumed a pre-existing session).     */    void calculateConnectionKeys(SecretKey masterKey) {        /*         * For both the read and write sides of the protocol, we use the         * master to generate MAC secrets and cipher keying material.  Block         * ciphers need initialization vectors, which we also generate.         *         * First we figure out how much keying material is needed.         */        int hashSize = cipherSuite.macAlg.size;        boolean is_exportable = cipherSuite.exportable;        BulkCipher cipher = cipherSuite.cipher;        int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;         // Which algs/params do we need to use?        String keyMaterialAlg;        PRF prf;         if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            keyMaterialAlg = "SunTls12KeyMaterial";            prf = cipherSuite.prfAlg;        } else {            keyMaterialAlg = "SunTlsKeyMaterial";            prf = P_NONE;        }         String prfHashAlg = prf.getPRFHashAlg();        int prfHashLength = prf.getPRFHashLength();        int prfBlockSize = prf.getPRFBlockSize();         TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(            masterKey, protocolVersion.major, protocolVersion.minor,            clnt_random.random_bytes, svr_random.random_bytes,            cipher.algorithm, cipher.keySize, expandedKeySize,            cipher.ivSize, hashSize,            prfHashAlg, prfHashLength, prfBlockSize);         try {            KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);            kg.init(spec);            TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();             clntWriteKey = keySpec.getClientCipherKey();            svrWriteKey = keySpec.getServerCipherKey();             // Return null if IVs are not supposed to be generated.            // e.g. TLS 1.1+.            clntWriteIV = keySpec.getClientIv();            svrWriteIV = keySpec.getServerIv();             clntMacSecret = keySpec.getClientMacKey();            svrMacSecret = keySpec.getServerMacKey();        } catch (GeneralSecurityException e) {            throw new ProviderException(e);        }         //        // Dump the connection keys as they're generated.        //        if (debug != null && Debug.isOn("keygen")) {            synchronized (System.out) {                HexDumpEncoder  dump = new HexDumpEncoder();                 System.out.println("CONNECTION KEYGEN:");                 // Inputs:                System.out.println("Client Nonce:");                printHex(dump, clnt_random.random_bytes);                System.out.println("Server Nonce:");                printHex(dump, svr_random.random_bytes);                System.out.println("Master Secret:");                printHex(dump, masterKey.getEncoded());                 // Outputs:                System.out.println("Client MAC write Secret:");                printHex(dump, clntMacSecret.getEncoded());                System.out.println("Server MAC write Secret:");                printHex(dump, svrMacSecret.getEncoded());                 if (clntWriteKey != null) {                    System.out.println("Client write key:");                    printHex(dump, clntWriteKey.getEncoded());                    System.out.println("Server write key:");                    printHex(dump, svrWriteKey.getEncoded());                } else {                    System.out.println("... no encryption keys used");                }                 if (clntWriteIV != null) {                    System.out.println("Client write IV:");                    printHex(dump, clntWriteIV.getIV());                    System.out.println("Server write IV:");                    printHex(dump, svrWriteIV.getIV());                } else {                    if (protocolVersion.v >= ProtocolVersion.TLS11.v) {                        System.out.println(                                "... no IV derived for this protocol");                    } else {                        System.out.println("... no IV used for this cipher");                    }                }                System.out.flush();            }        }    }     private static void printHex(HexDumpEncoder dump, byte[] bytes) {        if (bytes == null) {            System.out.println("(key bytes not available)");        } else {            try {                dump.encodeBuffer(bytes, System.out);            } catch (IOException e) {                // just for debugging, ignore this            }        }    }     /**     * Throw an SSLException with the specified message and cause.     * Shorthand until a new SSLException constructor is added.     * This method never returns.     */    static void throwSSLException(String msg, Throwable cause)            throws SSLException {        SSLException e = new SSLException(msg);        e.initCause(cause);        throw e;    }      /*     * Implement a simple task delegator.     *     * We are currently implementing this as a single delegator, may     * try for parallel tasks later.  Client Authentication could     * benefit from this, where ClientKeyExchange/CertificateVerify     * could be carried out in parallel.     */    class DelegatedTask<E> implements Runnable {         private PrivilegedExceptionAction<E> pea;         DelegatedTask(PrivilegedExceptionAction<E> pea) {            this.pea = pea;        }         public void run() {            synchronized (engine) {                try {                    AccessController.doPrivileged(pea, engine.getAcc());                } catch (PrivilegedActionException pae) {                    thrown = pae.getException();                } catch (RuntimeException rte) {                    thrown = rte;                }                delegatedTask = null;                taskDelegated = false;            }        }    }     private <T> void delegateTask(PrivilegedExceptionAction<T> pea) {        delegatedTask = new DelegatedTask<T>(pea);        taskDelegated = false;        thrown = null;    }     DelegatedTask getTask() {        if (!taskDelegated) {            taskDelegated = true;            return delegatedTask;        } else {            return null;        }    }     /*     * See if there are any tasks which need to be delegated     *     * Locked by SSLEngine.this.     */    boolean taskOutstanding() {        return (delegatedTask != null);    }     /*     * The previous caller failed for some reason, report back the     * Exception.  We won't worry about Error's.     *     * Locked by SSLEngine.this.     */    void checkThrown() throws SSLException {        synchronized (thrownLock) {            if (thrown != null) {                 String msg = thrown.getMessage();                 if (msg == null) {                    msg = "Delegated task threw Exception/Error";                }                 /*                 * See what the underlying type of exception is.  We should                 * throw the same thing.  Chain thrown to the new exception.                 */                Exception e = thrown;                thrown = null;                 if (e instanceof RuntimeException) {                    throw (RuntimeException)                        new RuntimeException(msg).initCause(e);                } else if (e instanceof SSLHandshakeException) {                    throw (SSLHandshakeException)                        new SSLHandshakeException(msg).initCause(e);                } else if (e instanceof SSLKeyException) {                    throw (SSLKeyException)                        new SSLKeyException(msg).initCause(e);                } else if (e instanceof SSLPeerUnverifiedException) {                    throw (SSLPeerUnverifiedException)                        new SSLPeerUnverifiedException(msg).initCause(e);                } else if (e instanceof SSLProtocolException) {                    throw (SSLProtocolException)                        new SSLProtocolException(msg).initCause(e);                } else {                    /*                     * If it's SSLException or any other Exception,                     * we'll wrap it in an SSLException.                     */                    throw (SSLException)                        new SSLException(msg).initCause(e);                }            }        }    }}

Lines 1001–1386 of 1386. Previous lines