0N/A/*
3002N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/Apackage sun.security.ssl;
0N/A
3002N/Aimport java.io.ByteArrayOutputStream;
0N/Aimport java.security.*;
3002N/Aimport java.util.Arrays;
3002N/Aimport java.util.LinkedList;
3002N/Aimport java.util.List;
3002N/Aimport java.util.Locale;
3002N/Aimport java.util.Set;
0N/A
0N/A/**
0N/A * Abstraction for the SSL/TLS hash of all handshake messages that is
0N/A * maintained to verify the integrity of the negotiation. Internally,
0N/A * it consists of an MD5 and an SHA1 digest. They are used in the client
0N/A * and server finished messages and in certificate verify messages (if sent).
0N/A *
0N/A * This class transparently deals with cloneable and non-cloneable digests.
0N/A *
3002N/A * This class now supports TLS 1.2 also. The key difference for TLS 1.2
3002N/A * is that you cannot determine the hash algorithms for CertificateVerify
3002N/A * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
3002N/A * that there is no messy MD5+SHA1 digests.
3002N/A *
3002N/A * You need to obey these conventions when using this class:
3002N/A *
3324N/A * 1. protocolDetermined(version) should be called when the negotiated
3002N/A * protocol version is determined.
3002N/A *
3002N/A * 2. Before protocolDetermined() is called, only update(), reset(),
3002N/A * restrictCertificateVerifyAlgs(), setFinishedAlg(), and
3002N/A * setCertificateVerifyAlg() can be called.
3002N/A *
3324N/A * 3. After protocolDetermined() is called, reset() cannot be called.
3002N/A *
3324N/A * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2,
3324N/A * getFinishedHash() and getCertificateVerifyHash() cannot be called. Otherwise,
3324N/A * getMD5Clone() and getSHAClone() cannot be called.
3002N/A *
3002N/A * 5. getMD5Clone() and getSHAClone() can only be called after
3324N/A * protocolDetermined() is called and version is pre-TLS 1.2.
3002N/A *
3002N/A * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
3324N/A * all protocolDetermined(), setCertificateVerifyAlg() and setFinishedAlg()
3324N/A * have been called and the version is TLS 1.2. If a CertificateVerify message
3324N/A * is to be used, call setCertificateVerifyAlg() with the hash algorithm as the
3324N/A * argument. Otherwise, you still must call setCertificateVerifyAlg(null) before
3002N/A * calculating any hash value.
3002N/A *
3002N/A * Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
3002N/A * setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
3002N/A *
3002N/A * Example:
3002N/A * <pre>
3002N/A * HandshakeHash hh = new HandshakeHash(...)
3324N/A * hh.protocolDetermined(ProtocolVersion.TLS12);
3002N/A * hh.update(clientHelloBytes);
3002N/A * hh.setFinishedAlg("SHA-256");
3002N/A * hh.update(serverHelloBytes);
3002N/A * ...
3002N/A * hh.setCertificateVerifyAlg("SHA-384");
3002N/A * hh.update(CertificateVerifyBytes);
3002N/A * byte[] cvDigest = hh.getCertificateVerifyHash();
3002N/A * ...
3002N/A * hh.update(finished1);
3002N/A * byte[] finDigest1 = hh.getFinishedHash();
3002N/A * hh.update(finished2);
3002N/A * byte[] finDigest2 = hh.getFinishedHash();
3002N/A * </pre>
3002N/A * If no CertificateVerify message is to be used, call
3002N/A * <pre>
3002N/A * hh.setCertificateVerifyAlg(null);
3002N/A * </pre>
3002N/A * This call can be made once you are certain that this message
3002N/A * will never be used.
0N/A */
0N/Afinal class HandshakeHash {
0N/A
3002N/A // Common
3002N/A
3002N/A // -1: unknown
3002N/A // 1: <=TLS 1.1
3002N/A // 2: TLS 1.2
3002N/A private int version = -1;
3002N/A private ByteArrayOutputStream data = new ByteArrayOutputStream();
3002N/A private final boolean isServer;
3002N/A
3002N/A // For TLS 1.1
3002N/A private MessageDigest md5, sha;
3002N/A private final int clonesNeeded; // needs to be saved for later use
3002N/A
3002N/A // For TLS 1.2
3002N/A // cvAlgDetermined == true means setCertificateVerifyAlg() is called
3002N/A private boolean cvAlgDetermined = false;
3002N/A private String cvAlg;
3002N/A private MessageDigest finMD;
0N/A
0N/A /**
0N/A * Create a new HandshakeHash. needCertificateVerify indicates whether
3002N/A * a hash for the certificate verify message is required. The argument
3002N/A * algs is a set of all possible hash algorithms that might be used in
3002N/A * TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
3002N/A * CertificateVerify message will be used, leave it null or empty.
0N/A */
3002N/A HandshakeHash(boolean isServer, boolean needCertificateVerify,
3002N/A Set<String> algs) {
3002N/A this.isServer = isServer;
3002N/A clonesNeeded = needCertificateVerify ? 3 : 2;
3002N/A }
0N/A
3002N/A void update(byte[] b, int offset, int len) {
3002N/A switch (version) {
3002N/A case 1:
3002N/A md5.update(b, offset, len);
3002N/A sha.update(b, offset, len);
3002N/A break;
3002N/A default:
3002N/A if (finMD != null) {
3002N/A finMD.update(b, offset, len);
3002N/A }
3002N/A data.write(b, offset, len);
3002N/A break;
0N/A }
0N/A }
0N/A
0N/A /**
3002N/A * Reset the remaining digests. Note this does *not* reset the number of
0N/A * digest clones that can be obtained. Digests that have already been
0N/A * cloned and are gone remain gone.
0N/A */
0N/A void reset() {
3002N/A if (version != -1) {
3002N/A throw new RuntimeException(
3002N/A "reset() can be only be called before protocolDetermined");
3002N/A }
3002N/A data.reset();
0N/A }
0N/A
3002N/A
3324N/A void protocolDetermined(ProtocolVersion pv) {
3002N/A
3002N/A // Do not set again, will ignore
3002N/A if (version != -1) return;
3002N/A
3324N/A version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1;
3002N/A switch (version) {
3002N/A case 1:
3002N/A // initiate md5, sha and call update on saved array
3002N/A try {
3002N/A md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
3002N/A sha = CloneableDigest.getDigest("SHA", clonesNeeded);
3002N/A } catch (NoSuchAlgorithmException e) {
3002N/A throw new RuntimeException
3002N/A ("Algorithm MD5 or SHA not available", e);
3002N/A }
3002N/A byte[] bytes = data.toByteArray();
3002N/A update(bytes, 0, bytes.length);
3002N/A break;
3002N/A case 2:
3002N/A break;
3002N/A }
3002N/A }
3002N/A
3002N/A /////////////////////////////////////////////////////////////
3002N/A // Below are old methods for pre-TLS 1.1
3002N/A /////////////////////////////////////////////////////////////
3002N/A
0N/A /**
0N/A * Return a new MD5 digest updated with all data hashed so far.
0N/A */
0N/A MessageDigest getMD5Clone() {
3002N/A if (version != 1) {
3002N/A throw new RuntimeException(
3002N/A "getMD5Clone() can be only be called for TLS 1.1");
3002N/A }
0N/A return cloneDigest(md5);
0N/A }
0N/A
0N/A /**
0N/A * Return a new SHA digest updated with all data hashed so far.
0N/A */
0N/A MessageDigest getSHAClone() {
3002N/A if (version != 1) {
3002N/A throw new RuntimeException(
3002N/A "getSHAClone() can be only be called for TLS 1.1");
3002N/A }
0N/A return cloneDigest(sha);
0N/A }
0N/A
0N/A private static MessageDigest cloneDigest(MessageDigest digest) {
0N/A try {
0N/A return (MessageDigest)digest.clone();
0N/A } catch (CloneNotSupportedException e) {
0N/A // cannot occur for digests generated via CloneableDigest
0N/A throw new RuntimeException("Could not clone digest", e);
0N/A }
0N/A }
0N/A
3002N/A /////////////////////////////////////////////////////////////
3002N/A // Below are new methods for TLS 1.2
3002N/A /////////////////////////////////////////////////////////////
3002N/A
3002N/A private static String normalizeAlgName(String alg) {
3002N/A alg = alg.toUpperCase(Locale.US);
3002N/A if (alg.startsWith("SHA")) {
3002N/A if (alg.length() == 3) {
3002N/A return "SHA-1";
3002N/A }
3002N/A if (alg.charAt(3) != '-') {
3002N/A return "SHA-" + alg.substring(3);
3002N/A }
3002N/A }
3002N/A return alg;
3002N/A }
3002N/A /**
3002N/A * Specifies the hash algorithm used in Finished. This should be called
3002N/A * based in info in ServerHello.
3002N/A * Can be called multiple times.
3002N/A */
3002N/A void setFinishedAlg(String s) {
3002N/A if (s == null) {
3002N/A throw new RuntimeException(
3002N/A "setFinishedAlg's argument cannot be null");
3002N/A }
3002N/A
3002N/A // Can be called multiple times, but only set once
3002N/A if (finMD != null) return;
3002N/A
3002N/A try {
3002N/A finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
3002N/A } catch (NoSuchAlgorithmException e) {
3002N/A throw new Error(e);
3002N/A }
3002N/A finMD.update(data.toByteArray());
3002N/A }
3002N/A
3002N/A /**
3002N/A * Restricts the possible algorithms for the CertificateVerify. Called by
3002N/A * the server based on info in CertRequest. The argument must be a subset
3002N/A * of the argument with the same name in the constructor. The method can be
3002N/A * called multiple times. If the caller is sure that no CertificateVerify
3002N/A * message will be used, leave this argument null or empty.
3002N/A */
3002N/A void restrictCertificateVerifyAlgs(Set<String> algs) {
3002N/A if (version == 1) {
3002N/A throw new RuntimeException(
3002N/A "setCertificateVerifyAlg() cannot be called for TLS 1.1");
3002N/A }
3002N/A // Not used yet
3002N/A }
3002N/A
3002N/A /**
3002N/A * Specifies the hash algorithm used in CertificateVerify.
3002N/A * Can be called multiple times.
3002N/A */
3002N/A void setCertificateVerifyAlg(String s) {
3002N/A
3002N/A // Can be called multiple times, but only set once
3002N/A if (cvAlgDetermined) return;
3002N/A
3002N/A cvAlg = s == null ? null : normalizeAlgName(s);
3002N/A cvAlgDetermined = true;
3002N/A }
3002N/A
3002N/A byte[] getAllHandshakeMessages() {
3002N/A return data.toByteArray();
3002N/A }
3002N/A
3002N/A /**
3002N/A * Calculates the hash in the CertificateVerify. Must be called right
3002N/A * after setCertificateVerifyAlg()
3002N/A */
3002N/A /*byte[] getCertificateVerifyHash() {
3002N/A throw new Error("Do not call getCertificateVerifyHash()");
3002N/A }*/
3002N/A
3002N/A /**
3002N/A * Calculates the hash in Finished. Must be called after setFinishedAlg().
3002N/A * This method can be called twice, for Finished messages of the server
3002N/A * side and client side respectively.
3002N/A */
3002N/A byte[] getFinishedHash() {
3002N/A try {
3002N/A return cloneDigest(finMD).digest();
3002N/A } catch (Exception e) {
3002N/A throw new Error("BAD");
3002N/A }
3002N/A }
0N/A}
0N/A
0N/A/**
0N/A * A wrapper for MessageDigests that simulates cloning of non-cloneable
0N/A * digests. It uses the standard MessageDigest API and therefore can be used
0N/A * transparently in place of a regular digest.
0N/A *
0N/A * Note that we extend the MessageDigest class directly rather than
0N/A * MessageDigestSpi. This works because MessageDigest was originally designed
0N/A * this way in the JDK 1.1 days which allows us to avoid creating an internal
0N/A * provider.
0N/A *
0N/A * It can be "cloned" a limited number of times, which is specified at
0N/A * construction time. This is achieved by internally maintaining n digests
0N/A * in parallel. Consequently, it is only 1/n-th times as fast as the original
0N/A * digest.
0N/A *
0N/A * Example:
0N/A * MessageDigest md = CloneableDigest.getDigest("SHA", 2);
0N/A * md.update(data1);
0N/A * MessageDigest md2 = (MessageDigest)md.clone();
0N/A * md2.update(data2);
0N/A * byte[] d1 = md2.digest(); // digest of data1 || data2
0N/A * md.update(data3);
0N/A * byte[] d2 = md.digest(); // digest of data1 || data3
0N/A *
0N/A * This class is not thread safe.
0N/A *
0N/A */
0N/Afinal class CloneableDigest extends MessageDigest implements Cloneable {
0N/A
0N/A /**
0N/A * The individual MessageDigests. Initially, all elements are non-null.
0N/A * When clone() is called, the non-null element with the maximum index is
0N/A * returned and the array element set to null.
0N/A *
0N/A * All non-null element are always in the same state.
0N/A */
0N/A private final MessageDigest[] digests;
0N/A
0N/A private CloneableDigest(MessageDigest digest, int n, String algorithm)
0N/A throws NoSuchAlgorithmException {
0N/A super(algorithm);
0N/A digests = new MessageDigest[n];
0N/A digests[0] = digest;
0N/A for (int i = 1; i < n; i++) {
0N/A digests[i] = JsseJce.getMessageDigest(algorithm);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return a MessageDigest for the given algorithm that can be cloned the
0N/A * specified number of times. If the default implementation supports
0N/A * cloning, it is returned. Otherwise, an instance of this class is
0N/A * returned.
0N/A */
0N/A static MessageDigest getDigest(String algorithm, int n)
0N/A throws NoSuchAlgorithmException {
0N/A MessageDigest digest = JsseJce.getMessageDigest(algorithm);
0N/A try {
0N/A digest.clone();
0N/A // already cloneable, use it
0N/A return digest;
0N/A } catch (CloneNotSupportedException e) {
0N/A return new CloneableDigest(digest, n, algorithm);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Check if this object is still usable. If it has already been cloned the
0N/A * maximum number of times, there are no digests left and this object can no
0N/A * longer be used.
0N/A */
0N/A private void checkState() {
0N/A // XXX handshaking currently doesn't stop updating hashes...
0N/A // if (digests[0] == null) {
0N/A // throw new IllegalStateException("no digests left");
0N/A // }
0N/A }
0N/A
0N/A protected int engineGetDigestLength() {
0N/A checkState();
0N/A return digests[0].getDigestLength();
0N/A }
0N/A
0N/A protected void engineUpdate(byte b) {
0N/A checkState();
0N/A for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
0N/A digests[i].update(b);
0N/A }
0N/A }
0N/A
0N/A protected void engineUpdate(byte[] b, int offset, int len) {
0N/A checkState();
0N/A for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
0N/A digests[i].update(b, offset, len);
0N/A }
0N/A }
0N/A
0N/A protected byte[] engineDigest() {
0N/A checkState();
0N/A byte[] digest = digests[0].digest();
0N/A digestReset();
0N/A return digest;
0N/A }
0N/A
0N/A protected int engineDigest(byte[] buf, int offset, int len)
0N/A throws DigestException {
0N/A checkState();
0N/A int n = digests[0].digest(buf, offset, len);
0N/A digestReset();
0N/A return n;
0N/A }
0N/A
0N/A /**
0N/A * Reset all digests after a digest() call. digests[0] has already been
0N/A * implicitly reset by the digest() call and does not need to be reset
0N/A * again.
0N/A */
0N/A private void digestReset() {
0N/A for (int i = 1; (i < digests.length) && (digests[i] != null); i++) {
0N/A digests[i].reset();
0N/A }
0N/A }
0N/A
0N/A protected void engineReset() {
0N/A checkState();
0N/A for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
0N/A digests[i].reset();
0N/A }
0N/A }
0N/A
0N/A public Object clone() {
0N/A checkState();
0N/A for (int i = digests.length - 1; i >= 0; i--) {
0N/A if (digests[i] != null) {
0N/A MessageDigest digest = digests[i];
0N/A digests[i] = null;
0N/A return digest;
0N/A }
0N/A }
0N/A // cannot occur
0N/A throw new InternalError();
0N/A }
0N/A
0N/A}